RESTEasy 不会使用自定义 Spring ContextLoader 映射我的 Spring bean
- RESTEasy 2.0.1GA
- Java 1.6
- Spring 3.0.3
我已经尝试了一切,但无法弄清楚发生了什么。我有一个 Spring MVC 应用程序,但是我希望在 Spring MVC 应用程序外部有一些可用的 RESTEasy 端点,但在同一个容器中,最终能够连接到相同的 bean 中。
第一步,我只是尝试在容器内建立 RESTEasy,为来自 Spring 配置的 bean 的请求提供服务。我已经尝试了说明中的样板,也尝试了手动设置,但无济于事。
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's infrastructure
</description>
<constructor-arg ref="resteasy.dispatcher"/>
</bean>
<bean id="neighborComparison" class="opower.api.customer.neighbor_comparison.NeighborComparison">
</bean>
根据文档,我所要做的就是“通过分配 org.jboss.resteasy.plugins 的实例来手动注册 RESTeasy BeanFactoryPostProcessor” .spring.SpringBeanProcessor”。我相信这个弹簧配置可以做到这一点。
Jetty 启动并且应用程序上下文旋转起来没有任何问题。应用程序正常工作,但是当我
> curl -H"Accept: text/plain" localhost:8080/ei/api/customer
(“ei”是应用程序上下文)时。日志显示(仅此而已):
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
即使我可以说服 RESTEasy 向我显示映射,它似乎也没有发现我的 bean。
如果我通过resteasy.resources上下文参数显式映射它,它就可以工作,尽管显然无法访问自动连接的Spring bean。
我还能尝试什么吗?我有整个 RESTEasy 代码库的调试日志,但没有收到任何消息。我还确认 Spring 实际上正在创建我的 bean,所以只是 RESTEasy 没有找到它。
- RESTEasy 2.0.1GA
- Java 1.6
- Spring 3.0.3
I have tried everything I can, and cannot make head or tail of what's going on. I have a Spring MVC application, however I'd like to have some RESTEasy endpoints available outside the Spring MVC app, but in the same container, ultimately being able to wire in the same beans.
As a first step, I'm simply trying to stand-up RESTEasy inside the container, serving requests from a Spring-configured bean. I have tried the boilerplate from the instructions and have also tried manual setup, 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's 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 that.
Jetty starts and the app context spins up with no issues. Application works normally, however when I
> curl -H"Accept: text/plain" localhost:8080/ei/api/customer
("ei" is the application context). The log 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 it's just not discovering my bean.
If I map it explicitly via the resteasy.resources
context param, it works, though obviously doesn't have access to auto-wired Spring beans.
Anything else I can try? I have debug log on the entire RESTEasy codebase and I don't get any messages. I've also confirmed that Spring is, in fact, creating my bean, so it's just that RESTEasy isn't finding it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的资源类需要使用
@Path
注释进行注释,以便 RESTeasy 在引导期间获取它:请注意
@Path("/{customerId}}
注释,如果没有该注释,您的资源类将无法使用该注释。 该服务由 RESTeasy 获取。@PathParam
参数将无法正确映射,从而导致非常详细的异常(以及客户端上附带的 500 响应)当然,假设 不要使用 RESTeasy 的SpringContextLoader
,您必须确保您的SpringBeanProcessor
实例已通过注册ApplicationContext
委托给它。SpringContextLoader
中的 code>ApplicationListener:如果使用自定义上下文加载器而不是 RESTEasy 提供的加载器,则此代码必须出现在上下文加载器中的某个位置,以便一切都有点复杂,是的,
SpringBeanProcessor
遍历所有 Spring bean,并向 RESTeasy 注册那些在其层次结构中具有@Path
注释的 bean。类型及其相应的接口)。Your resource class needs to be annotated with
@Path
annotation for RESTeasy to pick up on it during bootstrap:Note the
@Path("/{customerId}}
annotation without which your@PathParam
parameter would not have been mapped correctly, resulting in a pretty detailed exception (and an accompanying 500 response on the client side). Assuming the service is picked up by RESTeasy of course.In addition if you don't use RESTeasy's
SpringContextLoader
, you have to make sure yourSpringBeanProcessor
instance is registered with theApplicationContext
. RESTeasy delegates to it by registering anApplicationListener
inSpringContextLoader
:If using a custom context loader and not the RESTEasy-provided one, this code has to appear somewhere in your context loader so that everything gets wired up. A bit convoluted, yeah. It is
SpringBeanProcessor
that goes through all Spring beans and registers with RESTeasy those that have a@Path
annotation somewhere in their hierarchy (type and their corresponding interfaces).