Multiple resouceBean configuration in CXF using Spring - spring

I'm using CXF RS 2.5.1 with Spring 3.0.6-RELEASE. I would like to have multiple implementation classes for "a single endpoint". I see that this issue was reported and fixed https://issues.apache.org/jira/browse/CXF-2439, however, when I try to do it, CXF just selects the first resource class from jaxrs:serviceBeans tag. For the other request, I see this message on tomcat console as "No operation matching request path /account/rest/transfer is found". Below is the configuration. Appreciate any input.
web.xml
<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:account-servlet.xml</param-value>
</context-param>
<servlet>
<servlet-name>CXF Servlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXF Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
account-servlet.xml
<jaxrs:server id="accountService" address="/rest">
<jaxrs:serviceBeans>
<ref bean="transferService" />
<ref bean="balanceService"/>
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="xml" value="application/xml" />
</jaxrs:extensionMappings>
</jaxrs:server>
<bean id="transferService" class="com.mycompany.service.TransferService"/>
<bean id="balanceService" class="com.mycompany.service.BalanceService"/>
BalanceService.java (imports omitted)
package com.mycompany.service;
#Path("/")
#Produces("application/xml")
public class BalanceService{
#GET
#Path("/balance")
public String getBalance() {
StringBuilder response = new StringBuilder(128);
response.append("<Balance>")
.append("<amount>").append("250.00").append("</amount>")
.append("</Balance>");
return response.toString();
}
}
TransferService.java (imports omitted)
package com.mycompany.service;
#Path("/")
#Produces("application/xml")
public class TransferService {
#GET
#Path("/transfer")
public String getTransfer() {
StringBuilder response = new StringBuilder(128);
response.append("<Transfer>")
.append("<amount>").append("350.00").append("</amount>")
.append("</Transfer>");
return response.toString();
}
}
Please ignore any programming irregularities/standards as it's just a sample app for the POC.

I solved this problem by moving part of the #Path mapping to the service bean class. In your case:
BalanceService
#Path("/balance")
#Produces("application/xml")
public class BalanceService {
#GET
#Path("/{id}")
public String getBalance(#PathParam("id") long id) {
...
}
}
TransferService
#Path("/transfer")
#Produces("application/xml")
public class TransferService {
#GET
#Path("/{id}")
public String getTransfer(#PathParam("id") long id) {
...
}
}

So I spend some time searching the internet but found no solution to this problem. There is a note written in the documentation that can be used to deduce the solution.
http://cxf.apache.org/docs/jax-rs-basics.html#JAX-RSBasics-Customselectionbetweenmultipleresources
Hence I wrote a custom resource comparator, did the appropriate jaxrs:server configuration and Eureka! it worked!. Now, I have 2 implementation classes mapped to a single resource/address in javax:rs address.
Please be advised that logic in custom resource comparator shown below may vary based on the URL pattern.
Providing source of all the files. Hope that this will help someone in future :)
web.xml
<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/account-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>CXF Servlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXF Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
account-servlet.xml (applicationContext)
<beans>
<jaxrs:server id="accountService" address="/rest">
<jaxrs:serviceBeans>
<ref bean="accountServiceImpl" />
<ref bean="transferServiceImpl" />
</jaxrs:serviceBeans>
<jaxrs:resourceComparator>
<bean id="accountServiceComparator" class="com.etrade.comparator.AccountServiceComparator"/>
</jaxrs:resourceComparator>
<jaxrs:extensionMappings>
<entry key="xml" value="application/xml" />
</jaxrs:extensionMappings>
</jaxrs:server>
<bean id="accountServiceImpl" class="com.etrade.service.AccountService" />
<bean id="transferServiceImpl" class="com.etrade.service.TransferService" />
</beans>
pom.xml
<modelVersion>4.0.0</modelVersion>
<groupId>cxf.rest</groupId>
<artifactId>account</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>account Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-bundle-jaxrs</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<!-- This plugin is needed for the servlet example -->
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>7.2.0.v20101020</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution><goals><goal>java</goal></goals></execution>
</executions>
</plugin>
</plugins>
<finalName>account</finalName>
</build>
</project>
Custom Resource comparator
package com.etrade.comparator;
import java.lang.reflect.Method;
import javax.ws.rs.Path;
import org.apache.cxf.jaxrs.ext.ResourceComparator;
import org.apache.cxf.jaxrs.impl.UriInfoImpl;
import org.apache.cxf.jaxrs.model.ClassResourceInfo;
import org.apache.cxf.jaxrs.model.OperationResourceInfo;
import org.apache.cxf.message.Message;
public class AccountServiceComparator implements ResourceComparator{
public int compare(ClassResourceInfo arg0, ClassResourceInfo arg1,
Message message) {
UriInfoImpl uriInfo = new UriInfoImpl(message);
String path = uriInfo.getPath();
String[] pathArray = path.split("/");
String resourceUrlName = pathArray[1];
System.out.println("Path : "+resourceUrlName);
Method[] methods = arg0.getServiceClass().getMethods();
int value = 1;
String resource = null;
for(Method method : methods) {
Path annotationPath = method.getAnnotation(javax.ws.rs.Path.class);
if(null != annotationPath){
String pathValue = annotationPath.value();
String[] parts = pathValue.split("/");
resource = parts[1];
System.out.println("resource : "+resource);
}
if(resourceUrlName.contains(resource)){
value = -1;
}
}
return value;
}
public int compare(OperationResourceInfo arg0, OperationResourceInfo arg1,
Message arg2) {
return 0;
}
}
Implementation classes/beans
AccountService.java
package com.etrade.service;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
#Path("/account")
#Produces("application/xml")
public class AccountService {
#GET
#Produces("application/xml")
#Path("/balance/{id}")
public String accountBalance(#PathParam("id") long id) {
System.out.println("id : "+id);
StringBuilder response = new StringBuilder(256);
response.append("<Response>").append("<id>").append(id)
.append("</id>").append("<balance>").append("250.00").append("</balance>")
.append("</Response>");
return response.toString();
}
}
TransferService.java
package com.etrade.service;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
#Path("/account")
#Produces("application/xml")
public class TransferService {
#GET
#Produces("application/xml")
#Path("/transfer/{id}")
public String accountTransfer(#PathParam("id") long id) {
System.out.println("transfer id : "+id);
StringBuilder response = new StringBuilder(256);
response.append("<Response>").append("<id>").append(id)
.append("</id>").append("<transfer>").append("250.00").append("</transfer>")
.append("</Response>");
return response.toString();
}
}
URLs:
http://localhost:8080/rest/account/balance/12
http://localhost:8080/rest/transfer/balance/13

You can probably simplify the logic to do with comparing the root resources, example, knowing the request URI and the name of the root resource class can be sufficient to make the decision, checking the individual methods looks complicated. BTW, the custom resource comparators are only needed when either root resources and/or individual resource methods can become the equal candidates

I'd solve the problem this way:
Removing a "Custom Resource Comparator" (there's no need to)
Removing this:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-bundle-jaxrs</artifactId>
<version>2.5.0</version>
</dependency>
In the account-servlet.xml/applicationContext:
<beans>
<jaxrs:server id="accountService" address="/rest">
<jaxrs:serviceBeans>
<ref bean="accountServiceImpl" />
<ref bean="transferServiceImpl" />
</jaxrs:serviceBeans>
</jaxrs:server>
</beans>
In the beans/class implementation:
...
#Context("accountServiceImpl")
#Path("/account")
public class Accountservice{
...
And that's all. :)

Related

#Service Spring as Managed property of ManagedBean class in jsf is null

I've a webapp using JSF + Spring + Maven + JBoss (java 8).
I've a class ManagedBean with a property ManagedProperty which is a service spring.
In remote debugging I checked that the service is not injected and is null.
No errors in console (or server.log).
java class
#ManagedBean(name = "userBean")
#SessionScoped
public class UserBean implements Serializable {
...
#ManagedProperty(value = "#{loggedUserSession}")
private ILoggedUserSession loggedUserSession;
public String getUserLogin() {
return loggedUserSession.getUser();
}
public ILoggedUserSession getLoggedUserSession() {
return loggedUserSession;
}
public void setLoggedUserSession(ILoggedUserSession loggedUserSession) {
this.loggedUserSession = loggedUserSession;
}
...
}
service java class
#Service("loggedUserSession")
#Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class LoggedUserSessionImpl implements ILoggedUserSession, Serializable {...}
pom.xml
...
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.13</version>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>6.2</version>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0.SP1</version>
</dependency>
...
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
In the applicationContext.xml i mapped <context:component-scan ... /> and
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:conf.properties</value>
</property>
</bean>
I noticed the error at runtime.
I checked in web.xml, faces-config, applicationContext.xml and pom.xml but I didn't find anything strange.

Error creating bean 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#1'

I'm trying to create a web-app, using Maven and Intellij Idea. Tests work fine as installing in .war-file. But when I try to refer to my rest with jetty, I have lots of error cases:
Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#1' defined in ServletContext resource [/WEB-INF/rest-spring.xml]: Initialization of bean failed;
nested exception is java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonProcessingException
Here are rest module files:
Web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5"
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_2_5.xsd">
<servlet>
<servlet-name>restDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--the location of the spring context configuration file-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/rest-spring.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>restDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
rest-spring.xml
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.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/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:model.properties</value>
<value>classpath:database.properties</value>
<value>classpath:automobile.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath*:create-tables-model.sql"/>
<jdbc:script location="classpath*:create-tables-automobile.sql"/>
<jdbc:script location="classpath*:data-script.sql"/>
</jdbc:initialize-database>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonConverter"/>
</list>
</property>
</bean>
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
<property name="prettyPrint" value="true" />
</bean>
<bean id="modelDao" class="com.dao.ModelDaoImpl">
<constructor-arg ref="dataSource" />
</bean>
<bean id="automobileDao" class="com.dao.AutomobileDaoImpl">
<constructor-arg ref="dataSource" />
</bean>
<bean id="modelService" class="com.service.ModelServiceImpl">
<property name = "modelDao" ref = "modelDao"/>
</bean>
<bean id="automobileService" class="com.service.AutomobileServiceImpl">
<property name = "automobileDao" ref = "automobileDao"/>
</bean>
<context:component-scan base-package="com.rest"/>
</beans>
ModelRestController
package com.rest;
import com.dto.ModelDto;
import com.general.Model;
import com.service.ModelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List;
/**
* Created by kohtpojiep on 23.01.16.
*/
#RestController
public class ModelRestController
{
private static final Logger LOGGER = LogManager.getLogger();
#Autowired
private ModelService modelService;
#RequestMapping(value="/models", method = RequestMethod.GET)
public #ResponseBody List<Model> getAllModels()
{
LOGGER.debug("Getting all models");
return modelService.getAllModels();
}
#RequestMapping(value="/model", method = RequestMethod.POST)
#ResponseStatus(value = HttpStatus.CREATED)
public #ResponseBody Integer addModel(#RequestBody Model model)
{
LOGGER.debug("Adding model modelName = {}", model.getModelName());
return modelService.addModel(model);
}
#RequestMapping (value="/model/{modelId}/{modelName}", method=RequestMethod.PUT)
#ResponseStatus(value = HttpStatus.ACCEPTED)
public #ResponseBody void updateModel(#PathVariable(value="modelId") Integer modelId,
#PathVariable(value="modelName") String modelName)
{
LOGGER.debug("Updating model modelId = {}", modelId);
modelService.updateModel(new Model(modelId,modelName));
}
#RequestMapping (value="/model/{modelName}", method = RequestMethod.DELETE)
#ResponseStatus(value = HttpStatus.NO_CONTENT)
public #ResponseBody void deleteModelByName(#PathVariable(value = "modelName") String modelName)
{
LOGGER.debug("Deleting model modelName= {}",modelName);
modelService.deleteModelByName(modelName);
}
#RequestMapping (value="/modelsdto", method = RequestMethod.GET)
#ResponseStatus(value = HttpStatus.OK)
public #ResponseBody
ModelDto getModelsDto()
{
LOGGER.debug("Getting models Dto");
return modelService.getModelDto();
}
}
AutomobileRestController
package com.rest;
import com.dto.AutomobileDto;
import com.general.Automobile;
import com.service.AutomobileService;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List;
/**
* Created by kohtpojiep on 02.02.16.
*/
#RestController
public class AutomobileRestController
{
private static final Logger LOGGER = LogManager.getLogger();
#Autowired
AutomobileService automobileService;
private static LocalDate convertToLocalDate(String date)
{
DateTimeFormatter formattedDate = DateTimeFormat.forPattern("dd/MM/yyyy");
return formattedDate.parseLocalDate(date);
}
#RequestMapping(value = "/automobiles", method = RequestMethod.GET)
#ResponseStatus(value = HttpStatus.ACCEPTED)
public #ResponseBody List<Automobile> getAllAutomobiles()
{
LOGGER.debug("Getting all automobiles");
return automobileService.getAllAutomobiles();
}
#RequestMapping(value = "/automobile", method = RequestMethod.POST)
#ResponseStatus(value = HttpStatus.CREATED)
public #ResponseBody Integer addAutomobile (#RequestBody Automobile automobile)
{
LOGGER.debug("Adding automobile modelName = {}",automobile.getModelName());
return automobileService.addAutomobile(automobile);
}
#RequestMapping(value = "/automobile/update", method = RequestMethod.PUT)
#ResponseStatus(value = HttpStatus.ACCEPTED)
public #ResponseBody void updateAutomobile (#RequestBody Automobile automobile)
{
LOGGER.debug("Updating automobile automobileId = {}", automobile.getAutomobileId());
automobileService.updateAutomobile(automobile);
}
#RequestMapping(value = "/automobile/{automobileId}", method = RequestMethod.DELETE)
#ResponseStatus(value = HttpStatus.NO_CONTENT)
public #ResponseBody void depeteAutomobile (#PathVariable (value="automobileId")
Integer automobileId)
{
LOGGER.debug("Deleting automobile automobileId = {}",automobileId);
automobileService.deleteAutomobileById(automobileId);
}
#RequestMapping(value = "/automobiles/date-sort", method = RequestMethod.GET)
#ResponseStatus(value = HttpStatus.ACCEPTED)
public #ResponseBody List<Automobile> getAutomobilesSortedByDate (#RequestParam(value="firstDate")
String firstDate, #RequestParam (value="lastDate") String lastDate)
{
LOGGER.debug("Getting automobiles sorted by date:\n");
return automobileService.getAutomobilesSortedByDate(
convertToLocalDate(firstDate),convertToLocalDate(lastDate));
}
#RequestMapping(value = "/automobilesdto", method = RequestMethod.GET)
#ResponseStatus(value = HttpStatus.OK)
public #ResponseBody
AutomobileDto getAutomobileDto()
{
LOGGER.debug("Getting automobile DTO");
return automobileService.getAutomobileDto();
}
}
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">
<parent>
<artifactId>usermanagement</artifactId>
<groupId>com.epam.brest.course2015</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>app-rest</artifactId>
<name>${project.artifactId}</name>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>com.epam.brest.course2015</groupId>
<artifactId>app-service</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.16.v20140903</version>
<configuration>
<stopPort>9091</stopPort>
<stopKey>STOP</stopKey>
<webAppConfig>
<contextPath>/rest</contextPath>
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
</webAppConfig>
<scanIntervalSeconds>10</scanIntervalSeconds>
<connectors>
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<port>8081</port>
</connector>
</connectors>
</configuration>
</plugin>
</plugins>
</build>
</project>
I saw solutions for similar situations: people offer to change versions of used frameworks and up the search level of component scan, but it doesn't work for me.
Add dependency to your POM:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
As you use dependency management in parent POM, there is no need to specify version.
Solved! The problem was I use not only jackson-core dependency, but also jackson databind, datatype and annotations and these dependencies had different versions: 2.7.1 for "core" and 2.4.3 for other ones. Now I use the same version for all of them and thus adding dependency had an affect. Thx for your help!)
I had the same problem. I used spring version 5.0.5.RELEASE and Jackson Core version 2.4.3.
I upgraded Jackson core up to 2.9.5 and it works now : exception "Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter' " dissapeared and my rest service works.
Before in my pom.xml :
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.3</version>
</dependency>
After :
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
I hope it will help.
Yes. Using version 2.9.5 works:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
I'm using spring-webmvc: 5.0.12.RELEASE, if that helps.

Getting Null Pointer Exception implementing JAX_RS

I am new to JAX-RS. I am doing CRUD operation using JAX_RS. CRUD operation is working fine for JSF but when I call fetchAll() method present in Service layer using JAX-RS I am getting a NullPointerException.
Below is my JAX_RS code
package com.resource;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.neorays.resource.entity.Person;
import com.neorays.resource.service.PersonService;
#Path("/persons")
public class MyResource {
PersonService ser = new PersonService();
#GET
#Path("/pers")
#Produces(MediaType.APPLICATION_JSON)
public List<Person> getAllPerson() {
List<Person> list = null;
try {
list = ser.fetchAll();
for (Person person : list) {
person.getId();
System.out.println("person id is" + person.getId());
System.out.println("person name is" + person.getName());
System.out.println("person country is" + person.getCountry());
}
} catch (NullPointerException ne) {
System.out.println("null pt is occuring" + ne);
}
return list;
}
}
This is my Service Layer
package com.resource.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.neorays.resource.bean.PersonBean;
import com.neorays.resource.dao.PersonDao;
import com.neorays.resource.entity.Person;
#Component
#Transactional
public class PersonService
{
#Autowired
private PersonDao dao;
#Transactional
public List<Person> fetchAll()
{
return dao.fetchAll();
}
}
This is my DAO layer
package com.resource.dao;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.neorays.resource.bean.PersonBean;
import com.neorays.resource.entity.Person;
#Repository
public class PersonDao
{
#Autowired
private SessionFactory sessionFactory;
public List<Person> fetchAll()
{
Session ses = sessionFactory.getCurrentSession();
String query="from Person";
Query query2 =ses.createQuery(query);
List<Person> list = query2.list();
return list;
}
}
This is my web.xml
<?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_2_5.xsd"
version="2.5">
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.neorays.resource</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/webapi/*</url-pattern>
</servlet-mapping>
</web-app>
This is my pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.resource</groupId>
<artifactId>jsf_jaxrs</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<finalName>jsf_jaxrs</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
</dependency>
<!-- uncomment this to get JSON support -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.10.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<properties>
<jersey.version>2.16</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
Finally, this is my Bean
package com.neorays.resource.entity;
import java.io.Serializable;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
#Entity
#NamedQuery(name="Person.findAll", query="SELECT p FROM Person p")
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String country;
private String name;
public Person() {
}
public Person(int id, String country, String name) {
super();
this.id = id;
this.country = country;
this.name = name;
}
#Id
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getCountry() {
return this.country;
}
public void setCountry(String country) {
this.country = country;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
Your dependency injection is not constructed correctly. All of your beans must be created by Spring. If your applicationContext.xml file scan necessary packages (for services and daos at least), and if your hibernate session factory created correctly and since you already tell jersey to scan package for rest services this should work.
#Component
#Path("/persons")
public class MyResource {
#Autowired
PersonService ser;
...
}
Update
I just realise package name in web.xml and your rest service are different.
<?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_2_5.xsd"
version="2.5">
....
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.resource</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/webapi/*</url-pattern>
</servlet-mapping>
....
</web-app>
If jersey-spring3 is missing in your class path you can add it using maven.
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>${jersey.version}</version>
</dependency>
You can find additional info on jersey documentation.

Autowired Object is coming out null for a web project

I am always getting autowired object null, please help. From logs beans were initialized properly.
===================================================================================
web.xml
<?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" id="WebApp_ID" version="3.0">
<display-name>RestfulService</display-name>
<!-- <welcome-file-list>
<welcome-file>Readme.html</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list> -->
<servlet>
<servlet-name>Jersey 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>com.restfulservice.gateway</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/ApplicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
==========================================================================================
applicationcontext.xml
<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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- <bean
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/> -->
<context:component-scan base-package="com.restfulservice" />
<context:annotation-config/>
<!-- <context:property-placeholder location="classpath:testme.properties" /> -->
<bean id="incomingCall" class="com.restfulservice.gateway.IncomingCall" />
<bean id="testPropertyRead1" class="com.restfulservice.gateway.TestPropertyRead">
<property name="name" value="${name}"/>
<property name="address" value="${address}"/>
</beans>
===========================================================================================
incomingcall.java
package com.restfulservice.gateway;
import java.io.File;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
//#Path("/v1/status/*")
#Path("/v1status")
#Component
public class IncomingCall {
final static Logger logger = Logger.getLogger(IncomingCall.class);
public static final String Version = "0.0.1";
#Autowired
#Qualifier("testPropertyRead1")
private TestPropertyRead testPropertyRead;
public TestPropertyRead getTestPropertyRead() {
return testPropertyRead;
}
public void setTestPropertyRead(TestPropertyRead testPropertyRead) {
this.testPropertyRead = testPropertyRead;
}
#GET
#Produces(MediaType.TEXT_HTML)
public String returnTitle()
{
logger.debug("inside returnTitle function call");
return "<p> Java Rest Web Service JSB ....</p>";
}
#Path("/version")
#GET
#Produces(MediaType.TEXT_HTML)
public String returnVersion()
{
return "<p> Java Rest Web Service JSB ....</p>" + "Version:" + Version;
}
#Path("/testspring")
#GET
#Produces(MediaType.TEXT_HTML)
public String testSpring()
{
logger.debug("inside testSpring function call");
logger.info("sai baba is awesome he is making me work, he is my energy");
ApplicationContext context = new ClassPathXmlApplicationContext(
"SpringBeans.xml");
TestSpringSimple obj = (TestSpringSimple) context.getBean("testsprings1");
obj.printHello();
logger.info("going to call callhibernate");
obj.callHibernate();
logger.info("called callhibernate");
return "<p> Java Rest Web Service JSB ...testing spring</p>";
}
#Path("/testconfigreader")
#GET
#Produces(MediaType.TEXT_HTML)
public String testConfigReader()
{
logger.debug("inside testConfigReader function call");
/*ApplicationContext context = new ClassPathXmlApplicationContext(
"ApplicationContext.xml");
TestPropertyRead obj = (TestPropertyRead) context.getBean("testconfig");
*/
//TestPropertyRead testconfig = (TestPropertyRead) TestPropertyRead.getBean("testconfig");
return "<p> Java Rest Web Service JSB ...testing spring config reader "+ testPropertyRead.printAll()
+ "</p>";
//return "<p> Java Rest Web Service JSB ...testing spring config reader "+ ((TestPropertyRead)TestPropertyRead.getBean("testconfig")).printAll()+ "</p>";
}
/**
* Similarly one can download text data also
* #return
*/
#Path("/downloadimage")
#GET
#Produces("image/png")
public Response downloadimage()
{
logger.debug("inside downloadimage function call");
File file = new File("C:\\swamishiva.jpg");
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition",
"attachment; filename=image_from_server.png");
return response.build();
}
}
===============================================================================
testpropertyRead.java
package com.restfulservice.gateway;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
#Component
public class TestPropertyRead
{
//private static ApplicationContext CONTEXT;
private String name;
private String address;
public TestPropertyRead()
{
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String printAll() {
System.out.println("name:" + name + " Address:" + address);
return "name:" + name + " Address:" + address;
}
}
I am pretty new to spring but generally find that when I have null pointers for Autowired properties it is because the component scan is failing.
Perhaps have a look at this question Spring Boot MVC and check if anything helps?
One I always forget about is #EnableAutoConfiguration.
Pom Need support of rest and spring integration:
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>2.4.1</version>
<exclusions>
<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>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.4.1</version>
</dependency>

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