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