Jersey 子资源定位器错误

Posted

技术标签:

【中文标题】Jersey 子资源定位器错误【英文标题】:Jersey Sub-Resource Locators Error 【发布时间】:2015-07-28 07:25:56 【问题描述】:

我正在尝试让JSR-311 plugin 与 Grails 2.3.7 一起使用。我使用的是 0.10 版本,因为我认为 0.11 需要 Grails 2.4。

我使用generate-resource 命令为我的域类Product 创建了一个端点。创建了两个资源类ProductCollectionResourceProductResource。我对它们进行了一些调整,但基本上它们看起来像这样:

ProductCollectionResource

@Path('/api/products')
@Consumes(['application/json'])
@Produces(['application/json'])
class ProductCollectionResource 

    def productResourceService

    @Path('id')
    @GET
    ProductResource getResource(@PathParam('id') Long id) 
        new ProductResource(productResourceService: productResourceService, id:id)
    

    @GET
    Response readAll(@QueryParam("max") Integer max, @QueryParam("offset") Integer offset) 
        ok productResourceService.readAll(max, offset)
    

产品资源

@Consumes(['application/json'])
@Produces(['application/json'])
class ProductResource 

    def productResourceService
    def id

    @GET
    Response read() 
        ok productResourceService.read(id)
    

ProductCollectionResource 中的 readAll 方法工作正常 - 当我点击它时,我会返回一个产品列表,但是当我尝试通过 id(在 /api/products/123 上)访问特定产品时,我得到以下信息错误:

Caused by MessageException: A message body writer for Java class com.myapp.ProductResource, and Java type class com.myapp.ProductResource, and MIME media type application/json was not found
->>  285 | write              in com.sun.jersey.spi.container.ContainerResponse
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|   1479 | _handleRequest     in com.sun.jersey.server.impl.application.WebApplicationImpl
|   1391 | handleRequest . .  in     ''
|   1381 | handleRequest      in     ''
|    416 | service . . . . .  in com.sun.jersey.spi.container.servlet.WebComponent
|    538 | service            in com.sun.jersey.spi.container.servlet.ServletContainer
|    716 | service . . . . .  in     ''
|    193 | process            in org.grails.jaxrs.web.JaxrsContext$JaxrsServiceImpl
|     45 | handle . . . . . . in org.grails.jaxrs.JaxrsController
|    195 | doFilter           in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter . . . . . in grails.plugin.cache.web.filter.AbstractFilter
|    150 | invoke             in net.bull.javamelody.JspWrapper
|    285 | invoke . . . . . . in net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler
|    198 | doFilter           in net.bull.javamelody.MonitoringFilter
|    176 | doFilter . . . . . in     ''
|     67 | doFilter . . . . . in     ''
|     53 | doFilter           in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter
|     82 | doFilter           in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
|     63 | doFilter . . . . . in com.odobo.grails.plugin.springsecurity.rest.RestLogoutFilter
|     46 | doFilterInternal   in org.grails.jaxrs.web.JaxrsFilter
|     82 | doFilter . . . . . in com.brandseye.cors.CorsFilter
|   1145 | runWorker          in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . . . . . .  in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run                in java.lang.Thread

所以看起来它正在尝试将我的 ProductResource 类编组为 JSON,我认为这并不是我真正想要的。我认为它应该调用ProductResource.read() 方法,并将该方法的返回值编组为JSON。

【问题讨论】:

【参考方案1】:

我对 Grails 没有任何经验,但从纯粹的泽西岛的角度来看,看看你在这里得到了什么

@Path('id')
@GET
ProductResource getResource(@PathParam('id') Long id) 

这是资源方法(端点)。因此ProductsResource 将被视为响应主体,就像任何其他资源方法一样。

您似乎正在尝试使用子资源定位器功能,转发到ProductsResource 类。为此,子资源定位器 (getResource) 不应有 @HttpMethod 注释。这是区分资源方法和子资源定位器的因素之一。

所以只需从getResource 方法中删除@GET@GET 已经由ProductsResource 中的read() 方法建立,这就是将要调用的方法。

有关详细信息,请参阅Sub-Resource Locators 的文档

【讨论】:

以上是关于Jersey 子资源定位器错误的主要内容,如果未能解决你的问题,请参考以下文章

Jersey REST api 多种资源

带有 XML 参数的 REST 服务操作上的 HTTP 错误 415 不受支持的媒体类型(Jersey + Jetty)

jersey中的 404 Not Found 错误。

何时在 Jersey 资源中使用 @Singleton

使用 Jersey 访问 REST 资源和静态资源

如何使用 jersey 服务轮询资源