RESTful JPA Service

This example builds on the RESTful JSON Service example by adding an entity class that that enables the program to write to and read from an ObjectDB database.

The example was built with the following software configuration:

  • JDK1.8.0_45
  • Apache Tomcat v8.0.36
  • Eclipse Mars.2 Release (4.6.0)
  • ObjectDB 2.6.7_05

Steps

Before you begin, follow the instructions to create the RESTful JSON Service example, but name this project UIJSONJPABakerRESTJerseyServer. Make sure you change the name in the pom.xml and web.xml files for the new UIJSONJPABakerRESTJerseyServer project.

  1. Set up the class files.
  2. Add dependencies to the pom.xml file
  3. Prepare and Deploy the Project
  4. Start Tomcat Server
  5. Test Your Web Service
  6. Exercise

1. Set Up the Class Files

  • In the com.rest.jersey package, add the JPAEntity class.
  • Copy the following code into the JPAEntity class file.
  • Replace the contents of the  TbCupsService class file with the following TbsCupsService code. It follows the JPAEntity class code.

JPAEntity Class:

An entity class is a lightweight persistence domain object. Typically an entity represents a table in a relational database, and each entity instance corresponds to a row in that table. In this example, think of a table called JPAEntity with rows of text. Each time the user enters text and clicks the Click Me button, a new row with the entered text is added to the table.

A JPA entity class is a basic Java class that includes the @Entity notation and implements the Serializable interface. The required @ID notation indicates the field to be the primary key for the database table. The optional @GeneratedValue notation indicates how JPA generates the primary key. In this example, JPA auto-generates the primary key values.

A JPA entity class must have a no-argument constructor that JPA uses when it retrieves data from the database. The no-argument constructor is not used by the application.

package com.rest.jersey;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class JPAEntity implements Serializable{
  private static final long serialVersionUID = 1L;
  @Id 
  @GeneratedValue(strategy=GenerationType.AUTO)
  private int id;

  @SuppressWarnings("unused")
  private Double[] calc3;

  public JPAEntity() {/*No argument constructor for JPA to use*/}

    JPAEntity(Double[] calc3) {
    this.calc3 = calc3;
  }
}

TbsCupsService Class:

The code to access the entity class and to save and retrieve customer input is added to the ConvertTbstoCupsfromInput method. The method is shown in bold to make it easier to spot and the code is commented to explain what is going on.

package com.rest.jersey;
 
import java.util.Iterator;
import java.util.List;
import javax.persistence.*;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import com.rest.jersey.JPAEntity;
 
@Path("/ttocservice")
public class TbsCupsService {
 
  @GET
  @Produces("text/html")
  public Response convertTbstoCups() throws Exception {
    Double tbs = 32.0;
    Double cups;
    cups = (tbs/16.0);
    
    Double calc[];
    calc = new Double[2];
    calc[0] = tbs;
    calc[1] = cups;
      
    String result = "@Produces(\"text/html\") Output: \n\nTbs to Cups Output: \n\n" + "Tablespoons = " + calc[0] + "\n" + "Cups = " + calc[1];
    return Response.status(200).entity(result).build();
  }
  
  @Path("{t}")
  @GET
  @Produces("text/html")
  public Response convertTbstoCupsfromInput(@PathParam("t") 
         Double t) throws Exception { 
    Double cups;
    Double tbs = t;
    cups =  (tbs/16.0);
    
    Double calc[];
    Double calc2[];
    calc = new Double[2];
    calc2 = new Double[2];
    calc[0] = tbs;
    calc[1] = cups;
    
    //Call the method that writes to and reads from the database.
    //Capture the retrieved data in calc2, which is passed to the 
    //result string that is returned to the calling client.
    calc2 = accessDB(calc);
          
    String result = "@Produces(\"text/html\") Output: \n\nTbs to Cups Output from Database: \n\n" + "Tablespoons = " + calc2[0] + "\n" + "Cups = " + calc2[1];
    return Response.status(200).entity(result).build();
  }
  
  //Write data to and retrieve data from the ObjectDB database
  private Double[] accessDB(Double[] calc){
      Double[] calc3;
      calc3 = calc;
      Double[] entity = null;
      // Open a database connection
      // Create a new database if it doesn't exist yet
      EntityManagerFactory emf =
              Persistence.createEntityManagerFactory("$objectdb/db/JPAEntity.odb");
      EntityManager em = emf.createEntityManager();
      try {
      //Write to database:
        //Create entity class and intialize it with data
        JPAEntity jpaEntity = new JPAEntity(calc3);
        //Start a transaction
        em.getTransaction().begin();
        //Write data to the database
        em.persist(jpaEntity);
        //End the transaction
        em.getTransaction().commit();
      //Read all entries from the database
        em.getTransaction().begin();
        Query query = em.createQuery("SELECT calc3 FROM JPAEntity jpaEntity");
        @SuppressWarnings("rawtypes")
        List list = query.getResultList();
        @SuppressWarnings("rawtypes")
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
          entity = (Double[])iterator.next();
        }
        em.getTransaction().commit();
      } catch (com.objectdb.o._PersistenceException e) {
        System.out.println(e);
      } finally {
        try {
          em.close();
        } catch (java.lang.Exception e) {
          System.out.println(e);
      }
    }
    System.out.println("Values Read from DB:");
    System.out.println("#TBS to convert to cups: " + entity[0]);
    System.out.println("Equals the following #cups: " + entity[1] + "\n");
    return calc3;
  }  
}

2. Add Dependencies to the pom.xml File

  1. In the project, right-click pom.xml, select Open With > Maven POM Editor
  2. In the pom editor, select the Dependencies tab.
  3. Add the needed dependencies until the dependencies are the same as the following. Note that you can just copy and paste the repositories stanza (shown in bold) into the file into the location shown below. However, add the other dependencies through the pom editor as described in RESTful Web Service.
<project xmlns="http://maven.apache.org/POM/4.0.0" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>UIJSONJPABakerRESTJerseyServer</groupId>
  <artifactId>UIJSONJPABakerRESTJerseyServer</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <repositories>
    <repository>
        <id>objectdb</id>
        <name>ObjectDB Repository</name>
        <url>http://m2.objectdb.com</url>
    </repository>
    </repositories>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.5.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <warSourceDirectory>WebContent</warSourceDirectory>
          <failOnMissingWebXml>false</failOnMissingWebXml>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
      <dependency>
          <groupId>com.sun.jersey</groupId>
          <artifactId>jersey-bundle</artifactId>
          <version>1.19</version>
      </dependency>
      <dependency>
          <groupId>com.sun.jersey</groupId>
          <artifactId>jersey-server</artifactId>
          <version>1.19</version>
      </dependency>
      <dependency>
          <groupId>com.sun.jersey</groupId>
          <artifactId>jersey-core</artifactId>
          <version>1.19</version>
      </dependency>
      <dependency>
          <groupId>asm</groupId>
          <artifactId>asm</artifactId>
          <version>3.3.1</version>
      </dependency>
      <dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20151123</version>
    </dependency>
      <dependency>
          <groupId>com.googlecode.json-simple</groupId>
          <artifactId>json-simple</artifactId>
          <version>1.1</version>
      </dependency>
      <dependency>
          <groupId>javax.persistence</groupId>
          <artifactId>persistence-api</artifactId>
          <version>1.0</version>
      </dependency>
      <dependency>
          <groupId>javax.transaction</groupId>
          <artifactId>jta</artifactId>
          <version>1.1</version>
      </dependency>
      <dependency>
        <groupId>com.objectdb</groupId>
        <artifactId>objectdb</artifactId>
        <version>2.6.3</version>
    </dependency>
      <dependency>
          <groupId>com.google.appengine.orm</groupId>
          <artifactId>datanucleus-appengine</artifactId>
          <version>2.1.2</version>
      </dependency>
      <dependency>
          <groupId>org.hibernate.javax.persistence</groupId>
          <artifactId>hibernate-jpa-2.0-api</artifactId>
          <version>1.0.0-CR-1</version>
      </dependency>
  </dependencies>
</project>

3. Prepare and Deploy the Project

Specific instructions for the following steps are in the RESTful Web Service example:

    1. Clean, Update, and Build the service.
    2. Deploy the project to the server.
    3. Start Tomcat server.

4. Start Tomcat Server

    1. Right click Tomcat Server <version> at localhost.
    2. Select Start.

 5. Test Your Web Service

Add a numeric value at the end of the URI to indicate the number of tablespoons to convert to cups as shown in bold:

<protocol>://<service-name>/<ResourceType>/<ResourceID>/<Value>
http://localhost:8080/UIJSONJPABakerRESTJerseyServer/rest/ttocservice/16

ttocservice Parameterized Output:

@Produces("text/html") 
Output: Tbs to Cups Output from Database: 
Tablespoons = 16.0 Cups = 1.0

Note: Because a web service is accessed by many clients, once you make a URI public, it should always be available. If you must update a URI, use a redirect with the status code 300 to send clients from the old URI to the new one.

Check the Console window in Eclipse to see the following output.

Values Read from DB:
#TBS to convert to cups: 16.0
Equals the following #cups: 1.0

Try different values and then check both the web-based and console output. If you omit a value at the end of the URI, the convertTbstoCups method is called. There is no JPA code in that method because it always generates the same tablespoons and cups values.

Exercises

  1. Take the XML output and programmatically clean it up so that it can be put through an XLST transformer, and then displayed on a web page.
  2. Adapt the RESTful Client with JavaFX UI to work with this server. The main thing you would need to do is to change the URI call in the UICalculateCups class of the client.
Advertisements
RESTful JPA Service

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s