- to setup Hibernate to use a datasource defined under Glassfish, see my other post.
- usefull Jersey annotations:
- for the resource class: @Path("/person/")
- for a method: @GET @Path("{personId}/") @Produces("application/json"). Then, you can use public Person getUser(@PathParam("personId") int personId) for method declaration.
- add @Consumes("application/json") with public Person post(Person person) method declaration. Jersey takes care of unmarshaling the Json into Person object.
- to return an error code from the restfull webservice, throw a new WebApplicationException(Response.Status.NOT_FOUND), for example. This one would return 404 error. No Need to declare the jersey handler method as "throws ...".
- to unit test the service, use com.sun.jersey.api.client.Client:
Person result = Client.create().resource("http://localhost:8080/myapp/person") .type("application/json") .post(Person.class,new Person("Jon Smith",133)); Assert.assertEquals("Jon Smith", result.getName()); - To pass an object retrieved via Hibernate as a response from a webservice, it needs to be serializable. But objects retrieved this way have additional members and so they need to be converted to a pure entity object (Person, in my case). I have used the Dozer library for this purpose (see the code below).
- The entity classes (Person and PersonCollection, in my example)need to be annotated with @XmlRootElement.
Code:
Complete web service implementation class code (in RESTfull, call a resource):
package olcc.jersey.service;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import olcc.entity.HibernateUtil;
import olcc.entity.Person;
import olcc.entity.PersonCollection;
import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;
import org.hibernate.Transaction;
import org.hibernate.classic.Session;
@Path("/person/")
public class PersonResource {
@GET @Path("{personId}/") @Produces("application/json")
public Person getPerson(@PathParam("personId") int personId) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = null;
Person personClean;
try{
tx = session.beginTransaction();
Person person = (Person) session.load(Person.class,personId);
Mapper mapper = new DozerBeanMapper();
personClean = mapper.map(person,Person.class);
session.getTransaction().commit();
} catch( Exception ex) {
if( tx != null ) tx.rollback();
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return personClean;
}
@GET @Produces("application/json")
public PersonCollection get() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List<person> result = session.createQuery("from Person").list();
Mapper mapper = new DozerBeanMapper();
PersonCollection persons = new PersonCollection();
for( Person person : result ) {
persons.add(mapper.map(person,Person.class));
}
session.getTransaction().commit();
return persons;
}
@POST @Consumes("application/json")
@Produces("application/json")
public Person post(Person person) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.save(person);
session.getTransaction().commit();
return person;
}
@GET @Path("delete/{personId}/") @Produces("application/json")
public Person deleteOne(@PathParam("personId") int personId) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Transaction tx = null;
Person personClean;
try{
tx = session.beginTransaction();
Person person = (Person) session.load(Person.class,personId);
session.delete(person);
Mapper mapper = new DozerBeanMapper();
personClean = mapper.map(person,Person.class);
session.getTransaction().commit();
} catch( Exception ex) {
if( tx != null ) tx.rollback();
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return personClean;
}
}Open Questions:
- I'm not sure where the Hibernate session should be closed. I don't think this can be done at the end of each handler method.
- How to use JTA for transaction management instead of direct JDBC transaction management?
- Most of the Hibernate-specific code should go into a DAO, with most of it into a generic DAO. But the recommended by Hibernate documentation generic DAO is defined in terms of state-oriented data access API (makePersistent() and makeTransient() methods), which are less intuitive for me. What is the advantage of using them and how to use them from CRUD operations?

1 comment:
You could have used jersey-json directly to map JSON/XML to your POJOs.
See this :
http://jersey.java.net/nonav/documentation/latest/json.html
Post a Comment