This article introduces you to an example application which uses RESTEasy Client library to access a remote REST Service.
RESTeasy is a Java library that provides a simple interface to the REST server. It supports all of the features of the Jakarta REST Services and includes support for both synchronous and asynchronous communication.
Firstly, there are really two ways to create a REST Client.
- Use Jakarta REST Client API
- Use ResteasyClientBuilder class.
In this article we will cover ResteasyClientBuilder. If you want to use a standard approach to write REST Client, we recommend checking this article: Getting started with JAX-RS Client API
RESTEasy Client Core API
In order to connect to a Remote REST Service with Client API, you can use the following APIs:
ResteasyClient client = (ResteasyClient)ClientBuilder.newClient(); ResteasyWebTarget target = client.target("http://host/service");
- The ResteasyClient is a builder of WebTarget instances. This interface wraps jakarta.ws.rs.client.Client adding some helper methods
- The ResteasyWebTarget represents a distinct URL or URL template to build subresource WebTargets or invoke requests on. This interface wraps the jakarta.ws.rs.client.WebTarget with some additional methods
To build a project which uses Resteasy Client API, we recommend adding a Bill of material and the following dependencies in your project:
<dependencyManagement> <dependencies> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-bom</artifactId> <version>${version.org.jboss.resteasy}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-core</artifactId> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-client</artifactId> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jackson2-provider</artifactId> </dependency> </dependencies>
An example application
Let’s see a concrete example, starting from the following REST Endpoint definition. This is an Endpoint which produces and consumes a set of Person objects:
@Path("/person") public class PersonResource { @Inject PersonService service; @GET public List<Person> findAll() { return service.getPersons(); } @GET @Path("/single") public Person findBySurname(@QueryParam("surname") String surname) { return service.findPersonBySurname(surname); } @DELETE public Response delete(Person person) { service.removePerson(person); return Response.status(204).build(); } @POST public Response add(Person person) { service.addPerson(person); return Response.status(201).build(); } }
Next, let’s code an example RestEasy Client application:
import jakarta.ws.rs.client.ClientBuilder; import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.client.Invocation; import jakarta.ws.rs.core.GenericType; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.jboss.resteasy.client.jaxrs.ResteasyClient; import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; import java.util.List; public class RestEasyClientDemo { static String BASE_URL ="http://localhost:8080/person"; public static void main(String args[]) { RestEasyClientDemo demo = new RestEasyClientDemo(); demo.addPerson("Bruce","Banner"); demo.findPerson("Banner"); demo.deletePerson("Peter","Parker"); demo.findPersons(); } public void findPersons() { ResteasyClient client = (ResteasyClient)ClientBuilder.newClient(); ResteasyWebTarget target = client.target(BASE_URL); Invocation.Builder request = target.request(); Response response = null; try { response = request.get(); List<Person> list = response.readEntity(new GenericType<List<Person>>() {}); System.out.println(list); } finally { response.close(); client.close(); } } public void findPerson(String surname) { ResteasyClient client = (ResteasyClient)ClientBuilder.newClient(); ResteasyWebTarget target = client.target(BASE_URL+"/single"); Invocation.Builder request = target.request(); Response response = null; try { response = request.get(); Person person = target.queryParam("surname", surname).request().get(Person.class); System.out.println(person); } finally { response.close(); client.close(); } } public void addPerson(String name, String surname) { ResteasyClient client = (ResteasyClient)ClientBuilder.newClient(); ResteasyWebTarget target = client.target(BASE_URL); Invocation.Builder request = target.request(); Response response = null; try { Person person = new Person(name,surname); response = target.request().post(Entity.json(person)); System.out.println(response.getStatusInfo()); } finally { response.close(); client.close(); } } public void deletePerson(String name, String surname) { ResteasyClient client = (ResteasyClient)ClientBuilder.newClient(); ResteasyWebTarget target = client.target(BASE_URL); Invocation.Builder request = target.request(); Response response = null; try { Person person = new Person(name, surname); response = target.request("application/json") .build("DELETE", Entity.entity(person, MediaType.APPLICATION_JSON)) .invoke(); System.out.println(response.getStatusInfo()); } finally { response.close(); client.close(); } } }
- The findPersons method returns a List of Person instances
- The findPerson returns a single Person instance passing the surname as QueryParam.
- The addPerson executes an HTTP POST to add a Person
- The deletePerson executes an HTTP DELETE to delete a Person
Finally, in all methods, the result of an invocation is an instance of Response. Therefore, you need to use the Response.close() method to release the connection. Releasing a connection makes it available for reuse.
By running the main Class, you should be able to run all the above methods:
$ mvn install exec:java
Source code for this example: https://github.com/fmarchioni/mastertheboss/tree/master/jax-rs/resteasy-client
How to customize the HTTP Client implementation
RESTEasy by default uses the HttpClient interface from the Apache HttpComponents project. The interface between the RESTEasy client API and the Server is configured through the ClientHttpEngine interface.
RESTEasy ships with four implementations of this interface. The default implementation is ApacheHttpClient43Engine. This implementation uses Apache 4.3.
As a matter of fact, you can provide a different implementation through the httpEngine method of the ResteasyClientBuilder.
Example:
public Client newClient() { return new ResteasyClientBuilder() .httpEngine(new OkHttpClientEngine(ok)) .build(); }
On the other hand, a more complex example is the following one. Here we configure the HttpClient engine to authenticate preemptively by pre-populating the authentication data cache:
AuthCache authCache = new BasicAuthCache(); // 2. Generate BASIC scheme object and add it to the local auth cache AuthScheme basicAuth = new BasicScheme(); authCache.put(new HttpHost("sippycups.bluemonkeydiamond.com"), basicAuth); // 3. Add AuthCache to the execution context BasicHttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.AUTH_CACHE, authCache); // 4. Create client executor and proxy HttpClient httpClient = HttpClientBuilder.create().build(); ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient, localContext); ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
Conclusion
In conclusion, this was a walkthrough RestEasy Client API and its HTTP Implementation. We covered a complete example which invokes a REST Service using its fluent Client API.