users@jersey.java.net

Re: [Jersey] Jersey-Spring, _at_Context and InitializingBean

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Fri, 12 Feb 2010 10:34:50 +0100

Hi Patrick,

This is an issue with the Jersey/Spring integration.

Jersey gets a reference to the Spring bean and then performs its own
injection. It currently does not register a bean post process listener
or something like that (i cannot remember the exact name) to perform
injection at the appropriate stage in the spring bean construction
process.

Jersey does have framework support to integrate in such a manner as it
uses that for integration with CDI and EJBs so i think it should be
possible to support this properly with Spring. Gonna require a little
experimentation as my Spring knowledge is rusty. Could you log an issue?


A alternative work around may be to use setter methods:

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

   @FormParam("xml") private String xml;

   private TaskState state;

   @Context
   public void setTask(ResourceContext resourceContext) {
       state = resourceContext.getResource(...);
   }
}

JAX-RS setter methods are called after injection onto fields is
performed.


If TasksResource, TaskDO and TaskState are spring-managed beans you
may be able to use spring auto-wiring rather than use ResourceContext.

If you need the TaskDO instance to be created only for the resource
method "createTaskXHtml" rather than being created at class
construction you can do:

public Response createTaskXHtml(@com.sun.jersey.spi.inject.Inject
TaskDO t) {
   ...
}


The @Inject essentially does the same thing as one can do
programatically using ResourceContext. Also if using Jersey >= 1.1.4.1
you can do:

   @Inject Injectable<TaskDO> it;

   public Response createTaskXHtml() {
     TaskDO t = it.get();
   }

which also allows you to inject per-request or prototype scoped
references onto singletons.

Hth,
Paul.

On Feb 12, 2010, at 9:47 AM, Patrick Dreyer wrote:

> 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
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>