Coding a REST CRUD Service
As with my previous introduction article to RESTful services using JAX-RS, the steps for setting up the project are similar and shown below for convenience, along with a few changes.
Step 1: Download a Reference Implementation to JAX-RS
In order to get started, you need to download a reference implementation of JAX-RS provided by the GlassFish project. Jersey provides a servlet that analyzes the incoming HTTP request and selects the correct class and method to respond to this request. This selection is based on annotation in the class and methods.
You can download Jersey zip file (core dependencies) from the Jersey website.
Step 2: Create Your Java Project
Using Eclipse, NetBeans, Maven, or whatever you like, create the project's directory structure (i.e., with Eclipse, use Dynamic Web Project). I'm calling the project jaxrscrud.
Next, copy all the Jersey core-dependency jars into the WEB-INF/lib folder of the project.
Step 3: Register the Jersey Reference Implementation Servlet with the Project
In order to get Jersey intercepting the requests, you need to modify the Web.xml file like the following:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>jaxrscrud</display-name> <servlet> <servlet-name>Jersey REST Service</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>crudOperations</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey REST Service</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping> </web-app>
The parameter com.sunjersey.config.property.packages should have the package where the web service classes can be found. In this example, the crudOperations package will contain these classes.
Step 4: Set Up a Database and JPA
For purposes of this section, I'm going to reuse the second page from an earlier article I wrote for doing these tasks. Perform the steps starting at the section titled "Configuring Apache Derby to Work with Eclipse" near the top of the page. Stop performing these steps when you reach the section labeled "Adding the User Entity Class, Login, and Welcome Pages." The last step should be adding a persistence.xml file to your project. The only thing to replace in the persistence.xml file code is the package where the Users class will reside. logon.User should be changed to crudOperations.User (see step 5). Also, add a few records to your new database table, so the service will have some data to work with.
Step 5: Create a Package Called crudOperations
While crudOperations is a bit vague, we would normally be more specific if exposing a particular application's Entity class (in this example, a class called Users). For example, we would probably just keep the class name the same, or if we're going to bundle several Entity classes for CRUD operations, then the vague package name would be more applicable.
Step 6: Create the User Entity Class that Will Map the User Object to the Users Database Table Created in Step 3
Because we are using the User Entity class from a previous article, copy the code for that class into the crudOperations package. The code is the first code section under the section labeled "Adding the User Entity Class, Login, and Welcome Pages."
Step 7: Create a Class that Registers Itself with a GET HTTP Request to Perform a Read Operation Using the User Entity Class
To expose this class as a RESTful web service, a few annotations were added to the code:
package crudOperations; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; @Path("/users") public class Users { private static final String PERSISTENCE_UNIT_NAME = "User"; private static EntityManagerFactory factory; private static String userName = null; // This method is called if TEXT_PLAIN is request @GET @Produces(MediaType.TEXT_PLAIN) public String userList() { factory = Persistence.createEntityManagerFactory (PERSISTENCE_UNIT_NAME); EntityManager em = factory.createEntityManager(); Query q = em.createQuery("SELECT u FROM User u"); List<User> userList = q.getResultList(); for (User user : userList) { userName = user.Name; } return userName; } }
The class is small right now, but if a request is made to the path users, the service will return the last user name in the table. By doing this, we know our service is interfacing with the database and returning data appropriately.
The @GET annotation tells Jersey to map this method of the class to the HTTP GET method. The @Produces annotation tells the servlet to respond with the correct content type based on the request.
Step 8: Add the JPA Facet to Your Project
Another step that needs to be performed is adding the JPA Facet to your project. Right-click your project (if in Eclipse) and choose the JPA Facet. Once you click OK, you'll see a new section added to your project called JPA content. Copy the code from your WEB-CONTENT/META-INF/persistence.xml file into the persistence.xml file of this section.
Step 9: Test the Service
To test the service, browse to the URL hosting the "RESTlet": http://localhost:8080/jaxrscrud/rest/users.
Because the content type of our Request Header was for plain text, the service returns the last user name in the users table to the screen. While the scope of this article started with an existing class and doing the application set up, you only need to do the last few steps for an existing Java application.
Conclusion
This simple example should be enough to get you started with exposing existing or new Entity classes as RESTful services. In a later article, I'd like to expand on this example to include a web-based client using AJAX and JSON to use the service. The expanded example will show how to send and consume data from the service using basic HTML web forms.