users@jersey.java.net

Jersey-Spring, _at_Context and InitializingBean

From: Patrick Dreyer <Patrick_at_Dreyer.name>
Date: Fri, 12 Feb 2010 09:47:52 +0100

Hi Jersey cracks

Unfortunately, Spring is calling InitializingBean.afterPropertiesSet()
BEFORE Jersey had it's chance to inject @Context fields, like "@Context
private ResourceContext resourceContext".
Thus, being in afterPropertiesSet(), the resourceContext field is not
set yet. As you'll see, as temporary workaround I'm currently calling
TaskDO.init() after creation through ResourceContext.
Is this behaviour by design or, what I hope, can you spot a
misunderstanding/misconfiguration on my side?
Below you'll find my Environment, Bean, Jersey Resource, web.xml and
applicationContext.xml

Environment:
=========
* JRE 1.6.0_18-b07
* JDK 1.6.0_17
* Apache Tomcat/6.0.20
* Jersey 1.1.5
* Spring 3.0.0-RELEASE
* Jersey-Spring 1.1.5

Bean implementing InitializingBean:
=======================
@Component @Scope("prototype")
public final class TaskDO implements InitializingBean
{
    private static Logger logger =
Logger.getLogger(TaskDO.class.getName());

    @Context private ResourceContext resourceContext;
    @FormParam("xml") private String xml;
   
    private TaskState state;

    @Override public void afterPropertiesSet() {
        int i = 0; // <-- ISSUE: resourceContext is not set yet; same
goes for xml
    }

    public TaskDO init() throws Exception {
        state = resourceContext.getResource(...); // <-- obviously
resourceContext is set now, same applies to xml
        return this;
    }
}

Jersey resource instantiating the Bean:
=========================
@Path("/tasks")
@Component @Scope("request")
public class TasksResource
{
    @Context private ResourceContext resourceContext;

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Produces(MediaType.APPLICATION_XHTML_XML)
    public Response createTaskXHtml() throws Exception {
        TaskDO task = resourceContext.getResource(TaskDO.class).init());
        ...
        return ...
    }
}

web.xml
======
<?xml version="1.0" encoding="UTF-8"?>
<web-app
        id="WebApp_ID"
        version="2.5"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        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_2_5.xsd">
    <display-name>...</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:log4j.properties</param-value>
    </context-param>

    <listener>
        
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
    <listener>
        
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>

    </listener>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

    <servlet>
        <servlet-name>jersey</servlet-name>
        
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
        <init-param>
            
<param-name>com.sun.jersey.config.property.JSPTemplatesBasePath</param-name>
            <param-value>/WEB-INF</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey</servlet-name>
        <url-pattern>/ws/*</url-pattern>
    </servlet-mapping>
</web-app>

applicationContext.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: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:component-scan base-package="..."/>
</beans>


Regards
---
Patrick Dreyer