dimanche 4 juillet 2010

RESTful service with JAX-RS (and JPA 2 for the access to the data)

This is the first part of two, which have for purpose to create a RESTful service with JAX-RS (part 1) and to access it in JavaFX (part 2)
In this first part, we will create a RESTful service using JAX-RS and because this service will have  an access to a database, we will use JPA 2.0.
To do that, we are going:
  • to create the database and one table
  • to create a data source 
  • to create the JPA entity and the persistence.xml
  • and to create the RESTful service which will call the entity

Create the database and the table
for the database and the the table, we'll re-use the derby database and the table created for the post : Examples using JPA 2.0.

Create a data source
  • Create a data source named jdbc/javafxDB and connected to the database in your application server.
    For Glassfish V3, create :
   One Connection pools for Derby named JavafxDBPool and with the parameters to access to the database.
For the parameters you should have something like this.

   One JDBC Resources with jdbc/javafxDB as JNDI Name and JavafxDBPool as Pool Name

The Entity and the persistance.xml
   One named query which will be used by the RESTful service
@NamedQuery(name = "findAllAlbumWhereArtisteLike",query="select m from Music m where m.artisteName like :param")
   And the annotation @XmlRootAnnotation for the JAXB serialization
@XmlRootElement
public class Music implements Serializable {
 

Music.java
      package paddy.entities;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author Patrick
 */
@Entity
@NamedQueries({
   @NamedQuery(name = "findAllAlbum", query= "select m from Music m"),
   @NamedQuery(name = "findAllAlbumWhereArtisteLike",query="select m from Music m where m.artisteName like :param")
})

@XmlRootElement
public class Music implements Serializable {

    @Id
    @GeneratedValue
    private Long id;
    @Column(name = "artist_name")
    private String artisteName;
    @Column(name = "album_title")
    private String albumTitle;

    public Music() {
    }

    public String getAlbumTitle() {
        return albumTitle;
    }

    public void setAlbumTitle(String albumTitle) {
        this.albumTitle = albumTitle;
    }

    public String getArtisteName() {
        return artisteName;
    }

    public void setArtisteName(String artisteName) {
        this.artisteName = artisteName;
    }

    public Long getId() {
        return id;
    }

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

    @Override
    public String toString(){

        StringBuilder sb = new StringBuilder();
        sb.append("id : ");sb.append(id);sb.append(" ; ");
        sb.append("artisteName : ");sb.append(artisteName);sb.append(" ; ");
        sb.append("albumTitle : ");sb.append(albumTitle);
        sb.append(" \n");

        return sb.toString();
    }
}
  • The persistence.xml file is very simple, it contains only:
   The name of the data source
       jdbc/javafxDB
   And the entity managed by the persistence unit.
       paddy.entities.Music

persistence.xml
      <?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="MusicAndLight" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/javafxDB</jta-data-source>
    <class>paddy.entities.Music</class>
  </persistence-unit>
</persistence>

The RESTful service
The service is very simple; it returns a list of all the records from the table where the field artisteName begin by the parameter "beginby". 

MusicServices.java
package services.restful;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import paddy.entities.Music;

/**
 *
 * @author patrick
 */

// curl http://localhost:8080/RESTfulServices/rs/ArtisteNameBeginningBy/Arc

@Path("/ArtisteNameBeginningBy")
@Stateless
@Produces ("application/json")
public class MusicServices {

    @PersistenceContext(unitName="MusicAndLight")
    EntityManager em;

    @GET
    @Path("{beginBy}/")
    public List<Music> getArtisteNameBeginningBy(@PathParam("beginBy") String beginBy){

       System.out.println("beginBy : "+beginBy);

       String param = beginBy+"%";
 
       Query  query = em.createNamedQuery("findAllAlbumWhereArtisteLike");
       query.setParameter("param", param);
       List<Music> musicsDB = query.getResultList();

       System.out.println("musicsDB : "+musicsDB);

       return musicsDB;

    }
}

The key points :
  • @Path
  • @Produce, the service produces a JSON output with the help of JAXB
  • @GET, the service is accessible by the method GET
  • @PersistenceContext, the entity manager is created and injected by the container
The web.xml
And of course you have to configure the Jersey Servlet in the web.xml

web.xml
<servlet>
        <servlet-name>Jersey</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey</servlet-name>
        <url-pattern>/rs/*</url-pattern>
    </servlet-mapping>

Now, let's test the service with:

  • curl
curl http://localhost:8080/RESTfulServices/rs/ArtisteNameBeginningBy/Arc
  • or your browser
http://localhost:8080/RESTfulServices/rs/ArtisteNameBeginningBy/Arc

and the result should be :

1 commentaire:

Unknown a dit…

Hi, it`s very usefull example !!!! Thanks for it!

But, there is one problem. EntityManager is null, when query method calls =(

Maby it`s a problem in my config, but a jboss (version 7.1) doesn`t post any error when parse a persistence unit.

Can you give me a hint, what wrong ?