Я построил следующий ресурс JAX-RS, который производит желаемый объект ответа, который является multipart / mixed с вложенным multipart / related с (на данный момент только один единственный) вложенным application / 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();
}
Этот ресурс используется клиентом, построенным с помощью клиентского API RESTEasy через RESTEasy proxy framework . Сущность Response читается как MultipartInput . Тело каждой части теперь должно читаться как MultipartRelatedInput . Поскольку это невозможно (, вы можете проголосовать за ) , поскольку обходной путь для каждой части читается как 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
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)
Похоже, что ResteasyProviderFactory contextualData пусто, когда ContextParameterInjector $ GenericDelegatingProxy.invoke вызывается.
Как решить эту проблему? Это ошибка?
Интересно, если я сделаю сам клиентский метод 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) {}
}
}
Но все же та же проблема, если метод клиента вызывается напрямую.
Среда - Windows 10 Pro 1903, OpenJDK11U-jdk_x64_windows_hotspot_11.0.4_11, WildFly 17.0.1.Final, RESTEasy 3.7.0.Final.