Why are you using both Spring and Jersey annotations? You should stick to using the annotations meant for the framework. Since you are using Jersey, should stick to its its annotations.
So here are the things to consider about your current code and environment.
- There can't be two separate bodies. With your code, that's what it appears you expect to happen.
You can though put the JSON as part of the multi-part body. For that you should also annotate the SomeModel
with the Jersey @FormDataParam
@POST
@Path("somepath")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFileAndJSON(
@FormDataParam("model") SomeModel someModel,
@FormDataParam("file") FormDataBodyPart bodyPart) {
}
In the Jersey configuration, you need to make sure to register the MultiPartFeature
. If you don't the body won't be able to be deserialized, and you will get exceptions and error responses.
Now the Postman problem. You can see similar problem here. The problem was that the Content-Type
was not set for the JSON body part. For example the body might look something like
--AaB03x
Content-Disposition: form-data; name="model"
{"some":"model", "data":"blah"}
--AaB03x
Content-Disposition: form-data; name="file"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
You can actually see the body, if you hit the Preview button in Postman. The problem is that there is no Content-Type
for the "model"
part, as you can see in the "file"
part. This happens because you can't set individual parts' Content-Type
in Postman. The one that you will see will be discovered from the file extension. For example a .txt
file will make Postman set the Content-Type
to text/plain
and a .png
file to image/png
.
If you look in the link above, I proposed maybe you could use a .json
file instead of typing in the data. Of course that was just a theory. I didn't actually test it.
In any case, the Content-Type
must be set in order for Jersey to be able to know to deserialize it as JSON. If the .json
file extension theory doesn't pan out, then you can use a different client, like cURL, which I showed an example in the link, or you can use the Jersey client to test, as seen here.
Don't set the Content-Type
header to multipart/form-data
in Postman. It sets it for you when you use the form-data. I just saw a post where someone said there is bug when you set the header. Can't find the post now, and not something I've confirmed, but I'd just leave it out.
UPDATE
So the OP was able to find a way to set the Content-Type: application/json
to the "model" part. But it is sometimes the case where with a Javascript client, you are not able to set it. So there will be no Content-Type
. If this is the case, Jersey will not be able to deserialize the JSON, as it has no idea that it is actually JSON being sent. If you absolutely can't or have no idea how to set the Content-Type
for individual parts, you could resort to doing the following.
@POST
@Path("somepath")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFileAndJSON(@FormDataParam("model") FormDataBodyPart jsonPart,
@FormDataParam("file") FormDataBodyPart bodyPart) {
jsonPart.setMediaType(MediaType.APPLICATION_JSON_TYPE);
SomeModel model = jsonPart.getValueAs(SomeModel.class);
}