262

With JSR 311 and its implementations we have a powerful standard for exposing Java objects via REST. However on the client side there seems to be something missing that is comparable to Apache Axis for SOAP - something that hides the web service and marshals the data transparently back to Java objects.

How do you create Java RESTful clients? Using HTTPConnection and manual parsing of the result? Or specialized clients for e.g. Jersey or Apache CXR?

Makyen
  • 31,849
  • 12
  • 86
  • 121
Yaba
  • 5,979
  • 8
  • 38
  • 44
  • 2
    check this out: http://igorpolevoy.blogspot.com/2011/01/java-rest-with-ease.html thanks igor – ipolevoy Jan 21 '11 at 22:34
  • If you are interesting in Eclipse plugin to generate a java client class from WADL, you can see at link http://stackoverflow.com/questions/9159881/restful-client-from-wadl/16709008#16709008 – pasquy73 May 29 '13 at 08:23
  • Just found [Apache Wink](http://wiki.apache.org/incubator/WinkProposal) in the Apache Incubator. Could be a interesting project for creating REST servers and clients. – Yaba Jul 29 '09 at 12:13
  • Check out [Resting]( http://code.google.com/p/resting). It promises to invoke REST services and create list of objects from XML/JSON/YAML response in one step. – neel Jul 21 '11 at 12:58
  • Resting has issues with POST requests. – RyanBrady Apr 26 '12 at 15:37
  • 2
    You can do it in a very simple way with resteasy (by Jboss). I wrote a blog post about [how to develop a Java REST client](http://guidogarcia.net/blog/2012/03/02/how-to-develop-java-rest-client/) if you want a getting started guide. Anyway, there are hundreds of alternatives in Java. – Guido Sep 16 '12 at 14:17
  • please find my solution here: http://stackoverflow.com/a/38724942/6668328 – Aditya Aug 03 '16 at 05:39
  • Why in the world would this be closed as "off topic"? – RussellH Oct 01 '20 at 23:16

17 Answers17

238

This is an old question (2008) so there are many more options now than there were then:

UPDATES (projects still active in 2020):

  • Apache HTTP Components (4.2) Fluent adapter - Basic replacement for JDK, used by several other candidates in this list. Better than old Commons HTTP Client 3 and easier to use for building your own REST client. You'll have to use something like Jackson for JSON parsing support and you can use HTTP components URIBuilder to construct resource URIs similar to Jersey/JAX-RS Rest client. HTTP components also supports NIO but I doubt you will get better performance than BIO given the short requestnature of REST. Apache HttpComponents 5 has HTTP/2 support.
  • OkHttp - Basic replacement for JDK, similar to http components, used by several other candidates in this list. Supports newer HTTP protocols (SPDY and HTTP2). Works on Android. Unfortunately it does not offer a true reactor-loop based async option (see Ning and HTTP components above). However if you use the newer HTTP2 protocol this is less of a problem (assuming connection count is problem).
  • Ning Async-http-client - provides NIO support. Previously known as Async-http-client by Sonatype.
  • Feign wrapper for lower level http clients (okhttp, apache httpcomponents). Auto-creates clients based on interface stubs similar to some Jersey and CXF extensions. Strong spring integration.
  • Retrofit - wrapper for lower level http clients (okhttp). Auto-creates clients based on interface stubs similar to some Jersey and CXF extensions.
  • Volley wrapper for jdk http client, by google
  • google-http wrapper for jdk http client, or apache httpcomponents, by google
  • Unirest wrapper for jdk http client, by kong
  • Resteasy JakartaEE wrapper for jdk http client, by jboss, part of jboss framework
  • jcabi-http wrapper for apache httpcomponents, part of jcabi collection
  • restlet wrapper for apache httpcomponents, part of restlet framework
  • rest-assured wrapper with asserts for easy testing

A caveat on picking HTTP/REST clients. Make sure to check what your framework stack is using for an HTTP client, how it does threading, and ideally use the same client if it offers one. That is if your using something like Vert.x or Play you may want to try to use its backing client to participate in whatever bus or reactor loop the framework provides... otherwise be prepared for possibly interesting threading issues.

tkruse
  • 10,222
  • 7
  • 53
  • 80
Adam Gent
  • 47,843
  • 23
  • 153
  • 203
  • 1
    Unfortunately Jersey client does not support PATCH method if used with JDK < 8 – botchniaque Dec 18 '14 at 12:16
  • 1
    as well as Jersey client has some serious memory leaks https://java.net/jira/browse/JERSEY-2830 – Dejell Jun 05 '15 at 11:09
  • 3
    Unirest is very easy to use but its static design makes it unusable in shared and server environments. – bekce Oct 12 '15 at 20:23
  • Unirest is easier but slower as compared to apache HttpClient. – Heisenberg Apr 07 '16 at 16:58
  • Here's another new one: [Netflix/feign](https://github.com/Netflix/feign) – dnault Jun 15 '16 at 18:49
  • 9
    Regarding the **unirest** comment, I would like to add that it currently (end of 2016) looks as if this project is no longer maintained. There is even an [issue](https://github.com/Mashape/unirest-java/issues/166) open that asks for a new maintainer. – wegenmic Oct 20 '16 at 07:05
  • Just want to add about NIO and doubts about its performance improvement: as always it depends on how we use the target REST API. Indeed, NIO benefits servers a lot because they handle a lot of requests in parallel. And indeed, for clients, there will be few benefit for short single REST calls. However, same as for servers, NIO will also shine on a client when you issue many requests in parallel. For example, calling GMail API to download 10 messages will consume 10 "units of time" with blocking IO, or 1 "unit of time" with NIO. So, NIO can be very important, *depending* on your usage. – Tim Feb 08 '17 at 17:35
  • @Adam Gent retrofit2 can be compared to jersey with Apache HTTP client ?? can retrofit2 be used to any java reas API (not android) and supports a high performance like jersey? Thank u – Chris Sim Feb 20 '17 at 13:51
  • Netflix Feign is also a good alternative https://github.com/OpenFeign/feign – Sai Surya Kattamuri Jul 15 '17 at 13:54
  • 4
    For those who like [Unirest](http://unirest.io/#java), I've got a [fork](https://github.com/josueeduardo/rest-client) of it that's currently being actively maintained / updated. – Josh Mar 23 '18 at 13:30
  • Jetty, Netty, HttpURLConnection in Java 8 and HttpClient in Java 9/10 – Sam Jul 03 '18 at 06:08
  • @Adam Gent Any information about which one of these rest clients is performant (over HTTPS) in terms of response time? – Aryan Venkat Nov 27 '18 at 06:39
  • _Unirest_ actively uses static configuration. Even cookies are saved as a static state (see https://stackoverflow.com/q/32442318/355438). That's why I strongly recommend NOT to use Unirest! – Ilya Serbis Mar 17 '19 at 19:28
  • 3
    would be nice to turn the answer into a community wiki – tkruse Mar 05 '20 at 14:10
77

As I mentioned in this thread I tend to use Jersey which implements JAX-RS and comes with a nice REST client. The nice thing is if you implement your RESTful resources using JAX-RS then the Jersey client can reuse the entity providers such as for JAXB/XML/JSON/Atom and so forth - so you can reuse the same objects on the server side as you use on the client side unit test.

For example here is a unit test case from the Apache Camel project which looks up XML payloads from a RESTful resource (using the JAXB object Endpoints). The resource(uri) method is defined in this base class which just uses the Jersey client API.

e.g.

clientConfig = new DefaultClientConfig();
client = Client.create(clientConfig);

resource = client.resource("http://localhost:8080");
// let's get the XML as a String
String text = resource("foo").accept("application/xml").get(String.class);        

BTW I hope that future versions of JAX-RS add a nice client-side API along the lines of the one in Jersey.

António Ribeiro
  • 4,129
  • 5
  • 32
  • 49
James Strachan
  • 9,168
  • 34
  • 31
  • Is there a method where we can mention REST service server list in ClientResource, in case the server is down try the next server? – Njax3SmmM2x2a0Zf7Hpd Jul 17 '12 at 09:43
  • 1
    Just an update, but to address James' 'BTW' comment, the new version of JAX-RS 2.0 will have a client-side API: http://www.infoq.com/presentations/Java-REST – Nick Klauer Oct 15 '12 at 13:38
69

You can use the standard Java SE APIs:

private void updateCustomer(Customer customer) { 
    try { 
        URL url = new URL("http://www.example.com/customers"); 
        HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
        connection.setDoOutput(true); 
        connection.setInstanceFollowRedirects(false); 
        connection.setRequestMethod("PUT"); 
        connection.setRequestProperty("Content-Type", "application/xml"); 

        OutputStream os = connection.getOutputStream(); 
        jaxbContext.createMarshaller().marshal(customer, os); 
        os.flush(); 

        connection.getResponseCode(); 
        connection.disconnect(); 
    } catch(Exception e) { 
        throw new RuntimeException(e); 
    } 
} 

Or you can use the REST client APIs provided by JAX-RS implementations such as Jersey. These APIs are easier to use, but require additional jars on your class path.

WebResource resource = client.resource("http://www.example.com/customers"); 
ClientResponse response = resource.type("application/xml");).put(ClientResponse.class, "<customer>...</customer."); 
System.out.println(response); 

For more information see:

bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • 27
    13 lines for a simple rest call, **in 2018**, sounds like way too much... – Clint Eastwood Feb 15 '18 at 19:14
  • 3
    Once you add error handling and options, it's not really significantly different. If the SE approach seems long, you can always wrap it in a class... :> After two days of debugging JAX-RS library conflicts I'm really fine with 5 extra lines of code to avoid the whole SPI nightmare. – tekHedd Mar 12 '19 at 19:18
  • 4
    @ClintEastwood this post was wrote in 2010 – 0ddlyoko Mar 20 '19 at 13:44
17

If you only wish to invoke a REST service and parse the response you can try out Rest Assured

// Make a GET request to "/lotto"
String json = get("/lotto").asString()
// Parse the JSON response
List<String> winnderIds = with(json).get("lotto.winners.winnerId");

// Make a POST request to "/shopping"
String xml = post("/shopping").andReturn().body().asString()
// Parse the XML
Node category = with(xml).get("shopping.category[0]");
reevesy
  • 3,452
  • 1
  • 26
  • 23
Johan
  • 37,479
  • 32
  • 149
  • 237
10

You can also check Restlet which has full client-side capabilities, more REST oriented that lower-level libraries such as HttpURLConnection or Apache HTTP Client (which we can leverage as connectors).

Best regards, Jerome Louvel

Jerome Louvel
  • 307
  • 1
  • 4
7

You could try Rapa. Let us know your feedback about the same. And feel free to log issues or expected features.

Jasper
  • 2,166
  • 4
  • 30
  • 50
7

I'd like to point out 2 more options:

Ophir Radnitz
  • 1,783
  • 2
  • 20
  • 18
6

I've recently tried Retrofit Library from square, Its great and you can call your rest API very easily. Annotation based configuration allows us to get rid of lot of boiler plate coding.

Yasitha Waduge
  • 13,180
  • 5
  • 35
  • 42
6

OkHttp is lightweight and powerful when combined with Retrofit as well. This works well for general Java use as well as on Android.

OkHttp: http://square.github.io/okhttp/

public static final MediaType JSON
    = MediaType.parse("application/json; charset=utf-8");

OkHttpClient client = new OkHttpClient();

String post(String url, String json) throws IOException {
  RequestBody body = RequestBody.create(JSON, json);
  Request request = new Request.Builder()
      .url(url)
      .post(body)
      .build();
  Response response = client.newCall(request).execute();
  return response.body().string();
}

Retrofit: http://square.github.io/retrofit/

public interface GitHubService {
  @GET("/users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}
Sam Edwards
  • 874
  • 8
  • 19
5

I use Apache HTTPClient to handle all the HTTP side of things.

I write XML SAX parsers for the XML content that parses the XML into your object model. I believe that Axis2 also exposes XML -> Model methods (Axis 1 hid this part, annoyingly). XML generators are trivially simple.

It doesn't take long to code, and is quite efficient, in my opinion.

JeeBee
  • 17,476
  • 5
  • 50
  • 60
  • 4
    In my opinion this is the worst way to do REST. Manually handling serialization in Java is a waste of time when you have so many options like JAXB and Jackson. Even loading the whole document and using XPath is marginally slower than SAX and nothing compared to getting the XML (network speed). – Adam Gent Feb 28 '11 at 18:59
  • 1
    I agree too, and I wrote the original comment. Back then I had a desire for control of the deserialisation, but nowadays I would use Jackson and decently annotated model classes. – JeeBee Oct 15 '13 at 09:18
4

Since no one mentioned, here is another one: Feign, which is used by Spring Cloud.

Leon
  • 3,124
  • 31
  • 36
3

Though its simple to create a HTTP client and make a reuest. But if you want to make use of some auto generated clients, You can make use of WADL to describe and generate code.

You can use RestDescribe to generate and compile WSDL, you can generate clients in php, ruby, python, java and C# using this. It generates clean code and there is a good change that you have to tweak it a bit after code generation, you can find good documentation and underlying thoughts behind the tool here.

There are few interesting and useful WADL tools mentioned on wintermute.

GG.
  • 2,835
  • 5
  • 27
  • 34
2

I wrote a library that maps a java interface to a remote JSON REST service:

https://github.com/ggeorgovassilis/spring-rest-invoker

public interface BookService {
   @RequestMapping("/volumes")
   QueryResult findBooksByTitle(@RequestParam("q") String q);

   @RequestMapping("/volumes/{id}")
   Item findBookById(@PathVariable("id") String id);
}
2

Examples of Jersey Rest client

Adding the dependency :

<!-- Jersey -->
<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>1.8</version>
</dependency>

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-server</artifactId>
    <version>1.8</version>
</dependency>
    
<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-client</artifactId>
    <version>1.8</version>
</dependency>

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20090211</version>
</dependency>

For GetMethod and passing two parameters:

Client client = Client.create();
WebResource webResource1 = client
                        .resource("http://localhost:10102/NewsTickerServices/AddGroup/"
                                + userN + "/" + groupName);

ClientResponse response1 = webResource1.get(ClientResponse.class);
System.out.println("responser is" + response1);

GetMethod passing one parameter and getting a response of type List :

Client client = Client.create();
 
WebResource webResource1 = client
                    .resource("http://localhost:10102/NewsTickerServices/GetAssignedUser/"+grpName);    
//value changed
String response1 = webResource1.type(MediaType.APPLICATION_JSON).get(String.class);
 
List <String > Assignedlist = new ArrayList<String>();
JSONArray jsonArr2 = new JSONArray(response1);
for (int i =0;i<jsonArr2.length();i++){
        
    Assignedlist.add(jsonArr2.getString(i));    
}

Above it returns a list that we are accepting as a List object and then converts it to JSONArray and then from JSONArray to List.

Post request passing JSONObject as a parameter:

Client client = Client.create();
WebResource webResource = client
            .resource("http://localhost:10102/NewsTickerServices/CreateJUser");
// value added

ClientResponse response = webResource.type(MediaType.APPLICATION_JSON).post(ClientResponse.class, mapper.writeValueAsString(user));

if (response.getStatus() == 500) {

    context.addMessage(null, new FacesMessage("User already exist "));
}
António Ribeiro
  • 4,129
  • 5
  • 32
  • 49
abhishek ringsia
  • 1,970
  • 2
  • 20
  • 28
2

I used RestAssured most of the time to parse rest service response and test the services. Apart from Rest Assured, I used below libraries too to communicate with Resful services.

a. Jersey Rest Client

b. Spring RestTemplate

c. Apache HTTP Client

Hari Krishna
  • 3,658
  • 1
  • 36
  • 57
0

Try looking at http-rest-client

https://github.com/g00dnatur3/http-rest-client

Here is a simple example:

RestClient client = RestClient.builder().build();
String geocoderUrl = "http://maps.googleapis.com/maps/api/geocode/json"
Map<String, String> params = Maps.newHashMap();
params.put("address", "beverly hills 90210");
params.put("sensor", "false");
JsonNode node = client.get(geocoderUrl, params, JsonNode.class);

The library takes care of json serialization and binding for you.

Here is another example,

RestClient client = RestClient.builder().build();
String url = ...
Person person = ...
Header header = client.create(url, person);
if (header != null) System.out.println("Location header is:" + header.value());

And one last example,

RestClient client = RestClient.builder().build();
String url = ...
Person person = client.get(url, null, Person.class); //no queryParams

Cheers!

g00dnatur3
  • 1,173
  • 9
  • 16
0

I am currently using https://github.com/kevinsawicki/http-request I like their simplicity and the way examples are shown, but mostly I was sold when I read:

What are the dependencies?

None. The goal of this library is to be a single class class with some inner static classes. The test project does require Jetty in order to test requests against an actual HTTP server implementation.

which sorted out some problems on a java 1.6 project. As for decoding json into objects gson is just invincible :)

Community
  • 1
  • 1
Edoardo
  • 4,485
  • 1
  • 27
  • 31