Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Jersey Client: com.sun.jersey.api.client.UniformInterfaceException

DZone's Guide to

Jersey Client: com.sun.jersey.api.client.UniformInterfaceException

· Java Zone
Free Resource

Managing a MongoDB deployment? Take a load off and live migrate to MongoDB Atlas, the official automated service, with little to no downtime.

As I mentioned in a post a couple of weeks ago we’ve been doing some which involved calling the neo4j server’s HA URI to determine whether a machine was slave or master.

We started off with the following code using jersey-client:


public class HaSpike {
    public static void main(String[] args) {
        String response = client()
                .resource("http://localhost:7474/db/manage/server/ha/slave")
                .accept(MediaType.TEXT_PLAIN)
                .get(String.class);
 
        System.out.println("response = " + response);
    }
 
    private static Client client() {
        DefaultClientConfig defaultClientConfig = new DefaultClientConfig();
        defaultClientConfig.getClasses().add(JacksonJsonProvider.class);
        return Client.create(defaultClientConfig);
    }
}

which works fine when the server is actually a slave:

response = true

but blows up in style if the server is the master:

Exception in thread "main" com.sun.jersey.api.client.UniformInterfaceException: GET http://localhost:7474/db/manage/server/ha/slave returned a response status of 404 Not Found
	at com.sun.jersey.api.client.WebResource.handle(WebResource.java:686)
	at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
	at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:507)
	at HaSpike.main(HaSpike.java:10)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

We return a 404 status code from that URI if you’re not a slave because it simplifies things for upstream load balancers but I thought Jersey would just return the body of the response rather than throwing an exception.

A quick browse of the Jersey code showed a way around this:

 private <T> T handle(Class<T> c, ClientRequest ro) throws UniformInterfaceException, ClientHandlerException {
        setProperties(ro);
        ClientResponse r = getHeadHandler().handle(ro);
 
        if (c == ClientResponse.class) return c.cast(r);
 
        if (r.getStatus() < 300) return r.getEntity(c);
 
        throw new UniformInterfaceException(r,
                ro.getPropertyAsFeature(ClientConfig.PROPERTY_BUFFER_RESPONSE_ENTITY_ON_EXCEPTION, true));
    }

WebResource#handle gets called by WebResource#get and if we pass ClientResponse.class to it instead ofString.class we can get around this because the code returns without checking the status of the response.

Our code needs to read like this:

public class HaSpike {
    public static void main(String[] args) {
        ClientResponse response = client()
                .resource("http://localhost:7474/db/manage/server/ha/slave")
                .accept(MediaType.TEXT_PLAIN)
                .get(ClientResponse.class);
 
        System.out.println("response = " + response.getEntity(String.class));
    }
 
    ...
}

And if we run it, this time we get the expected result:

response = false

MongoDB Atlas is the easiest way to run the fastest-growing database for modern applications — no installation, setup, or configuration required. Easily live migrate an existing workload or start with 512MB of storage for free.

Topics:

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}