2

我有在 JBOSS 7.1 下运行的 REST (Resteasy) 客户端。从服务器返回的响应要求我使用自己的 JAXB ObjectFactory,因为相同的 Java 类型映射到多个 XML 元素:

@XmlRegistry
public class ObjectFactory {

    private final static QName RESPONSE_QNAME = new QName("response");
    private final static QName ORDER_QNAME = new QName("order");

    @XmlElementDecl(name="response")
    public JAXBElement<PurchaseResponse> getPurchaseResponse(PurchaseResponse r) {
        return new JAXBElement<PurchaseResponse>(RESPONSE_QNAME, PurchaseResponse.class, null);
    }

    @XmlElementDecl(name="order")
    public JAXBElement<PurchaseResponse> getOrderResponse(PurchaseResponse r) {
        return new JAXBElement<PurchaseResponse>(ORDER_QNAME, PurchaseResponse.class, null);
    }

我像这样构建 RestEasy 客户端:

    ResteasyClient client = new ResteasyClientBuilder().build();
    ResteasyWebTarget httpTarget = client.target( endpoint );
    RestService target = httpTarget.proxy(RestService.class);
            Response resp = target.callAPI();
            return resp.readEntity(PurchaseResponse.class);

其中 RestService 是表示 REST API 方法的接口。如果 PurchaseResponse 类在该类上具有 XmlRootElement 注释,则此方法有效。一旦我删除它, readEntity() 调用就会失败,并显示“找不到消息正文处理器”。但是,我不希望 JAXB 在我的 ObjectFactory 中使用 XmlRootElement 注释,而是使用 XmlElementDecl 注释,并且它没有发生。

我可以通过为我的包显式构建 JAXB 上下文、手动将响应读取到字符串、然后将其解析为 XML 文档并最终输入由上下文生成的 JAXB 解组器来使其工作(啊!)。我不想每次调用 API 时都这样做。

为什么默认的 JAXB 解组器不选择我的 ObjectFactory 类并使用它?我使用本地捆绑的 RestEasy 库(JBOSS 提供的 RestEasy 模块是过时的)。

4

2 回答 2

1

在深入研究 Resteasy 源之后,在我看来,目标类必须使用 XmlType 进行注释,以便 RE 开始寻找 ObjectFactory:

public abstract class AbstractJAXBContextFinder implements JAXBContextFinder
{
   protected static final String OBJECT_FACTORY_NAME = ".ObjectFactory";

   public static Class<?> findDefaultObjectFactoryClass(Class<?> type)
   {
      XmlType typeAnnotation = type.getAnnotation(XmlType.class);
      if (typeAnnotation == null) return null;
      if (!typeAnnotation.factoryClass().equals(XmlType.DEFAULT.class)) return null;
      StringBuilder b = new StringBuilder(getPackageName(type));
      b.append(OBJECT_FACTORY_NAME);
      Class<?> factoryClass = null;
      try
      {
         factoryClass = Thread.currentThread().getContextClassLoader().loadClass(b.toString());
      }
      catch (ClassNotFoundException e)
      {
         return null;
      }
      if (factoryClass.isAnnotationPresent(XmlRegistry.class)) return factoryClass;
      return null;
   }
}

我在类上添加了@XmlType 注释,现在 RestEasy readEntity() 调用可以正确解组。我仍然需要运行完整的测试,但现在在我看来这很有效。

似乎是 Resteasy 中的一个错误:还应该为 @XmlRootElement 注释的类加载对象工厂。

于 2013-11-05T21:16:58.137 回答
1

当 aJAXBContext在一个类(或多个类)上构建时,它不会自动引入。l您可以创建 aContextResolver来控制实现JAXBContext使用的JAX-RS

于 2013-11-05T18:38:03.493 回答