JSP file not rendering in Spring Boot web application - spring-boot

I have a Spring Boot web application up and running using embedded Tomcat (the default). When it serves up JSP files as part of rendering the view I specified in my controller, the JSPs are not being rendered as such, and instead print out the contents. For example:
index.jsp
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>Test</body>
</html>
When the view is rendered in the browsers, the contents above are displayed, instead of the expected contents:
Test

Make sure that your pom.xml specifies the Tomcat JSP dependency as follows:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
It seems that embedded Tomcat treats the JSP rendering as optional.
As mentioned below, this JAR is sometimes necessary as well:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<scope>provided</scope>
</dependency>
(I added provided since this JAR should be included by the servlet container.

You will need not one but two dependencies (jasper and jstl) in your pom.xml for this to work.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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>
</dependencies>

For me worked the same like Dan mentioned. Removing the provided scope.
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
Thanks guy's!

Worked for me too but, I had to remove
<scope>provided</scope>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>

Better you can use gradle (which is catching up over Maven). Use this dependency in build.gradle file.
//Required dependency for JSP
providedRuntime 'org.apache.tomcat.embed:tomcat-embed-jasper'

Make sure, spring-boot-starter-tomcat, tomcat-embed-jasper and jstl dependencies are in the pom.xml.
Make sure the packaging type is war.
If there are multiple modules (IntelliJ), go into Run -> Edit configuration -> Configuration, and select or put $MODULE_WORKING_DIR$ in the 'Working directory'.
That's it.

I think you missed some configuration because it is easy to integrate JSP just follow below steps
1 - tomcat-embad-jasper dependency
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
2 - Add below configuration is application.properties
spring.mvc.view.prefix: /
spring.mvc.view.suffix: .jsp
That's it still have some doubt then check it out below link
Spring Boot and JSP Integration

The reason is because you are using the annotation #RestController instead of #Controller
When you annotate a class with RestController, all methods annotated with #RequestMapping assume #ResponseBody semantics by default. In other words, your method #index is serializing the String /webapp/WEB-INF/index.jsp as JSON, instead of mapping its value to a view.
Like mentioned in one of the answers, it has to be
#Controller
public class YourController {
...
}

I resolved my issue when in addition to described before:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
added ViewResolver:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#ComponentScan
#EnableWebMvc
public class SpringServletConfig {
#Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}
}
from: Why does Spring MVC respond with a 404 and report "No mapping found for HTTP request with URI [...] in DispatcherServlet"?

Just change the dependency
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
to
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>

Full gradle setup for Spring-Boot with Spring-MVC and with embedded Tomcat server:
build.gradle
buildscript {
ext {
springBootVersion = '1.5.8.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
//WEB-MVC
compile 'org.springframework.boot:spring-boot-starter-web:1.5.8.RELEASE'
compile 'org.apache.tomcat.embed:tomcat-embed-jasper:9.0.1'
compile 'javax.servlet:jstl:1.2'
App.class
#SpringBootApplication
public final class App {
public static void main(final String[] args) {
new SpringApplicationBuilder(App.class)
.build(args)
.run();
}
#Bean
public ViewResolver viewResolver() {
final InternalResourceViewResolver r = new InternalResourceViewResolver();
r.setPrefix("/WEB-INF/jsp/");
r.setSuffix(".jsp");
return r;
}
}

You need jsp compiler jar (tomcat-jasper) in class-path. Embedded tomcat does not come with it.
Remove tomcat-embed-jasper.jar if added already and add below
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>9.0.1</version>
</dependency>

As seen Spring and Spring Boot has been changing, here is an up-to-date solution.
build.gradle:
dependencies {
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.3.0.RELEASE'
compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '9.0.35'
}
IndexController.java looks as follows:
#Controller
public class IndexController {
#RequestMapping("/index")
public String index(Model model) {
model.addAttribute("name", "jancsi");
return "index";
}
}
WebConfig.java:
#Configuration
#EnableWebMvc
#ComponentScan
public class WebConfig implements WebMvcConfigurer {
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/views/", ".jsp");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
Here, instead of using WebMvcConfigurerAdapter, you should use WebMvcConfigurer interface, and do not to forget to enalbe the default servlet hander.
And then the structure of folders of jsp files.
src/main/webapp
└── WEB-INF
└── views
└── index.jsp

Sometimes tomcat-embed-jasper not available so need to remove provided from the maven dependency of tomcat-embed-jasper.
eg.
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<!--scope>provided</scope-->
</dependency>

If you want to use 1.5.8.RELEASE or similar, then, runable example and its explanation is in here https://www.surasint.com/spring-boot-jsp/
You just need this in pom.xml
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
org.springframework.boot
spring-boot-starter-parent
1.5.8.RELEASE
<groupId>com.surasint.example</groupId>
<artifactId>spring-boot-02</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JSP -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<!-- jstl for jsp -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
And this in application.properties
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
Then you keep your jsp in the /WEB-INF/jsp/ folder.
This is the controller.
package com.surasint.example.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Date;
import java.util.Map;
#Controller
public class TestController {
#GetMapping("/testjsp")
public String list(Map<String, Object> model) {
model.put("this_time",new Date().toString());
return "testjsp-view";
}
}

I had this problem and finally resolved it!
My problem was that I had been putting JSP code in my /WEB-INF/index.jsp page. However, this page is served directly, without being processed by any servlet or controller. Therefore, it had no chance of being compiled.
My solution:
Move index.jsp into a subfolder called views.
Edit web.xml so that it passes control of the root directory to the dispatcher servlet.
<!-- WEB-INF/web.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
<display-name>18-655_lab_1</display-name>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Edit dispatcher-servlet.xml to ensure that it's looking in the views directory for files ending in .jsp.
<!-- WEB-INF/dispatcher-servlet.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.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.xsd">
<mvc:annotation-driven />
<context:component-scan
base-package="com.app.controller" />
<mvc:default-servlet-handler />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
Using the same base-package path as specified in dispatcher-servlet.xml, create controller that will return a ModelAndView.
package com.app.controller;
#Controller
#RequestMapping(value = "/")
public class RootController {
#RequestMapping(method = RequestMethod.GET)
public ModelAndView homeGet() {
return new ModelAndView("index", "message", "IT WORKS!!!");
}
}
The syntax new ModelAndView("index", "message", "IT WORKS!!!") means that
dispatcher-servlet looks for a file called "/WEB-INF/views/" + "index" + ".jsp".
It compiles the jsp file, replacing all instances of ${message} with IT WORKS!!!.
Therefore, the final thing to do is to put ${message} somewhere in our index.jsp file.
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>${message}</h1>
</body>
</html>
Load the project into your Tomcat server, start it, and go to http://localhost:8080/[project name]/.

For me with Spring Boot version 1.5.10.RELEASE, it worked on adding below maven dependencies.
Note: worked only on not providing the <scope> for these two.
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<!--<scope>provided</scope>-->
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<!--<scope>provided</scope>-->
</dependency>
And providing below configuration in application.properties file
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp

I faced the issue like printed the jsp file name in the browser instead of its contents.
By adding the below snippet for jsp page rendering in pom.xml , it renders properly.
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>

<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherSe rvlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
I took the * off so it was just from web.xml
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherSe rvlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

Please consider, there are some JSP Limitations. You can not set the packaging of your pom to jar. Read this JSP Limitations

Related

JAVA Migration from jdk1.7 and weblogic 12c to jdk 1.8 and weblogic 14c

i ve migrate a web application from weblogic 12c and jdk1.7 to weblogic 14c and jdk1.8. The web application use jax-re for rest services and has the following custom JacksonContextProvider for mapping json:
package eu.sia.mdp.backoffice.common;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
/**
* ObjectMapper settings
*
* #author g.palladino
*
*/
#Provider
#Produces(MediaType.APPLICATION_JSON)
public class JacksonContextResolver implements ContextResolver<ObjectMapper> {
private final ObjectMapper objectMapper;
private static final Logger log = LoggerFactory.getLogger( JacksonContextResolver.class );
public JacksonContextResolver() {
this.objectMapper = new ObjectMapper().setSerializationInclusion(Include.NON_NULL);
// DATEFORMAT DF = NEW SIMPLEDATEFORMAT("YYYY-MM-DD HH:MM:SS.SSSZ");
// this.objectMapper.setDateFormat(df);
this.objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
this.objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT,true);
this.objectMapper.getSerializationConfig().getDateFormat().setTimeZone(TimeZone.getTimeZone("CET"));
}
#Override
public ObjectMapper getContext(Class<?> objectType) {
return null;
}
}
the application, for the webservices, use the jax-rs 2.0.1 and jersey 2.29 provided by server weblogic 14.1.1 (14c). In version built with jdk1.7 and deployed on server weblogic 12c the libraries was not provided by the server but put in pom file without scope provided and the custom ContextResolver was worked fine. Now, with provided libraries, the custom ContextResolver is completely ignored and the webservices return json in a format that is not as i want, for example the dates was in the format 'yyyy-MM-ddTHH:mm:ss.SSSZ' (2022-12-16T11:33:21.123 0100' and now I receive the dates in the format 'yyyy-MM-ddTHH:mm:ss.SSSZ [UTC]' (2022-12-16T11:33:21.123Z [UTC]) and if pass this date to a rest service in my application i have the type mismatch error. Seems that is used the server's ObjectMapper.
could someone help me figure out how to configure the weblogic.xml and/or web.xml files to pass the jax-rs and jersey libraries without provided scope in order to then use the custom ObjectMapper in the class JacksonContextResolver implements ContextResolver ObjectMapper and not the server ObjectMapper???
the current server is Weblogic 14.1.1.
pom file:
<!-- JAX-RS -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
<scope>provided</scope>
</dependency>
<!--<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1.1</version>
<scope>provided</scope>
</dependency>-->
<!-- CDI -->
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<!-- Jersey -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>${jersey.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
<version>${jersey.version}</version>
<scope>provided</scope>
</dependency>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
metadata-complete="false">
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>eu.sia.mdp.backoffice</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.tracing</param-name>
<param-value>ALL</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<mime-mapping>
<extension>json</extension>
<mime-type>application/json</mime-type>
</mime-mapping>
<resource-ref>
<description>Database MP</description>
<res-ref-name>jdbc/MPDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
weblogic.xml
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="...">
<container-descriptor>
<prefer-application-packages>
<package-name>org.slf4j.*</package-name>
<package-name>org.apache.commons.logging.*</package-name>
<package-name>com.sun.jersey.*</package-name>
<!--<package-name>org.glassfish.jersey.*</package-name>
<package-name>org.glassfish.hk2.*</package-name>-->
<package-name>org.jvnet.hk2.*</package-name>
<!--<package-name>jersey.repackaged.org.objectweb.asm.*</package-name>-->
<package-name>org.objectweb.asm.*</package-name>
<package-name>com.sun.ws.rs.ext.*</package-name>
<!--<package-name>javax.ws.rs.*</package-name>
<package-name>javax.validation.*</package-name>-->
<package-name>org.hibernate.validator.*</package-name>
</prefer-application-packages>
<prefer-application-resources>
<resource-name>org/slf4j/impl/StaticLoggerBinder.class</resource-name>
<resource-name>org.hibernate.validator.*</resource-name>
<resource-name>javax.validation.*</resource-name>
</prefer-application-resources>
</container-descriptor>
<context-root>mdp-portale-bo</context-root>
<library-ref>
<library-name>jax-rs</library-name>
<specification-version>2.0</specification-version>
<exact-match>false</exact-match>
</library-ref>
<resource-description>
<res-ref-name>jdbc/MDPDB</res-ref-name>
<jndi-name>jdbc/MDPDB</jndi-name>
</resource-description>
</weblogic-web-app>
Thanks

Adding Spring Security starter to my Spring Boot app automatically redirects all paths to one that's set in a completely different project

I added Spring Security Starter dependency (I use Maven) to secure my app (following a tutorial); the problem is that once I add it, whenever I go to localhost to check my progress, I'm always redirected to a path that's coded in another project (I can't even find the view right now).
I currently follow the tutorial on TutorialsPoint, but I use Spring Tools Suite 4 for adding dependencies, coding and running my Spring application instead of CLI on localhost:8080.
I tried finding the view in question, tinkering with another project's web.xml, but I can't find the source of the problem, all I know is that Spring Security Starter is somehow mucking it up.
Thymeleaf template
<!DOCTYPE html>
<html>
<head>
<meta charset = "ISO-8859-1" />
<link href = "css/styles.css" rel = "stylesheet"/>
<title>Spring Boot Application</title>
</head>
<body>
<h4>Welcome to Thymeleaf Spring Boot web application</h4>
</body>
</html>
Web controller
package com.example.vj7.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class WebController {
#RequestMapping(value = "/index")
public String index() {
return "index";
}
}
Application class
package com.example.vj7;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Vj7Application {
public static void main(String[] args) {
SpringApplication.run(Vj7Application.class, args);
}
}
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 http://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.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>vj7</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Vj7</name>
<description>Vježba 7</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
The expected result from "localhost:8080" is just a header "Demo" (like in index.html and set in web controller), but instead a form I worked on before on another Spring project shows up with path "/login".
You need to override some of web security's default configurations if you want index.html to be accessed without authorization. taken from https://docs.spring.io/spring-security/site/docs/4.2.5.RELEASE/apidocs/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.html
#Configuration
#EnableWebSecurity
public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/index").permitAll().anyRequest()
.permitAll();
}
}

CSS and JS file not loading while deploying war file on apache tomcat

was using the spring-boot-starter-web-mvc for initial development.When I deploy the war file on the server it is not loading css and js files, but when I run the same code using spring boot, it is working fine. Below is the directory structure and configuration loading the js and css file. Can anyone please let me know how to what is the problem ? Using only java based configuration for project. I have referred 8.1.1 in the doc before deploying the project and used the same pom file configuration as below.
Configuration file -
public class ViewWebAppConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// configuration for assets/ static files
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource rb = new ResourceBundleMessageSource();
rb.setBasenames(new String[] { "validation" });
return rb;
}
}
pom.xml file
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.4.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>
<log4j.version>2.7</log4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- Dependency for rendering jsp pages -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-compiler</artifactId>
<version>5.5.23</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-runtime</artifactId>
<version>5.5.23</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-compiler-jdt</artifactId>
<version>5.5.23</version>
<scope>provided</scope>
</dependency>
<!-- Dependency for rendering jsp pages -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
</dependencies>
Loading the js and css using spring-tags as below -
<%#taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<spring:url value="/resources/assets/js/custom.min.js" var="customJS" />
<script src="${customJS}"></script>
<link href="${customFieldAgent}" rel="stylesheet"/>
<spring:url value="/resources/assets/css/customfieldAgent.css" var="customFieldAgent" />
Below is the server log -
17:03:10.014 [http-nio-8080-exec-7] DEBUG
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
- Did not find handler method for [/${starrrJS}] 17:03:10.014 [http-nio-8080-exec-7] WARN
org.springframework.web.servlet.PageNotFound - No mapping found for
HTTP request with URI [/ui/$%7BstarrrJS%7D] in DispatcherServlet with
name 'dispatcher' 17:03:10.014 [http-nio-8080-exec-7] DEBUG
org.springframework.web.servlet.DispatcherServlet - Successfully
completed request 17:03:10.018 [http-nio-8080-exec-4] DEBUG
org.springframework.web.servlet.DispatcherServlet - DispatcherServlet
with name 'dispatcher' processing GET request for
[/ui/$%7BcustomJS%7D] 17:03:10.018 [http-nio-8080-exec-4] DEBUG
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
- Looking up handler method for path /${customJS} 17:03:10.019 [http-nio-8080-exec-4] DEBUG
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
- Did not find handler method for [/${customJS}] 17:03:10.019 [http-nio-8080-exec-4] WARN
org.springframework.web.servlet.PageNotFound - No mapping found for
HTTP request with URI [/ui/$%7BcustomJS%7D] in DispatcherServlet with
name 'dispatcher' 17:03:10.019 [http-nio-8080-exec-4] DEBUG
org.springframework.web.servlet.DispatcherServlet - Successfully
completed request
Try this way it is working for me.
Project Structure:
src/main/webapp/static/[css,js,images]
src/main/webapp/WEB-INF/views/[for all .jsp pages]
Configuration
#Configuration
#ComponentScan(basePackages = "parent package name where all packages reside")
public class ApplicationConfiguration extends WebMvcConfigurerAdapter {
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
registry.viewResolver(viewResolver);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// when static resources are inside resources folder under WEB-INF
// registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/");
// when static resources are inside static folder under webapp
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}
}
Let DispatcherServlet know how to pack things up...
import javax.servlet.Filter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { ApplicationConfiguration.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
Now call these on view like...
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<link href="<c:url value='/static/css/application.css' />" rel="stylesheet"></link>
</head>
Add this in your pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
Hope this will help you.
In my Spring Boot project,i tried to deploy as WAR file into TOMCAT,but it does not recognize the resource path,it throws 404 File not found error,But when i run as SpringBootApplication,it works properly,issue only when deploy as a WAR file into TOMCAT. so finally i revealed the issue now it works perfectly on my project structure
adding those lines into application.properties file
spring.resources.add-mappings=true
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/
i got from https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
it works perfectly...
for this js,images,css or from outside of the war file images or any file can be shown and also get access by using
this below line is common to two scenarios
spring.resources.add-mappings=true
For in the spring boot war file or any file of spring to get accessed or shown this u have to put in application.properties file or any property file
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/
For external access file or showing external files of images u may put as
spring.resources.static-locations=file:///C:/xxxxxxxxx/xxxxxxxxx
AS said vignesh R it was working great try it

I have an application to run with spring boot. I need to use hibernate with it. I get this exception

I have an application to run with spring boot. I need to use hibernate with it. I get this exception. I'm not sure about the configuration files I should have. Since I have searched so much and new to spring: I have pom.xml, and I don't know whether I should have web.xml or not. I need to get it work as soon as possible. this is my exception thrown:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'userController' defined in file
[C:\Users\Mehrnaz\JEEKeplerWorkspace\rest-stack\target\classes\com\jl\crm\contoller\UserController.class]:
Unsatisfied dependency expressed through constructor argument with index 0 of type
[com.jl.crm.services.CrmService]: : Error creating bean with name 'jpaCrmService' defined in file
[C:\Users\Mehrnaz\JEEKeplerWorkspace\rest-stack\target\classes\com\jl\crm\services\JpaCrmService.class]:
Unsatisfied dependency expressed through constructor argument with index 0 of type
[com.jl.crm.repository.CustomerRepository]: : No qualifying bean of type
[com.jl.crm.repository.CustomerRepository] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations: {};
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.jl.crm.repository.CustomerRepository]
found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations: {};
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'jpaCrmService' defined in file
[C:\Users\Mehrnaz\JEEKeplerWorkspace\rest-stack\target\classes\com\jl\crm\services\JpaCrmService.class]:
Unsatisfied dependency expressed through constructor argument with index 0 of type
[com.jl.crm.repository.CustomerRepository]: : No qualifying bean of type
[com.jl.crm.repository.CustomerRepository] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
=======
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>rest-stack</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.2.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</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-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- other project -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring3</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.1.Final</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.xsd">
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.jl.crm.services.ServiceConfiguration</param-value>
</context-param>
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<servlet-name>appServlet</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
I have log4j.properties:
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
# Root logger option
log4j.rootLogger=DEBUG,stdout
and Application.properties:
#
## Database configuration
#
spring.datasource.url= jdbc:mysql://localhost:3307/spring
spring.datasource.username= spring
spring.datasource.password= spring
spring.datasource.driverClassName= com.mysql.jdbc.Driver
spring.view.prefix=/WEB-INF/jsp/
spring.view.suffix=.jsp
this is service.configuration class, that I think may have problem:
#ComponentScan
#Configuration
#EnableJpaRepositories
public class ServiceConfiguration {
public static final String CRM_NAME = "crm";
/**
* The root directory to which all uploads for the application are uploaded.
*/
public static final File CRM_STORAGE_DIRECTORY = new File(
System.getProperty("user.home"), CRM_NAME);
/**
* Things are first uploaded by the application server to this directory. it's a sort
* of staging directory
*/
public static final File CRM_STORAGE_UPLOADS_DIRECTORY = new File(CRM_STORAGE_DIRECTORY, "uploads");
/**
* When a profile photo is uploaded, the resultant, completely uploaded image is
* stored in this directory
*/
public static final File CRM_STORAGE_PROFILES_DIRECTORY = new File(CRM_STORAGE_DIRECTORY, "profiles");
#PostConstruct
protected void setupStorage() throws Throwable {
File[] files = {CRM_STORAGE_DIRECTORY, CRM_STORAGE_UPLOADS_DIRECTORY, CRM_STORAGE_PROFILES_DIRECTORY};
for (File f : files) {
if (!f.exists() && !f.mkdirs()) {
String msg = String.format("you must create the profile photos directory ('%s') " +
"and make it accessible to this process. Unable to do so from this process.", f.getAbsolutePath());
throw new RuntimeException(msg);
}
}
}
#Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory( JpaVendorAdapter adapter, DataSource dataSource) {
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setPackagesToScan(User.class.getPackage().getName());
emf.setDataSource(dataSource);
emf.setJpaVendorAdapter(adapter);
return emf;
}
#Bean
PlatformTransactionManager transactionManager( EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
#Configuration
#Profile({"default", "test"})
static class DefaultDataSourceConfiguration {
private Log log = LogFactory.getLog(getClass());
#PostConstruct
protected void setupTestProfileImages() throws Exception {
long userId = 5;
File profilePhotoForUser5 = new File(ServiceConfiguration.CRM_STORAGE_PROFILES_DIRECTORY, Long.toString(userId));
if (!profilePhotoForUser5.exists()) {
// copy the profile photo back
String pathForProfilePhoto = "/sample-photos/spring-dog-2.png";
ClassPathResource classPathResource = new ClassPathResource(pathForProfilePhoto);
Assert.isTrue(classPathResource.exists(), "the resource " + pathForProfilePhoto + " does not exist");
OutputStream outputStream = new FileOutputStream(profilePhotoForUser5);
InputStream inputStream = classPathResource.getInputStream();
try {
IOUtils.copy(inputStream, outputStream);
} finally {
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
}
log.debug("setup photo " + profilePhotoForUser5.getAbsolutePath() + " for the sample user #" + Long.toString(userId) + "'s profile photo.");
}
if (!profilePhotoForUser5.exists()) {
throw new RuntimeException("couldn't setup profile photos at " + profilePhotoForUser5.getAbsolutePath() + ".");
}
}
}
}
#ComponentScan
#Configuration(basePackages = {"<Specify your base package here>"})
#EnableJpaRepositories
public class ServiceConfiguration {
---
}
you missed base package name for the componentscan annotation.

Spring DI - Autowired property is null in a REST service

I'm getting started with Spring DI, but I'm struggling with dependency injection and the worse part is that I'm not even sure why as it seems ok to me. Hopefully you guys can help me out!
The problem is that a property annotated as #Autowired is always null
I've got a few projects with Maven structure:
com.diegotutor.lessondeliver
com.diegotutor.utility
I'm running the examples over Tomcat 7
I'm using the following dependencies in my pom.xml:
spring-context 3.2.4
spring-web 3.2.4
jersey-server 1.17.1
jersey-core 1.17.1
jersey-servlet 1.17.1
The simple idea is to have a RESTful service that through Dependency Injection is able to print out the value of a property located in a config file located at: D:\configuracion.conf.
At com.diegotutor.utility I have the following interface:
package com.diegotutor.utility;
public interface ConfigService {
public String getProperty(final String propertyName);
}
Implemented by:
package com.diegotutor.utility.impl;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;
import com.diegotutor.utility.ConfigService;
public class PropertyFileConfigService implements ConfigService{
Properties prop;
public PropertyFileConfigService (final InputStream input) throws IOException {
if(input == null) {
throw new IllegalArgumentException("Input stream can't be null");
}
prop = new Properties();
prop.load(input);
}
public PropertyFileConfigService (final String fileName) throws IOException {
final FileInputStream input = new FileInputStream(fileName);
prop = new Properties();
prop.load(input);
}
public PropertyFileConfigService(final Reader input) throws IOException {
prop = new Properties();
prop.load(input);
}
public String getProperty(final String propertyName) {
return prop.getProperty(propertyName);
}
}
And at com.diegotutor.lessondeliver I have the RESTful service where I would like to use an injected instance of the ConfigService:
package com.diegotutor.lessondeliver;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.diegotutor.utility.ConfigService;
#Path("/")
#Component
public class HelloWorld {
private static final Log log = LogFactory.getLog(HelloWorld.class);
#Autowired
private ConfigService configService;
#Path("/helloworld")
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getHello() {
String host = configService.getProperty("host");
return "Hello World! HOST" + host;
// configService IS NULL!!
//SO IT THROWS A NULLPOINTER EXCEPTION WHEN INVOKING getProperty ON IT
}
}
Finally at /com.diegotutor.lessondeliver/src/main/webapp/WEB-INF/service-beans.xml I have the following XML application context file, where I use the implementation of ConfigService (PropertyFileConfigService) injecting on it the path for the configuration file to read:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="configService" class="com.diegotutor.utility.impl.PropertyFileConfigService">
<constructor-arg type="java.lang.String"
value="D:\configuracion.conf" />
</bean>
<context:component-scan base-package="com.diegotutor" />
</beans>
Obviously I have specified in the web.xml of this com.diegotutor.lessondeliver web app that I want service-beans.xml as ConfigLocation and a listener ContextLoaderListener, and the RESTful service relies on ServletContainer
If I'm specifying context:component-scan to look for Components in com.diegotutor as suggested here and I'm forcing object creation through Spring by not using any new Statement as suggested here, Why am I getting the annotated configService as null? Why Spring is unable to inject an instance of com.diegotutor.utility.impl.PropertyFileConfigService?
Any help will be much appreciated!
Thank you
EDITED:
As requested, my web.xml is as follows:
<?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"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>com.diegotutor.lessondeliver</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/service-beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
You were right!
It seems that the problem is that Jersey is totally unaware of Spring and instantiates its own object. In order to make Jersey aware of Spring object creations (through dependency injection) I had to integrate Spring + Jersey.
To integrate:
Add maven dependencies
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-spring</artifactId>
<version>1.17.1</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
</exclusions>
</dependency>
Use SpringServlet for jersey-servlet in web.xml
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>
com.sun.jersey.spi.spring.container.servlet.SpringServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
Now the #Autowired works properly and the object is not null anymore.
I'm a little bit confused about the exclusions I have to use in maven when using jersey-spring dependency, but that's another issue :)
Thank you!
Integration Spring with Jersey 2 (org.glassfish.*):
Maven
Some dependencies may be unnecessary, please check & clear it after things got working.
<properties>
<jersey.version>2.5</jersey.version>
</properties>
<!-- Jersey -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core" -->
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-inmemory</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- Jersey + Spring -->
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>${jersey.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>
web.xml
<servlet>
<servlet-name>my-rest-service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>my.package.with.rest.services</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>my-rest-service</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
applicationContext.xml
During the Spring upgrading I had to move it from /main/webapp/WEB-INF/ to /main/resources/ (details).
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config />
<context:component-scan base-package="my.package.with.rest.services" />
</beans>
Example REST service
public interface MyService
{
String work(String s);
}
...
#Service
public class MyServiceImpl implements MyService
{
#Override
public String work(String s)
{
return "Hello, " + s;
}
}
...
#Path("demo/")
#Component
public class DemoRestService
{
#Autowired
private MyService service;
#GET
#Path("test")
public Response test(#FormParam("param") String par)
{
try
{
String entity = service.work(par);
return Response.ok(entity).build();
}
catch (Exception e)
{
e.printStackTrace();
return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Epic REST Failure").build();
}
}
}
or you can simply extend SpringBeanAutoWiringSupport class. Like this: public class DemoRestService extends SpringBeanAutoWiringSupport. By extending this support class, properties of your service class can be auto-wired.
Another possible option is to manually invoke autowiring in your jersey resource:
#Context
private ServletContext servletContext;
#PostConstruct
public void init() {
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, servletContext);
}
Hmm, you get a "manual autowiring"...

Resources