Thymeleaf template not connecting correctly to Java POJO - spring

I am following the Spring in Action (5th Edition) by Craig Walls, and I am stuck trying to figure out why the form element my Thymeleaf view isn't passing on the correct data type to my pojo object.
Short of it is: When visiting localhost:8080/design, I should be able to select whatever checkboxes from a Thymeleaf html view which should then add those ingredients to a Taco object's List<Ingredient> ingredients parameter.
However, when I select the ingredients in the form and hit the submit button, I get the following error:
Fri Oct 28 14:07:37 EDT 2022
There was an unexpected error (type=Bad Request, status=400).
Validation failed for object='taco'. Error count: 1
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'taco' on field 'ingredients': rejected value [FLTO,GRBF,CHED,TMTO,SLSA]; codes [typeMismatch.taco.ingredients,typeMismatch.ingredients,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [taco.ingredients,ingredients]; arguments []; default message [ingredients]]; default message [Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.List' for property 'ingredients'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'FLTO'; nested exception is java.lang.NumberFormatException: For input string: "FLTO"]
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:175)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:146)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:833)
Is someone able to offer some guidance on why this issue is happening?
Below is the my code that makes up the above workflow:
Dependencies
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>sia</groupId>
<artifactId>taco-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>taco-cloud</name>
<description>Taco Cloud Example Project from Spring In Action</description>
<properties>
<java.version>15</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>htmlunit-driver</artifactId>
<scope>test</scope>
</dependency>
<!-- Installed as a dependency as well as installed
on Eclipse IDE: https://projectlombok.org/setup/eclipse -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- For JavaBean Validation Annotations -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.16.Final</version>
</dependency>
<!-- For JDBCTemplate and embedded H2 database -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- For Spring Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Database
I am using the H2 embedded database so the schema and accomponying data is loaded at runtime
src/main/resources/schema.sql
create table if not exists Ingredient (
id varchar(10) not null,
name varchar(25) not null,
INGREDIENT_TYPE ENUM('WRAP', 'PROTEIN', 'VEGGIES', 'CHEESE', 'SAUCE') NOT NULL
);
create table if not exists Taco (
id identity,
name varchar(50) not null,
createdAt timestamp not null
);
create table if not exists Taco_Ingredients (
taco bigint not null,
ingredient varchar(4) not null
);
alter table Ingredient
add constraint Ingredient_PK primary key (id);
alter table Taco_Ingredients
add foreign key (taco) references Taco(id);
alter table Taco_Ingredients
add foreign key (ingredient) references Ingredient(id);
create table if not exists Taco_Order (
id identity,
deliveryName varchar(50) not null,
deliveryStreet varchar(50) not null,
deliveryCity varchar(50) not null,
deliveryState varchar(2) not null,
deliveryZip varchar(10) not null,
ccNumber varchar(16) not null,
ccExpiration varchar(5) not null,
ccCVV varchar(3) not null,
placedAt timestamp not null
);
create table if not exists Taco_Order_Tacos (
tacoOrder bigint not null,
taco bigint not null
);
alter table Taco_Order_Tacos
add foreign key (tacoOrder) references Taco_Order(id);
alter table Taco_Order_Tacos
add foreign key (taco) references Taco(id);
src/main/resources/data.sql
delete from Taco_Order_Tacos;
delete from Taco_Ingredients;
delete from Taco;
delete from Taco_Order;
delete from Ingredient;
insert into Ingredient(id, name, INGREDIENT_TYPE )
values ('FLTO', 'Flour Tortilla', 'WRAP' );
insert into Ingredient(id, name, INGREDIENT_TYPE )
values('COTO','Corn Tortilla', 'WRAP');
insert into Ingredient(id, name, INGREDIENT_TYPE )
values('GRBF', 'Ground Beef', 'PROTEIN');
insert into Ingredient(id, name, INGREDIENT_TYPE )
values('CARN', 'Carnitas', 'PROTEIN');
insert into Ingredient(id, name, INGREDIENT_TYPE )
values('TMTO', 'Diced Tomatoes', 'VEGGIES');
insert into Ingredient(id, name, INGREDIENT_TYPE )
values('LETC', 'Lettuce', 'VEGGIES');
insert into Ingredient(id, name, INGREDIENT_TYPE )
values('CHED', 'Cheddar', 'CHEESE');
insert into Ingredient(id, name, INGREDIENT_TYPE )
values('JACK', 'Monterrey Jack', 'CHEESE');
insert into Ingredient(id, name, INGREDIENT_TYPE )
values('SLSA', 'Salsa', 'SAUCE');
insert into Ingredient(id, name, INGREDIENT_TYPE )
values('SRCR', 'Sour Cream', 'SAUCE');
POJOs
src/main/java/tacos/domain/Taco
#Data
#Entity
public class Taco {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private String id;
private Date createdAt;
#NotNull
#Size(min=4, message="Name must be at least 4 characters long")
private String name;
#ManyToMany(targetEntity=Ingredient.class)
#Size(min=1, message="You must choose at least 1 ingredient")
private List<Ingredient> ingredients;
#PrePersist
void createdAt() {
this.createdAt = new Date();
}
}
src/main/java/tacos/domain/Ingredient
#Data
#RequiredArgsConstructor
#NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
#Entity
public class Ingredient {
#Id
private final String id;
private final String name;
#Enumerated(EnumType.STRING)
private final Type ingredientType;
public static enum Type {
WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE
}
}
src/main/java/tacos/domain/Order
#Data
#Entity
#Table(name="Taco_Order")
public class Order implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private Date placedAt;
#NotBlank(message="Name is required")
private String name;
#NotBlank(message="Street is required")
private String street;
#NotBlank(message="City is required")
private String city;
#NotBlank(message="State is required")
private String state;
#NotBlank(message="Zip Code is required")
private String zip;
#CreditCardNumber(message="Not a valid credit card number")
private String ccNumber;
#Pattern(regexp="^(0[1-9]|1[0-2])([\\/])([1-9][0-9])$", message="Must be formatted MM/YY")
private String ccExpiration;
#Digits(integer=3, fraction=0, message="Invalid CVV")
private String ccCVV;
#ManyToMany(targetEntity=Taco.class)
private List<Taco> tacos = new ArrayList<>();
public void addTaco(Taco taco) {this.tacos.add(taco);}
#PrePersist
void placedAt() {this.placedAt = new Date();}
}
Controllers
src/main/java/tacos/controllers/DesignTacoController
#Slf4j
#Controller
#RequestMapping("/design")
#SessionAttributes("order")
public class DesignTacoController {
private final IngredientRepository ingredientRepo;
private TacoRepository tacoRepo;
#Autowired
public DesignTacoController(IngredientRepository ingredientRepo, TacoRepository tacoRepo) {
this.ingredientRepo = ingredientRepo;
this.tacoRepo = tacoRepo;
};
#ModelAttribute(name = "order")
public Order order() {
return new Order();
}
#ModelAttribute(name = "taco")
public Taco taco() {
return new Taco();
}
#GetMapping
public String showDesignForm(Model model) {
List<Ingredient> ingredients = new ArrayList<>();
ingredientRepo.findAll().forEach(i -> ingredients.add(i));
log.info(ingredients.toString());
Type[] types = Ingredient.Type.values();
for (Type type : types) {
model.addAttribute(type.toString().toLowerCase(),
filterByType(ingredients, type));
}
model.addAttribute("taco", new Taco());
return "design";
}
#PostMapping
public String processDesign(
#Valid Taco design,
#ModelAttribute Order order,
Errors errors) {
log.info("design: " + design);
log.info("order: " + order);
log.warn("errors: " + errors);
if(errors.hasErrors()) return "design";
Taco savedTaco = tacoRepo.save(design);
order.addTaco(savedTaco);
return "redirect:orders/current";
}
private List<Ingredient> filterByType(
List<Ingredient> ingredients,
Type type) {
return ingredients
.stream()
.filter(x -> x.getIngredientType().equals(type))
.collect(Collectors.toList());
}
}
src/main/java/tacos/controllers/OrderController
#Slf4j
#Controller
#RequestMapping("/orders")
#SessionAttributes("order")
public class OrderController {
private OrderRepository orderRepo;
public OrderController(OrderRepository orderRepo) {this.orderRepo = orderRepo;}
#GetMapping("/current")
public String orderForm(Model model) {
log.info(model.toString());
return "orderForm";
}
#PostMapping
public String processOrder(#Valid Order order, SessionStatus sessionStatus, Errors error) {
if(error.hasErrors()) return "orderForm";
orderRepo.save(order);
sessionStatus.setComplete();
return "redirect:/";
}
}
Views
src/main/resources/templates/design.html
<body>
<h1>Design Your Taco</h1>
<img th:src="#{/images/TacoCloud.jpeg}" />
<form method="POST" th:object="${taco}">
<div class="grid">
<div class="ingredient-group" id="wraps">
<h3>Design Your Wrap:</h3>
<div th:each="ingredient : ${wrap}">
<!-- <input name="ingredients" type="checkbox" th:value="${ingredient.id}" /> -->
<!-- <input name="ingredients" type="checkbox" th:value="${ingredient.getId()}" /> -->
<input name="ingredients" type="checkbox" th:value="${ingredient.getId()}" th:field="*{ingredients}" />
<span th:text="${ingredient.getName()}">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}" /> -->
<!-- <input name="ingredients" type="checkbox" th:value="${ingredient.getId()}" /> -->
<input name="ingredients" type="checkbox" th:value="${ingredient.getId()}" th:field="*{ingredients}" />
<span th:text="${ingredient.getName()}">INGREDIENT</span>
<br>
</div>
</div>
<div class="ingredient-group" id="cheeses">
<h3>Pick Your Cheese:</h3>
<div th:each="ingredient : ${cheese}">
<!-- <input name="ingredients" type="checkbox" th:value="${ingredient.id}" /> -->
<!-- <input name="ingredients" type="checkbox" th:value="${ingredient.getId()}" /> -->
<input name="ingredients" type="checkbox" th:value="${ingredient.getId()}" th:field="*{ingredients}" />
<span th:text="${ingredient.getName()}">INGREDIENT</span>
<br>
</div>
</div>
<div class="ingredient-group" id="veggies">
<h3>Pick Your Veggies:</h3>
<div th:each="ingredient : ${veggies}">
<!-- <input name="ingredients" type="checkbox" th:value="${ingredient.id}" /> -->
<!-- <input name="ingredients" type="checkbox" th:value="${ingredient.getId()}" /> -->
<input name="ingredients" type="checkbox" th:value="${ingredient.getId()}" th:field="*{ingredients}" />
<span th:text="${ingredient.getName()}">INGREDIENT</span>
<br>
</div>
</div>
<div class="ingredient-group" id="sauces">
<h3>Pick Your Sauces:</h3>
<div th:each="ingredient : ${sauce}">
<!-- <input name="ingredients" type="checkbox" th:value="${ingredient.id}" /> -->
<!-- <input name="ingredients" type="checkbox" th:value="${ingredient.getId()}" /> -->
<input name="ingredients" type="checkbox" th:value="${ingredient.getId()}" th:field="*{ingredients}" />
<span th:text="${ingredient.getName()}">INGREDIENT</span>
<br>
</div>
</div>
</div>
<div>
<h3>Name Your Taco Creation:</h3>
<input type="text" th:field="*{name}" /> <br>
<button>Submit Your Taco</button>
</div>
</form>
</body>
src/main/resources/templates/orderForm.html
<body>
<form method="POST" th:action="#{/orders}" th:object="${order}">
<h1>Order Your Taco Creations!</h1>
<img th:src="#{/images/TacoCloud.jpeg}" /> <a th:href="#{/design}"
id="another"> Design Another Taco</a> <br>
<div th:if="${#fields.hasErrors()}">
<span class="validationError">Please correct the problems below and resubmit</span>
</div>
<h3>Deliver my taco masterpieces to ...</h3>
<label for="name">Name: </label> <input type="text" th:field="*{name}" />
<span class="validationError" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"> Name Can't be Empty </span>
<br>
<label for="street"> Street Address: </label>
<input type="text" th:field="*{street}" />
<span class="validationError" th:if="${#fields.hasErrors('street')}" th:errors="*{street}"> Street Can't be Empty </span>
<br>
<label for="city"> City: </label>
<input type="text" th:field="*{city}" />
<span class="validationError" th:if="${#fields.hasErrors('city')}" th:errors="*{city}"> City Can't be Empty </span>
<br>
<label for="state"> State:</label>
<input type="text" th:field="*{state}" />
<span class="validationError" th:if="${#fields.hasErrors('state')}" th:errors="*{state}"> State Can't be Empty </span>
<br>
<label for="zip"> Zip Code: </label>
<input type="text" th:field="*{zip}" />
<span class="validationError" th:if="${#fields.hasErrors('zip')}" th:errors="*{zip}"> Zip Code Can't be Empty </span>
<br>
<h3>Here's How I'll Pay ...</h3>
<label for="ccNumber"> Credit Card #: </label>
<input type="text" th:field="*{ccNumber}" />
<span class="validationError" th:if="${#fields.hasErrors('ccNumber')}" th:errors="*{ccNumber}"> CC Number Error </span>
<br>
<label for="ccExpiration"> Expiration: </label>
<input type="text" th:field="*{ccExpiration}" />
<span class="validationError" th:if="${#fields.hasErrors('ccExpiration')}" th:errors="*{ccExpiration}"> CC Expiration Date Invalid </span>
<br>
<label for="ccCVV">CVV: </label>
<input type="text" th:field="*{ccCVV}" />
<span class="validationError" th:if="${#fields.hasErrors('ccCVV')}" th:errors="*{ccCVV}"> CVV Invalid </span>
<br>
<input type="submit" value="Submit Order" />
</form>
</body>
I have tried changing the schema for my sql file but this didn't work.

Related

Spring Boot, Can't reach a different Controller Class

Request is always made to method(/login) in same Controller.
When you press Save button in Register.html, /login method in UserController.java class works automatically although it must run saveRegisterPage method (/registration/saveRegister) in RegisterController.java class.
What must be done in order to run saveRegisterPage method?
Thank you.
UserController.java
#Controller
public class UserController {
#RequestMapping(value = "/register", method = RequestMethod.GET)
public String registerPage(Model model) {
model.addAttribute("user", new User());
return "register";
}
#RequestMapping("/")
public String index() {
return "login";
}
#RequestMapping("/login")
public String login() {
return "login";
}
#RequestMapping("/home")
public String home() {
return "home";
}
}
RegisterController.java
#Controller
#RequestMapping(value="/registration")
public class RegisterController {
#Autowired
UserServiceImpl userServiceImpl;
#RequestMapping(value = "/saveRegister", method = RequestMethod.POST)
public String saveRegisterPage(#ModelAttribute("user") User user, BindingResult result, Model model, RedirectAttributes attributes) {
model.addAttribute("user", user);
if (result.hasErrors()) {
return "register";
} else {
userServiceImpl.save(user);
}
return "home";
}
}
home.html
<html>
<head>...</head>
<body>
<div class="container">
<h2>Welcome</h2>
Logout
</div>
</body>
</html>
login.html
<html xmlns:th="http://www.w3.org/1999/xhtml">
<head>...</head>
<body>
<div class="container">
<div class="alert alert-danger" role="alert" th:if="${param.error}">
Wrong Username or Passrod
</div>
<form th:action="#{/login}" method="post">
<h1 class="h3 mb-3 font-weight-normal">Signin</h1>
<label>Username</label>
<input type="text" name="username" class="form-control"/>
<label>Password</label>
<input type="password" id="password" name="password" class="form-control"/>
<br/>
<button class="btn btn-lg btn-primary btn-block" type="submit">SignIn</button>
<br/>
<div class="margin-top20 text-center"><a th:href="#{/register}">Go Register</a>
</div>
</form>
</div>
</body>
</html>
register.html
<html xmlns:th="http://www.w3.org/1999/xhtml">
<head>....</head>
<body>
<div class="container">
<form autocomplete="off" th:action="#{/registration/saveRegister}" th:object="${user}" method="post">
<label>Name </label>
<input type="text" id="firstName" placeholder="First Name" th:field="*{firstName}"
class="form-control"/><br/>
<label>Last name </label>
<input type="text" id="lastName" placeholder="First Name" th:field="*{lastName}" class="form-control"/><br/>
<label>Email </label>
<input type="text" id="email" placeholder="First Name" th:field="*{email}" class="form-control"/><br/>
<label>Username</label>
<input type="text" id="username" placeholder=" Username" th:field="*{username}" class="form-control"/><br/>
<label>Password</label>
<input type="text" id="password" placeholder=" Password" th:field="*{password}" class="form-control"/><br/>
<button type="submit" class="btn btn-success text-center form-control">Save</button>
</form>
</div>
</body>
</html>
SecurityConfiguration.java
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
#Autowired
private UserAuthService userAuthService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http
.authorizeRequests()
.antMatchers("/", "/register", "/webjars/**", "/h2-console/**","/webjars/").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").defaultSuccessUrl("/home", true).permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/home").permitAll()
.and()
.httpBasic();
http.headers().frameOptions().disable();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userAuthService).passwordEncoder(encoder());
}
#Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zorogluresul.springexample1</groupId>
<artifactId>springexample1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springexample1</name>
<description>Spring Boot, Web, Thymeleaf, Jpa, Postgresql, Security</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7-1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1-1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
You should add RegisterController's requestMapping /registration into antMatchers like this:
.antMatchers("/", "/register", "/registration/*", "/webjars/**", "/h2-console/**","/webjars/").permitAll()
It contains /* at the end of the /registration/* in order to allow all requests in RegisterController. If you write it like /registration/register, it also runs saveRegisterPage method in RegisterController.
Try this Resul
import java.io.IOException;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/")
public class UserController {
#GetMapping("/register")
public String registerPage(Model model) {
model.addAttribute("user", new Fragment3());
return "register";
}
#GetMapping //main page
public String index() {
return "login";
}
#GetMapping("/login") //logging out from home
public String logout() {
return "login";
}
#PostMapping("/home")
public String home() {
return "home";
}
}
---------------------------------------------------------------------------
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/registration")
public class RegisterController {
#Autowired
UserServiceImpl userServiceImpl;
#PostMapping("/saveRegister")
public String saveRegisterPage(#ModelAttribute("user") User user, BindingResult result, Model model, RedirectAttributes attributes) {
model.addAttribute("user", user);
if (result.hasErrors()) {
return "register";
} else {
userServiceImpl.save(user);
}
return "home";
}
}`
most changes are at the backend
although do replace 2 lines in home.html for the logout.
<h2>Welcome</h2>
<a th:href="#{/login}" class="btn btn-danger">Logout</a>

how fix form validation, when itdoesn't work

I need your help, form validation doesn't work, after following several articles, its still not working
here my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.3.2.RELEASE
com.king
Gestpeacesecurity
0.0.1-SNAPSHOT
Gestpeacesecurity
peace security project for Spring Boot
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- <dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency> -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
My entitie Agent, i use lomback for getter and setter
package com.king.Entities;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.springframework.format.annotation.DateTimeFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
#Entity
#Data #NoArgsConstructor #AllArgsConstructor
public class Agent implements Serializable {
#Id
#NotNull
#Size(min=5,max=5)
private String matricule;
#NotNull
#Size(min=4,max=15)
private String nom;
private String prenom;
private String postnom;
private String fonction;
private String typeagent;
private String niveaetude;
private String contact1;
private String contact2;
private String sexe;
private String adresse1;
private String adresse2;
private String photo;
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date dateNaiss;
private String lieuNais;
private String status;
}
this is my controller
#RequestMapping(value="/showFormAgent", method = RequestMethod.GET)
public String showFormAgent(Model model) {
model.addAttribute("agent", new Agent());
return "peacedrh/formAgent";
}
#RequestMapping(value="addAgent", method = RequestMethod.POST)
public String addAgent(#RequestParam(name="picture")MultipartFile file, Model model, String matricule, #Valid Agent A, BindingResult result) {
try {
if (!(file.isEmpty())) {
A.setPhoto(file.getOriginalFilename());
}
agentDao.AddAgent(matricule, A);
if (!(file.isEmpty())) {
A.setPhoto(file.getOriginalFilename());
file.transferTo(new File (imageDir+A.getMatricule()));
}
} catch (Exception e) {
// TODO: handle exception
model.addAttribute("error", e);
return "redirect:/showFormAgent?matricule="+matricule+"&error="+e.getMessage();
}
model.addAttribute("agent", agentDao.getBymatricule(matricule));
return "peacedrh/Accuse";
}
this my html page(thymeleaf)
<form role="form" method="post" th:action="#{addAgent}" th:object="${agent}" enctype="multipart/form-data">
<div class="card-body">
<div class="form-group">
<label for="exampleInputEmail1">Matricule</label>
<input type="text" th:field="*{matricule}" class="form-control" id="exampleInputEmail1" placeholder="Enter Matricule"/>
<span class="text-danger" th:errors="*{matricule}"> </span>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="exampleInputEmail1">Nom</label>
<input type="text" th:field="*{nom}" class="form-control" id="exampleInputEmail1" placeholder="Enter Nom"/>
<span class="text-danger" th:errors="*{matricule}"> </span>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Post nom</label>
<input type="text" th:field="*{postnom}" class="form-control" id="exampleInputPassword1" placeholder="Post nom"/>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Prenom</label>
<input type="text" th:field="*{prenom}" class="form-control" id="exampleInputPassword1" placeholder="Prenom"/>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Sexe</label>
<select th:field="*{sexe}">
<option value="M">M</option>
<option value="F">F</option>
</select>
</div>
<div class="input-group mb-3">
<div class="form-group">
<label for="exampleInputPassword1">Statut Sociale</label>
<select th:field="*{status}">
<option value="Single">Single</option>
<option value="Maried">Maried</option>
<option value="Veuve">Veuve</option>
<option value="Veuf">Veuf </option>
<option value="Divorce">Divorce</option>
<option value="separe">Separe(é)</option>
</select>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Lieu de naissance</label>
<input type="text" th:field="*{lieuNais}" class="form-control" id="exampleInputPassword1" placeholder="Lieu de naissance"/>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Date de naissance</label>
<input type="date" th:field="*{dateNaiss}" class="form-control"/>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Niveau Etudet</label>
<input type="text" th:field="*{niveaetude}" class="form-control" id="exampleInputPassword1" placeholder="Niveau d'étude"/>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Type Agent</label>
<select th:field="*{typeagent}">
<option value="Admin">Admnistratif</option>
<option value="Terrain">Terrain</option>
</select>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="exampleInputPassword1">Fonction</label>
<select th:field="*{fonction}">
<option value="Comptable">Comptable</option>
<option value="DRH">Direc Res Hum</option>
</select>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Contact 1</label>
<input type="text" th:field="*{contact1}" class="form-control" id="exampleInputPassword1" placeholder="Contat 1"/>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Contact 2</label>
<input type="text" th:field="*{contact2}" class="form-control" id="exampleInputPassword1" placeholder="Contact 2"/>
</div>
<div class="form-group">
<label for="exampleInputFile">File input</label>
<div class="input-group">
<div class="custom-file">
<input type="file" name="picture" class="custom-file-input" id="exampleInputFile"/>
<label class="custom-file-label" for="exampleInputFile">Choose file</label>
</div>
</div>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Adresse 1</label>
<textarea th:field="*{adresse1}" class="form-control" rows="5" cols="5"></textarea>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Adresse 2</label>
<textarea th:field="*{adresse2}" class="form-control" rows="5" cols="5"></textarea>
</div>
</div>
</div>
<div class="card-footer">
<div class="row col-md-5 ml-20" >
<div class="col-md-6"><button type="submit" class="btn btn-primary">Submit</button></div>
<div class="col-md-6"><button type="reset" class="btn btn-primary">Cancel</button></div>
</div>
</div>
</form>
the addition is going well but the form validation still does not work
You must add a #RequestBody because you want to request the form from the view:
#Valid Agent A
Becomes
#Valid #RequestBody Agent A
Otherwise you can pass the Agent object as a #ModelAttribute on your showFormAgent
public String showFormAgent(#ModelAttribute Agent A) {
return "peacedrh/formAgent";
}
and then just get the data from your addAgent
#RequestMapping(value="addAgent", method = RequestMethod.POST)
public String addAgent(#ModelAttribute #Valid Agent A, BindingResult result) { //doSomething }
and the BindingResult holds the validation result so you have to check whether you have errors or not:
if (result.hasErrors()) {
return "previus_form";
} else {
return "success";
}

No message available JSP SpringBoot

I've been looking through almost every post that is related to my problem and tried every solution that i've found and this problem keeps appearing.
I'm developing a web application and i have almost all the pages that will include, but when i try to connect the Controllers with any JSP this messages appears every time, so i created a new project with only one table and a couple pages, and still get the same "error" but only with pages that load some information, i've tried with one very simple page and it works
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
There was an unexpected error (type=Not Found, status=404).
No message available
Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>mjsl.gineco</groupId>
<artifactId>GinecObstWeb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>GinecObstWeb</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.core</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.asm</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.antlr</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa.jpql</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
<version>2.5.2</version>
<scope>provided</scope>
</dependency>
<!-- standard.jar -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
spring.datasource.url=jdbc:mysql://localhost:13366/ginecoweb?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=gineco
spring.datasource.password=Gineco-94.Aguila
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=none
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.generate-ddl=false
spring.jpa.properties.hibernate.hbm2ddl.auto=none
spring.mvc.view.prefix: /WEB-INF/views/
spring.mvc.view.suffix: .jsp
Entity
Clientes.java
package mjsl.gineco.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import lombok.Data;
#Data
#Entity
#Table(name = "clientes")
public class Clientes implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "CLAVCLI")
private Integer clavCli;
#Size(max = 100)
#Column(name = "NOMBCLI")
private String nombCli;
#Size(max = 100)
#Column(name = "DIRECLI")
private String direCli;
#Size(max = 50)
#Column(name = "COLOCLI")
private String coloCli;
#Size(max = 50)
#Column(name = "POBLCLI")
private String poblCli;
#Size(max = 30)
#Column(name = "TELCLI")
private String telCli;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Column(name = "ESTACLI")
private Double estaCli;
#Size(max = 100)
#Column(name = "OCUPCLI")
private String ocupCli;
#Size(max = 100)
#Column(name = "NOCOCLI")
private String nocoCli;
#Size(max = 100)
#Column(name = "OCCOCLI")
private String occoCli;
#Lob
#Column(name = "EXPECLI")
private byte[] expeCli;
#Column(name = "FECHANACCli")
#Temporal(TemporalType.DATE)
private Date fechanacCli;
#Size(max = 5)
#Column(name = "GYRH")
private String gyrhCli;
#Column(name = "EMBARAZO")
private Boolean embarazoCli;
#Size(max = 50)
#Column(name = "SEGUROCli")
private String seguroCli;
#Column(name = "NOSI")
private Boolean nosiCli;
#Size(max = 500)
#Column(name = "FOTO")
private String fotoCli;
// #Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email")//if the field contains email address consider using this annotation to enforce field validation
#Size(max = 200)
#Column(name = "EMAIL")
private String emailCli;
}
ClientesController
package mjsl.gineco.controller;
import java.util.List;
import mjsl.gineco.entity.Clientes;
import mjsl.gineco.service.ClientesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class ClientesController {
#Autowired
ClientesService ctesService;
#RequestMapping("")
public String inicio() {
return "inicio";
}
#RequestMapping("listcte")
public String listaCtes(Model model) {
List<Clientes> clientes = ctesService.getAllCtes();
model.addAttribute("clientList", clientes);
return "indexpac";
}
#RequestMapping("newcte")
public String nuevoCte(Model model) {
Clientes clientes = new Clientes();
model.addAttribute("clienteNuevo", clientes);
return "nuevopac";
}
}
ClientesRepository
package mjsl.gineco.repository;
import mjsl.gineco.entity.Clientes;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ClientesRepository extends JpaRepository<Clientes, Integer> {
}
ClientesService
package mjsl.gineco.service;
import java.util.List;
import java.util.Optional;
import mjsl.gineco.entity.Clientes;
public interface ClientesService {
void saveCte(Clientes clientes);
List<Clientes> getAllCtes();
Optional<Clientes> getCte(Integer clavCli);
void deleteCte(Integer clavCli);
}
ClientesServiceImpl
package mjsl.gineco.service;
import java.util.List;
import java.util.Optional;
import mjsl.gineco.entity.Clientes;
import mjsl.gineco.repository.ClientesRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class ClientesServiceImpl implements ClientesService {
#Autowired
ClientesRepository ctesRepo;
#Override
public void saveCte(Clientes clientes) {
ctesRepo.save(clientes);
}
#Override
public List<Clientes> getAllCtes() {
return ctesRepo.findAll();
}
#Override
public Optional<Clientes> getCte(Integer clavCli) {
return ctesRepo.findById(clavCli);
}
#Override
public void deleteCte(Integer clavCli) {
ctesRepo.deleteById(clavCli);
}
}
indexpac.jsp
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>GinecoObstetricia Avanzada - Pacientes</title>
</head>
<body>
<p><%# include file="/WEB-INF/views/jspf/menu.jspf"%></p>
<p></p>
<div class="container-fluid">
<div class="row-fluid">
<div class="col-md-12">
<h4 class="text-center">Listado de Pacientes</h4>
<hr>
<i class="glyphicon glyphicon-edit"></i> Nuevo(a) Paciente
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Buscar">
<div class="input-group-append">
<button class="btn btn-primary" type="submit">Ir</button>
</div>
</div>
<p/>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Id</th>
<th>Nombre</th>
<th>Teléfono</th>
<th>Ver</th>
<th>Expediente</th>
<!-- <th>Eliminar</th>-->
</tr>
</thead>
<tbody>
<c:forEach var="clients"
items="${clientList}">
<c:url var="updateCteLink" value="/clientes/editapac">
<c:param name="clavCli" value="${clients.clavCli}"/>
</c:url>
<c:url var="openCteLink" value="/clientes/datospac">
<c:param name="clavCli" value="${clients.clavCli}"/>
</c:url>
<tr>
<td>${clients.clavCli}</td>
<td>${clients.nombCli}</td>
<td>${clients.telCli}</td>
<td>
<a href="${updateCteLink}">
<span class="fa-stack">
<i class="far fa-edit" style="color:blue"> </i>
</span>
</a>
</td>
<td><a href="${openCteLink}">
<span class="fa-stack">
<i class="far fa-folder-open"> </i>
</span>
</a>
</td>
<!-- <td>><a href="${pageContext.request.contextPath}/product/delete/${clients.clavCli}">
<span class="fa-stack">
<i class="far fa-trash-alt"> </i>
</span>
</a>
</td>-->
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</html>
menu.jspf
<%# page pageEncoding="UTF-8" %>
<%!
public String getPath(){
String path = getServletContext().getContextPath();
return path;
}
%>
<nav class="navbar navbar-default navbar-fixed-top navbar-expand-md bg-light navbar-light">
<div class="container-fluid">
<!-- -->
<div class="navbar-header">
<a class="navbar-brand" href="#">GinecoObstetricia</a>
</div>
<!-- -->
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="<%=getPath()%>/index.jsp">Inicio <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="<%=getPath()%>/login.jsp">Iniciar Sesión</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Pacientes
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<!-- <a class="dropdown-item" href="<%response.sendRedirect("indexpac");%>">Inicio</a>-->
<a class="dropdown-item" href="<%=getPath()%>/indexpac.jsp">Inicio</a>
<a class="dropdown-item" href="<%=getPath()%>/nuevopac.jsp">Agregar</a>
<a class="dropdown-item" href="<%=getPath()%>/datospac.jsp">Expediente Médico</a>
<a class="dropdown-item" href="<%=getPath()%>/datoscons.jsp">Consulta</a>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Estudios
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="<%=getPath()%>/listadoest.jsp">Listado</a>
<a class="dropdown-item" href="<%=getPath()%>/nuevoest.jsp">Nuevo</a>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Agenda
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="<%=getPath()%>/index.jsp">Listado</a>
<a class="dropdown-item" href="<%=getPath()%>/index.jsp">Nueva</a>
</div>
</li>
</ul>
</div>
</div>
</nav>
nuevopac.jsp
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%#taglib uri="http://www.springframework.org/tags/form" prefix="mvc" %>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>GinecoObstetricia Avanzada - Pacientes</title>
</head>
<body>
<p><%# include file="/WEB-INF/views/jspf/menu.jspf"%></p>
<p></p>
<div class="col-md-10 order-md-1">
<mvc:form modelAttribute="clienteNuevo" action="createCte">
<mvc:hidden path="clavCli" />
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Nombre</span>
</div>
<mvc:input path="nombCli" type="text" class="form-control"/>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Fecha de Nacimiento</span>
</div>
<mvc:input path="fechanacCli" type="date" class="form-control btn btn-outline-secondary col-md-3"/>
<div class="input-group-prepend">
<span class="input-group-text">Ocupación</span>
</div>
<mvc:input path="ocupCli" type="text" class="form-control col-md-3"/>
<div class="input-group-prepend">
<span class="input-group-text">GyRH</span>
</div>
<mvc:input path="gyrhCli" type="text" aria-labelledby="GyRH-ariaLabel" class="form-control col-md-3"/>
<div class="input-group-prepend">
<span class="input-group-text">Estatura</span>
</div>
<mvc:input path="estaCli" type="text" class="form-control col-md-3"/>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Domicilio</span>
</div>
<mvc:input path="direCli" type="text" class="form-control" placeholder="Calle y Número"/>
<mvc:input path="coloCli" type="text" class="form-control" placeholder="Colonia o Fraccionamiento"/>
<mvc:input path="poblCli" type="text" class="form-control" placeholder="Población"/>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Teléfono</span>
</div>
<mvc:input path="telCli" type="text" class="form-control col-md-6"/>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Conyuge</span>
</div>
<mvc:input path="nocoCli" type="text" placeholder="Nombre" class="form-control col-md-3"/>
<mvc:input path="occoCli" type="text" placeholder="Ocupación" class="form-control col-md-3"/>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Compañía de Seguros</span>
</div>
<mvc:input path="seguroCli" type="text" placeholder="Nombre de la Compañía de Seguros" class="form-control col-md-6"/>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">E-mail</span>
</div>
<mvc:input path="emailCli" type="text" placeholder="Correo Electrónico" class="form-control col-md-6"/>
</div>
<div class="form-check-inline mb-3">
<label class="form-check-label">
<mvc:checkbox path="nosiCli" class="form-check-input" value=""/>Recomendada
</label>
</div>
<div class="input-group mb-3">
<input type="submit" value="Guardar" class="btn btn-success">
<button type="button" class="btn btn-danger">Cancelar</button>
</div>
</mvc:form>
</div>
<!--<p style="text-align: center"><img src="Resources/logo_mrysi.png" align="bottom"/></p>-->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
Project Map
Based on your Controller mapping when you hit
localhost:8080/ => inicio page will load
localhost:8080/listcte => indexpac page will load
localhost:8080/newcte => nuevopac page will load
Now let's see what you were trying
localhost:8080/listado => will throw error page as no mapping is found for this URL in Controller class.
localhost:8080/newcte => should load nuevopac page. Check console for error and please add nuevopac code. May be JSP throwing some error.
Replace in your Controller Client class #Controller for #RestController

Spring Thymeleaf Cannot resolve 'global'

i am trying to create login-register page application in spring framework.
In my registration form, intelij idea says Cannot resolve 'global'.
i changed springsecurity4 to springsecurity3 but didn't change anything.
This my form element:
<form class="form-signin" th:action="#{/registration}" th:object="${user}" method="post">
<input type="text" class="form-control" placeholder="Full Name" th:field="*{fullname}" required autofocus>
<label style="color: red" th:if="${#fields.hasErrors('fullname')}" th:errors="*{fullname}">Username Error</label>
<input type="text" class="form-control" placeholder="email" th:field="*{email}" required autofocus>
<label style="color: red" th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Username Error</label>
<input type="password" class="form-control" placeholder="Password ..." name="password" required>
<label style="color: red" th:if="${#fields.hasErrors('password')}" th:errors="*{password}">Password Error</label>
<input type="submit" class="btn btn-lg btn-default btn-block" value="Sign Up" />
<td th:if="${#fields.hasGlobalErrors()}" th:errors="*{global}">Global Error</td>
</form>
this is my html element:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
This is my controller method :
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public ModelAndView createNewUser(#Valid User user, BindingResult bindingResult) {
ModelAndView modelAndView = new ModelAndView();
User userExists = userService.findUserByEmail(user.getEmail());
if (userExists != null) {
bindingResult
.rejectValue("email", "error.user",
"There is already a user registered with the email provided");
}
if (bindingResult.hasErrors()) {
modelAndView.setViewName("registration");
} else {
userService.saveUser(user);
modelAndView.addObject("successMessage", "User has been registered successfully");
modelAndView.addObject("user", new User());
modelAndView.setViewName("registration");
}
return modelAndView;
}
This is my pom.xml file :
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
</dependency>
</dependencies>
I believe the source of the problem is related to the th:object tag and that the solution (actually linked to other related questions) is already to be found here: Spring Thyme Leaf checking for global errors results in NPE
Additionally, I noticed you are using <td> tag outside of a <table> element, this is not how it should be used according to: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td

Spring MVC: Controller function not getting called on form submit

I am new to using Spring MVC framework and have designed a html page which has two forms. One is login(form id: loginform) and other is for signup((form id:signupform). The controller is being called correctly for the login page but for the signup, nothing happens (no controller is called) and the page just refreshes. I am not able to find out the source of the problem. Here is my JSP page:
Login.jsp
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%#page session="true"%>
<html>
<head>
<title>Login Page</title>
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp"
crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous">
</script>
<spring:url value="/resources/css/mylogin.css" var="mainCss" />
<link href="${mainCss}" rel="stylesheet" />
<%-- <link href="<spring:url value='/resources/css/mylogin.css'/>" rel="stylesheet"> --%>
</head>
<body>
<div class="container">
<div id="loginbox" style="margin-top: 50px;"
class="mainbox col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
<div class="panel panel-info">
<div class="panel-heading">
<div class="panel-title">Sign In</div>
</div>
<div style="padding-top: 30px" class="panel-body">
<c:if test="${not empty error}">
<!-- Invalid Username Password -->
<div class="error">${error}</div>
</c:if>
<c:if test="${not empty msg}">
<!-- Logged out successfully -->
<div class="msg">${msg}</div>
</c:if>
<div style="display: none" id="login-alert"
class="alert alert-danger col-sm-12"></div>
<form id="loginform" class="form-horizontal" role="form"
name="loginform"
action="<c:url value='/j_spring_security_check' />" method='POST'>
<div style="margin-bottom: 25px" class="input-group">
<span class="input-group-addon"><i
class="glyphicon glyphicon-user"></i></span> <input id="login-username"
type="text" class="form-control" name="username" value=""
placeholder="username">
</div>
<div style="margin-bottom: 25px" class="input-group">
<span class="input-group-addon"><i
class="glyphicon glyphicon-lock"></i></span> <input id="login-password"
type="password" class="form-control" name="password"
placeholder="password">
</div>
<div style="margin-top: 10px" class="form-group">
<div class="col-sm-12 controls">
<input class="btn btn-success" id="btn-login" name="submit"
type="submit" value="LOG IN" /> <input type="hidden"
name="${_csrf.parameterName}" value="${_csrf.token}" />
</div>
</div>
<div class="form-group">
<div class="col-md-12 control">
<div
style="border-top: 1px solid #888; padding-top: 15px; font-size: 85%">
Don't have an account! <a href="#"
onClick="$('#loginbox').hide(); $('#signupbox').show()">
Sign Up Here </a>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<div id="signupbox" style="display: none; margin-top: 50px"
class="mainbox col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
<div class="panel panel-info">
<div class="panel-heading">
<div class="panel-title">Sign Up</div>
</div>
<div class="panel-body">
<form:form id="signupform" class="form-horizontal" role="form"
method="POST" modelAttribute="userForm"
action="<c:url value='/adduser' />">
<div id="signupalert" style="display: none"
class="alert alert-danger">
<p>Error:</p>
<span></span>
</div>
<form:hidden path="id" />
<spring:bind path="name">
<div class="form-group">
<label for="name" class="col-md-3 control-label">Name</label>
<div class="col-md-9">
<form:input path="name" type="text" class="form-control"
name="name" placeholder="Name" />
</div>
</div>
</spring:bind>
<spring:bind path="email">
<div class="form-group">
<label for="email" class="col-md-3 control-label">Email</label>
<div class="col-md-9">
<form:input path="email" type="text" class="form-control"
name="email" placeholder="Email Address" />
</div>
</div>
</spring:bind>
<spring:bind path="username">
<div class="form-group">
<label for="username" class="col-md-3 control-label">Username</label>
<div class="col-md-9">
<form:input path="username" type="text" class="form-control"
name="username" placeholder="Username" />
</div>
</div>
</spring:bind>
<spring:bind path="password">
<div class="form-group">
<label for="password" class="col-md-3 control-label">Password</label>
<div class="col-md-9">
<form:input path="password" type="password"
class="form-control" name="passwd" placeholder="Password" />
</div>
</div>
</spring:bind>
<spring:bind path="dob">
<div class="form-group">
<label for="date" class="col-md-3 control-label">Date of
Birth</label>
<div class="col-md-9">
<form:input path="dob" type="date" name="bday"
class="form-control" />
</div>
</div>
</spring:bind>
<spring:bind path="image">
<div class="form-group">
<label for="pic" class="col-md-3 control-label">Profile
Picture</label>
<div class="col-md-9">
<form:input path="image" type="file" name="pic"
class="form-control" />
</div>
</div>
</spring:bind>
<spring:bind path="genreName">
<div class="form-group">
<label for="genre" class="col-md-3 control-label">Favorite
Genres</label>
<div class="col-md-9">
<!-- <input type="file" name="pic" class="form-control"> -->
<form:select multiple="" path="genreName" name="genreNames"
class="form-control">
<c:forEach items="${genres}" var="genre" varStatus="ctr">
<option id="${genre.id}" value="${genre.name}">${genre.name}</option>
</c:forEach>
</form:select>
</div>
</div>
</spring:bind>
<div class="form-group">
<!-- Button -->
<div class="col-md-offset-3 col-md-9">
<input class="btn btn-info" id="tn-signup" name="submit"
type="submit" value="Sign Up" />
</div>
</div>
<div class="form-group">
<div class="col-md-12 control">
<div
style="border-top: 1px solid #888; padding-top: 15px; font-size: 85%">
Already have an account? <a id="signinlink" href="#"
onClick="$('#signupbox').hide(); $('#loginbox').show()">
Sign In </a>
</div>
</div>
</div>
</form:form>
</div>
</div>
</div>
</div>
</body>
</html>
Controller:
package com.moviebase.web.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
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.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.moviebase.web.model.user.UserDao;
import com.moviebase.web.model.genre.Genre;
import com.moviebase.web.model.genre.GenreDao;
import com.moviebase.web.model.user.User;
#Controller
public class MainController {
#Autowired
public UserDao userDao;
#Autowired
public GenreDao genreDao;
#RequestMapping(value = { "/", "/welcome**" }, method = RequestMethod.GET)
public ModelAndView defaultPage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Moviebase");
model.addObject("message", "This is default page!");
model.setViewName("hello");
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName(); //get logged in username
User user = userDao.findByUsername(username);
System.out.println(user.toString());
return model;
}
#RequestMapping(value = "/admin**", method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Moviebase");
model.addObject("message", "This page is for ROLE_ADMIN only!");
model.setViewName("admin");
return model;
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login(#RequestParam(value = "error", required = false) String error,
#RequestParam(value = "logout", required = false) String logout) {
ModelAndView model = new ModelAndView();
if (error != null) {
System.out.println(" error:"+error);
model.addObject("error", "Invalid username and password!");
}
if (logout != null) {
model.addObject("msg", "You've been logged out successfully.");
}
List<Genre> genreList = genreDao.getAllGenres();
model.addObject("genres", genreList);
User user = new User();
model.addObject("userForm", user);
model.setViewName("login");
return model;
}
#RequestMapping(value = "/adduser", method = RequestMethod.POST)
public ModelAndView createUser(#ModelAttribute("userForm") User user,
BindingResult result) {
// ModelAndView model = new ModelAndView();
// model.setViewName("redirect:/");
System.out.println("Came here");
userDao.insert(user);
return new ModelAndView("redirect:/admin");
}
//for 403 access denied page
#RequestMapping(value = "/403", method = RequestMethod.GET)
public ModelAndView accesssDenied() {
ModelAndView model = new ModelAndView();
//check if user is login
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (!(auth instanceof AnonymousAuthenticationToken)) {
UserDetails userDetail = (UserDetails) auth.getPrincipal();
System.out.println(userDetail);
model.addObject("username", userDetail.getUsername());
}
model.setViewName("403");
return model;
}
}
Web.xml
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>MovieBase</display-name>
<!-- Spring MVC -->
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-security.xml,
/WEB-INF/spring-database.xml
</param-value>
</context-param>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>database</groupId>
<artifactId>moviebase</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Moviebase</name>
<properties>
<jdk.version>1.7</jdk.version>
<spring.version>3.2.8.RELEASE</spring.version>
<spring.security.version>3.2.3.RELEASE</spring.security.version>
<jstl.version>1.2</jstl.version>
<mysql.connector.version>5.1.30</mysql.connector.version>
</properties>
<dependencies>
<!-- Spring 3 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<!-- Spring Security JSP Taglib -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>
<!-- jstl for jsp page -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
</dependencies>
<build>
<finalName>moviebase</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
<wtpversion>2.0</wtpversion>
</configuration>
</plugin>
</plugins>
</build>
</project>
mvc-dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.moviebase.*" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:annotation-driven />
<mvc:resources mapping="/resources/**" location="/resources/" />
</beans>
Your singup form has the http method POST but your controller is form http method GET
Your JSP:
<form:form id="signupform" class="form-horizontal" role="form"
method="POST" modelAttribute="userForm"
action="<c:url value='/adduser' />">
Your controller:
#RequestMapping(value = "/adduser", method = RequestMethod.GET)
public ModelAndView createUser(#ModelAttribute("userForm") User user,
BindingResult result) {

Resources