Consuming RESTful Web Services With the Jersey Client API

Guest Author

by Jakub Podlesak

Jersey 1.0 is an open-source, production-ready reference
implementation of JAX-RS, the Java API for RESTful
Web Services (JSR-311). Jersey makes it easy to create RESTful web services using Java technology.

An earlier Tech Tip,
Implementing RESTful
Web Services in Java
, introduced RESTful Web Services, JAX-RS, and Jersey. It also showed how using Java technology
you can write RESTful web services that conform to the JAX-RS specification. Another tip,
Configuring JSON for RESTful
Web Services in Jersey 1.0
, showed how to configure data in
JSON (JavaScript Object Notation) using Jersey 1.0.

In this tip, you will learn how to use the

Jersey 1.0.2 Client API
to consume HTTP-based RESTful Web Services. The Jersey 1.0.2 client API
is an easy-to-use, high level, Java technology API that can help you write clients for any HTTP-based RESTful
web service. The API is built on the uniform interface concept, one of the key principles of REST.
The uniform interface concept means that whatever URIs a REST-based application accesses, the interface to those
URIs should be the same

Jersey Client API Basics

To start working with the Jersey client API, you need to create an instance of the com.sun.jersey.api.client.Client
class. The simplest way to do that is as follows:

   import com.sun.jersey.api.client.Client;
Client client = Client.create();

The Client class is the main configuration point for building a RESTful web service client.
You use it to configure various client properties and features and indicate which resource providers to use.
Creating an instance of a Client is an expensive operation, so try to avoid creating an unnecessary
number of client instances. A good approach is to reuse an existing instance, when possible.

After you create a Client instance, you can start using it. However, to issue requests, you need
to create a WebResource object, which encapsulates a web resource for the client. For example, the following code
creates a WebResource object for a web resource whose URI is http://example.com/base:

   import com.sun.jersey.api.client.WebResource;
WebResource webResource = client.resource("http://example.com/base");

You use the WebResource object to build requests to send to the web resource and to process responses
returned from the web resource. For example, you can use the WebResource object for HTTP
GET, PUT, POST, and DELETE requests.

GET Request: Use the get() method in the WebResource class to submit an
HTTP GET request to the web resource:

   String s = webResource.get(String.class);

This means that if the URI for the WebResource object is http://example.com/base, an HTTP GET request is submitted
to the resource whose URI is http://example.com/base. If you're familiar with
curl, the command line HTTP tool, you'll see that:

   String s = webResource.get(String.class);

corresponds to the following curl command:

   curl http://example.com/base

You can specify query parameters in the get() request. For example, the following code specifies
two query parameters in the get() request:

   MultivaluedMap queryParams = new MultivaluedMapImpl();
queryParams.add("param1", "val1");
queryParams.add("param2", "val2");
String s = webResource.queryParams(queryParams).get(String.class);

This corresponds to the following curl command:

   curl http://example.com/base?param1=val1&param2=val2

You can also specify the acceptable MIME type for the response. For example, the following code specifies an acceptable
MIME type of text:

   String s = webResource.accept("text/plain").get(String.class);

This corresponds to the following curl command:

   curl -HAccept:text/plain http://example.com/base

In addition, you can get the HTTP status code for the request. Here, for example, is a request that returns a text entity
and a status code:

   ClientResponse response = webResource.accept("text/plain").get(ClientResponse.class);
int status = response.getStatus();
String textEntity = response.getEntity(String.class);

The ClientResponse object represents an HTTP response in the client.

PUT Request: Use the put() method in the WebResource class to submit an
HTTP PUT request to the web resource. For example, the following request puts a text entity foo:bar
into a web resource:

   ClientResponse response = webResource.type("text/plain").put(ClientResponse.class, "foo:bar");

This corresponds to the following curl command:

   curl -XPUT -HContent-type:text/plain --data "foo:bar" http://example.com/base

You can also specify query parameters in the put()request. You do this in a way that is similar to specifying
query parameters for a get() request. In the following example, the same query parameters that were used in the
previous get() method example are specified in a put() request:

  MultivaluedMap queryParams = new MultivaluedMapImpl();
queryParams.add("param1", "val1");
queryParams.add("param2", "val2");
ClientResponse response = webResource.queryParams(queryParams).put(ClientResponse.class, "foo:bar");

This corresponds to the following curl command:

   curl -XPUT -HContent-type:text/plain --data "foo:bar" http://example.com/base?param1=val1&param2=val2

POST Request: A POST request is a syntactic combination of a GET request and a PUT request, that is, you can
use a POST request to send an entity to a web resource and receive another entity. Use the post() method
in the WebResource class to submit an HTTP POST request to the web resource. For example, the following
code submits a POST request with query parameters and URL-encoded form data:

  MultivaluedMap formData = new MultivaluedMapImpl();
formData.add("name1", "val1");
formData.add("name2", "val2");
ClientResponse response = webResource.type("application/x-www-form-urlencoded").post(ClientResponse.class, formData);

This corresponds to the following curl command:

   curl -d name1=val1 -d name2=val2 http://example.com/base

DELETE Request: Use the delete() method in the WebResource class to submit an
HTTP DELETE request to the web resource. For example, the following request deletes the resource whose URI is

  ClientResponse response = webResource.path("user/123").delete(ClientResponse.class);

This corresponds to the following curl command:

   curl -XDELETE http://example.com/base/user/123

Note that the WebResource.path() method, which can also be used in all the HTTP request methods, allows you to
specify an additional path for the requested web resource. Another WebResource method, header(),
allows you to add an HTTP header to your request.

Configuring the Jersey Client

Before submitting requests, you might need to configure the client. This can involve
registering providers. You also have the option of adding filters.
See the

Jersey 1.0.2 Client API
for an overview of all possible options.

Registering Providers: In JAX-RS, a provider is an implementation of a JAX-RS extension.
A provider class is marked with a @Provider annotation. The Jersey server presents an infrastructure
for providers. In implementing JAX-RS, Jersey includes standard provider classes.
The Jersey client API reuses the same provider infrastructure as the Jersey server. However, you need to explicitly
register all non-standard providers because no automatic classpath scan takes place on the client side.

To register a provider, you need to add its provider class to the ClientConfig object for the
Client instance. The ClientConfig class declares the common property names, features, properties,
provider classes, and singleton provider instances that can be used by a Client object. For example, the
following code registers a JSON provider class for use by a Client object:

   ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);

Notice the use of the DefaultClientConfig class. It declares the default client configuration.

Adding Filters: Another option you have in configuring a client is to add filters to the client instance.
A filter dynamically intercepts requests and responses targeted to a resource class and can be used to modify the
request or response. The Jersey client API provides a number of classes that implement filters. One of them is
LoggingFilter, which implements a logging filter. You can use a logging filter to track communication
between the client and a server application, something that can be valuable in debugging. Here is how to add a
logging filter to the client:

   import com.sun.jersey.api.client.filter.LoggingFilter
client.addFilter(new LoggingFilter());

An Example of a Jersey-Based Client

Accompanying this tip is an example application that uses the Jersey client API to access the popular
Twitter web service. The example demonstrates the ability of the
Jersey Client API to consume real-world, HTTP-based web services. You can download the example application as a
Twitter client ZIP archive.
If you expand the archive, you can examine the source code for the client. You can also download a runnable
Twitter client JAR file
to test the application and see how it works. Note that you need Java SE Runtime Environment (JRE) 6 to run
the application.

Twitter: Twitter is a service that allows you to exchange short text messages with friends,
coworkers, family members, and others. The messages are designed to answer the question, "What are you doing?"
Here is an example of some messages displayed through Twitter.

Twitter messages
Twitter Messages


Twitter also provides a public Twitter API that you can
use to programmatically produce or consume Twitter messages and access other aspects of the service. If you use
the Twitter API, one thing you need to take into account is Twitter's authentication and security mechanism
and requirements.

Twitter Authentication and Security: Twitter uses a Basic HTTP authentication schema. This means that
if you access Twitter through its API, you need to add a special Authorization header to your request.
Then you will probably also want to secure the communication using the Secure Sockets Layer (SSL). You can do this
simply with the following code:

   ClientConfig config = new DefaultClientConfig();
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(null, myTrustManager, null);
config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(hostnameVerifier, ctx));
Client client = Client.create(config);

Examining the Client: Download the
Twitter client ZIP archive
and expand it. Navigate to the TwitterClient class in the
src\\main\\java\\com\\sun\\jersey\\techtips\\twitter directory. This is the Jersey-based client for the application.

As you examine the source code in the TwitterClient class, notice especially the following:

  • Code that creates the Client and WebResource objects:

       import com.sun.jersey.api.client.Client;
    import com.sun.jersey.api.client.WebResource;
    private static final String BaseURI = "https://twitter.com";
    private final WebResource wr;
    Client client = Client.create(config);
    wr = client.resource(BaseURI);

  • Code that configures the client:

       import com.sun.jersey.api.client.config.ClientConfig;
    import com.sun.jersey.api.client.config.DefaultClientConfig;
    ClientConfig config = new DefaultClientConfig();
    config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(hv, ctx));

  • Code that issues a get request:

       public List<StatusBean> getFriendsTimelineJson() {
    return wr.path("statuses/friends_timeline.json")
    .header(AUTHENTICATION_HEADER, authentication)
    .get(new GenericType<List<StatusBean>>() {

    Notice the addition of an Authentication header to the request.

Running the Example Application

To run the example application, do the following:

  1. If you do not have JRE 6 installed, download and install it .
  2. Download the
    Twitter client JAR file
  3. Issue the following command from the command line:

       java -jar jersey-twitter-client-1.0-SNAPSHOT-jar-with-dependencies.jar

    In response, you will be prompted for your Twitter user name and password. Respond to the prompts as appropriate.
    You should see then Twitter messages with timestamps. Here is an example:

    Simple Jersey (http://jersey.dev.java.net) based twitter client
    Twitter username:mytwitter
    Hello mytwitter!
    Status will get updated every 60 secs.
    Enter !exit to finish the session.
    Arun Gupta (1238705837), at: Mon Feb 23 00:04:40 +0000 2009:
    #slumdog is a favorite ... have not seen the movie yet but would be great if it
    's the first Indian movie to win ... fingers crossed!
    LarryLary (1238103969), at: Mon Feb 23 00:07:33 +0000 2009:
    Gonna go for a walk. Need some fresh air.
    kmollo (1239025876), at: Mon Feb 23 01:43:34 +0000 2009:
    enjoying everyone's '15 Albums That Changed Your Life' lists. I have been so
    bored, it's nice to have some 'new' music to check out!
    iFab @fauntleroy (1239103887), at: Mon Feb 23 02:02:20 +0000 2009:
    It's a beautiful day
    JessicaxG (1239248068), at: Mon Feb 23 02:36:34 +0000 2009:
    Shop. Shop. Shop. Another way to avoid things I need to do.
    DoughJoe (1239571723), at: Mon Feb 23 03:55:39 +0000 2009:
    Slumdog grabs it all
    > Congratulations to Kate Winslet on her best actress Oscar.
    Posted at: Tue Feb 24 16:54:17 +0000 2009

    Notice that you can also enter your own messages in the client.

Further Reading

For more information on Jersey, see the following resources:

About the Author

Jakub Podlesak is a member of the Jersey project team. Previously, he participated in the development of
Metro, the GlassFish web services stack, as a member of
the WS-Policy team. Read his blog.

2009 JavaOne Conference, June 2-5, San Francisco \*\* Register Now\*\*

Stay on top of everything new and different, both inside and around Java technology. Register by April 22, 2009,
and save $200 off a Conference Pass or Conference Plus Pass. Register now at

Join the discussion

Comments ( 24 )
  • govardhan reddy Saturday, March 7, 2009


  • reader Wednesday, March 18, 2009

    I am confused: how does the curl command tool have anything to do with jersey?

  • yadoo86 Wednesday, March 18, 2009


  • Jakub Wednesday, March 18, 2009

    @reader: curl has nothing to do with Jersey. I just have used curl as an analogy, because i believed many people interested in how web works were familiar with it.

  • Arnold Reuser Sunday, March 29, 2009

    Thanks for this wonderful piece of art:) Just a small question. While reading the sourcecode of jersey-client I wondered why the feature rich httpclient project wasn't used as the foundation layer.

    Any particular reason?

  • Patrick Monday, March 30, 2009

    In the twitter client code, for the postUpdate method, would it be simpler to have a way of populating the StatusBean with setters and just posting the resulting pojo ?

  • Patrick Monday, March 30, 2009

    While Im at it :) Would it also be easier and possible to have an annotated pojo build the proper path value instead of having a path and post method when working with URI's (a bit like on the server side of things) ?

  • Jakub Monday, March 30, 2009

    @Arnold Reuser: if you are referring to the apache httpclient project, there is another Jersey module (http://download.java.net/maven/2/com/sun/jersey/contribs/jersey-apache-client/ ) in Jersey contribs area, which uses just this as a basis.

    @Patrick: Do you mean, instead of sending the form data, or using the StatusBean to populate the form data? If the former, i am not sure twitter API allows this. If the latter, you would need another code to take care of the transformation. Another option would be to use Form class.

  • Patrick Monday, March 30, 2009


    Basically, add getters/setters to the status bean and post the populated bean instead of the map and the bean class.

    For my other post, it was a general point (not for Twitter specifically). I would really like to have the ability to create a simple annotated pojo that, once populated, I could post, which would build the proper uri (like the path/pathParam/queryParam annotation for the server).

  • Jakub Tuesday, March 31, 2009


    when posting, only the map parameter matters for the request, the bean class parameter is used just to tell Jersey, what instance you want to get out of the response.

    Regarding your POJO suggestion, could you, please, elaborate a bit and post a sample to users@jersey.dev.java.net of how the client code would look like?

  • Confused Friday, May 8, 2009

    I'm totally stuck with this...

    MultivaluedMap queryParams = new MultivaluedMapImpl();

    queryParams.add("param1", "val1");

    queryParams.add("param2", "val2");

    String s = webResource.queryParams(queryParams).get(String.class);

    I'm using netbeans 6.5.1 and when I make a webresource from the client the webresource object has no .queryParams method???? It's driving me crazy as I can't pass parameters on get requests!!!

  • Jakub Monday, May 11, 2009

    @Confused: it depends on what version of Jersey is actually used, and i am not sure about what you get by default with NetBeans 6.5.1. The methods have changed in the recent versions of Jersey so that your code could look like: webResource.queryParam("param1","val1").get(String.class)

    Please see https://jersey.dev.java.net/nonav/apidocs/1.1.0-ea/jersey/com/sun/jersey/api/client/WebResource.html for more details

  • Adhir Aima Wednesday, June 3, 2009

    is there not a way by which we can have a MVC based application consume the web services?

    e.g. I want to develop a small application which has a login page and the auth is done by a restful webservice, and then the flow is directed to another JSP page using the 1.1 impl of JAX-RS in jersey.

    Any example would be really helpful

  • Jakub Thursday, June 4, 2009

    @Adhir: you might want to download http://download.java.net/maven/2/com/sun/jersey/samples/jersey-samples/1.1.1-ea-SNAPSHOT/jersey-samples-1.1.1-ea-SNAPSHOT-project.zip which contains a number of Jersey examples, and look at the Bookstore application there. It shows, how to use MVC with Jersey. It does not cover authentication part, but for this you could look at the atompub-contacts example (consists of 3 separate modules). Also please feel free to e-mail to users@jersey.dev.java.net if you have further questions.

  • Virtual girl Sunday, August 23, 2009

    Realy Impressive. Jersey examples, and look at the Bookstore application there. It shows, how queryParams.add("param1", "val1");

    queryParams.add("param2", "val2");

  • Java Techie Tuesday, September 1, 2009

    How can I consume a restful web service that has a basic authentication mechanism. I mean how to pass the user credential through Client and WebResource?

  • Jakub Wednesday, September 2, 2009

    In the article, i have been directly adding the corresponding HTTP authentication header to each request. The simpler approach would be to employ com.sun.jersey.api.client.filter.HTTPBasicAuthFilter, and set it on the client like follows: client.addFilter(new HTTPBasicAuthFilter(username, password)); This should then automatically add the authentication header to all requests issued via web resources created from the client.

  • Paul Michiels Friday, November 6, 2009


    Just what I was searching for and what I was needing.


    Paul Michiels


  • vishal Friday, November 20, 2009

    I have used client.addFilter(new HTTPBasicAuthFilter(username, password)); to set the header from my client but in jax-rs webservice method when I am receiving it like "@HeaderParam("Authorization") String auth" then I am not getting the encoded value but some thing else.

    How to get the same encoded value which was set by client (internally) at recieving end.

  • moundir jamal Friday, November 20, 2009

    I'm trying to develop a simple client resful. The example I made work fine but I can't add an Authorization header with a user and password to my request !!! I need this data in the server side

    Any idea why this doesn't work ?


    Here is the code

    ClientConfig clientConfig = new DefaultClientConfig();

    Client client = Client.create(clientConfig);

    BASE64Encoder encoder = new BASE64Encoder();

    String encodedCredential = encoder.encode( (username + ":" + password).getBytes() );

    String authentication = "Basic " + encodedCredential;

    WebResource webResource = client.resource("http://localhost:8087/extranet/resteasy/algoService/algos");


    header(AUTHENTICATION_HEADER, authentication);

    // body is a hard-coded string, with replacements for the variable bits

    String response = webResource.get(String.class);

  • moundir jamal Friday, November 20, 2009

    Hi vishal

    I resolve my problem and yours by the way

    There's a problem on HTTPBasicAuthFilter in the method encodeCredentialsBasic(..).

    You need juste to change this method.

    I change it like this :

    authentication = "Basic " + encode(username + ":" + password);

    private String encode(final String string)


    byte[] bytes = getBytes(string);

    final int padding = (3 - (bytes.length % 3)) % 3;

    bytes = zeroPad(bytes.length + padding, bytes);

    final StringBuilder encoded = new StringBuilder();

    for (int i = 0; i < bytes.length; i += 3)


    final int threeBytes = (bytes[i] << 16) + (bytes[i + 1] << 8) + bytes[i + 2];

    encoded.append(c_base64code.charAt((threeBytes >> 18) & 0x3f)).

    append(c_base64code.charAt((threeBytes >> 12) & 0x3f)).

    append(c_base64code.charAt((threeBytes >> 6) & 0x3f)).

    append(c_base64code.charAt(threeBytes & 0x3f));


    return encoded.substring(0, encoded.length() - padding) + "==".substring(0, padding);


    private byte[] getBytes(final String string)


    byte[] bytes;



    bytes = string.getBytes("UTF-8");


    catch (final UnsupportedEncodingException e)


    bytes = string.getBytes();


    return bytes;


    private byte[] zeroPad(final int length, final byte[] bytes)


    final byte[] padded = new byte[length];

    System.arraycopy(bytes, 0, padded, 0, bytes.length);

    return padded;


    private static final String c_base64code = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +


    It works fine for me

    Hope it will help

  • Jakub Monday, November 23, 2009

    @Moundir Jamal, Visal: there was a bug - https://jersey.dev.java.net/issues/show_bug.cgi?id=278 - in previous versions of Jersey, which indeed caused Jersey client to sent a wrong Authentication header in the request. The issue was fixed. And at least from the version 1.1.3-ea, (i am using this in another project) this feature should behave correctly. If you use something older, you might want to try to upgrade the Jersey version used in your application (the newest stable version is now 1.1.4) to see if it fixes your issue in a more ellegant way than encoding the header by yourself. If it still breaks, please feel free to re-open the bug. Thanks!

  • Computer Service Toronto Monday, October 4, 2010

    what does curl has to do with jerserys.

  • Computer Service Toronto Monday, October 4, 2010

    curl and jerseys how they are united?

Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.