我目前正在开发一款Android应用程序,它使用Resteasy-mobile进行REST(JAXRS)实现,而Jackson用于与JSON进行序列化。后者由Resteasy在后台完成。
Serverside我有一个Jersey webservice,也使用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);
}
Clientside,此接口被加载到工厂,并返回一个带有此接口的对象,该接口在调用方法时处理HTTP / URL /序列化过程。
当调用具有无效ID的Equipment实体时,如果找不到该实体,服务器将抛出WebApplicationException
。客户端,这可能导致该方法返回null。
如果我想对状态代码执行某些操作,例如404 - Not found
或401 - 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)
答案 0 :(得分:2)
按照以下方式运行:
Resteasy-mobile是JBOSS Resteasy 2.2.1 GA的修剪版本。已删除许多内容以使其在Android上运行。但是有点太多了。
我发现如果抛出ClientResponseFailure
,则将其实体的响应转换为Byte
数组,并将再次读取以复制到ClientResponseFailure
。问题是,修剪后的版本只包含用于字符串和text / plain的Messagebody读取器/写入器,而不包含字节数组。因此,在尝试阅读实体时,它会尝试抛出新的ClientResponseFailure
,因为无法找到与MessageBodyReader
兼容的Byte[]
。然后它再次将此实体强制转换为字节数组,尝试再次读取它,从而进入一个以StackOverflowError
结尾的无限循环。
通过将未修剪版本的Resteasy中缺少的ByteArrayProvider
和ReadFromStream
类添加到类路径(org.jboss.resteasy.plugins.providers.ByteArrayProvider
和org.jboss.resteasy.util.ReadFromStream
),ClientErrorInterceptor
(link)就像一个魅力!
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);