10

I'm trying to perform a request to a jaxrs service which has media type set to multipart/form-data. This request contains a list of entities(xml) and an image(png, binary). I have created the request as described in this thread by BalusC.

The request seems ok after inspecting it in wireshark, except for the ip header checksum being wrong.(says something about "may be caused by IP checksum offload".)

My big issue here is how to handle the multipart request on the service side. I do not wish to include any libraries from apache.cxf, resteasy or anything of the sort. All I want to rely on is the jaxrs api.

The two parts in the request have names deliveries and signature, where the signature is a png image file sent as binary. The list of deliveries should be parsed from an xml(the entity has the xmlrootelement annotation and such, so this part works separately). I've attempted with this way of reading the different parts, but this was really a longshot;

@PUT
@Path("signOff")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public void signOffDeliveries(@FormParam("deliveries") List<Delivery> deliveries, @FormParam("signature")File signature) {
    //do something with the signature(image) and the list of deliveries.
}

This does off course not work, and it gives me a 404 http status code if I run the request on Websphere, and a 415 when I run the request towards an embedded openejb (in our integration test framework). If I remove the FormParam annotations the request succeeds.

How can I read the different parts of the multipart request using only the jaxrs api?

EDIT Ok, so I canged the PUT to POST, and added an @Encoding annotation to the params as so:

@POST
@Path("signOff")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public void signOffDeliveries(
    @Encoded @FormParam("deliveries") String deliveries,
    @Encoded @FormParam("signature") File signature) {

}

Now I get the xml as a text string, but I am not able to automatically unmarshal it to a list of deliveries even though the Content-Type of this part of the payload is set to application/xml. The other problem is that the file I receive has length==0, and I am not able to read any bytes from it.

Am I missing an essential point here?

Community
  • 1
  • 1
Runar Halse
  • 3,528
  • 10
  • 39
  • 59
  • The specification isn‘t providing anything for this case. But jaxrs is based on servlet api. With servlet api you can access request body and handover it to Apache commons FileUpload library https://commons.apache.org/proper/commons-fileupload/. This is not conflicting with the jaxrs implementation. – Christian13467 Jun 24 '19 at 18:18

3 Answers3

8

Indeed I find it hard to understand why the JAX-RS spec doesn't standardize a support for this (I've just created https://java.net/jira/browse/JAX_RS_SPEC-413 to address this).

However it is nevertheless possible to support multi-part forms in an implementation independent fashion. Either you write your own MessageBodyReader for MultiPart form or you use a library like Apache Clerezza jaxrs.utils which provide a MultiPartBody object which respective MessageBodyReader. This library has no implementation specification dependency so your application will run on any jax-rs implementation.

For an example on how Clerezza jaxrs.utils is used see line 105 in http://svn.apache.org/viewvc/stanbol/trunk/development/archetypes/stateless-webmodule/src/main/resources/archetype-resources/src/main/java/MultiEnhancer.java?revision=1465777&view=markup. If you're not using OSGi (with white-board registration of resources) you will have to add to org.apache.clerezza.jaxrs.utils.form.MultiPartFormMessageBodyReader to your Application.

Reto Gmür
  • 2,497
  • 1
  • 20
  • 25
1

I have implemented this in Glassfish 4 without coupling with Jersey. @See this post for details

Community
  • 1
  • 1
Ioannis Deligiannis
  • 2,679
  • 5
  • 25
  • 48
-2

I do not wish to include any libraries from apache.cxf, resteasy or anything of the sort. All I want to rely on is the jaxrs api

You can't "rely on" the API, since it contains only interfaces. Classes that implement that interfaces come from RESTeasy, or Jersey, or CXF.

and a 415 when I run the request towards an embedded openejb

415 means "Method not supported", which happens when you send GET request to a PUT-expecting resource.

I would recommend to use POST instead of PUT in this case. I suspect that @FormParam is not suitable to work with PUT, in your particular case.

yegor256
  • 102,010
  • 123
  • 446
  • 597
  • 8
    I know the API is just interfaces, but as long as I do not include any references to any apache cxf specific implementations, I should be able to change the container without much trouble. However, changing the method to a POST does nothing. – Runar Halse Jan 29 '13 at 06:11