POST call to Jersey/Jax-rs endpoints with @FormParam using Retrofit @Field
As part of testing my endpoints, I use Retrofit. It is brilliant to say the least. But finding documentation on it can be a little tricky.
My endpoints had several parameters annotated with the @FormParam
annotation. When I tried to write an equivalent method in the Retrofit interface, I didn’t know what to annotate the fields with.
API (Ignore the Swagger annotations (ApiParam)
):
1
2
3
4
5
6
7
8
9
10
11
12
@POST
@Path ("/{category}/{type}")
@ApiOperation (value = "Upsert", notes = "Upserts data")
@Produces (MediaType.APPLICATION_JSON)
public Response upsertData(
@HeaderParam ("authorization") final String authorizationHeader,
@ApiParam (value = "Category to upsert", required = true) @PathParam (value = "category") final String category,
@ApiParam (value = "Type to upsert", required = true) @PathParam (value = "type") final String type,
@ApiParam (value = "Data", required = true) @FormParam (value = "data") final String data )
{
// Cutting things down to the bare necessities...
}
I tried the @Field
annotations:
1
2
3
4
@POST ("/{category}/{type}") Response upsertData(
@Path (value = "category") final String category,
@Path (value = "type") final String type,
@Field (value = "data") final String data);
I got this exception:
1
2
3
4
5
6
7
8
9
10
11
12
13
retrofit.RetrofitError: Client.upsertData: @Field parameters can only be used with form encoding. (parameter #3)
at retrofit.RetrofitError.unexpectedError(RetrofitError.java:44)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:400)
at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
at com.inferlytics.databrowser.helper.$Proxy6.upsertTrait(Unknown Source)
...
Caused by: java.lang.IllegalArgumentException: Client.upsertTrait: @Field parameters can only be used with form encoding. (parameter #3)
at retrofit.RestMethodInfo.methodError(RestMethodInfo.java:107)
at retrofit.RestMethodInfo.parameterError(RestMethodInfo.java:111)
at retrofit.RestMethodInfo.parseParameters(RestMethodInfo.java:356)
at retrofit.RestMethodInfo.init(RestMethodInfo.java:118)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:294)
... 32 more
I tried to change the @Field
annotations to @Part
and added a @Multipart
encoding. This time my server complained:
1
2
3
javax.servlet.ServletException: java.lang.IllegalStateException: The @FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:423)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:386)
As my endpoint didn’t have a problem when called correctly, I knew the problem was my client. I finally realized that I was missing the @FormUrlEncoded
annotation. I added it:
1
2
3
4
@POST ("/{category}/{type}") @FormUrlEncoded Response upsertData(
@Path (value = "category") final String category,
@Path (value = "type") final String type,
@Field (value = "data") final String data);
Things worked perfectly this time around! I hope this helps people who were stuck with something similar. I recommend Retrofit to everyone!