For a project, we had to migrate from WebSphere 8.5 with Java EE 6 to Liberty with Java EE 7. With these kinds of migrations, you tend to run into some trouble, where things no longer work as you expect.

Now, as a part of Java EE 7, Liberty supports JAX-RS 2.0, whereas on WebSphere 8.5 with Java EE 6 only JAX-RS 1.1 is supported. This is where the trouble began since there are several behavior changes between JAX-RS 1.1 and JAX-RS 2.0.

The issue I ran into had to do with a Multipart FileUpload which no longer worked on Liberty with the new version of JAX-RS 2.0.

In this blog, I like to highlight this specific issue, and how I solved this.

Multipart FileUpload with Java EE 6 and JAX-RS 1.1

The application I work on has a REST service which is called from an Angular front-end and has some functionality with a Multipart FileUpload. With JAX-RS 1.1 this is pretty straightforward coding using the @FormParm annotation for each part, like:

Multipart FileUpload with Java EE 7 and JAX-RS 2.0

In JAX-RS 2.0 there have been many API changes in handling a Multipart file. In JAX-RS 1.1 the @FormParam  could be used, in JAX-RS 2.0 only the @IMultipartBody  or @IAttachment  are available to handle a Multipart file.

Although the IBM knowledge center describes a resource method implementation for handling Multipart files with JAX-RS 2.0, it is no longer as straightforward and as clean of an implementation as it was with JAX-RS 1.1. With JAX-RS 2.0 we should now implement a resource method as follows (also see Configuring a resource to receive multipart/form-data parts from an HTML form submission in JAX-RS 2.0):

Drawbacks of the new implementation with JAX-RS 2.0

Why am I not too happy with the IBM knowledge center’s solution, and what are the drawbacks of this new implementation?

  • First of all, this code looks quite nasty and is hard to maintain, let alone unit test.
  • Secondly, this implementation is vendor-specific (IBM/WebSphere).
  • Lastly, this implementation only works for JAX-RS 2.0, whereas the first solution only works for JAX-RS 1.1.

Especially the last point is a bit of a concern. Since we gradually migrate from WebSphere 8.5, to WebSphere 9.0, to Liberty, we need to support multiple environments for a certain period. Therefore we prefer a single solution for the Multipart FileUpload which works for all three.

In my search, I came across a blog from Jason Lee: File Uploads with JAX-RS 2. In his blog, he describes an alternative solution for implementing Multipart FileUpload. The advantage of his solution is that the implementation is not vendor-specific.

Surprisingly, it works for WebSphere 8.5 and WebSphere 9.0, as well as for Liberty.

This is because the solution uses the Servlet 3 specification, which provides an implementation-independent way of dealing with multipart requests. Namely the javax.servlet.http.Part , which is supported in WebSphere 8.5, WebSphere 9.0 and Liberty.

Let’s try it out

For the generic solution, I took the code from Jason’s blog and refactored it a bit. The main logic is embedded in a MultipartRequestMap (for more details see File Uploads with JAX-RS 2):

Now the implementation of the resource method becomes fairly simple and clean again:

The method gets the HttpServletRequest  injected via the @Context  which we can then pass to the MultipartRequestMap . The MultipartRequestMap  constructor creates a map with all the parts from the request and through some convenience methods we then get the fields we need from the map for further processing.

All that’s left is to add the servlet and servlet-mapping details to your web.xml  Or use the correct annotations @ApplicationPath , @MultipartConfig , etc. if you want to do it without a deployment descriptor:

Isn’t there a more straightforward way?

Sure there is. As Jason also mentions in his blog, you can pass ‘real’ models as a method argument in the resource method, where all the magic is handled automatically. But you need the proper libraries for that, like Jersey, which are not always available by default.

The IBM JRE also often tends to have its own versions of a library, so including another external version often leads to conflicts, changes in classloading policies, etc. Which you want to avoid.

Besides, not every company allows you to include just any 3rd party library, which is the case for this project as well.

Conclusion

H/T to Jason Lee, his solution works in all of our three environments (WebSphere 8.5, WebSphere 9.0 and Liberty). It solves the breaking changes between JAX-RS 1.1 and JAX-RS 2.0 with regards to handling Multipart FileUpload. Without the abovementioned drawbacks.

Resources

JAX-RS 2.0 behavior changes
Multipart FileUpload
Configuring a resource to receive multipart/form-data parts from an HTML form submission in JAX-RS 2.0
Jason Lee: File Uploads with JAX-RS 2