spring boot 1.3.5 form:errors not showing for jsp - validation

I am upgrading a spring-mvc web app from spring 4.X to be a spring boot war.
The page serves, the form is posted, the validation is executed (and records an error) but the jsp does show any errors in form:errors
THe same jsp works fine outside of spring-boot.
To be sure I'm setting my spring boot jsp app correctly I've simply added a form post to the existing "spring-boot-sample-web-jsp" (see https://github.com/spring-projects/spring-boot/tree/1.3.x/spring-boot-samples )
Here is the model object
package sample.jsp;
import java.io.Serializable;
public class EmailHolderPageModel implements Serializable {
private String emailAddress;
public EmailHolderPageModel() {
super();
}
public EmailHolderPageModel(String emailAddress) {
super();
this.emailAddress = emailAddress;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
}
Here is the server side:
#Autowired
private EmailSaveValidator emailSaveValidator;
#RequestMapping("/saveEmail.html")
public ModelAndView processEmail(#ModelAttribute("myModel") EmailHolderPageModel pageModel, BindingResult result){
ModelAndView modelAndView = null;
emailSaveValidator.validate(pageModel, result);
if(result.hasErrors()){
modelAndView = new ModelAndView("enterEmail");
EmailHolderPageModel pm = new EmailHolderPageModel("");
modelAndView.addObject("myModel", pm);
System.err.println("!!!Failed Validation!!!");
} else {
modelAndView = new ModelAndView("thankyou");
ThankyouPageModel thankYoupageModel = new ThankyouPageModel();
modelAndView.addObject("thankyouModel", thankYoupageModel);
}
return modelAndView;
}
Here is the validator
#Component
public class EmailSaveValidator implements Validator {
public boolean supports(Class candidate) {
return EmailHolderPageModel.class.isAssignableFrom(candidate);
}
public void validate(Object obj, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "emailAddress", "emailRequired", "required field");
}
}
Here is the jsp (truncated a little because stackoverflow is getting confused)
<%# page session="false"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
<title>test entering email</title>
</head>
<body>
<form:form commandName="myModel" method="POST" action="saveEmail.html" >
<form:errors path="emailAddress" htmlEscape="false" />
<div id="formIntro">
<spring:message text="enter email address" />
<p><strong><label>
<spring:message text="email address:" /> </label><form:input path="emailAddress" size="35" maxlength="200"/>
</label>
</strong></p>
</div>
<input type="submit" value="Submit" />
</form:form>
</body>
</html>
The pom file is (unmodified from spring-boot-sample-web-jsp)
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<!-- Your own application should inherit from spring-boot-starter-parent -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-samples</artifactId>
<version>1.3.6.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-sample-web-jsp</artifactId>
<packaging>war</packaging>
<name>Spring Boot Web JSP Sample</name>
<description>Spring Boot Web JSP Sample</description>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
<m2eclipse.wtp.contextRoot>/</m2eclipse.wtp.contextRoot>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
</configuration>
</plugin>
</plugins>
</build>
</project>
==============
And the solution is do not create a new model object on error (though works fine when not a spring boot app):
#RequestMapping("/saveEmail.html")
public ModelAndView processEmail(#ModelAttribute("myModel") EmailHolderPageModel pageModel, BindingResult result){
ModelAndView modelAndView = null;
emailSaveValidator.validate(pageModel, result);
if(result.hasErrors()){
modelAndView = new ModelAndView("enterEmail");
// !! SOLUTION !!
// DO NOT CREATE A NEW MODEL OBJECT
// !! SOLUTION !!
// EmailHolderPageModel pm = new EmailHolderPageModel("");
modelAndView.addObject("myModel", pageModel);
System.err.println("!!!Failed Validation!!!");
} else {
modelAndView = new ModelAndView("thankyou");
ThankyouPageModel thankYoupageModel = new ThankyouPageModel();
modelAndView.addObject("thankyouModel", thankYoupageModel);
}
return modelAndView;
}

You commandName should be exacty the name of your model class: eg.
public class EmailHolderPageModel{}...
And in your controller any function:
public ModelAndView anythink(#Valid EmailHolderPageModel email...)
So, in you jsp form should be:
<form:form commandName="emailHolderPageModel" />...

Related

I was following a spring tutorial to make coronavirus tracker application.but then encountered a problem in parsing using thymeleaf

P.S - I just started spring boot
while parsing the file I got this error:
This application has no explicit mapping for /error, so you are seeing
this as a fallback.
Wed Feb 24 00:20:45 IST 2021 There was an unexpected error
(type=Internal Server Error, status=500). An error happened during
template parsing (template: "class path resource
[templates/home.html]")
org.thymeleaf.exceptions.TemplateInputException: An error happened
during template parsing (template: "class path resource
[templates/home.html]")
This is my home.html file
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>CoronaVirus Tracker Application</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="${testName}"></p>
<table>
<tr>
<th>State</th>
<th>Country</th>
<th>Total cases reported</th>
</tr>
<tr th:each="locationStat : ${locationStats}">
<td th:text="${locationStat.state}"></td>
<td th:text="${locationStat.country}"></td>
<td th:text="${locationStat.latestTotalCases}">0</td>
</tr>
</table>
</body>
</html>
This is my HomeController
package com.project.coronavirustracker.controllers;
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 java.util.*;
import com.project.coronavirustracker.models.LocationStats;
import com.project.coronavirustracker.services.CoronaVirusDataService;
#Controller
public class HomeController {
#Autowired
CoronaVirusDataService coronaVirusDataService;
#GetMapping("/")
public String home(Model model) {
List<LocationStats> allStats = coronaVirusDataService.getAllStats();
model.addAttribute("locationStats", allStats);
return "home";
}
}
This is my LocationStats file
package com.project.coronavirustracker.models;
public class LocationStats {
private String state;
private String country;
private int latestTotalCases;
public void setState(String state) {
this.state = state;
}
public String getState() {
return this.state;
}
public void setCountry(String country) {
this.country = country;
}
public String getCountry() {
return this.country;
}
public void setlatestTotalCases(int cases) {
latestTotalCases = cases;
}
public int getlatestTotalCases() {
return this.latestTotalCases;
}
#Override
public String toString() {
return "LocationStats{" +
"state='" + state + '\'' +
", country='" + country + '\'' +
", latestTotalCases=" + latestTotalCases +
'}';
}
}
And this is my 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.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.project</groupId>
<artifactId>coronavirus-tracker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>coronavirus-tracker</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</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.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
It is true that there is no testName but this does not generate an error. This will output an empty <p></p>.
The problem is that it cannot find the latestTotalCases method. (It must start with a capital letter.)
Solution 1
It will fix when you change this method as follows:
public int getLatestTotalCases() {
return this.latestTotalCases;
}
Solution 2
If you don't want to change the name of method, you need to call the method in the html file as follow:
<td th:text="${locationStat.getlatestTotalCases}">0</td>

why i am getting nullpointerexception in JSP page for Spring DAO methods?

here, whenever I trying to access or call the DAO method (which is written in #Repository class) in the JSP page in My spring MVC Project using Hibernate, it showing NullPointerException.
it works fine when I accessing this method in Controller class, it just throwing an exception in the JSP page.
and here expection i am getting,
SEVERE: Servlet.service() for servlet [jsp] threw exception
java.lang.NullPointerException
at com.lms.service.BookDetailsServiceImpl.getBookStatusForLibrarianById(BookDetailsServiceImpl.java:62)
here is my code,
in pom.xml,
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.libmansystem</groupId>
<artifactId>LibraryManagementSystems</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>LibraryManagementSystems Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<springframework.version>5.0.2.RELEASE</springframework.version>
<springsecurity.version>5.0.0.RELEASE</springsecurity.version>
<hibernate.version>5.4.14.Final</hibernate.version>
<mysql.connector.version>8.0.20</mysql.connector.version>
<c3po.version>0.9.5.5</c3po.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- Spring MVC support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Spring Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Spring ORM -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Hibernate Core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- Add MySQL and C3P0 support -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3po.version}</version>
</dependency>
<!-- Servlet, JSP and JSTL support -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jstl-impl</artifactId>
<version>1.2</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>LibraryManagementSystems</finalName>
<pluginManagement>
<plugins>
<plugin>
<!-- Add maven co-ordinates for : maven-war-plugin -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
entity class,
#Entity
#Table(name = "book_status_forlibrarian")
public class BookStatusForLibrarian {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "s_id")
private Integer id;
#Column(name = "status")
private String status;
public BookStatusForLibrarian() {
}
public BookStatusForLibrarian(Integer id, String status) {
this.id = id;
this.status = status;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
#Override
public String toString() {
return "BookStatusForLibrarian [id=" + id + ", status=" + status + "]";
}
}
Dao interface and class,
public interface BookDetailsDAO {
public BookStatusForLibrarian getBookStatusForLibrarianById(int statusId);
}
#Repository
public class BookDetailsDAOImpl implements BookDetailsDAO{
private SessionFactory sessionFactory;
#Autowired
public BookDetailsDAOImpl(SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
public BookDetailsDAOImpl()
{
}
#Override
public BookStatusForLibrarian getBookStatusForLibrarianById(int statusId) {
Session theSession = sessionFactory.getCurrentSession();
BookStatusForLibrarian theBookStatusForLibrarian = theSession.get(BookStatusForLibrarian.class, statusId);
return theBookStatusForLibrarian;
}
}
my service interface and class,
public interface BookDetailsService {
public BookStatusForLibrarian getBookStatusForLibrarianById(int statusId);
}
#Service
public class BookDetailsServiceImpl implements BookDetailsService {
#Autowired
BookDetailsDAO theBookDetailsDAO;
#Override
#Transactional
public BookStatusForLibrarian getBookStatusForLibrarianById(int statusId) {
System.out.println("inside service ");
return theBookDetailsDAO.getBookStatusForLibrarianById(statusId);
}
}
my controller,
#Controller
public class HomePageController {
#GetMapping("/homepage")
public String getHomePage()
{
return "homepage";
}
}
in my JSP page I am getting exception,
/WEB-INF/view/homepage.jsp,
<%#page import="com.lms.service.NonServiceMethod"%>
<%#page import="com.lms.dao.BookDetailsDAOImpl"%>
<%#page import="com.lms.service.BookDetailsServiceImpl"%>
<%#page import="com.lms.service.BookDetailsService"%>
<%#page import="com.lms.entity.BookStatusForLibrarian"%>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%# page isELIgnored="false"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Show All Book</title>
</head>
<body>
<%
System.out.println("getting exception while calling Spring DAO method (which is written in #Repository class) in JSP page");
BookDetailsServiceImpl theBookDetailsService = new BookDetailsServiceImpl();
BookStatusForLibrarian getBookStatus= theBookDetailsService.getBookStatusForLibrarianById(3);
%>
</body>
</html>
and here expection i am getting,
SEVERE: Servlet.service() for servlet [jsp] threw exception
java.lang.NullPointerException
at com.lms.service.BookDetailsServiceImpl.getBookStatusForLibrarianById(BookDetailsServiceImpl.java:62)
please help me.
If you create the service in the JSP, it is not a Spring bean. There is no dependency injection done by Spring, you DAO is not injected in your service (NullPointerException). The correct way to pass the model (BookStatusForLibrarian) into the view (JSP) is to use the Controller.
#Controller
public class HomePageController {
#Autowired
BookDetailsService bookDetailsService;
#GetMapping("/homepage")
public String getHomePage(Model model) {
BookStatusForLibrarian bookStatus = bookDetailsService.getBookStatusForLibrarianById(3);
model.addAttribute("bookStatus", bookStatus);
return "homepage";
}
}
Then you can use bookStatus directly in the JSP without <% %> just like this: ${bookStatus.id}

Spring REST controller file upload - Request method 'POST' not supported error

I'm in the process of creating a prototype for a web app, where one of the functions should allow someone to upload an excel file with some extra info. The file alongside the info is stored in an object, which is serialized and stored.
I have created the upload method, and while trying to test the function it throws the "Request method 'POST' not supported" whitelabel error page.
I have suspicions that it might be the pom.xml at fault, but I'm not entirely sure.
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>project</groupId>
<artifactId>answers</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>MVC 1.0 Blank Project (from https://github.com/making/mvc-1.0-blank)</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.ozark</groupId>
<artifactId>ozark</artifactId>
<version>1.0.0-m02</version>
</dependency>
<!-- Swing exercise -->
<dependency>
<groupId>com.miglayout</groupId>
<artifactId>miglayout</artifactId>
<version>3.5.5</version>
</dependency>
<!-- Web exercise -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>1.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.3.6.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
Here is the Controller class. We will move to a Thymeleaf configuration in a day or two, this html is just for testing purposes currently.
#MultipartConfig
#RestController
#RequestMapping(value = "/Teacher", produces = "text/html;charset=UTF-8")
public class Teacher {
#GetMapping("")
#ResponseBody
TestController testcont;
public String homePage(#RequestParam(value = "file", required = false) String name, HttpServletRequest request,
HttpServletResponse response){
StringBuilder sb = new StringBuilder();
sb.append("<p> <a href='/Teacher/NewTest'>New Test upload</a></p>\n"
+ "<p><a href='/SelectTest'>Select Test File</a> <button type='button'>Send Test</button></p>"
+ "\n \n \n"
+ "<p><a>Current Test for students:</a>\n <a href='/getCurrentTest'></a></p>"
);
return sb.toString();
}
#GetMapping("/NewTest")
#ResponseBody
public String newTestUpload(HttpServletRequest request, HttpServletResponse response){
StringBuilder sb = new StringBuilder();
if(!request.getParameterNames().hasMoreElements()){
sb.append("<p><form action='' method='post' enctype='multipart/form-data'>"
+ "<label>Enter file</label><input type='file' name='file'>"
+ "<button type='submit'>Upload</button></p>"
+ "<p><form action='/testName'>Test Name: <input type='text' name='name' value=''></p>"
+ "<p><form action='/addInfo'>Comment: <input type='text' comment='comment' value=''></p>"
+ "<p>Answer 1: <input type='text' Answer='answer1' value=''></p>"
+ "<p>Answer 2: <input type='text' Answer='answer2' value=''></p>"
+ "</form>"
+ "<a href='/Teacher'>Back</a>\n"
);
return sb.toString();
}
else if(request.getParameter("file") != null && request.getParameter("name") != ""
&& request.getParameter("comment") != "" && request.getParameter("answer1") != null
&& request.getParameter("answer2") != null){
try{
// Upload happens here
Part filePart = request.getPart("file");
String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString();
InputStream fileContent = filePart.getInputStream();
File testExcel = new File(fileName);
testExcel.createNewFile();
Files.copy(fileContent, Paths.get(testExcel.getName()), StandardCopyOption.REPLACE_EXISTING);
double ans1 = Double.parseDouble(request.getParameter("answer1"));
double ans2 = Double.parseDouble(request.getParameter("answer2"));
Test test = new Test(testExcel, request.getParameter("name"),
request.getParameter("comment"), ans1, ans2);
testcont.addTest(test);
sb.append("New test uploaded!<br/>\n<a href='/'>Back</a>\n");
return sb.toString();
} catch (Exception e){
sb.append("<h1>Couldnt insert test</h1>");
response.setStatus(HttpServletResponse.SC_OK);
return sb.toString();
}
}
else{
sb.append("failed<br/>\n<a href='/'>Back</a>\n");
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return sb.toString();
}
}
}
From the controller code you've posted, both of your endpoints are GET.
/Teacher :- #GetMapping
/Teacher/NewTest :- #GetMapping
You are trying to POST to an endpoint which does not support POST method, which is why you see error message, specifying 'POST' method not supported.
Both methods in your controller has #GetMapping annotation, that means that they support GET requests. You need to replace one with #PostMapping(to support POST requests)
Correct your method to:
#PostMapping
#RequestMapping("/NewTest")
public String newTestUpload(HttpServletRequest request, HttpServletResponse response) {
or
#PostMapping(path = "/NewTest")
public String newTestUpload(HttpServletRequest request, HttpServletResponse response) {

Spring Boot + Thymeleaf = "Whitelabel Error Page" when trying to render index.html

I am trying to do simple Spring MVC LibraryDo You have any idea why I have problem with View, when i use homepage method in my controller it should show me index.html but i only get Whitelabel Error Page all the time, and i dont know why:/
My structure:
[https://i.imgur.com/5TrGGrB.png]
My controller:
package controller;
import model.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
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 service.BookService;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
#Controller
public class LiberianController{
#Autowired
private BookService bookService;
#RequestMapping(value = "/")
public String homepage() {
return "index";
}
#GetMapping(value = "/allBooks")
public ModelAndView allBooks(ModelAndView modelAndView) {
List<Book> books = bookService.getAllBooks();
modelAndView.addObject("listBooks", books);
modelAndView.setViewName("allBooks");
return modelAndView;
}
#GetMapping(value = "/addBook")
public ModelAndView newBook(ModelAndView modelAndView) {
Book book = new Book();
modelAndView.addObject("book", book);
modelAndView.setViewName("addBook");
return modelAndView;
}
#GetMapping(value = "updateBook")
public ModelAndView updateBook(HttpServletRequest httpServletRequest) {
long id = Long.parseLong(httpServletRequest.getParameter("id"));
Book book = bookService.getBook(id);
ModelAndView modelAndView = new ModelAndView("addBook");
modelAndView.addObject("book", book);
return modelAndView;
}
#RequestMapping(value = "/saveBook",method = RequestMethod.POST)
public ModelAndView saveBook(#ModelAttribute Book book) {
if (book.getId() == 0) {
bookService.addBook(book);
} else {
bookService.updateBook(book.getId(), book);
}
return new ModelAndView("redirect:/allBooks");
}
#GetMapping(value = "/deleteBook")
public ModelAndView deleteBook(HttpServletRequest httpServletRequest) {
long id = Long.parseLong(httpServletRequest.getParameter("id"));
bookService.deleteBook(id);
return new ModelAndView("redirect:/allBooks");
}
}
My POM:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>MyLibrary</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.12.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Something</title>
</head>
<body>
<h1>Hello</h1>
</body>
</html>
aplication.properties
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/book?useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.mvc.view.prefix=/WEB-INF/
spring.mvc.view.suffix=.jsp
spring.thymeleaf.mode=LEGACYHTML5
There are a few things wrong with your demo project.
1. Incorrect package structure
You put your Runner class to a default package. It not a good idea, because in this case Spring Boot is not able to set a default package for component scanning. When you run your application you should see something like:
** WARNING ** : Your ApplicationContext is unlikely to start due to a #ComponentScan of the default package.
Solution: move all your classes to common package.
2. spring-boot-starter-thymeleaf is missing
In your pom.xml file add following dependency to make Thymeleaf templates working:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Then remove following dependency that is present in your pom.xml:
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
3. spring.thymeleaf.mode=LEGACYHTML5 requires additional dependency
When you run your app and you open http://localhost:8080 you will see following exception:
org.thymeleaf.exceptions.ConfigurationException: Cannot perform conversion to XML from legacy HTML: The nekoHTML library is not in classpath. nekoHTML 1.9.15 or newer is required for processing templates in "LEGACYHTML5" mode [http://nekohtml.sourceforge.net]. Maven spec: "net.sourceforge.nekohtml::nekohtml::1.9.15". IMPORTANT: DO NOT use versions of nekoHTML older than 1.9.15.
at org.thymeleaf.templateparser.html.AbstractHtmlTemplateParser.parseTemplate(AbstractHtmlTemplateParser.java:90) ~[thymeleaf-2.1.6.RELEASE.jar:2.1.6.RELEASE]
at org.thymeleaf.TemplateRepository.getTemplate(TemplateRepository.java:278) ~[thymeleaf-2.1.6.RELEASE.jar:2.1.6.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1104) ~[thymeleaf-2.1.6.RELEASE.jar:2.1.6.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1060) ~[thymeleaf-2.1.6.RELEASE.jar:2.1.6.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1011) ~[thymeleaf-2.1.6.RELEASE.jar:2.1.6.RELEASE]
This is because you have specified:
spring.thymeleaf.mode=LEGACYHTML5
and you haven't add nekoHTML library to the classpath.
Solution: add following dependency to your pom.xml:
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.22</version>
</dependency>
After applying all these steps you will see "Hello" on your app's home page. Hope it helps.

Spring Boot Security with Jdbc Annotation

WebSecurityConfig.java
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
DataSource dataSource;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/css/**", "/icons/**", "/js/**", "/images/**").permitAll();
http.authorizeRequests().antMatchers("/bootstrap/**", "/icons/**", "/datatables/**", "/jquery/**",
"/font-awesome/**", "/select2/**").permitAll();
http.authorizeRequests().antMatchers("/", "/")
.permitAll()
.anyRequest()
.authenticated()
.and().formLogin()
.loginPage("/userForm")
.usernameParameter("userName").passwordParameter("password")
.defaultSuccessUrl("/login")
.failureUrl("/userForm")
.permitAll().and()
.logout().logoutUrl("/logout")
.logoutSuccessUrl("/logout").permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery(
"select username, password, active_status from bgtool_test_users where username = ? and active_status = 'Y'")
.authoritiesByUsernameQuery(
"select username, role from bgtool_test_users where username = ?")
.passwordEncoder(passwordEncoder())
;
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
UserController.java
#Controller
public class UserController {
private final Logger logger = LoggerFactory.getLogger(UserController.class);
#Autowired
private GameFacade gameFacade;
#RequestMapping("/userList")
public String list(Model model) {
List<User> users = gameFacade.findAllUsers();
model.addAttribute("users", users);
logger.debug("Users: {}", users);
return "userList";
}
#RequestMapping(value = "/userForm", method = RequestMethod.GET)
public String userForm(Model model) {
User entry = new User();
model.addAttribute("userLogin", entry);
logger.debug("Login Form");
return "loginForm";
}
#RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(#Valid #ModelAttribute("userLogin") User entry, BindingResult result, Model model) {
System.out.println("setting status N");
if (result.hasErrors()) {
logger.debug("Login Form validation error");
return "loginForm";
} else {
entry = gameFacade.findUserByName(entry.getUserName(), entry.getPassword());
if (entry == null) {
result.rejectValue("password", "error.userLogin", "Username or Password incorrect !!");
return "loginForm";
}
logger.debug("Login Successful", entry);
return "home";
}
}
pom.xml
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>frau</groupId>
<artifactId>bgtweb</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<derby.version>10.12.1.1</derby.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-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>${commons-dbcp.version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>${derby.version}</version>
<scope>runtime</scope>
</dependency>
<!-- SPRING SECURITY -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jheinzel.maven</groupId>
<artifactId>derby-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<derbyHome>${project.basedir}/data</derbyHome>
<port>1527</port>
<database>EMDb</database>
</configuration>
</plugin>
</plugins>
</build>
</project>
When i try to login, i am redirected back to loginform page. The controller method for mapping "/login" is not getting called as i am not getting my logger messages of same method in the console.
I have checked the SQL queries.they are correct.I am unable to find what is missing.
Any help is appreciated. Thanks in Advance
Your login page url and default success url is the same:
.loginPage("/userForm").usernameParameter("userName").passwordParameter("password")
.defaultSuccessUrl("/userForm")
Do you understand logical chain of Spring Security? You declare pages for each authentication step, configure authentication provider that check you username and and password. it's it. So there are two possible places for error - your mapping (pages and controller) and your DB (jdbcAuthentication()).
You event don't need a controller - only pages and and security config. try to simplify your example and remove controller and debug jdbc authentication
This example show correct way of configuration

Resources