Extending the CRUD Example Utilizing JAX-B and Jersey’s JSON

Introduction

In the previous article, REST CRUD:Jersey,Spring and JPA, we made a simple example which linked the technologies: REST, Spring, Jersey and JPA. We will take the example a little further, this time, by engaging the services of JAX-B and Jersey’s JSON.  There are some very useful annotations available to quickly make our classes accessible.

Previously when we sent the list of persons, in the database, to the client we did this with JSON but we constructed the JSON object via a utility method.  Now with the use of JAX-B 2.x and jersey-json we will do this throught the use of annotations.

From Model to JSON

There are two major steps that occur to transform our objects from the java instance to the JSON representation.

  1. The object is transformed into XML through the annotations provided by JAX-B. The actual transformation occurs behind the scenes involked as part of the following step.
  2. The REST operation on the object is marked-up to produce JSON.  This annotation is where the work happens.

On the client side we are already expecting the JSON objects so no change is required.  We will go on now to explain how to make these annotations.

Implemenation

New Dependencies

To enable these service a couple more dependencies need to be added to our pom.xml file: 

<dependency>
	<groupId>com.sun.jersey</groupId>
	<artifactId>jersey-json</artifactId>
	<version>${jersey-version}</version>
</dependency>
<dependency>
	<groupId>com.sun.xml.bind</groupId>
	<artifactId>jaxb-impl</artifactId>
	<version>2.1.10</version>
</dependency>

Marking up the Model

The entity we our using in our example is implemented in the Person.java class.   To make the Person class available for the JAX-B XML transformation we add two javax.xml.bind annotations.  Note that this is a minimal case and there are many options that can be explored to taylor what is exposed to XML.   The annotations are:

  • @XmlAccessorType(XmlAccessType.FIELD)
  • @XmlRootElement(name = "person")

The annotation express their purpose well.  The first indicates that the class fields used to construct the name/value pairs of the JSON object.  The second defines the top-level element available to us now through the name ‘person’. 

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "person")
@Entity
@Table(name = "PERSON")
@NamedQueries( { @NamedQuery(name = "Person.findAll", query = "SELECT p FROM Person p") })
public class Person {
	private static final long serialVersionUID = -142950147106627845L;
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;
	private String name;
	private int age;

	public Person() {
	}

The entire class can be viewed from the link below.

package com.persistent.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "person")
@Entity
@Table(name = "PERSON")
@NamedQueries( { @NamedQuery(name = "Person.findAll", query = "SELECT p FROM Person p") })
public class Person {
	private static final long serialVersionUID = -142950147106627845L;
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;
	private String name;
	private int age;

	public Person() {
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getId() {
		return id;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getAge() {
		return age;
	}
}

Annotating the Rest Resource

One annotation is required to configure the resource method to return using JSON:

  • @Produces("application/json")
     

 This annotation appears before the mthod as shown below.

 

@GET
@Produces("application/json")
public List<Person> getPersons() {
	log.info("getPersons entered");
	List<Person> persons = personService.getAll();
	return persons;
}

The entire class can be viewed in the  link below.

package com.persistent.rest;

import java.util.List;

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.QueryParam;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.persistent.entity.Person;
import com.persistent.service.PersonService;

@Component
@Path("/persons")
@Scope("request")
public class PersonResourceWs implements PersonResource {
	@Autowired
	PersonService personService;
	@Context
	UriInfo ui;
	private Logger log = Logger.getLogger(this.getClass());

	// The Java method will process HTTP GET requests

	/*
	 * (non-Javadoc)
	 *
	 * @see com.persistent.rest.PersonResource#getPersons()
	 */
	@GET
	@Produces("application/json")
	public List<Person> getPersons() {
		log.info("getPersons entered");
		List<Person> persons = personService.getAll();
		return persons;
	}

	@GET
	@Path("/{id}")
	@Produces("application/json")
	public Person getPerson(@PathParam("id") String id) {
		Person person = personService.getById(Integer.parseInt(id));
		return person;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see com.persistent.rest.PersonResource#updatePerson(java.lang.String,
	 * java.lang.String, java.lang.String)
	 */
	@PUT
	@Produces("text/plain")
	public String updatePerson(@QueryParam("id") String id,
			@QueryParam("name") String name, @QueryParam("age") String age) {
		log.info("updatePerson entered");
		log.info("name: " + name);
		log.info("age : " + age);
		log.info("id : " + id);

		if (StringUtils.hasText(id)) {
			log.info("It has an ID");
			int idd = Integer.parseInt(id);
			Person person = personService.getById(idd);
			if (person != null) {
				log.info("We found the person with that id");
				person.setAge(Integer.parseInt(age));
				person.setName(name);
				personService.update(person);
			}
		} else {
			Person person = new Person();
			person.setName(name);
			person.setAge(Integer.parseInt(age));
			personService.save(person);
		}
		return "nothing";
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see com.persistent.rest.PersonResource#addPerson(java.lang.String,
	 * java.lang.String)
	 */
	@POST
	@Produces("text/plain")
	public String addPerson(@QueryParam("name") String name,
			@QueryParam("age") String age) {
		log.info("addPerson entered");

		log.info("name: " + name);
		log.info("age : " + age);

		Person person = new Person();
		person.setName(name);
		person.setAge(Integer.parseInt(age));
		personService.save(person);
		return "nothing";
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see com.persistent.rest.PersonResource#deletePerson(java.lang.String)
	 */

	@DELETE
	@Path("/{id}")
	@Produces("text/plain")
	public String deletePerson(@PathParam("id") String id) {
		if(id!=null) {
			deletePersonById(id);
		}

		MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
		List<String> ids = queryParams.get("id");
		if(ids == null) {
			log.info("\n\nThe ids is null");
		} else {
			for (String currentid : ids) {
				deletePersonById(currentid);
			}
		}
		return "success";
	}

	private void deletePersonById(String id) {
		log.info("Delete Id: " + id);
		Person person = personService.getById(Integer.parseInt(id));
		if (person == null) {
			log.info("Null was returned for ID: " + id);
		} else {
			personService.delete(person);
		}
	}
}

 The Source Code

 Download the source code here:

crud2.zip

About The Author

David Sells is a computer consultant in Toronto, Ontario who specializing 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

1 comment to Extending the CRUD Example Utilizing JAX-B and Jersey’s JSON

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>