Over a million developers have joined DZone.

Jersey WebResource - Header Don't Get Appended

· Java Zone

Learn more about the advantages of moving from a monolithic to microservices architecture.  Brought to you in partnership with IBM.

Yesterday I ran into a strange problem when using the Jersey WebResource class for doing HTTP calls: it seemed as if the headers I set, simply got ignored when executing the HTTP call. Read ahead.

What I tried to achieve was to call a REST Api to get some data from on of our applications. For doing so, I used the Jersey client, and obviously I also had to forward the received authorization token in order to authenticate the user on the target application. Not knowing the Jersey Api in detail, what I did was the following (not exactly, but adapted for this post to illustrate the scenario):

WebResource resource = Client.create(new DefaultClientConfig()).resource("http://myapp.org/api/v1/data");
resource.header(HttpHeaders.AUTHORIZATION, "Negotiate " + token);

return resource.get(String.class);

However, the Negotiate token didn't get appended, at least that was what I noticed explicitly as I got a "401 Authorization denied" response. Logging the HTTP requests on my Apache further underlined my assumptions.

As an attempt, I slightly rewrote the code to the following

return Client
    .create(new DefaultClientConfig()).resource("http://myapp.org/api/v1/data")
    .header(HttpHeaders.AUTHORIZATION, "Negotiate " + token)

..and hey, it worked! WTF? What was going on here?

The Builder pattern

What seems insane initially, gets much clearer when you take a look at how - for instance - accept(...) is implemented on thecom.sun.jersey.api.client.WebResource class:

public Builder accept(String... types) {
    return getRequestBuilder().accept(types);

You get a new Builder object each time! That's why it doesn't work. So instead of the wrong version above, you rather have to write it like this:

WebResource resource = Client.create(new DefaultClientConfig()).resource("http://myapp.org/api/v1/data");

WebResource.Builder builder = resource.accept(MediaType.APPLICATION_JSON);
builder.header(HttpHeaders.AUTHORIZATION, "Negotiate " + token);

return builder.get(String.class);

Note, the first call resource.accept() returns the Builder object, and any subsequent calls to type() and header() work directly on that builder instance.

You can even invert the sequence of calls, like, calling firstresource.type(..) and then accept and so on. Why? Because both,WebResource.Builder as well as WebResource itself implement the same interface RequestBuilder, just that the WebResource's implementation creates a new Builder object, while the Builder's implementation really adds the passed information onto a metadata collection.


The Builder pattern is a common approach to simplify the creation of object instances by hiding the implementation details, especially in Java. Normally you invoke a series of methods that add information to your object, to finally call the build() method which returns the desired instance. The WebResource class totally hides this. Now, not having coded in Java for quite a while, I'm not sure whether the way WebResource implemented the Builder pattern is a common one, but I find it highly distracting and might lead to nasty errors. At least, it cost me a couple of hours to figure out why my authentication scenario didn't work.

From Idea to Application gives you the architecture to quickly build, manage and run a range of applications (web, mobile, big data, new smart devices, etc.) on an open-standard, cloud-based platform. See why developers are using IBM Bluemix. Brought to you in partnership with IBM.


Published at DZone with permission of Juri Strumpflohner, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}