I am really new to Spring Boot, and I am currently going through the book. Spring Boot in action.
I created and complied my first web simple web app fine, expect the css file shows up blank in the console. I have already looked up the following post:
Spring Boot - CSS not loading
Spring Boot CSS Stripped
I am using Thymleaves and my css file is placed within the static folder as the post and book states, but nothing shows up. my current external link, seems to be the correct way too.
<link rel="stylesheet" th:href="#{/main.css}" />
Although, the css appear to show in the resources in console, the css file remains blank. Below are my files and code.
File Structure:
Template:
body {
background-color: #cccccc;
font-family: arial,helvetica,sans-serif;
}
.bookHeadline {
font-size: 12pt;
font-weight: bold;
}
.bookDescription {
font-size: 10pt;
}
label {
font-weight: bold;
}
<html xmlns:th="http://www.springframework.org/schema/data/jaxb">
<head>
<title>Reading List</title>
<link rel="stylesheet" th:href="#{/main.css}" />
</head>
<body>
<h2>Your Reading List</h2>
<div th:unless="${#lists.isEmpty(books)}">
<dl th:each="book : ${books}">
<dt class="bookHeadline">
<span th:text="${book.title}">Title</span> by
<span th:text="${book.author}">Author</span>
(ISBN: <span th:text="${book.isbn}">ISBN</span>)
</dt>
<dd class="bookDescription">
<span th:if="${book.description}"
th:text="${book.description}">Description</span>
<span th:if="${book.description eq null}">
No description available</span>
</dd>
</dl>
</div>
<div th:if="${#lists.isEmpty(books)}">
<p>You have no books in your book list</p>
</div>
<hr/>
<h3>Add a book</h3>
<form method="POST">
<label for="title">Title:</label>
<input type="text" name="title" size="50"></input><br/>
<label for="author">Author:</label>
<input type="text" name="author" size="50"></input><br/>
<label for="isbn">ISBN:</label>
<input type="text" name="isbn" size="15"></input><br/>
<label for="description">Description:</label><br/>
<textarea name="description" cols="80" rows="5">
</textarea><br/>
<input type="submit"></input>
</form>
</body>
</html>
Controller:
package codenotes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
#Controller
#RequestMapping("/")
public class BookController {
private BookRepository bookRepository;
#Autowired
public BookController(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
#RequestMapping(value = "/{reader}", method = RequestMethod.GET)
public String readerBooks(
#PathVariable("reader") String reader,
Model model) {
List<Book> readingList =
bookRepository.findByReader(reader);
if (readingList != null) {
model.addAttribute("books", readingList);
}
return "readingList";
}
#RequestMapping(value = "/{reader}", method = RequestMethod.POST)
public String addToReadingList(
#PathVariable("reader") String reader, Book book) {
book.setReader(reader);
bookRepository.save(book);
return "redirect:/{reader}";
}
}
Repository:
package codenotes;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BookRepository extends JpaRepository<Book, Long> {
List<Book> findByReader(String reader);
}
I believe you should read this, how to serve static content:
http://docs.spring.io/spring-boot/docs/1.4.2.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-static-content
To sum it up, your browser is caching your static resources, such as CSS files.
In order to break this behavior, try first clean your browser cache, in google chrome you go to settings then clear browsing data.
Secondly, add these lines to your application.properties file in order to bust the cache:
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
or add this instead:
spring.resources.chain.strategy.fixed.enabled=true
spring.resources.chain.strategy.fixed.paths=/**
spring.resources.chain.strategy.fixed.version=v12
Please make the following changes
1. Move main.css into /static/css folder
2. Change
Let me know if does not work.
If you are using Spring Auth and you're not logged in, you'll also have to make sure that the user has access to see the styling.
In the WebSecurityConfig you just have to add "*/.css" to your list of allowed routes.
#Override
protected void configure(final HttpSecurity http) throws Exception {
...
.authorizeRequests()
//allow requests to all urls that match the pattern
.antMatchers("/", "/signup", "/login", "/*.css", "/*.jpg").permitAll()
//anything else you must be logged in
...
}
Related
I have just began to work with Html + springboot. I have prepared two files
the HTML file with a form as bellow
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Add Info</title>
<link rel="stylesheet" type="text/css" th:href="#{/css/style.css}"/>
</head>
<body>
<h1>Insert an Info:</h1>
<!--
In Thymeleaf the equivalent of
JSP's ${pageContext.request.contextPath}/edit.html
would be #{/edit.html}
-->
<form th:action="#{}" method="post">
<input type="text" th:name="Coord1"/> </br>
<input type="text" th:name="Coord2"/> </br>
<input type="text" th:name="Coord3"/> </br>
<input type="text" th:name="Coord4"/> </br>
<input type="submit"/>
</form>
<br/>
<!-- Check if errorMessage is not null and not empty -->
<div th:if="${errorMessage}" th:utext="${errorMessage}"
style="color:red;font-style:italic;">
...
</div>
</body>
</html>
I want to get the four values coord1 coord2, coord3 and coord4. My java controller file contains the lines
package com.example.project.controller;
import java.io.IOException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
#Controller
public class MainController {
#RequestMapping(value="",method=RequestMethod.GET)
public void addAObjectForm(#RequestParam("Coord1") String Coord1,#RequestParam("Coord2") String Coord2,#RequestParam("Coord3") String Coord3, #RequestParam("Coord4")String Coord4) throws IOException {
System.out.println(Coord1);
}
}I
When I run this code I get the error
[2m2021-07-12 22:28:57.206[0;39m [33m WARN[0;39m [35m18812[0;39m [2m---[0;39m [2m[nio-8080-exec-3][0;39m [36m.w.s.m.s.DefaultHandlerExceptionResolver[0;39m [2m:[0;39m Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'Coord1' for method parameter type String is not present]
Could anyone help me please
you use POST action in your form, and u use GET method in your controller. match those things and update status please :)
Firstly add thymeleaf dependency in your pom.xml.
Give some action inside the:action like
<form th:action="#{detail}" method="post">
Use make controller like
#Controller
public class MainController {
#GetMapping("/")
public String show() {
return "show"; // I had given name to view part as show.html
}
#RequestMapping(value = "/detail", method = RequestMethod.POST)
public void addAObjectForm(#RequestParam(value = "Coord1", required = false) String Coord1,
#RequestParam(value = "Coord2", required = false) String Coord2,
#RequestParam(value = "Coord3", required = false) String Coord3,
#RequestParam(value = "Coord4", required = false) String Coord4) throws IOException {
System.out.println(Coord1);
}
}
i'm new in Spring and i trying to learn it with help Spring in action 5 (Craig Walls).I'm creating small Spring Boot MVC-application.Now i have a little problem with Thymeleaf.
I have Controller,View and model as POJO object.When i'm trying to get data from form Intellij Idea told me that something wrong with my Thymeleaf view in this line:
Model
import java.util.Date;
import java.util.List;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import lombok.Data;
#Data
public class Taco {
private Long id;
private Date createdAt;
#NotNull
#Size(min=5, message="Name must be at least 5 characters long")
private String name;
#Size(min=1, message="You must choose at least 1 ingredient")
private List<Ingredient> ingredients;
}
View
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Taco Cloud</title>
<link rel="stylesheet" th:href="#{/styles.css}"/>
</head>
<body>
<h1>Design your taco!</h1>
<img src="../static/images/TacoCloud.png" alt="TacoCloud.png" th:src="#{/images/TacoCloud.png}">
<form method="POST" th:object="${taco}">
<div class="grid">
<div class="ingredient-group" id="wraps">
<h3>Designate yor wrap:</h3>
<div th:each="ingredient:${wrap}">
<input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
<div class="ingredient-group" id="proteins">
<h3>Pick your protein:</h3>
<div th:each="ingredient: ${protein}">
<input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
<span th:text="${ingredient.name}">INGREDIENT</span>
</div>
</div>
<div class="ingredient-group" id="cheeses">
<h3>Choose your cheese:</h3>
<div th:each="ingredient:${cheese}">
<input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
<div class="ingredient-group" id="veggies">
<h3>Determine your veggies:</h3>
<div th:each="ingredient : ${veggies}">
<input name="ingredients" type="checkbox" th:value="${ingredient.id}"
/>
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
<div class="ingredient-group" id="sauces">
<h3>Select your sauce:</h3>
<div th:each="ingredient : ${sauce}">
<input name="ingredients" type="checkbox" th:value="${ingredient.id}"
/>
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
</div>
<div>
<h3>Name your taco creation:</h3>
<input type="text" name="name" th:field="*{name}"/>
<br/>
<button>Submit your taco</button>
</div>
</form>
</body>
</html>
Controller
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import tacos.Ingredient.Type;
import tacos.Ingredient;
import org.springframework.web.bind.annotation.ModelAttribute;
import tacos.Taco;
import tacos.data.IngredientRepository;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
#Slf4j
#Controller
#RequestMapping("/design")
public class DesignTacoController {
private final IngredientRepository ingredientRepo;
#Autowired
public DesignTacoController(IngredientRepository ingredientRepo){
this.ingredientRepo=ingredientRepo;
}
#GetMapping
public String showDesignForm(Model model) {
List<Ingredient> ingredients=new ArrayList<>();
ingredientRepo.findAll().forEach(i->ingredients.add(i));
Type[] types = Ingredient.Type.values();
for (Type type : types) {
model.addAttribute(type.toString().toLowerCase(),
filterByType(ingredients, type));
}
return "design";
}
private List<Ingredient> filterByType(
List<Ingredient> ingredients, Type type) {
return ingredients
.stream()
.filter(x -> x.getType().equals(type))
.collect(Collectors.toList());
}
#PostMapping
public String processDesign(#Valid #ModelAttribute("design") Taco design, Errors errors, Model model) {
if (errors.hasErrors()) {
return "design";
}
// Save the taco design...
// We'll do this in chapter 3
log.info("Processing design: " + design);
return "redirect:/orders/current";
}
}
And finally i get this error:
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/design.html]")
Caused by: org.attoparser.ParseException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "design" - line 64, col 45)
I noticed two things on your code.
I don't see th:action on your form that is required for form submission.
change form method="POST" th:object="${taco}" to form method="POST" th:object="${design}"
Try fixing these two and it should work.
I encountered same issue.
Resolution for me was to add getters in Taco.java for name. Somehow lombok is not generating getters automatically at run time.
And th:object="${taco}" should be th:object="${design}"
No need to make changes for th:action. From tutorial
If you take another look at the tag in your view, you can see that its method attribute is set to POST. Moreover, the doesn’t declare an action attribute. This means that when the form is submitted, the browser will gather up all the data in the form and send it to the server in an HTTP POST request to the same path for which a GET request displayed the form—the /design path.
I found two thing in code:
I do not find any action your form in html. You should use th:action tag to add an action.
in html you used th:object="${taco}" for declare an object for your html form. But you do not add “taco” object in your model in controller method from where you return the html design. You should add the “taco” object in your controller method like below.
model.addAttribute(“taco”, taco Object);
I've been wrestling with this one for a while.
I have a web application that I'm trying to put Spring Security into. I have successfully made it so that whenever a user attempts to access pages they are not authorized to, it redirects them to the login page. The problem is that the login page is not showing - just the header for the login page (and it isn't stylized). I'm very confused by this, because all other pages are displaying fine.
This is the example I'm working from I'm pretty much trying to follow it to the letter and have even downloaded it, but I'm not able to quite see what I am doing differently in my own project.
The only big difference I see is that I'm using Gradle and this guy is using Maven.
Here is my build.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.7.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
jar {
baseName = 'gs-spring-boot'
baseName = 'gs-handling-form-submission'
baseName = 'gs-serving-mobile-web-content'
baseName = 'gs-accessing-data-mongodb'
baseName = 'gs-rest-service-cors'
baseName = 'gs-securing-web'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: "spring-boot-starter-tomcat"
}
compile("org.springframework.boot:spring-boot-starter-jetty")
testCompile("org.springframework.boot:spring-boot-starter-test")
compile("org.springframework.boot:spring-boot-starter-actuator")
testCompile 'junit:junit:4.12'
compile("org.springframework.boot:spring-boot-starter-data-mongodb")
compile group: 'joda-time', name: 'joda-time', version: '2.8.1'
compile("org.springframework.boot:spring-boot-starter-web:1.3.0.RELEASE")
compile 'org.slf4j:slf4j-api:1.7.13'
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-parent:1.5.3.RELEASE")
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
compile("org.springframework.boot:spring-boot-starter-data-mongodb")
compile("org.springframework.boot:spring-boot-starter-mobile")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("com.h2database:h2")
compile("net.sourceforge.nekohtml:nekohtml:1.9.21")
compile("org.springframework.boot:spring-boot-starter-data-mongodb:1.2.0.RELEASE")
compile("org.springframework.boot.spring-boot-starter-remote-shell:1.2.0.RELEASE")
compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity4")
compile("org.springframework.boot:spring-boot-devtools:true")
testCompile("org.springframework.security:spring-security-test")
compile("org.springframework.boot:spring-boot-starter-security")
}
Here is my Controller:
#Controller
public class WebController { //implements ErrorController{
private static final String PATH = "/error";
private BlogPostRepo blogPostRepo;
#Autowired
public WebController(BlogPostRepo blogPostRepo) {
this.blogPostRepo = blogPostRepo;
}
#RequestMapping("/index")
public String displayBlogPosts(Model model){
model.addAttribute("blogPosts", blogPostRepo.findAll());
return "index";
}
#RequestMapping("/login")
public String login(){
return "/login";
}
#GetMapping("/403")
public String error403() {
return "/error/403";
}
}
Here is SpringSecurityConfig.java :
package com.stereoscopics.app.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.AccessDeniedHandler;
#Configuration
// http://docs.spring.io/spring-boot/docs/current/reference/html/howto-security.html
// Switch off the Spring Boot security configuration
//#EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AccessDeniedHandler accessDeniedHandler;
// roles admin allow to access /admin/**
// roles user allow to access /user/**
// custom 403 access denied handler
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/", "/index", "/submitAnArticle").permitAll()
.antMatchers("/admin/**").hasAnyRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
.and()
.withUser("admin").password("password").roles("ADMIN");
}
}
Here is my AccessDeniedHandler.java:
package com.stereoscopics.app.error;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
// handle 403 page
#Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
private static Logger logger = LoggerFactory.getLogger(MyAccessDeniedHandler.class);
#Override
public void handle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AccessDeniedException e) throws IOException, ServletException {
Authentication auth
= SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
logger.info("User '" + auth.getName()
+ "' attempted to access the protected URL: "
+ httpServletRequest.getRequestURI());
}
httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/403");
}
}
Here is my login:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
>
<head>
<title>Spring Security Example </title>
<div th:replace="fragments/header :: header-css"/>
</head>
<body>
<div th:replace="fragments/header :: header"/>
<div class="container">
<div class="row" style="margin-top:20px">
<div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3">
<form th:action="#{/login}" method="post">
<fieldset>
<h1>Please Sign In</h1>
<div th:if="${param.error}">
<div class="alert alert-danger">
Invalid username and password.
</div>
</div>
<div th:if="${param.logout}">
<div class="alert alert-info">
You have been logged out.
</div>
</div>
<div class="form-group">
<input type="text" name="username" id="username" class="form-control input-lg"
placeholder="UserName" required="true" autofocus="true"/>
</div>
<div class="form-group">
<input type="password" name="password" id="password" class="form-control input-lg"
placeholder="Password" required="true"/>
</div>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<input type="submit" class="btn btn-lg btn-primary btn-block" value="Sign In"/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
</div>
</div>
</fieldset>
</form>
</div>
</div>
</div>
<div th:replace="fragments/footer :: footer"/>
</body>
</html>
Here is my header:
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:fragment="header-css">
<!-- this is header-css -->
<link rel="stylesheet" type="text/css"
href="webjars/bootstrap/3.3.7/css/bootstrap.min.css" />
<link rel="stylesheet" th:href="#{/css/main.css}"
href="../../css/main.css" />
</div>
</head>
<body>
<div th:fragment="header">
<!-- this is header -->
<nav class="navbar navbar-inverse">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" th:href="#{/}">Spring Boot</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><a th:href="#{/}">Home</a></li>
</ul>
</div>
</div>
</nav>
</div>
</body>
</html>
Here's what I've tried:
Checking the file paths - the header and footer are in \resources\templates\fragments and the other files are in resources\templates
Google (cannot find anything)
Double-Checking Dependencies
Downloading the example and cross checking
I am very, very confused. Please help.
It's hard to debug without a runnable example (a git repository that I could clone would be nice), but one thing I see is that your security config requires authentication to access the stylesheets.
Add
.antMatchers("/webjars/**").permitAll()
.antMatchers("/css/**").permitAll()
to your security config and the stylesheets should load.
Additionally you should probably use an absolute path to the stylesheets in your header since ../../css/main.css might not work for all your URLs.
A good way to debug these things is to use the web console in your browser and look at the network requests and see whether or not all assets are loaded correctly.
Are you sure that its your login page that isn't showing properly? I believe that you could be redirecting improperly authenticated requests to the wrong page. When you handle requests that are denied in your MyAccessDeniedHandler class you execute the following:
httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/403");
This is in turn handled by the WebController class with the following code:
#GetMapping("/403")
public String error403() {
return "/error/403";
}
So, it seems as if you are not actually rendering the login page when you handle 403's.
I'm not familiar with thyme leaf, but my guess is that you have not defined the error/403 file, and that a header is rendered even if the html file is not found when rendering pages.
I know there are many threads on this topic i have tried most of them, still cant fix my problem.I am using SpringMVC and MongoDB What i am trying to achieve is, I will Store some data in database and then i will retrieve it back from data base to a select options. here is my codes.
Jsp page..
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="f"%>
<%# taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<!DOCTYPE html>
<html lang="en">
<title>Master Referral</title>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width= device-width, initial-scale=1">
<link type="text/css" rel="stylesheet" href='<spring:url value="/resources/css/bootstrap.min.css" />' >
<link type="text/css" rel="stylesheet" href='<spring:url value="/resources/css/stylesvitalbeat.css" />' >
</head>
<body>
<div class="container-fluid">
<div class="row">
<form action="http://localhost:8080/LoginMavenSpringMVC/admin/create" method="post">
<div class="col-md-2 col-sm-3">
<label class="control-label">Create Category:</label></div>
<div class="col-md-2 col-sm-4">
<input type="text" class="form-control input-sm field_color" name="categoryName" placeholder="Name of the Category">
</div>
<div class="col-md-1 col-sm-3">
<input type="submit" class="btn btn-primary btn-sm height_margin" name="create" value="Create">
</div>
</form>
<div>
<form class="form-horizontal" action="http://localhost:8080/LoginMavenSpringMVC/admin/saveReferral" method="post">
<div class="row margin_div">
<div class="col-sm-3 col-md-2">
<label class="control-label">Select Category</label>
</div>
<div class="col-sm-5 col-md-4">
<f:select path="categoryOptions">
<f:options items="${list}"/>
</f:select>
</div>
</div>
</div>
controller class
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.java.Dao.services.RegisterDao;
import com.java.Dao.services.RegisterDaoImplementaion;
#Controller
#RequestMapping("/admin")
public class ReferralController {
#Autowired
RegisterDao registerDao;
#RequestMapping(value="/create", method=RequestMethod.POST)
public ModelAndView create(#ModelAttribute("create") Category create){
ModelAndView model =new ModelAndView("referralPage");
System.out.println("Referral Controller.");
System.out.println( create.getCategoryName());
if((StringUtils.hasText(create.getId()))) {
registerDao.UpdateCategory(create);
} else {
registerDao.addCategory(create);
}
List<Category> list= registerDao.categoryList();
model.addObject("list", list);
return model;
}
#RequestMapping(value="/saveReferral", method=RequestMethod.POST)
public ModelAndView save(#ModelAttribute("saveReferral") Referrals referral){
ModelAndView model=new ModelAndView("referralPage");
return model;
}
}
Dao services
dao class...
package com.java.Dao.services;
import java.util.List;
import com.java.Package.Login.Category;
public interface RegisterDao {
public void addCategory(Category createCategory);
public void UpdateCategory(Category createCategory);
public List<Category> categoryList();
}
Dao Implementation
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Repository;
import com.java.Package.Login.Category;
import com.mongodb.DBCollection;
#Repository
public class RegisterDaoImplementaion implements RegisterDao {
#Autowired
private MongoTemplate mongoTemplate;
public static final String Collection_Category="CategoryList";
public void addCategory(Category createCategory) {
// TODO Auto-generated method stub
createCategory.setId(UUID.randomUUID().toString());
System.out.println("Object in Repos::"+createCategory);
mongoTemplate.insert(createCategory, Collection_Category);
}
public void UpdateCategory(Category createCategory) {
// TODO Auto-generated method stub
mongoTemplate.insert(createCategory, Collection_Category);
}
#Override
public List<Category> categoryList() {
return mongoTemplate.findAll(Category.class, Collection_Category);
}
}
Class to map categoryOptions
public class Referrals {
private String categoryOptions;
public String getCategoryOptions() {
return categoryOptions;
}
public void setCategoryOptions(String categoryOptions) {
this.categoryOptions = categoryOptions;
}
}
and I am getting this error log
Servlet.service() for servlet [spring-dispatcher] in context with path [/LoginMavenSpringMVC] threw exception [An exception occurred processing JSP page /WEB-INF/views/referralPage.jsp at line 366
363: </div>
364: <div class="col-sm-5 col-md-4">
365:
366: <f:select path="categoryOptions">
367: <f:options items="${list}"/>
368: </f:select>
369: <!-- <select class="form-control input-sm" name="categoryOptions" >
Stacktrace:] with root cause
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'categoryOptions' available as request attribute
Where I am getting wrong? I have tried solutions from different question but couldn't solve it.
You are missing adding Referrals object to model.
#RequestMapping(value="/saveReferral", method=RequestMethod.POST)
public ModelAndView save(#ModelAttribute("saveReferral") Referrals referral){
ModelAndView model=new ModelAndView("referralPage");
model.addAttribute("categoryOptions",new Referrals()); //or referral
return model;
}
Exception is occuring because of <f:select path="categoryOptions">,you have mentioned categoryOptions in path but no where you are returning to this jsp with categoryOptions.
Update : So this says whenever you are loading referral jsp, you have to load with categoryOptions bean
And in below lines list is added to model using model.addObject() but path variable categoryOptions is missing. So after the line model.addObject("list", list); add model.addAttribute("categoryOptions", new Referrals());
<f:select path="categoryOptions">
<f:options items="${list}"/>
</f:select>
I am developing a webapp. In that app i have a page which have three search options based on id. If the ID is wrong i want to retain the id in search textbox and i want to show an error message. I tried that with
ModelAndView.addObject("id", value);
And this is working fine , Now i want to know if there is a better way to do this because assume i have a big form and i want to retain the value of every field than it will be difficult using the above approch. Please help!
And i am using search by ID and Name both thats why i have try and catch blocks
this is my jsp file
html>
<head>
<link rel="stylesheet" type="text/css" href="./css/style.css" />
<link rel="stylesheet" type="text/css" href="./bootstrap/css/bootstrap.css" />
<link rel="stylesheet" type="text/css" href="./bootstrap/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="./bootstrap/css/bootstrap-responsive.css" />
<link rel="stylesheet" type="text/css" href="./bootstrap/css/bootstrap-responsive.min.css" />
<script>
function redirectToSearchResult(textBoxId){
window.location.href= document.getElementById(textBoxId).name+'.htm?'+'id='+document.getElementById(textBoxId).value;
}
</script>
</head>
<body>
<div class="page-header"></div>
<div id="searchByBuyer">
<label id="E_B_I"><h2>Buyer Search<h2></label><br>
<input type="text" id="S_B_B" class="text-box" name="searchByBuyer" value=${buyerId} ></input>
<input type="button" id="BuyerSearch" class="btn-custom" value="search" onclick="redirectToSearchResult('S_B_B')"/>
</div>
<div id="searchByCategory">
<label id="E_C_I"><h2>Category Search<h2></label><br>
<input type="text" id="S_B_C" class="text-box" name="searchByCategory" value=${categoryId} ></input>
<input type="button" id="CategorySearch" class="btn-custom" value="search" onclick="redirectToSearchResult('S_B_C')"/>
</div>
<div id="searchByArticle">
<label id="E_A_I"><h2>Article Search<h2></label><br>
<input type="text" id="S_B_I" class="text-box" name="searchByArticle" value=${articleId} ></input>
<input type="button" id="ArticleSearch" class="btn-custom" value="search" onclick="redirectToSearchResult('S_B_I')"/><br>
</div>
<br>
<label style="color:red; padding-left:45em; padding-top:15em"><h4>${error}</h4></label>
</body>
</html>
And this my controller
`
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class BuyerController {
#Autowired
private BuyerRepo buyerRepo;
#RequestMapping(value = "/searchByBuyer.htm", method = RequestMethod.GET)
public ModelAndView searchFields(#RequestParam(value = "id") String buyerId) throws InvalidIdException {
Buyer buyer = null;
ModelAndView buyerSearch = new ModelAndView("buyerSearch");
ModelAndView errorView = ErrorView.getErrorView("buyerId", buyerId, "Enter a valid Buyer id!");
try {
buyer = buyerRepo.getBuyer(Long.parseLong(buyerId));
} catch (NumberFormatException e) {
buyer = buyerRepo.getBuyer(buyerId);
if (buyer == null) return errorView;
} catch (Exception e) {
buyerSearch = errorView;
}
buyerSearch.addObject("buyer", buyer);
return buyerSearch;
}
}
`
This is the error and view class to create error view with parameters
`
import org.springframework.web.servlet.ModelAndView;
public class ErrorView {
public static ModelAndView getErrorView(String key, String value, String message) {
ModelAndView errorView = new ModelAndView("index");
errorView.addObject("error", message);
errorView.addObject(key, value);
return errorView;
}
}
`
Spring has JSR 303-Bean-Validation support for web forms.
This build in way is much easyer to use than some own implementation.
You need:
a command object that gets all the values from the form. Each fields can have JSR 303-Bean-Validation annotations to indicate the constaints you want to enforce
you need a web controller method with (at least) two parameters: #Valid command object, BindingResult (The BindingResult must be THE parameter after the command object)
in you web controller method you need to check the BindingResult, and if it has failure you need to render the form again
in your form you need to use form:errors to show the errors (form:errors can also show the errors for an specific field)
you need some spring configuration: <mvc:annotation-driven /> (there is more possible but this should be enough for the begin)
you need a JSR 303-Bean-Validation libary, for example: Hibernate Validator (this is not the Hibernate ORM)
But an example explain it the best: http://www.mkyong.com/spring-mvc/spring-3-mvc-and-jsr303-valid-example/