How to handle a multipart form request with JAX-RS. Any non-vendor specific ideas?
Asked Answered
A

2

0

I am asking this question after a couple of days on research and finding no definitive answer to this question: How do I process multipart form-data requests (clean and nice) with JAX-RS (not servlets) in a vendor agnostic way?

Similar questions asked over the years:

  1. asked in 2013
  2. asked in 2019
  3. for some reason this didn't work with JakartaEE 9.1

I asked so I could as well share my best findings of a solution that I think could work.

Aymara answered 26/7, 2022 at 18:49 Comment(0)
A
1

I landed on this blog by Gunther Rotsch. Checkout the GitHub repo I have tested his portable solution out and so far so good. I think it is what I have been looking for. Feel feel to try it out and share your comments.

The JAX-RS resource would look like this:

@POST
@Consumes("multipart/form-data")
public Response postFormData(MultiPartMessage message) {
    ...
}

And the MessageBodyReader, the entry point of JAXRS integration like this:

@Provider
@Consumes("multipart/form-data")
public class MultiPartMessageBodyReader implements MessageBodyReader<MultiPartMessage> {

private static final Logger LOGGER = LoggerFactory.getLogger(MultiPartMessageBodyReader.class);

@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
    LOGGER.info("isReadable called with type: {} and mediaType: {}", type, mediaType);
    return MultiPartMessage.class.isAssignableFrom(type)
            && mediaType.toString().toLowerCase().startsWith("multipart/form-data");
}

@Override
public MultiPartMessage readFrom(Class<MultiPartMessage> type, Type genericType, Annotation[] annotations,
        MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
        throws IOException, WebApplicationException {
    ...
}

"The @Provider annotation declares the class to JAXRS, which calls this reader when the de-marshalling of messages of content type multipart/from-data is required."

Aymara answered 26/7, 2022 at 18:49 Comment(0)
R
2

Jakarta RESTful web services 3.1 (since JakartaEE 11) has a simpler syntax:

@Path("myprettyuploadfile")
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(@FormParam("name") String name,
                           @FormParam("part") EntityPart part) {

jakarta.ws.rs.core.EntityPart.getContent() returns the content of the uploaded file. Implementing your own MessageBodyReader is no longer necessary.

Reference: https://itnext.io/jakarta-rest-3-1-by-examples-dbe13fe6988c

Riser answered 14/2 at 14:6 Comment(0)
A
1

I landed on this blog by Gunther Rotsch. Checkout the GitHub repo I have tested his portable solution out and so far so good. I think it is what I have been looking for. Feel feel to try it out and share your comments.

The JAX-RS resource would look like this:

@POST
@Consumes("multipart/form-data")
public Response postFormData(MultiPartMessage message) {
    ...
}

And the MessageBodyReader, the entry point of JAXRS integration like this:

@Provider
@Consumes("multipart/form-data")
public class MultiPartMessageBodyReader implements MessageBodyReader<MultiPartMessage> {

private static final Logger LOGGER = LoggerFactory.getLogger(MultiPartMessageBodyReader.class);

@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
    LOGGER.info("isReadable called with type: {} and mediaType: {}", type, mediaType);
    return MultiPartMessage.class.isAssignableFrom(type)
            && mediaType.toString().toLowerCase().startsWith("multipart/form-data");
}

@Override
public MultiPartMessage readFrom(Class<MultiPartMessage> type, Type genericType, Annotation[] annotations,
        MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
        throws IOException, WebApplicationException {
    ...
}

"The @Provider annotation declares the class to JAXRS, which calls this reader when the de-marshalling of messages of content type multipart/from-data is required."

Aymara answered 26/7, 2022 at 18:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.