1

我目前正在开发一个 Android 应用程序,该应用程序使用 Resteasy-mobile 进行 REST(JAXRS) 实现,并使用 Jackson 序列化到 JSON 和从 JSON 序列化。后者由 Resteasy 在后台完成。

服务器端我有一个 Jersey 网络服务,也使用 jackson 对 JSON 进行序列化。

Resteasy 客户端和 webresource 都实现了一个带有 JAXRS 注释的接口,如下所示:

    @Path("/equipment")
    @Consumes({"application/json"})
    @Produces({"application/json"})
    public interface AndroidEquipmentResourceIF
    {
      @GET 
      public Model getModel();

      @GET 
      @Path("/version") 
      public String getVersion();

      @GET 
      @Path("/{eId}") 
      public List<Equipment> getEquipmentListWithId(@PathParam("eId") String eId);
    }

客户端,这个接口被加载到一个工厂中,并用这个接口返回一个对象,该对象处理调用方法时的HTTP/URL/序列化过程。

当调用具有无效 ID 的设备实体时,WebApplicationException如果未找到该实体,则服务器会抛出 a。客户端,这可能会导致该方法返回 null。

如果我想对状态码做一些事情,比如404 - Not foundor 401 - Unauthorized,我可能需要响应对象,对吗?我认为 Resteasy 和 Jersey 确实在后台使用 Response 对象,那么有没有办法使用 Resteasy 访问 Response 对象或状态代码?

EDIT1:忘了提到第二个选项。我注意到可以将对象包装在响应对象中。因此,如果我将所有特定的域对象返回类型替换为响应,并以某种方式将对象包装在响应中,我可以从响应对象中提取对象吗?这对我来说听起来不是很干净,只是为了能够看到状态码。此外,我想尽可能避免手动解析 JSON。

EDIT2:发现可以拦截WebApplicationException,Resteasy客户端抛出一个ClientResponseFailure异常,可以在拦截器中捕获。问题是,永远不会抛出异常?看起来它卡在某个地方的无限循环中。

我收到以下异常:

10-26 10:52:10.048: E/AndroidRuntime(282): Caused by: java.lang.StackOverflowError
10-26 10:52:10.048: E/AndroidRuntime(282):  at java.util.regex.Matcher.reset(Matcher.java:151)
10-26 10:52:10.048: E/AndroidRuntime(282):  at java.util.regex.Matcher.reset(Matcher.java:211)
10-26 10:52:10.048: E/AndroidRuntime(282):  at java.util.regex.Matcher.<init>(Matcher.java:127)
10-26 10:52:10.048: E/AndroidRuntime(282):  at java.util.regex.Pattern.split(Pattern.java:405)
10-26 10:52:10.048: E/AndroidRuntime(282):  at java.util.regex.Pattern.split(Pattern.java:355)
10-26 10:52:10.048: E/AndroidRuntime(282):  at java.lang.String.split(String.java:2125)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.plugins.delegates.MediaTypeHeaderDelegate.parse(MediaTypeHeaderDelegate.java:33)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.plugins.delegates.MediaTypeHeaderDelegate.fromString(MediaTypeHeaderDelegate.java:18)
10-26 10:52:10.048: E/AndroidRuntime(282):  at javax.ws.rs.core.MediaType.valueOf(MediaType.java:173)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.getMediaType(BaseClientResponse.java:362)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:346)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:319)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:442)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.copyFromError(BaseClientResponse.java:94)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.ClientResponseFailure.<init>(ClientResponseFailure.java:32)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.createResponseFailure(BaseClientResponse.java:488)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.createResponseFailure(BaseClientResponse.java:479)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.readFrom(BaseClientResponse.java:384)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:346)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:319)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:442)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.copyFromError(BaseClientResponse.java:94)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.ClientResponseFailure.<init>(ClientResponseFailure.java:32)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.createResponseFailure(BaseClientResponse.java:488)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.createResponseFailure(BaseClientResponse.java:479)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.readFrom(BaseClientResponse.java:384)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:346)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:319)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:442)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.core.BaseClientResponse.copyFromError(BaseClientResponse.java:94)
10-26 10:52:10.048: E/AndroidRuntime(282):  at org.jboss.resteasy.client.ClientResponseFailure.<init>(ClientResponseFailure.java:32)
4

1 回答 1

2

得到它的工作方式如下:

Resteasy-mobile 是 JBOSS Resteasy 2.2.1 GA 的精简版。为了在 Android 上运行,我们删除了很多东西。但是删除的有点太多了。

我发现如果ClientResponseFailure抛出 a ,它的实体将被转换为一个Byte数组,并将再次读取以复制到ClientResponseFailure. 问题是,修剪后的版本仅包含用于字符串和文本/纯文本的 Messagebody 读取器/写入器,而不包含字节数组。因此,当尝试读取实体时,它会尝试抛出一个新ClientResponseFailure的,因为无法找到MessageBodyReaderByte[]. 然后它再次将此实体转换为字节数组,尝试再次读取它,从而进入一个无限循环,该循环将以StackOverflowError.

通过将未修剪版本的 Resteasy 中的缺失ByteArrayProvider和类添加到类路径(在和)中,(链接)就像一个魅力!ReadFromStreamorg.jboss.resteasy.plugins.providers.ByteArrayProviderorg.jboss.resteasy.util.ReadFromStreamClientErrorInterceptor

编辑:我说得太早了,还没有像魅力一样工作。ResteasyProviderFactory 也进行了修改以使其在 Android 中工作。.getInstance() 方法不断返回一个新实例,因此如果您使用以下方法注册 ClientErrorInterceptor:ResteasyProviderFactory.getInstance().addClientErrorInterceptor(new DataExceptionInterceptor());它不起作用。ProxyFactory 将在内部使用 ResteasyProviderFactory 的新实例。

要解决此问题,应将用于添加拦截器的 ResteasyProviderFactory 传递给ProxyFactory.create().

像这样:

ResteasyProviderFactory pf;
BasicHttpParams params;

pf = ResteasyProviderFactory.getInstance();

pf.addClientErrorInterceptor(new DataExceptionInterceptor());

params = new BasicHttpParams();
HttpProtocolParams.setVersion(params,
                              HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params,
                                     HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params,
                                        false);
return ProxyFactory.create(AndroidEquipmentResourceIF.class,
                           ProxyFactory.createUri(requestURI),
                           new ThreadSafeApacheHttpClient4Executor(params),
                           pf);
于 2012-10-29T10:04:28.763 回答