Accessing JPA from JAX-RS service directly

I wanted to create a REST service that uses JPA bean and i wanted to see if i can do that without using a EJB and these are my notes about how to do that. You can download the sample application from here. I am using JEE 6 compliant Websphere application Server for testing this code. First i did create the Contact.java which is my JPA entity like this

package com.webspherenotes.jpa;

import java.io.Serializable;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlRootElement;


/**
 * The persistent class for the CONTACT database table.
 * 
 */
@Entity
@XmlRootElement
public class Contact implements Serializable {
  private static final long serialVersionUID = 1L;

  @Id
  private int contactid;

  private String email;

  private String firstname;

  private String lastname;

    public Contact() {
    }

  public int getContactid() {
    return this.contactid;
  }

  public void setContactid(int contactid) {
    this.contactid = contactid;
  }

  public String getEmail() {
    return this.email;
  }

  public void setEmail(String email) {
    this.email = email;
  }

  public String getFirstname() {
    return this.firstname;
  }

  public void setFirstname(String firstname) {
    this.firstname = firstname;
  }

  public String getLastname() {
    return this.lastname;
  }

  public void setLastname(String lastname) {
    this.lastname = lastname;
  }

}
Next i had to create a persistence.xml file like this in the META-INF folder like this

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="MyJPAJAXRS">
    <jta-data-source>jdbc/demodb</jta-data-source>
    <class>com.webspherenotes.jpa.Contact</class>
  </persistence-unit>
</persistence>
As you can see from my persistence.xml my application has only one entity which is Contact.java. Next declare the persistence-context-ref in the web.xml file like this

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name>MyJPAJAXRS</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <persistence-context-ref>
    <persistence-context-ref-name>
      MyJPAJAXRS
    </persistence-context-ref-name>
    <persistence-unit-name>MyJPAJAXRS</persistence-unit-name>
    <persistence-context-type>Transaction</persistence-context-type>
  </persistence-context-ref>
</web-app>
This is how my REST service looks like, note that you cannot inject EntityManager directly in your REST service class because your creating object of the REST service class in Application object instead of container creating it, so you would have to do some more work to look up the EntityManager in the init method of the REST service class like this

package com.webspherenotes.jpa;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
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.MediaType;

@Path("/contact")
public class ContactService {
  
  @PersistenceContext(name="MyJPAJAXRS")
  EntityManager entityManager;
  
  @PostConstruct
  public void init(){
    System.out.println("Entering ContactService.init()");
    try {
      InitialContext context = new InitialContext();
      entityManager = (EntityManager)context.lookup("java:comp/env/MyJPAJAXRS");
      System.out.println("Object of mySessionBeanLocal " + entityManager);
    } catch (NamingException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    System.out.println("Exiting ContactService.init()");
  }

  @GET
  @Produces(MediaType.APPLICATION_XML)
  public List getContactList(){
    System.out.println("Inside ContactService.getContactList() " );
    Query q = entityManager.createQuery("SELECT x from Contact x");
  
    return (List)q.getResultList();
  }

  @POST
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
  @Produces(MediaType.APPLICATION_XML)
  public Contact insertContact(@FormParam("contactId")int contactId,@FormParam("firstName")
  String firstName,
      @FormParam("lastName")String lastName,@FormParam("email") String email) {
    Contact contact = new Contact();
    contact.setContactid(contactId);
    contact.setFirstname(firstName);
    contact.setLastname(lastName);
    contact.setEmail(email);
    entityManager.persist(contact);
    return contact;
  }
  
  @GET
  @Path("/{contactId}")
  @Produces(MediaType.APPLICATION_XML)
  public Contact getContact(@PathParam("contactId")int contactId) {
    Contact contact = entityManager.find(Contact.class, contactId);
    return contact;
  }

  @PUT
  @Path("/{contactId}")
  @Produces(MediaType.APPLICATION_XML)
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
  public Contact updateContact(@PathParam("contactId")int contactId,@FormParam("firstName") 
  String firstName,
      @FormParam("lastName")String lastName,@FormParam("email") String email) {
    Contact contact = new Contact();
    contact.setContactid(contactId);
    contact.setFirstname(firstName);
    contact.setLastname(lastName);
    contact.setEmail(email);
    entityManager.merge(contact);
    return contact;
  }
  @DELETE
  @Path("/{contactId}")
  public void deleteContact(@PathParam("contactId")int contactId) {
    Contact contact = new Contact();
    contact.setContactid(contactId);
    entityManager.remove(contact);
  }
  
  
}

2 comments:

Anonymous said...

the init() method was never called for me

Softql said...

Good blog better services more information our site <a href='http://www.softql.com/services/infrastructure-management-services/datacenter">rf services </a>