users@jersey.java.net

[Jersey] Re: How to access a Spring bean from Jersey resource?

From: Frederic Bergeron <FBergeron_at_rocketmail.com>
Date: Wed, 6 Apr 2011 20:28:35 -0700 (PDT)

Hmmm, it seems that the Spring beans are never instanciated. I put a trace in my bean's constructor and it's never shown.

As in the Spring Annotations example, my test class looks like this:

public class RESTAPITest extends JerseyTest {

    public RESTAPITest() throws Exception {
        super( new WebAppDescriptor.Builder( "resource" ).
            contextPath( "/" ).
            contextParam( "contextConfigLocation", classpath:properties/servlet-applicationContext.xml" ).
            servletClass( SpringServlet.class ).
            contextListenerClass( ContextLoaderListener.class ).build());
    }

...

}

I was expecting that referring to SpringServlet class would trigger the beans instanciation but after putting a trace in SpringServlet, I know that the SpringServlet class is not even loaded.

So, how can Spring beans can be instanciated? Is it even possible to do so using the InMemoryTestContainerFactory?

Frederic Bergeron


--- On Wed, 4/6/11, Frederic Bergeron <FBergeron_at_rocketmail.com> wrote:

From: Frederic Bergeron <FBergeron_at_rocketmail.com>
Subject: [Jersey] Re: How to access a Spring bean from Jersey resource?
To: users_at_jersey.java.net
Date: Wednesday, April 6, 2011, 11:53 PM

Hi Tauren,

Thanks for your quick reply.  Your solution works when I'm using the real servlet but for some reasons, it doesn't work in my unit tests when I use the InMemoryTestContainerFactory. 

The error I got is this one:

--- BEGIN OUTPUT ---
INFO: Initiating Jersey application, version 'Jersey: 1.6 04/06/2011 10:19 PM'

Apr 6, 2011 10:30:36 PM com.sun.jersey.spi.inject.Errors processErrorMessages

SEVERE: The following errors and warnings have been detected with resource and/or provider classes:
  SEVERE: Missing dependency for field: private ItemImpl resource.MyResource.item

Apr 6, 2011 10:30:36 PM com.sun.jersey.test.framework.spi.container.inmemory.InMemoryTestContainerFactory$InMemoryTestContainer stop

INFO: Stopping low level InMemory test container
--- END OUTPUT ---

I've put
 some traces in Jersey code (1.6) and the error occurs in com.sun.jersey.server.spi.component.ResourceComponentInjector in the processFields() method.  In the for loop that process the parameters, the InjectableScopePair isp is null and that's what triggers the error. I don't understand why though. 

Anyone has an idea?

Regards,

Frederic Bergeron

--- On Tue, 4/5/11, Tauren Mills <tauren_at_groovee.com> wrote:

From: Tauren Mills <tauren_at_groovee.com>
Subject: Re: [Jersey] How to access a Spring bean from Jersey resource?
To: users_at_jersey.java.net
Cc: "Frederic Bergeron" <FBergeron_at_rocketmail.com>
Date: Tuesday, April 5, 2011, 7:36 PM

Frederic,
Add an @Component annotation to your resource class and then use @InjectParam to
 inject your beans:
@Component_at_Path("/resource")public class MyResource {


  @InjectParam  private MySpringBean bean;
  @GET  public Response doGet() {    bean.getSomething()    // ...  }

}
Your Spring configuration XML will need something like this in it:
    <!-- Enable annotation configuration -->    <context:annotation-config/>


    <context:component-scan base-package="com.company.rest.resources"/>
I might have missed something, but I think that's it.


Tauren


On Tue, Apr 5, 2011 at 2:02 AM, Frederic Bergeron <FBergeron_at_rocketmail.com> wrote:


Hi,



I'm implementing a REST API on top of a web application using the Spring framework.  I managed to implement interoperability between Jersey and Spring using the following method:



@GET

@Produces( MediaType.APPLICATION_XML )

public List<Item> getItems( @Context HttpServletRequest req ) {

    HttpSession ses = req.getSession( true );

    WebApplicationContext ctxt = WebApplicationContextUtils.getWebApplicationContext( ses.getServletContext() );

    ItemCatalogImpl itemCatalog = (ItemCatalogImpl)ctxt.getBean( "itemCatalog" );



    ...

}



My Jersey resource is able to access successfully a bean that has been instanciated by Spring.  Yeah!



However now, I would like to implement unit tests for my REST API using InMemoryTestContainerFactory.  My solution fails when using InMemoryTestContainerFactory.  I think the InMemoryTestContainerFactory is not able to instanciate/simulate the HttpServletRequest and I cannot access the servlet context that is required to get the WebApplicationContext.





Is there another way for my Jersey resource to access a Spring bean in both situations (real servlet and InMemoryTestContainerFactory)?  I suspect that there are many ways to do it but when I google about that, I'm a bit lost.  I have seen references to @Component, @Inject, @Autowire, and SpringServlet.  I have also seen that @Inject is deprecated in the 1.6's javadoc.  Which way is the best?  Any good links on this topic?





Regards,



Frederic Bergeron