The intention of this article is to provide help to all people struggling with sending multipart requests using Spring Boot and Feign. I spent myself some time in research to solve this problem and thus, I want to share my experiences about this topic. Thanks to my company I have some days called labs to spend time on interesting topics. Hopefully it will help some of you to save some time configuring all necessary parts to get this up and running.
One additional word before we are starting with setting up the projects and configuration: In my sample project I am using Kotlin in the source code and Gradle configuration. However you can easily transfer this to Java or Groovy and use it the same way.
First we create a client and server application using the Spring Boot Initializr. In the client application Feign has also to be added as dependency, the server application does not need Feign. After generating the projects we have everything to get started with Spring Boot and Feign.
Before we are starting to create the Feign client and the configuration I want to point out a project which is included in the Spring Cloud Feign dependency. It is called Feign Form. In earlier versions of Spring Cloud OpenFeign this dependency had to be added manually. This is an important dependency when it comes to Spring Boot, Feign and multipart requests. It is providing the needed converter to use multipart files in our Feign client. We will revisit this at a later point.
We will now focus more on the client. The server is a simple Spring Boot application using REST. The interesting part is the Feign client and its configuration.
Creating Feign client
Now it is time to create our Feign client. I am using the domain “robots” for illustration in this article.
Now we have a Feign client with the name
robot-service-client using the path
/robots and sends its requests to
http://localhost:8080. On this address our server is listening to process the sent requests.
The next step is to add methods to interact with the server. We will start with the creation of some robots and the related methods to retrieve one robot and all robots: After this extension our client looks like as follows:
So far there is nothing special to handle multipart requests. The client application can now create a new robot, retrieve a specific robot or all robots. At this point our Feign client provides common methods to interact with our server.
Now we want to add a construction plan to a specific robot. Thus, we need a method to define the robot and handle the construction plan file. To achieve this the following method is added to our Feign client:
At a first glance we see all necessary parameters and an additional parameter
description. Furthermore we are using another media type to handle form-data. Normally form-data are sent by HTML forms but it also fits our case. We have the
description and the
document which could be single form-fields.
After a second glance something looks strange in this declaration. The first thing is the usage of
consumes and the second is the declaration of the fields
document. How on earth is this working? Is it working at all?
When all parts are finished, this includes the configuration, this declaration is working as expected. The usage of
consumes makes sense if we take into consideration that Feign is the client here and not the server. Using it on a controller
consumes defines the
Content-Type of a request. Feign switches the behaviour of
produces and thus, it defines the
Accept value of a Feign client. Because of this it is correct here.
The other thing using
@PathVariable as annotation for multipart requests is also strange. Unfortunately I do not have any good explanation why we have to declare our multipart fields in such a way. I did some research here as well but could not find any good explanation. Perhaps Feign is using other annotations like
@RequestPart for other purposes or it is not possible to use it for multipart requests. Another idea is that Feign Form is not supporting this annotation. These are all wild guesses. If somebody have more information about it leave a comment with the explanation. For now we have no choice but to accept that.
To conclude the Feign client creation here is the whole client declaration:
Configuring Feign client
We have to create a small configuration to use Feign clients in our application. To use Feign in our Spring Boot application we have to enable it:
Normally this would do the trick with Feign. In our case the Feign client is created and can be used. When we are adding a construction plan to one of our robots our client application is responding as follows:
As mentioned before a converter is missing to handle
MultipartFile parameters with a content type
multipart/form-data. Fortunately the aforementioned dependency Feign Form is providing such a converter. Therefore we have to adapt our
FeignConfig to use this converter:
With this addition we are able to send multipart request. Now the encoder of Feign Form is used and delegates all other types back to the normal Spring encoder. To give a short explanation why this is now working: Feign Form adds a specific multipart content processor to create a proper request. This is a Feign-specific content processor implementing Feign’s
ContentProcessor interface. Feign’s content processing is happing before Spring’s conversion service kicks in for content conversion.
This is all what I have to say about this topic. At the end the Feign client and its configuration is not so difficult but to find all information was quite hard. Hopefully it will help others to use Feign for multipart requests in a smooth way. If you have any comments about this article please leave a comment.
This blogpost is published by Comsysto Reply GmbH