RESTEasy won't match my Spring bean with custom Spring ContextLoader

  • RESTEasy 2.0.1GA
  • Java 1.6
  • Spring 3.0.3

I tried everything that I could, and I can not understand what is happening. I have a Spring MVC application, however I would like to have some RESTEasy endpoints accessible outside the Spring MVC application, but in the same container, ultimately able to connect to the same beans.

As a first step, I'm just trying to get RESTEasy inside a container, serving requests from a Spring-configured bean. I tried the template from the instructions and also tried manual configuration, but to no avail.

Bean

@Resource @Path("/") public class NeighborComparison { private String foo; @GET @Path(value="customer") @Produces("text/plain") public String getNeighborComparison() { return "foo"; } } 

web.xml

 <context-param> <param-name>resteasy.servlet.mapping.prefix</param-name> <param-value>/api</param-value> </context-param> <listener> <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class> </listener> <!-- NOT configuring SpringContextLoaderListener because I declare my own, so if I do, everything blows up, plus all it actually does is sanity check configuration --> <listener> <listener-class>com.example.MyCustomContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>Resteasy</servlet-name> <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> </servlet> <servlet-mapping> <servlet-name>Resteasy</servlet-name> <url-pattern>/api/*</url-pattern> </servlet-mapping> 

applicationContext.xml

 <bean id="resteasy.providerFactory" class="org.jboss.resteasy.spi.ResteasyProviderFactory" factory-method="getInstance"> </bean> <bean id="resteasy.dispatcher" class="org.jboss.resteasy.core.SynchronousDispatcher"> <constructor-arg ref="resteasy.providerFactory"/> </bean> <bean id="resteasy.spring.bean.processor" class="org.jboss.resteasy.plugins.spring.SpringBeanProcessor"> <description> Add Resources and @Providers to the appropriate places in Resteasy infrastructure </description> <constructor-arg ref="resteasy.dispatcher"/> </bean> <bean id="neighborComparison" class="opower.api.customer.neighbor_comparison.NeighborComparison"> </bean> 

According to the documentation, all I have to do is "manually register the RESTeasy BeanFactoryPostProcessor by allocating an instance of org.jboss.resteasy.plugins.spring.SpringBeanProcessor". I believe this Spring configuration does this.

Jetty starts and the application context rotates without problems. The application works fine, however, when I

 > curl -H"Accept: text/plain" localhost:8080/ei/api/customer 

("ei" is the application context). The magazine shows (this and only this):

 2011-03-29 16:44:24,153 DEBUG [qtp-575315405-0] [EI] [] [asy.core.SynchronousDispatcher] PathInfo: /customer 2011-03-29 16:44:24,156 DEBUG [qtp-575315405-0] [EI] [] [asy.core.SynchronousDispatcher] Failed executing GET /customer org.jboss.resteasy.spi.NotFoundException: Could not find resource for relative : /customer of full path: http://localhost:8080/ei/api/customer 

Even if I could convince RESTEasy to show me the mappings, it seems that he just did not find my bean.

If I explicitly map it using the resteasy.resources context parameter, it works, although it obviously does not have access to the automatically connected Spring beans.

Anything else I can try? I have a debug log in the entire RESTEasy code base, and I am not receiving any messages. I also confirmed that Spring essentially creates my bean, so RESTEasy just doesn't find it.

+6
java spring spring-mvc resteasy
source share
1 answer

Your resource class must be annotated with the @Path annotation for RESTeasy in order to pick it up at boot time:

 @Path("/customer") @Resource public class NeighborComparison { @GET @Path("/{customerId}") @Produces("text/plain") public String getNeighborComparison(@PathParam("customerId") long customerId) { return "foo"; } } 

Pay attention to the annotation @Path("/{customerId}} , without which your @PathParam parameter @PathParam not be displayed correctly, which would lead to a rather detailed exception (and an accompanying 500 response on the client side). Assuming the service is taken by RESTeasy, of course .

In addition, if you are not using RESTeasy SpringContextLoader , you must ensure that your SpringBeanProcessor instance SpringBeanProcessor registered in the ApplicationContext . RESTeasy delegates to it the registration of ApplicationListener in SpringContextLoader :

  ApplicationListener listener = new ApplicationListener() { public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextRefreshedEvent) { ContextRefreshedEvent cre = (ContextRefreshedEvent) event; ConfigurableListableBeanFactory autowireCapableBeanFactory = (ConfigurableListableBeanFactory) cre .getApplicationContext().getAutowireCapableBeanFactory(); new SpringBeanProcessor(dispatcher, registry, providerFactory) .postProcessBeanFactory(autowireCapableBeanFactory); } } }; configurableWebApplicationContext.addApplicationListener(listener); 

If you are using a custom context loader and not provided by RESTEasy, this code should appear somewhere in your context loader for everything to connect. A bit confusing, yes. This is a SpringBeanProcessor that goes through all Spring beans and registers RESTeasy for those who have the @Path annotation somewhere in their hierarchy (type and their corresponding interfaces).

+8
source share

All Articles