= JPA with EclipseLink and Jersey
:index-group: JPA
:jbake-type: page
:jbake-status: published

In this example a web service is created that stores and retrieves data from the database.
https://jersey.github.io/[Jersey] will be used to create the web service.
For the database, https://www.eclipse.org/eclipselink/[EclipseLink] JPA provider will be used.

The web service will store and retrieve information about persons:

[source,java]
----
@Entity
@XmlRootElement
@NamedQuery(name = "Person.findAll", query = "select p from Person p")
public class Person {

    @Id
    @GeneratedValue
    private long id;
    private String name;

    public long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
----

The two services our application provide are: persisting a person, retrieving all persons from the database:

[source,java]
----
@Singleton
@Lock(LockType.READ)
public class PersonDAO {

    @PersistenceContext
    private EntityManager em;

    public Person save(final String name) {
        final Person person = new Person();
        person.setName(name);
        em.persist(person);
        return person;
    }

    public List<Person> findAll() {
        return em.createNamedQuery("Person.findAll", Person.class).getResultList();
    }
----

Next, we are ready to expose as a service this business logic:

[source,java]
----
@Path("/person")
@RequestScoped
public class PersonService {

    @Inject
    private PersonDAO dao;

    public PersonService() {
        System.out.println();
    }

    @GET
    @Path("/create/{name}")
    public Person create(@PathParam("name") final String name) {
        return dao.save(name);
    }

    @GET
    @Path("/all")
    public List<Person> list() {
        return dao.findAll();
    }
----

Now, that we have a service class, defining the resources provided by the application, we extend the `javax.ws.rs.core.Application` class and we add our `PersonService`:

[source,java]
----
public class JerseyApplication extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        final Set<Class<?>> classes = new HashSet<Class<?>>();
        classes.add(PersonService.class);
        return classes;
    }
}
----

There is one more step to do, to configure a servlet provided by Jersey.
This can be done in `webapp/WEB-INF/web.xml`:

[source,xml]
----
<web-app 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"
         version="3.0">
  <servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>javax.ws.rs.Application</param-name>
      <param-value>org.superbiz.service.JerseyApplication</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey Web Application</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>
----

The web service is ready to be tested. For this, we will write an unit test using http://arquillian.org/[Arquillian]:

[source,java]
----
@RunWith(Arquillian.class)
public class JerseyApplicationTest {

    @Deployment(testable = false)
    public static WebArchive createDeployment() {
        return ShrinkWrap.create(WebArchive.class, "jersey-application.war")
                .addPackage(JerseyApplication.class.getPackage())
                .addPackage(Person.class.getPackage())
                .addPackage(PersonDAO.class.getPackage())
                .addAsManifestResource(new FileAsset(new File("src/main/webapp/WEB-INF/web.xml")), "web.xml")
                .addAsManifestResource(new ClassLoaderAsset("META-INF/persistence.xml"), "persistence.xml")
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
    }

    @ArquillianResource
    private URL webapp;

    @Test
    public void test() {
        get("person/create/TestPerson");

        String allPersons = get("person/all");

        assertTrue(allPersons.contains("<name>TestPerson</name>"));
    }

    private String get(String url) {
        final CloseableHttpClient client = HttpClients.custom().build();
        final HttpHost httpHost = new HttpHost(webapp.getHost(), webapp.getPort(), webapp.getProtocol());
        final HttpClientContext context = HttpClientContext.create();

        final HttpGet get = new HttpGet(webapp.toExternalForm() + url);
        CloseableHttpResponse response = null;
        try {
            response = client.execute(httpHost, get, context);
            return EntityUtils.toString(response.getEntity());
        } catch (final IOException e) {
            throw new IllegalStateException(e);
        } finally {
            try {
                IO.close(response);
            } catch (final IOException e) {
                // no-op
            }
        }
    }
}
----

We use Arquillian to programmatically start a new test container. In a test a person is persisted, then it's presence in database is checked by retrieving all person entities.

Full example can be found https://github.com/apache/tomee/tree/master/examples/tomee-jersey-eclipselink[here].
It's a maven project, and the test can be run with `mvn clean install` command.
