Continue the series about Java REST client, I’d like to share how to create Java REST client using Apache CXF Proxy based API. In similar to the JBoss Resteasy Client Framework, there are several ways to implement REST client with Apache CFX client. The first one is to leverage the JAX-RS 2.0 Client API, the second is to use the Apache CFX Proxy-based API.
1. Preparation
Assume that we have a RESTful web service with several API as below:
1.1 Get all books
1 |
GET http://localhost:8080/v1/books |
1.2 Create a new book
1 |
POST http://localhost:8080/v1/books |
Example:
1 2 3 4 |
{ "name": "Java How To Program", "author": "Paul Deitel" } |
Responses: application/json
Example:
1 2 3 4 5 |
{ "id": 5 "name": "Java How To Program", "author": "Paul Deitel" } |
STATUS 201 if the book is created successfully.
1.3 Update a book
1 |
PUT http://localhost:8080/v1/books/{id} |
Example:
1 2 3 4 5 |
{ "id": 1, "name": "Java How To Program 2nd", "author": "Paul Deitel" } |
Responses: application/json
STATUS 200 if the book is updated successfully.
STATUS 400 if there is no book with given id
1.4 Delete a book
1 |
DELETE http://localhost:8080/v1/books/{id} |
STATUS 204 if the book is deleted successfully.
STATUS 400 if there is no book with given id or cannot delete the book.
1.5 Source code
The demo source code can be found on the Github.
We use Apache CXF Client API to communicate with the RESTful service above, and we will use Jackson JSON providers to deal with JSON content.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-client</artifactId> <version>3.0.3</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <version>3.0.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.7.5</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.6.3</version> </dependency> |
2. Create Java REST Client Using Apache CXF Proxy based API
Below are examples of creating Java REST client using Apache CXF Proxy based API. We will try to query, create, update and delete resources from the above REST service.
2.1. Define a Proxy Interface at the client side.
In similar to the JBoss Resteasy Client Proxy Framework approach, we just need to define a Proxy Interface at client side using JAX-RS annotation to invoke on a remote HTTP resource. Apache CXF Proxy-based API will take care of communicating with the resource over HTTP protocol and try to map the response to Java objects.
Here is the Proxy Interface defined based on the specification of the above REST API.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public interface BookResource { @GET List<Book> getAllBooks(); @POST Book createBook(Book book); @PUT @Path("/{id}") Book updateBook(@PathParam("id") Long id, Book book); @DELETE @Path("/{id}") void deleteBook(@PathParam("id") Long id); } |
The Book model is temporarily defined as below:
1 2 3 4 5 6 7 8 |
@JacksonXmlRootElement(localName = "book") public class Book { private Long id; private String name; private String author; //All getters and setters should be here } |
Let’s take a look at several methods of the BookResource
1 2 |
@GET List<Book> getAllBooks(); |
We just need to define the HTTP method required by the remote resource. This method will be intended to get all books from the resource; therefore, we use the HTTP GET method. We also want the response to be converted into a list of Books.
Another method is the updateBook
1 2 3 |
@PUT @Path("/{id}") Book updateBook(@PathParam("id") Long id, Book book); |
We defined this method based on the specification of the 3rd API which requires HTTP PUT method, the id of as the Path and the book as the request body.
2.2. Invoke methods on the Proxy
2.2.1. Make a GET request to the RESTful web service (Get all books)
1 2 3 4 5 6 7 8 9 10 11 12 |
public class BookRepositoryImplCXFProxy { private static final String URI_BOOK = "http://localhost:8080/v1/books"; public List<Book> getAllBooks() throws Exception { BookResource proxy = JAXRSClientFactory.create(URI_BOOK, BookResource.class, Collections.singletonList(new JacksonJsonProvider())); WebClient.client(proxy).accept(MediaType.APPLICATION_JSON_TYPE); return proxy.getAllBooks(); } } |
We create a simple main method to test as below:
1 2 3 4 5 |
public static void main(String[] args) throws Exception { BookRepositoryImplCXFProxy bookRepository = new BookRepositoryImplCXFProxy(); List<Book> books = bookRepository.getAllBooks(); System.out.println(books); } |
The output of my console is:
1 |
[Book [id=1, name=Java How To Program, author=Paul Deitel], Book [id=2, name=Thinking in Java, author=Bruce Eckel]] |
2.2.2. Make a POST request to the RESTful web service (create a book)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class BookRepositoryImplCXFProxy { private static final String URI_BOOK = "http://localhost:8080/v1/books"; public Book createBook(Book book) throws Exception { BookResource proxy = JAXRSClientFactory.create(URI_BOOK, BookResource.class, Collections.singletonList(new JacksonJsonProvider())); WebClient.client(proxy).type(MediaType.APPLICATION_JSON_TYPE); WebClient.client(proxy).accept(MediaType.APPLICATION_JSON_TYPE); Book createdBook = proxy.createBook(book); return createdBook; } } |
It’s pretty similar to above method, we need to specify the JacksonJsonProvider, accept the application/json MediaType produced by the remote resource and especially the MediaType of the request.
We update the main method to test:
1 2 3 4 5 6 |
public static void main(String[] args) throws Exception { BookRepositoryImplCXFProxy bookRepository = new BookRepositoryImplCXFProxy(); Book book = new Book(null, "Effective Java", "Joshua Bloch"); Book createdBook = bookRepository.createBook(book); System.out.println(createdBook); } |
The output of my console:
1 |
Book [id=4, name=Effective Java, author=Joshua Bloch] |
The book that has just been created, has the new field: id = 4
2.2.3. Make a PUT request to the RESTful web service (Update a book)
1 2 3 4 5 6 7 8 9 10 11 12 |
public class BookRepositoryImplCXFProxy { private static final String URI_BOOK = "http://localhost:8080/v1/books"; public Book updateBook(Book book) throws Exception { BookResource proxy = JAXRSClientFactory.create(URI_BOOK, BookResource.class, Collections.singletonList(new JacksonJsonProvider())); WebClient.client(proxy).accept(MediaType.APPLICATION_JSON_TYPE); WebClient.client(proxy).type(MediaType.APPLICATION_JSON_TYPE); Book updatedBook = proxy.updateBook(book.getId(), book); return updatedBook; } } |
1 2 3 4 5 6 7 8 9 10 11 |
public static void main(String[] args) throws Exception { BookRepositoryImplCXFProxy bookRepository = new BookRepositoryImplCXFProxy(); // Getting the first book from the RESTful service Book book = bookRepository.getAllBooks().get(0); System.out.println(book); // Change the name book.setName(book.getName() + " 3rd"); // Then update the book book = bookRepository.updateBook(book); System.out.println(book); } |
1 2 |
Book [id=1, name=Java How To Program, author=Paul Deitel] Book [id=1, name=Java How To Program 3rd, author=Paul Deitel] |
2.2.4. Make a DELETE request to the RESTful web service (delete a book)
1 2 3 4 5 6 7 8 9 |
public class BookRepositoryImplCXFProxy { private static final String URI_BOOK = "http://localhost:8080/v1/books"; public void deleteBook(Long id) { BookResource proxy = JAXRSClientFactory.create(URI_BOOK, BookResource.class); WebClient.client(proxy).accept(MediaType.APPLICATION_JSON_TYPE); proxy.deleteBook(id); } } |
1 2 3 4 5 |
public static void main(String[] args) throws Exception { BookRepositoryImplCXFProxy bookRepository = new BookRepositoryImplCXFProxy(); Book book = bookRepository.getAllBooks().get(0); bookRepository.deleteBook(book.getId()); } |
3. Conclusion
We have learned how to create Java REST client using Apache CXF Proxy based API. Apache CXF Proxy-based API provides us an easy way to implement REST client. One special point we can see that we can re-use the server resource interface for the Proxy Interface at the client. Note that on above examples, we have used the JAXRSClientFactory utility class to create the proxy, and this proxy can be reused many times, we don’t need to create a proxy for each request. On next posts, I’d like to share more examples of how to implement Java REST client with other frameworks like Netflix Fiegn, Retrofit.
Recently, I have posted some articles on the Java REST client topic, if you’d like to try other frameworks, you can reference from following links.
Java REST Client Using Retrofit 2
Simple Java REST Client Using java.net.URL package
Java REST Client Using Spring RestTemplate
Java REST Client Using Apache HttpClient
Java REST Client With Jersey Client
Java REST Client Using Resteasy Client Proxy Framework
Java REST Client Using Resteasy Client
Java REST Client Using Netflix Feign