针对XML或JSON的JAX-RS响应不起作用 [英] JAX-RS Response for XML or JSON is not working

查看:104
本文介绍了针对XML或JSON的JAX-RS响应不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下GenericRest类,我用它来扩展基于以@XmlRootElement注解的实体类的休息类。

  public class GenericRest< T extends BaseEntity> {

@Inject @Service
GenericService< T>服务;

public GenericService< T> getService(){
return service;
}

@GET
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public Response getAll(){
// This Works对于JSON,但不适用于XML请求。
列表< T> list = getService()。findAll();
//这只是给出了BaseEntity的属性。
// GenericEntity< List< T>> list = new GenericEntity< List< T>>(getService()。findAll()){};
return Response.ok(list).build();


APPLICATION_JSON 在当前未注释的情况下工作正常,但 APPLICATION_XML 给出错误:


无法找到MessageBodyWriter类型的响应对象:
媒体类型的java.util.ArrayList:application / xml

注释的情况对于两种MediaTypes均正常工作,但仅返回 BaseEntity 的属性,而不是扩展类的添加属性。如何获得扩展类的两个MediaTypes工作的属性?



可以在此找到完整的存储库(正在进行中): https://github.com/martijnburger/multitenant



===更新1 ===



我更改了实体上的 @XmlSeeAlso 注释。它在特定实体上,但需要在 BaseEntity 上。此外,我使用上面的 GenericList 实现。这给出了正确的 XML 响应。但是,它仍然只返回 JSON repropses中的 BaseEntity 属性。我有两个后续问题:


  1. 如何返回包含属性的 JSON 响应对于所请求的特定对象?

  2. 如果在添加或删除特定对象时无需触摸 BaseEntity 实体类。由于每次添加新的 Entity 类时都需要 @XmlSeeAlso 注释,所以我需要更新注释。是否有另一种方法来实现这一点,我不需要触及 BaseEntity



有关更改的存储库可以在这里找到: https://github.com/martijnburger/multitenant/树/ so_36291250



===更新2 ===



我非常希望杰克逊的 @JsonSubTypes 注解将解决我的问题1.但是,它没有。我使用Jackson注释更新了存储库,但是我看不到结果中的任何更改。



===更新3 ===



请忽略我的更新2.当使用Jackson 2而不是Jackson 1时,它完全有效。初学者错误。 :(
这让我不禁要问:每次添加实体时,是否可以在不触及BaseEntity的情况下使用此工作。

解决方案<除了使用JAXB for XML,您可以使用具有XML模块的Jackson。对于JAX-RS,您可以使用这个神器

 <依赖项> 
< groupId> com.fasterxml.jackson.jaxrs< / groupId>
< artifactId> jackson-jaxrs-xml-provider< / artifactId>
< version> $ { jackson2.version}< / version>

<! - 您可能想要使用与
相同的版本,在wildfly上使用jackson - >

< / dependency>

如果使用这个,XML将被处理通过杰克逊,它没有像JAXB那样的一些怪癖,还有你所有的杰克逊JSON注释也将与此一起工作,所以您只需要一组注释,即XML和JSON。在较低级别上,Jackson XML提供程序使用 jackson-dataformat-xml ,如果您想了解更多关于它的信息。



从我测试的结果来看,只需将项目添加到项目中就足够了让它工作,虽然我没有在Wildfly上测试,但我只是用RESTeasy进行测试。但我想应该仍然有效。



如果它不能解决问题,我唯一能想到的就是JAXB提供者优先于这个。您可能需要在jboss-structure.xml文件中排除 resteasy-jaxb-provider 。但就像我说的,我认为这不是必需的。我会用Wildfly测试,但我真的不想下载它: - )



额外



OP使用classpath扫描 2 选择自动注册资源和提供程序,但是如果您在 Application 子类,如果需要JAXB,您还需要手动注册 JacksonXMLProvider.class (或 JacksonJaxbXMLProvider.class 注释支持)。




1 - 链接的项目显示为已弃用,但链接至未弃用后来的版本。我链接到已弃用的版本,因为它在自述文件中有一些文档,尽管它很少。更新的项目根本没有文档。 使用 @ApplicationPath 足以触发类路径扫描。一旦您重载 getClasses() getSingletons()并返回一个非空集合,则类路径扫描将被禁用。 / sub>


I have the following GenericRest class which I use to extend rest classes which are based on Entity classes annotated with @XmlRootElement.

public class GenericRest<T extends BaseEntity> {

    @Inject @Service
    GenericService<T> service;

    public GenericService<T> getService() {
        return service;
    }

    @GET
    @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
    public Response getAll() {
        // This works for JSON but does not work for XML Requests.
        List<T> list = getService().findAll();
        // This just gives the attributes for the BaseEntity.
        //GenericEntity<List<T>> list = new GenericEntity<List<T>>(getService().findAll()) {};
        return Response.ok(list).build();
    }
}

The APPLICATION_JSON is working fine in the currently uncommented situation, but the APPLICATION_XML give the error:

Could not find MessageBodyWriter for response object of type: java.util.ArrayList of media type: application/xml

The commented situation works fine for both MediaTypes, but returns just the attributes of the BaseEntity, not the added attributes for the extended classes. How can I get the attributes for the extended classes and have both MediaTypes working?

Complete repository can be found here (work in progress): https://github.com/martijnburger/multitenant

=== Update 1 ===

I changed the @XmlSeeAlso annotation on the Entities. It was on the specific entities, but needed to be on the BaseEntity. Further I used the GenericList implementation above. This gives correct XML responses. However, it still returns only the BaseEntity attributes in JSON repsonses. I have two followup questions:

  1. How to return a JSON response including the attributes for the specific object that is requested?
  2. I would prefer it if the BaseEntity does not have to be touched when adding or removing specific Entity classes. Because the @XmlSeeAlso annotation every time I add a new Entity class, I need to update the annotation. Is there another method to implement this where I do not need to touch the BaseEntity?

Repository with changes can be found here: https://github.com/martijnburger/multitenant/tree/so_36291250

=== Update 2 ===

I had good hope that the @JsonSubTypes annotation from Jackson would solve my problem 1. However, it did not. I updated the repository with the Jackson annotations, but I cannot see any changes in the result.

=== Update 3 ===

Please ignore my Update 2. It totally works when using Jackson 2 instead of Jackson 1. Beginners mistake. :( Which leaves me with the question: Is it possible to get this working without touching the BaseEntity every time you add an entity.

解决方案

Instead of using JAXB for XML, you can use Jackson, which has an XML module. For JAX-RS you would use this artifact1

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-xml-provider</artifactId>
    <version>${jackson2.version}</version>

    <!-- you'll probably want to use the same version as
         the jackson being used on your wildfly -->

</dependency>

If you use this, the XML will be handle by Jackson, which doesn't have some of the same quirks that JAXB does. And all your Jackson JSON annotations will work with this also, so you only need one set of annotations, for both XML and JSON. At a lower level, the Jackson XML provider, uses jackson-dataformat-xml, if you want any more information about it.

From what I tested, just adding the artifact to your project is enough to make it work, though I did not test on Wildfly, I just tested with RESTeasy by itself. But I imagine is should still work.

If it doesn't work out the box, the only thing I could imagine is that the JAXB provider is taking precedence over this one. You may need to exclude the resteasy-jaxb-provider in a jboss-structure.xml file. But like I said, I don't think this will be required. I would've tested with Wildfly, but I really didn't feel like downloading it :-)

Extra

The OP is using classpath scanning2 to pick auto-register resources and providers, but if you are manually registering your resources and providers in your Application subsclass, you will also need to manually register the JacksonXMLProvider.class (or JacksonJaxbXMLProvider.class, if you want JAXB annotation support).


1 - The linked project shows as deprecated, but it links to the non-deprecated later version. I linked to the deprecated one, as it has some documentation in the README, though it is very little. The newer project has no documentation at all.

2 - Empty Application subclass annotated with @ApplicationPath is enough to trigger classpath scanning. Once you override either getClasses() or getSingletons() and return an non empty set, classpath scanning is disabled.

这篇关于针对XML或JSON的JAX-RS响应不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆