Search code examples
javajerseyjersey-2.0jersey-clientjersey-1.0

Convert Jersey 1.x client to Jersey 2.x client


I have the following code which works with jersey 1.x. However, I need to make it work with jersey 2.x and I noticed that a lot of the jersey classes and methods changed from one version to another. Any idea?

Client client = null;

try {
    URLConnectionClientHandler ch = new URLConnectionClientHandler(new ProxyConnectionFactory(proxyHost, proxyPort));
    client = new Client(ch);
    WebResource webResource = client.resource(url);
    ClientResponse response = ((Builder) webResource.type("application/json").header(authKey, authCreds)).post(ClientResponse.class, input);
    
    String output = (String) response.getEntity(String.class);
    System.out.println(output);
    if (response.getStatus() != 200) {
        System.out.println("Status Failed, Status: " + response.getStatus());
    }
    else {
        System.out.println("Connection Successful!");
        //additional code
    }
    
} catch (Exception e) {
    System.out.println("Exception occurred");
} finally {
    client.destroy();
}

In this code snippet, ProxyConnectionFactory is a class which sets the proxy configuration. It implements HttpURLConnectionFactory which is also a jersey 1.x interface.


Solution

  • The basic type analogs would be as follows:

    Jersey 1.x Jersey 2.x
    Client javax.ws.rs.client.Client
    WebResource javax.ws.rs.client.WebTarget
    ClientResponse javax.ws.rs.core.Response

    To build the client, you generally use one of the ClientBuilder static builder methods. The most basic one to use would be the newClient() method, which returns a new instance of the Client

    Client client = ClientBuider.newClient();
    

    If you need to configure the client, you can do so in multiple ways. For instance, if you need to register some properties or providers, you can:

    • Configure while building:

      Client client = ClientBuilder.newBuilder()
              .property("...", "...")
              .register(SomeProvider.class)
              .build();
      
    • Use a ClientConfig:

      ClientConfig config = new ClientConfig()
              .property("...", "...")
              .register(SomeProvider.class);
      Client client = ClientBuilder.newClient(config);
      
    • Configure the client directly

      Client client = ClientBuilder.newClient();
      client.property("...", "...");
      client.register(SomeProvider.class);
      

    Once you have a Client, you want to get a WebTarget. You would do that by providing a URI to the Client#target() method.

    Client client = ClientBuilder.newClient();
    WebTarget target = client.target(uri);
    

    If you need to do anything to the URI like add a path, query param, or matrix param, you would do so on the WebTarget. Otherwise you would now call the WebTarget#request() method to get an Invocation.Builder

    Client client = ClientBuilder.newClient();
    WebTarget target = client.target(uri);
    Invocation.Builder invBuilder = target.request();
    

    With the Invocation.Builder, you can add headers and finally make the request. You don't have to assign any new variable to the Invocation.Builder (or even the WebTarget for that matter). I did so for demonstrative purposes. You can continue to chain the method calls. For example

    Client client = ClientBuilder.newClient();
    client.target(url)
            .request()
            .header(authHey, authCreds)
    

    Finally to make the request, you would use one of the HTTP methods of the Invocation.Builder. In your case it would be the post() method. You can pass an Entity to this method and the result would be a Response

    Client client = ClientBuilder.newClient();
    Response res = client.target(url)
            .request()
            .header(authHey, authCreds)
            .post(Entity.json(input));
    

    To read the response, you use Response#readEntity(Class)

    String data = res.readEntity(String.class);
    

    If you have a POJO class you want the response to be deserialized to then pass that class to the readEntity() method. You will need to have a provider for whatever data type is expected. For example if it is JSON to be converted to a POJO, then you'll want to have the Jackson provider:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>${jersey2.version}</version>
    </dependency>
    

    Proxies

    As far as the proxy goes, Jersey has some properties you can set

    • ClientProperties.PROXI_URI

      Client client = ClientBuilder.newClient()
              .property(ClientProperties.PROXY_URI, String.format("%s:%s", host, port));
      

    See also

    • For full documentation on the Jersey 2.x client, see the docs