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

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}

Related

Form validation does not work in Spring Mvc Application

I have a Spring Mvc Application using Spring 5.2.8.RELEASE, which is deployed in a Tomcat 9.0.37 instance.
The dependencies section of my pom.xml is the following:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.8.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
<type>maven-plugin</type>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>6.1.5.Final</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
My WebConfig class (which is returned in the getServletConfigClasses()) is:
#Configuration
#EnableWebMvc
#ComponentScan({"com.example.myapp.web", "com.example.myapp.data"})
public class WebConfig implements WebMvcConfigurer {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
I have the following bean that contains some validation constraints:
public class User {
private Long id;
#NotBlank
#Size(min = 5, max = 16)
private String firstName;
...
}
I have a JSP file for registering a new user:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="sf" %>
<%# page session="false" %>
<html>
<head>
<title>User</title>
</head>
<body>
<h1>Register</h1>
<sf:form method="POST" modelAttribute="user">
First Name: <sf:input path="firstName"/><br/>
<!-- other fields -->
<input type="submit" value="Register"/>
</sf:form>
</body>
</html>
The controller that processes the request is the following:
#Controller
#RequestMapping("/user")
public class UserController {
// ...
#RequestMapping(value = "/register", method = POST)
public String processRegistration(#Valid User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "registerForm";
}
userRepository.save(user);
return "redirect:/user/" + user.getUsername();
}
// ...
}
The validation doesn't get triggered whenever I click the "Register" button in the browser.
However, when I invoke the method from a unit test, the validation is performed as expected (the test below fails because the redirection is not performed):
public class UserControllerTest {
#Test
public void shouldProcessRegistration() throws Exception {
UserRepository mockRepository = mock(UserRepository.class);
User unsaved = new User("John", "Doe", "jdoe", "pass");
User saved = new User(1L, "John", "Doe", "jdoe", "pass");
when(mockRepository.save(unsaved)).thenReturn(saved);
UserController controller = new UserController(mockRepository);
MockMvc mockMvc = standaloneSetup(controller).build();
mockMvc.perform(post("/user/register")
.param("firstName", "John")
.param("lastName", "Doe")
.param("username", "jdoe")
.param("password", "pass"))
.andExpect(redirectedUrl("/user/jdoe"));
verify(mockRepository, atLeastOnce()).save(unsaved);
}
}
UserController is in the web package, WebConfig in the config package and User in the package above these two (com.example.myapp).
Anyone has any idea what am I doing wrong?
I have read all related questions on this problem, but wasn't able to find any solution for my problem.
You answered your question.
Unit Test works and your form submit doesn't mean Your Data is not been set when you submit Form
Try this
#RequestMapping(value = "/register", method = POST)
public String processRegistration(#Valid #ModelAttribute("user") User user, BindingResult bindingResult) {
If the above doesn't work try adding a log to see if the value is been added to User Object.
I eventually managed to figure it out.
It was not a code problem, but a project configuration one.
After adding some dependencies in the pom.xml (namely hibernate-validator and hibernate-validator-annotation-processor), the corresponding artifacts were not automatically added in the output directory in WEB-INF/lib by IntelliJ IDEA.
I had to add these libraries manually: https://imgur.com/a/WRkD56F.
After doing so, the validation works as expected.

Can't solve this issue UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl

i've tried alot to fix this issue but couldn't. I find, if we use "abstractBinder" then this could be fix but once i've my Binder in place, i start having 404 error.
UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl
Please help
My Resource:
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.walmart.services.helpers.IUserService;
import com.walmart.services.helpers.ServicesTest;
#Path("/sayHello")
public class ControllerTest {
#Inject
private IUserService service;
#Inject
private ServicesTest service2;
#GET
#Path("/{name}")
#Produces(MediaType.TEXT_PLAIN)
public String method(#PathParam("name") String msg) {
return service.method() + " msg";
}
#GET
#Path("/v2/{name}")
#Produces(MediaType.TEXT_PLAIN)
public String method2(#PathParam("name") String msg) {
return service2.method() + " msg";
}
}
My resource configuration file:
#ApplicationPath("/rest/*")
public class ResourceConfiguration extends ResourceConfig {
public ResourceConfiguration() {
//register(new MyBinder());
this.packages(true, "com.walmart.services.*");
}
}
My Binder [ if in place ]
public class MyBinder extends AbstractBinder
{
#Override
protected void configure() {
// TODO Auto-generated method stub
bind(new ServicesTest()).to(ServicesTest.class);
// bind(UserServiceImpl.class).to(IUserService.class).in(RequestScoped.class);
}
}
Services:
IUserService and its implementation
public interface IUserService {
public String method();
}
public class UserServiceImpl implements IUserService {
#Inject
public UserServiceImpl() {
System.out.println("test");
}
#Override
public String method() {
return "Welcome ";
}
}
Other
public class ServicesTest {
public ServicesTest() {
System.out.println("created ");
}
public String method() {
return "Welcome";
}
}
WEbXML
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>com.walmart.learning.javaee</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Now, i can access my resource using
http://localhost:8080/javaeeLearning/rest/sayHello/h
Which gives me below errors
SEVERE: Servlet.service() for servlet [com.walmart.configuration.ResourceConfiguration] in context with path [/javaeeLearning] threw exception [A MultiException has 4 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=IUserService,parent=ControllerTest,qualifiers={},position=-1,optional=false,self=false,unqualified=null,2007960340)
2. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=ServicesTest,parent=ControllerTest,qualifiers={},position=-1,optional=false,self=false,unqualified=null,10615079)
3. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.walmart.services.rest.controller.ControllerTest errors were found
4. java.lang.IllegalStateException: Unable to perform operation: resolve on com.walmart.services.rest.controller.ControllerTest
] with root cause
And to resolve, i uncomment my Binder in Resource configuration
then i start having 404.
Please help....
Other details;
Pom
<name>javaeeLearning</name>
<properties>
<maven.compiler.source>10</maven.compiler.source>
<maven.compiler.target>10</maven.compiler.target>
<jaxrs.version>2.0.1</jaxrs.version>
<jersey2.version>2.23</jersey2.version>
<jersey2.gf.cdi.version>2.14</jersey2.gf.cdi.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/javax/javaee-api -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>${jaxrs.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-war-plugin -->
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</dependency>
<!-- Jersey2.x Dependencies -->
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-server -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey2.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-common -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>${jersey2.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-client -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey2.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey2.version}</version>
</dependency>
<!-- Jersey2.x Dependency injection -->
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.inject/jersey-hk2 -->
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.27</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.activation/activation -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jaxb/jaxb-core -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-impl -->
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.4.0-b180830.0438</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-json-jackson -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey2.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.containers.glassfish/jersey-gf-cdi -->
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
<version>${jersey2.gf.cdi.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.enterprise/cdi-api -->
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
Make your JAX-RS resource a CDI bean like this:
#Path("/sayHello")
#RequestScoped
public class ControllerTest {
Then you don't need the Binder and injection should work.
You could set bean discovery mode to all in beans.xml:
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
</beans>
or annatate UserServiceImpl with an scope annotation (like #Dependent)

Spring MVC 5 & Tomcat 9 - Unable to render the model attribute in the JSP [duplicate]

This question already has answers here:
EL expressions not evaluated in JSP
(5 answers)
Closed 5 years ago.
I want to pass the model attribute to the JSP file and print it using the appropriate JSTL tags. When I call the /home, all I see is the tag I used to be placeholder (${name}) for the attribute; not the value I have set.
Here is my controller:
#Controller
#RequestMapping(value = "/*")
public class MainController {
#RequestMapping(value = "/home", method = RequestMethod.GET)
public void home(Model model) {
model.addAttribute("name", "John");
}
}
The WebConfig class which implements WebMvcConfigurer
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"com.tk"})
public class WebConfig implements WebMvcConfigurer {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public InternalResourceViewResolver jspViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
WebAppInitializer class
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) {
AnnotationConfigWebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcherServlet = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(context));
dispatcherServlet.setLoadOnStartup(1);
dispatcherServlet.addMapping("/");
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
servletContext.addFilter("characterEncodingFilter", characterEncodingFilter).addMappingForUrlPatterns(null, false, "/*");
}
private AnnotationConfigWebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.tk.spring5App.config");
return context;
}
}
home.jsp file content:
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<body>
<h1><c:out value="${name}"/></h1>
</body>
</html>
And finally here is my pom.xml file:
<properties>
<java.version>1.8</java.version>
<spring.framework.version>5.0.3.RELEASE</spring.framework.version>
</properties>
<dependencies>
<!-- **********************************************************************
** SPRING DEPENDENCIES **
********************************************************************** -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.framework.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<!--javax.servlet-api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<!--<scope>runtime</scope>-->
</dependency>
<!-- JSP Dependency -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<!-- JSTL Dependency -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>javax.servlet.jsp.jstl-api</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!--javax.xml-->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
The web app is hosted on Apache Tomcat 9.0.4.
You probably have a (possible empty) web.xml with a version of 2.4 or lower in there. With that version evaluating EL expressions is disabled by default and as such expressions will show up as regular text.
Now you have 2 options either switch to a newer version 2.5
<web-app
version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
or remove the web.xml altogether relying only on annotations. Beware that not everything can be configured through annotations as you can in the web.xml or with web-fragment.xml if you need those configuration options (like <distributable />, extensive session configuration etc.) you still need an XML configuration (but just make sure it has a proper version).

spring boot 1.3.5 form:errors not showing for jsp

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" />...

Where I should place the jsp files in a spring-boot project

Recently, I start to work with the spring-boot, and I am trying convert my old spring projects, all of them being web applications, to use this. I manage to compile, package and run the application, but when I try access them in the browser, I can't reach out my views.
First, I try put the jsp pages in the usual folder src/main/webapp/WEB-INF/jsp, but after read this article from official documentation:
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-static-content
I try put them in the folder src/main/resources. None of this works. Anyone can tell me where I should put this files to allow them be acessible when the application is running?
My pom.xml is this:
<?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>com.spring</groupId>
<artifactId>app</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.8.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<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.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901-1.jdbc4</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<start-class>com.spring.app.Application</start-class>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I have this controller to map the views:
#Controller
public class AcessoController {
#RequestMapping(value = "/signin")
public String signin(Model model) {
return "acesso/signin";
}
#RequestMapping(value = "/admin")
public String admin(Model model) {
return "private/admin";
}
#RequestMapping(value = "/index")
public String index(Model model) {
return "public/index";
}
}
and this configuration classes:
WebAppConfig.java
#EnableWebMvc
#Configuration
#ComponentScan(value="com.spring.app")
public class WebAppConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
WebAppInitializer.java
#Order(value=1)
public class WebAppInitializer implements WebApplicationInitializer {
#SuppressWarnings("resource")
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(WebAppConfig.class);
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext jspContext = new AnnotationConfigWebApplicationContext();
jspContext.register(DispatcherConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(jspContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
DispatcherConfig.java
#Configuration
#Import(WebAppConfig.class)
public class DispatcherConfig {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
If using Jetty or Tomcat as embedded servlet container just change your packaging from jar to war, and launch it with java -jar ...

Resources