Over a million developers have joined DZone.

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

· Java Zone

Discover how powerful static code analysis and ergonomic design make development not only productive but also an enjoyable experience, brought to you in partnership with JetBrains

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

Learn more about Kotlin, a new programming language designed to solve problems that software developers face every day brought to you in partnership with JetBrains.

Topics:

The best of DZone straight to your inbox.

SEE AN EXAMPLE
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.
Subscribe

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

{{ parent.tldr }}

{{ parent.urlSource.name }}