如何覆盖在JAX-RS内容协商过程中做出的决定? [英] How can I override the decisions made during JAX-RS Content Negotiation?

查看:154
本文介绍了如何覆盖在JAX-RS内容协商过程中做出的决定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用RESTEasy 2.2.1.GA作为我的JAX-RS实现,以创建客户端以连接到第三方服务提供商. (如果需要的话,Education.com的REST API)

I'm using RESTEasy 2.2.1.GA as my JAX-RS implementation to create a client to connect to a third party service provider. (Education.com's REST API if it matters)

为确保我没有错过重要的实现细节,以下是代码示例:

To make sure I haven't missed an important implementation detail here are code samples:

服务界面

@Path("/")
public interface SchoolSearch {

@GET
@Produces({MediaType.APPLICATION_XML})
Collection<SchoolType> getSchoolsByZipCode(@QueryParam("postalcode") int postalCode);
}

呼叫班

public class SimpleSchoolSearch {

public static final String SITE_URL = "http://api.education.com/service/service.php?f=schoolSearch&key=****&sn=sf&v=4";

SchoolSearch service = ProxyFactory.create(SchoolSearch.class, SITE_URL);

public Collection<SchoolType> getSchools() throws Exception {
    Collection<SchoolType> schools = new ArrayList<SchoolType>();
    Collection<SchoolType> response = service.getSchoolsByZipCode(35803);
    schools.addAll(response);
    return schools;

}
}

设置测试以进行此调用后,我执行并看到抛出了以下异常.

After setting up tests to make this call, I execute and see the following exception being thrown.

org.jboss.resteasy.plugins.providers.jaxb.JAXBUnmarshalException: Unable to find JAXBContext for media type: text/html;charset="UTF-8"

据我了解,通过阅读RESTEasy/JAX-RS文档,当响应被返回给客户端时,在取消封送数据之前,会确定(内容协商?)使用哪种机制进行编组. (我认为我们在这里谈论的是MessageBodyReader,但不确定.)通过查看响应的正文,我看到返回的是格式正确的XML,但是是内容协商(通过HTTP标头content-type确实是text/html; charset ="UTF-8")不允许JAXB解析文本.

From reading the RESTEasy/JAX-RS documentation, as I understand it, when the response is returned to the client, prior to the unmarshaling of the data, a determination is made (Content Negotiation??) about which mechanism to use for unmarshalling. (I think we're talking about a MessageBodyReader here but I'm unsure.) From looking at the body of the response, I see that what is returned is properly formatted XML, but the content negotiation (via HTTP header content-type is indeed text/html;charset ="UTF-8") is not allowing the text to be parsed by JAXB.

我认为实现正确,并且错误的是服务,但是,我不控制服务,但仍想使用它.

I think that the implementation is behaving correctly, and it is the service that is in error, however, I don't control the service, but would still like to consume it.

这样说:

我对为什么引发异常的理解正确吗?

Am I correct in my understanding of why the exception is thrown?

我该如何解决?

是否有一个简单的单行注释可以强制JAXB解组数据,还是需要实现自定义MessageBodyReader? (如果那甚至是要实现的正确类).

Is there a simple one line annotation that can force JAXB to unmarshal the data, or will I need to implement a custom MessageBodyReader? (If that is even the correct class to implement).

谢谢!

跟进:

我只想发布我对Eiden的答案所做的一些更改.我使用他的代码和 Resteasy ClientExecutionInterceptor文档.我的最后一堂课看起来像

I just wanted to post the few changes I made to Eiden's answer. I created a ClientExecutionInterceptor using his code and the information available at Resteasy ClientExecutionInterceptor documentation. My final class looks like

@Provider
@ClientInterceptor
public class SimpleInterceptor implements ClientExecutionInterceptor {

@Override
  public ClientResponse execute(ClientExecutionContext ctx) throws Exception {
      final ClientResponse response = ctx.proceed();
      response.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML);
      return response;
  }
}

最大的区别是添加了@Provider和@ClientExecutionInterceptor批注.这应该确保拦截器已正确注册.

The big difference is the addition of the @Provider and @ClientExecutionInterceptor annotations. This should insure that the interceptor is properly registered.

此外,出于完整性考虑,我为测试注册的拦截器略有不同.我用过:

Also, just for completeness, I registered the Interceptor slightly differently for my tests. I used:

        providerFactory.registerProvider(SimpleInterceptor.class);

推荐答案

我确定有几个解决此问题的方法,但我只能想到一个.

I'm sure there are several solutions to this problem, but I can only think of one.

尝试使用ClientExecutionInterceptor设置内容类型:

Try so set the content-type using a ClientExecutionInterceptor:

public class Interceptor implements ClientExecutionInterceptor {

    @Override
    public ClientResponse<?> execute(ClientExecutionContext ctx) throws Exception {
        final ClientResponse<?> response = ctx.proceed();

        response
            .getHeaders()
            .putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML);

        return response;
    }

}

public void getSchools() throws Exception {
    ResteasyProviderFactory.getInstance()
        .getClientExecutionInterceptorRegistry()
        .register( new Interceptor() );

    SchoolSearch service =
            ProxyFactory.create(SchoolSearch.class, SITE_URL);
}

这篇关于如何覆盖在JAX-RS内容协商过程中做出的决定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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