我构建了以下JAX资源,它生成所需的响应对象,这个响应对象是multipart/混合嵌套的multipart/关联的(目前只有一个)嵌套的应用程序/json。
@GET
@Path("test")
@Produces("multipart/mixed")
public Response test() {
List<Entity> entities;
...
final MultipartOutput multipartOutput = new MultipartOutput();
entities.stream().map(entity -> {
MultipartRelatedOutput multipartRelatedOutput = new MultipartRelatedOutput();
multipartRelatedOutput.addPart(entity, MediaType.APPLICATION_JSON_TYPE);
return multipartRelatedOutput;
}).forEach(multipartRelatedOutput ->
multipartOutput.addPart(multipartRelatedOutput, MediaType.valueOf("multipart/related"))
);
return Response.ok(multipartOutput, MediaType.valueOf("multipart/mixed")).build();
}
此资源由用通过RESTEasy代理框架实现RESTEasy客户端API构建的客户端使用。响应的实体被读取为MultipartInput。每个部分的身体现在应该被读为MultipartRelatedInput。作为这在我的RESTEasy版本中是不可能的(但已经在4.5.5.Final中得到了修正),作为解决每个部分的身体被读为MultipartInput。
public void get()
{
try (Response response = this.proxy.test();) {
...
MultipartInput multipartInput = response.readEntity(MultipartInput.class);
for (InputPart inputPart : multipartInput.getParts()) {
try {
//MultipartRelatedInput relatedInput = inputPart.getBody(MultipartRelatedInput.class, null); // not working with NPE with my RESTEasy version
MultipartInput relatedInput = inputPart.getBody(MultipartInput.class, null);
String json = relatedInput.getParts().get(0).getBodyAsString(); // fails
// Entity entity = relatedInput.getParts().get(0).getBody(Entity.class, null); // also fails
} catch (IOException exception) {}
}
}
将封装的实体读取为JSON-String (为了简单起见,但也将其读取为具有实体的类类型的对象)失败,例外情况如下:
Caused by: org.jboss.resteasy.spi.LoggableFailure: RESTEASY003880: Unable to find contextual data of type: javax.ws.rs.ext.Providers
at org.jboss.resteasy.resteasy-jaxrs@3.7.0.Final//org.jboss.resteasy.core.ContextParameterInjector$GenericDelegatingProxy.invoke(ContextParameterInjector.java:77)
at javax.ws.rs.api@1.0.2.Final//com.sun.proxy.$Proxy145.getMessageBodyReader(Unknown Source)
at org.jboss.resteasy.resteasy-multipart-provider@3.7.0.Final//org.jboss.resteasy.plugins.providers.multipart.MultipartInputImpl$PartImpl.getBody(MultipartInputImpl.java:336)
at org.jboss.resteasy.resteasy-multipart-provider@3.7.0.Final//org.jboss.resteasy.plugins.providers.multipart.MultipartInputImpl$PartImpl.getBodyAsString(MultipartInputImpl.java:392)
看起来,当调用ContextParameterInjector$GenericDelegatingProxy.invoke时,ResteasyProviderFactory的contextualData是空的。
如何解决这个问题?这是个窃听器吗?
有趣的是,如果我使客户端方法本身成为JAX-RS资源,并从另一个客户端请求它,一切都可以工作。contextualData人口稠密。
@GET
@Path("get")
@Produces(MediaType.APPLICATION_JSON)
public void get()
{
try (Response response = this.proxy.test();) {
...
MultipartInput multipartInput = response.readEntity(MultipartInput.class);
for (InputPart inputPart : multipartInput.getParts()) {
try {
MultipartRelatedInput relatedInput = inputPart.getBody(MultipartRelatedInput.class, null);
} catch (IOException exception) {}
}
}
但是,如果直接调用客户端方法,则仍然存在相同的问题。
环境为Windows10Pro1903,OpenJDK11U-JDKx64_ Windows _hotspot_11.0.4_11,WildFly 17.0.1,WildFly,RESTEasy 3.7.0.Final。
--我最近一次尝试来了解出了什么问题--揭示了它很可能是餐厅-多部分-供应商中的一个bug。目前,当从响应流读取多部分层次结构的第一级时,已注册的提供程序被缓存在MultipartInputImpl的MultipartInputImpl中。从响应流中读取MultipartInput之后,contextualData就消失了,但是在读取它们的身体时,注册的提供者仍然可以通过savedProviders为嵌套的PartImpl提供程序。问题是,在创建嵌套的savedProviders实例时,MultipartInput没有被填充到多部分层次结构的下一层。
--我现在的解决办法是在之前手动推送提供程序,并在使用pushContext和popContextData进行处理后弹出它们。
public void get()
{
try (Response response = this.proxy.test();) {
...
MultipartInput multipartInput = response.readEntity(MultipartInput.class);
for (InputPart inputPart : multipartInput.getParts()) {
try {
MultipartInput relatedInput = inputPart.getBody(MultipartInput.class, null);
ResteasyProviderFactory.pushContext(Providers.class, ResteasyProviderFactory.getInstance());
String json = relatedInput.getParts().get(0).getBodyAsString(); // does not fail anymore
ResteasyProviderFactory.popContextData(Providers.class);
} catch (IOException exception) {}
}
}
我要开始一个问题。
发布于 2020-06-25 12:57:07
根据链接Framework.html,您可以看到引号
Resteasy将自动加载一组默认提供程序。(基本上所有
META-INF/services/javax.ws.rs.ext.Providers
文件中列出的所有类)。此外,您还可以通过方法调用Configuration
提供的Client.configuration()
对象手动注册其他提供程序、过滤器和拦截器。Configuration
还允许您设置可能需要的各种配置属性。
因此,如果添加类名org.jboss.resteasy.plugins.providers.multipart.MultipartReader
,那就足够了
https://stackoverflow.com/questions/58751034
复制相似问题