如何覆盖在JAX-RS内容协商过程中做出的决定? [英] How can I override the decisions made during JAX-RS Content Negotiation?
问题描述
我正在使用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屋!