Reputation: 95
Greetings StackOverflow members.
background information: This is a spring-boot-based project that uses JAX-RS / Jersey as its rest HTTP server instead of spring rest.
Error explanation and question:
send a file from one server to another and receive a response back. (simple right?) functionally the code is below is working. but instead of a 200 response, the sender gets 500 internal server error with the following stack trace.
java.lang.IllegalStateException: No such MIME Part: Part=0:binary
at org.jvnet.mimepull.DataHead.read(DataHead.java:115)
at org.jvnet.mimepull.MIMEPart.read(MIMEPart.java:69)
at org.glassfish.jersey.media.multipart.BodyPartEntity.getInputStream(BodyPartEntity.java:65)
at org.glassfish.jersey.media.multipart.internal.FormDataParamValueParamProvider$FormDataParamValueProvider.apply(FormDataParamValueParamProvider.java:263)
at org.glassfish.jersey.media.multipart.internal.FormDataParamValueParamProvider$FormDataParamValueProvider.apply(FormDataParamValueParamProvider.java:222)
at org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.apply(ParamValueFactoryWithSource.java:50)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:64)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:109)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:176)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:79)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:469)
After debugging i noticed that the receiver server @FormDataParam are included into the Response.ok() object.
And this is the part I do not understand if I define Response.ok(). why is it that its including the request params? by the type the response is sent the file has already been consumed.
The following picture is taken in debug when you go into the Response.
Configuration: Jersey settings
@Configuration
@ApplicationPath("/idoc") public class JerseyConfiguration extends ResourceConfig {
private static final Logger logger = LoggerFactory.getLogger(JerseyConfiguration.class);
public JerseyConfiguration() {
packages("ctx.cf.arcus.controllers");
register(MultiPartFeature.class);
register(CORSResponseFilter.class);
register(JacksonProvider.class);
register(DebugExceptionMapper.class);
HashMap<String, Object> properties = new HashMap<String, Object>();
properties.put("jersey.config.server.response.setStatusOverSendError", true);
setProperties(properties);
}
}
The sending server I have the following code configured:
Client client = ClientBuilder.newClient(new ClientConfig().register(MultiPartFeature.class));
WebTarget webTarget = client.target(url);
FormDataMultiPart part = new FormDataMultiPart();
final FormDataBodyPart p1 = new StreamDataBodyPart("file", this.document.getStream());
part.bodyPart(p1);
final FormDataBodyPart p2 = new FormDataBodyPart("size", String.valueOf(this.document.getSize()));
part.bodyPart(p2);
Response response = null;
try {
response = webTarget.request().header("Authorization", "Bearer " + token)
.post(Entity.entity(part, MediaType.MULTIPART_FORM_DATA), Response.class);
} catch (Exception e) {
response = Response.serverError().build();
}
Recieving server
@POST
@Path("/idoc")
public Response idocPassThroughTranslation(@FormDataParam("file") InputStream uploadedInputStream,
@FormDataParam("size") long size, @Context HttpServletRequest request)
throws IOException, ServletException, FormatException {
<Logic omitted>
return Response.ok().build();
}
Upvotes: 1
Views: 666
Reputation: 95
Alright. It took me a day to try and resolve this. but was not able to find root cause of this behavior.
So I opted for a workaround solution.
Using jersey exception mapper i check for the specific expectation that is thrown and the method since it should only apply to that location of the code and the response status to see if it needs to be overwritten with 200 ok or pass along with 500.
@Provider
public class RouterResponseExceptionMapper implements
ExceptionMapper<IllegalStateException> {
@Context
private HttpServletResponse response;
@Context
private ResourceInfo resourceInfo;
@Override
public Response toResponse(IllegalStateException exception) {
if (this.resourceInfo.getResourceMethod().getName().equals("PassThrough")
&& this.response.getStatus() == 200) {
return Response.ok().build();
} else {
return Response.serverError().entity(Throwables.getStackTraceAsString(exception)).build();
}
}
}
Upvotes: 0