gpt4 book ai didi

java - 为什么 Resteasy-mobile 中的 ClientResponseFailure 会导致 StackOverflowError?解决方法?

转载 作者:行者123 更新时间:2023-11-29 21:56:33 25 4
gpt4 key购买 nike

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

服务器端我有一个 Jersey 网络服务,也使用 jackson 序列化到 JSON 或从 JSON 序列化。

Resteasy 客户端和 web 资源都实现了一个 JAXRS 注释接口(interface),如下所示:

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

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

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

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

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

最佳答案

得到它的工作方式如下:

Resteasy-mobile 是 JBOSS Resteasy 2.2.1 GA 的精简版。为了让它在 Android 上运行,已经删除了很多东西。但是删除了太多。

我发现,如果抛出 ClientResponseFailure,Response 的实体将被转换为 Byte 数组,并将再次读取以复制到 客户端响应失败。问题是,修剪后的版本只包含字符串和文本/纯文本的消息体读取器/写入器,而不包含字节数组。因此,当尝试读取实体时,它会尝试抛出新的 ClientResponseFailure,因为无法找到与 Byte[] 兼容的 MessageBodyReader >。然后它再次将该实体转换为字节数组,尝试再次读取它,从而进入一个无限循环,该循环将以 StackOverflowError 结束。

通过将未修剪版本的 Resteasy 中缺少的 ByteArrayProviderReadFromStream 类添加到类路径(位于 org.jboss.resteasy.plugins.providers. ByteArrayProviderorg.jboss.resteasy.util.ReadFromStream),ClientErrorInterceptor(link)就像一个魅力!

编辑:我说得太快了,还没有发挥出魅力。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);

关于java - 为什么 Resteasy-mobile 中的 ClientResponseFailure 会导致 StackOverflowError?解决方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13083214/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com