如何覆盖JAX-RS内容协商期间做出的决策?

时间:2011-11-19 22:51:13

标签: java rest jax-rs resteasy

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

为了确保我没有错过重要的实现细节,这里有代码示例:

服务界面

@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;

}
}

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

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头内容类型确实是text / html; charset =“UTF-8”)不允许JAXB解析文本。

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

所以说:

我是否理解为什么抛出异常?

我该如何解决?

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

谢谢!

跟进:

我只是想对艾登的回答发表一些变化。我使用他的代码和Resteasy ClientExecutionInterceptor documentation提供的信息创建了一个ClientExecutionInterceptor。我的最后一堂课看起来像

@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注释。这应该确保拦截器已正确注册。

另外,为了完整起见,我为我的测试注册了Interceptor略有不同。我用过:

        providerFactory.registerProvider(SimpleInterceptor.class);

2 个答案:

答案 0 :(得分:2)

我确信这个问题有几个解决方案,但我只能想到一个。

尝试使用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);
}

答案 1 :(得分:0)

我不知道任何此类注释,其他人可能会这样做,但解决方法是创建本地代理。创建一个控制器,使用a将所有参数传递给education.com      java.Net.URL.get() 返回您收到的答案,但修改标题。然后将您的客户端连接到本地代理控制器。