| = 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. |