nacho4d
nacho4d

Reputation: 45128

Send JSON body but with ContentType=application/x-www-form-urlencoded with ClientBuilder

I know the question is weird. Unfortunately I have a service that requires everything to have the header ContentType=application/x-www-form-urlencoded, eventhough the body is JSON

I am trying to use JAX-RS 2.0 ClientBuilder to call it:

String baseUrl = "http://api.example.com/";

JSONObject body = new JSONObject();
body.put("key", "value");

Client client = ClientBuilder.newClient();
client.register(new LoggingFilter());
Builder builder = client.target(baseUrl).path("something").request();

Invocation inv = builder
    .header("Content-type", MediaType.APPLICATION_FORM_URLENCODED)
    .buildPost(Entity.json(body));
Response response = inv.invoke();

int status = response.getStatus();
// I get 415, unsupported media type (in this case is unexpected)

I have checked my logs and I eventhough I am setting application/x-www-form-urlencoded (via the MediaType) the request appearantly has the Content-type of application/json

How can I force the request to have the Content-type I want?


BTW: This is my custom logger:

public class LoggingFilter implements ClientRequestFilter {
    private static final Logger LOG = Logger.getLogger(LoggingFilter.class.getName());

    @Override
    public void filter(ClientRequestContext requestContext) throws IOException {
        LOG.log(Level.INFO, "body");
        LOG.log(Level.INFO, requestContext.getEntity().toString());
        LOG.log(Level.INFO, "headers");
        LOG.log(Level.INFO, requestContext.getHeaders().toString());
    }
}

And these are the logs I get:

com.acme.LoggingFilter                   I body
com.acme.LoggingFilter                   I {"key":"value"}
com.acme.LoggingFilter                   I headers
com.acme.LoggingFilter                   I {Content-type=[application/json]}

Upvotes: 1

Views: 4666

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 209092

The problem with trying to use one of the static Entity helper methods is that it overrides any previous Content-Type header you may have set. In your current case, Entity.json automatically sets the header to application/json.

Instead of using the .json method, you can just use the general purpose Entity.entity(Object, MediaType) method. With your current case though, you can just do Entity.entity(body, MediaType.APPLICATION_FORM_URLENCODED_TYPE) though. The reason is that the client will look for a provider that knows how to serialize a JSONObject to application/x-www-form-urlencoded data, which there is none. So you will need to first serialize it to a String. That way the provider that handles application/x-www-form-urlencoded doesn't need to serialize anything. So just do

Entity.entity(body.toString(), MediaType.APPLICATION_FORM_URLENCODED_TYPE);

Upvotes: 1

Related Questions