Spring DI - Autowired property is null in a REST service
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);}...@Servicepublic class MyServiceImpl implements MyService{ @Override public String work(String s) { return "Hello, " + s; }}...@Path("demo/")@Componentpublic 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.