Introduction
In this article we are constructing a simple Jersey REST client API that will be available for use within projects that wish to take advantage of our Company Directory REST web service. This project is part of the continuing project whose purpose is to integrate technologies various technologies with in a Maven2 build environment. This article is extending a client project, presented in: Simple SOAP Client using XMLBeans, in this article we constructed client classes to interact with our SOAP interface into our web service. At the end of this article we will have a Maven2 dependency that will allow applications to interact with the Company Directory web service by either SOAP or REST.
When we introduced our our REST web service we created to client programs to interact with this service: one through Ajax calls and the other through Groovy. These articles are:
- The Ajax client was in the original REST article: REST Project Digest and Generic Data Repository
- The Groovy client was presented in: A Groovy Rest Client for the JPA, Jersey, Spring Integration Project
Implementation
One class is required for the implementation utilizing Jersey’s APIs. The coding is straight foward with a couple of places of interest. One being the use of Jersey’s GenericType. The GenericType class allows us to deal with type erase that happens in generic collections at run time. This loss of type information makes unmarshalling of collection data difficult as the type information has been removed.
The solution of this problem was done in steps.
- The entity objects was mapped into Data Transfer Objects.
- The data transfer classes have the JAXB annotations that will provide the XML utilized by Jersey’s JSON adapter.
- The collection classes of entities types are preserved through Jersey’s GenericType class
The REST server has the following API for providing a list of Companies:
@GET @Path("/companies") @Produces("application/json") public List<com.persistent.dto.Company> getCompanies() { List<Company> companies = companyDirectory.getCompanies(); List<com.persistent.dto.Company> companyDtos = new ArrayList<<com.persistent.dto.Company>(); for (Company company : companies) { com.persistent.dto.Company companyDto = servermapper.map(company, com.persistent.dto.Company.class); companyDtos.add(companyDto); } return companyDtos; }
The Jersey software intercepts the request and wraps the Generic collection with their GenericType. At the client side as shown in the code snippet below we are able to retrieve the Collection of Company objects through the use of the GenericType.
public Collection<Company> getCompanies() { WebResource.Builder builder = createWebResourceBuilder(UriBuilder .fromUri("http://localhost/").port(getPort(DEFAULT_PORT)).path( URL + "companies").build((Object[]) null)); GenericType<Collection<Company>> genericType = new GenericType<Collection<Company>>() { }; return builder.get(genericType); }
The remainder of the class is in the link below.
package com.persistent.rest; import java.util.ArrayList; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.UriInfo; import org.apache.log4j.Logger; import org.dozer.Mapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import com.persistent.entity.Person; import com.persistent.entity.Company; import com.persistent.service.CompanyDirectory; @Component @Path("/") @Scope("singleton") public class CompanyDirectoryRest { Logger log = Logger.getLogger(this.getClass()); @Autowired Mapper servermapper; @Autowired private CompanyDirectory companyDirectory; @Context UriInfo ui; @GET @Path("/persons") @Produces("application/json") public List<com.persistent.dto.Person> getPersons() { log.info("getPersons entered"); List<Person> persons = companyDirectory.getPersons(); List<com.persistent.dto.Person> personDTOs = new ArrayList<com.persistent.dto.Person>(); for (Person person : persons) { personDTOs.add(getPersonDto(person)); } return personDTOs; } private com.persistent.dto.Person getPersonDto(Person person) { com.persistent.dto.Person personDTO = servermapper.map(person, com.persistent.dto.Person.class); return personDTO; } @GET @Path("/companies") @Produces("application/json") public List<com.persistent.dto.Company> getCompanies() { List<Company> companies = companyDirectory.getCompanies(); List<com.persistent.dto.Company> companyDtos = new ArrayList<com.persistent.dto.Company>(); for (Company company : companies) { com.persistent.dto.Company companyDto = servermapper.map(company, com.persistent.dto.Company.class); companyDtos.add(companyDto); } return companyDtos; } @GET @Path("/person/{id}") @Produces("application/json") public com.persistent.dto.Person getPerson(@PathParam("id") final String sid) { Long id = Long.parseLong(sid); com.persistent.dto.Person result = null; Person person = companyDirectory.getPerson(id); if(person!=null) { result = getPersonDto(person); } return result; } @PUT @Consumes("application/json") @Path("/person/update") public void updatePerson(final com.persistent.dto.Person person) { Person personE = servermapper.map(person,Person.class); companyDirectory.updatePerson(personE); } @POST @Path("/person") @Consumes("application/json") @Produces("application/json") public com.persistent.dto.Person addPerson(final com.persistent.dto.Person person) { Person personE = servermapper.map(person,Person.class); return getPersonDto(companyDirectory.addPerson(personE)); } @DELETE @Path("/persons/{id}") @Produces("text/plain") public String deletePerson(@PathParam("id") final String sid) { Long id = Long.parseLong(sid); companyDirectory.deletePerson(id); final MultivaluedMap<String, String> queryParams = ui .getQueryParameters(); final List<String> ids = queryParams.get("id"); if (ids == null) { log.debug("\n\nThe ids is null"); } else { log.info("The ids are: "+ids.size()); for (String currentid : ids) { log.info("Delete: "+currentid); companyDirectory.deletePerson(Long.parseLong(currentid)); } } return "finished"; } @GET @Path("/company/{id}") @Produces("application/json") public com.persistent.dto.Company getCompany(@PathParam("id") final String sid) { log.info("Entering findByCompanyId Rest method"); return servermapper.map(companyDirectory.getCompany(Long.parseLong(sid)), com.persistent.dto.Company.class); } @GET @Path("/company/count") @Produces("text/plain") public String countSCompanies() { return companyDirectory.countCompanies().toString(); } @GET @Path("/person/count") @Produces("text/plain") public String countSPersons() { return companyDirectory.countPersons().toString(); } // The Java method will process HTTP GET requests @GET @Path("/persons/test") public String simpleTest() { return "Hello Foo"; } }
The installation instruction are similar to those given in this link:Simple SOAP Client using XMLBeans. There are JUnit test cases that will exercise the newly added functionality.
The Source Code
Follow this link to down load the source code.
About The Author
David Sells is a computer consultant in Toronto, Ontario who specializes in Java Enterprise Development. He has provided innovative solutions for clients including: IBM, Goldman Sachs, Merrill Lynch and Deutsche Bank.
He also holds the following certifications:
- Sun Certified Enterprise Architect for the Java Platform, Enterprise Edition 5 (2009)
- Sun Certified Web Component Developer
- Sun Certified Java Programmer.
Contact: david@persistentdesigns.com
[…] Jersey REST Client […]