In this tutorial we will learn how to create a simple Hello World JPA application to be deployed on WildFly or any Java EE container.
Create the Maven project
We will need a Maven archetype to bootstrap a Web application project. You can use one simple like the following one:
mvn -DarchetypeGroupId=org.codehaus.mojo.archetypes \ -DarchetypeArtifactId=webapp-javaee7 \ -DgroupId=com.mastertheboss -DartifactId=jpa-basic \ -Dversion=1.1 -Dpackage=com.mastertheboss \ -Darchetype.interactive=false --batch-mode --update-snapshots \ archetype:generate
Now Let’s write our simple Entity class that we will persist in the Database:
package com.mastertheboss.model; import javax.enterprise.event.Event; import javax.inject.Inject; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.PostRemove; @Entity public class SimpleProperty { @Id @Column(name="id") private String key; private String value; public String getKey() { return key; } public void setKey(String key) { this.key = key; } @Override public String toString() { return "SimpleProperty [key=" + key + ", value=" + value + "]"; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
Now, in order to store our Entity in a transactional way, we need an EJB:
package com.mastertheboss.ejb; import java.util.List; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import com.mastertheboss.model.SimpleProperty; @Stateless public class ServiceBean { @PersistenceContext private EntityManager em; public void put(SimpleProperty p){ em.persist(p); } public void delete(SimpleProperty p){ Query query = em.createQuery("delete FROM SimpleProperty p where p.key='"+p.getKey()+"'"); query.executeUpdate(); } public List<SimpleProperty> findAll(){ Query query = em.createQuery("FROM SimpleProperty"); List <SimpleProperty> list = query.getResultList(); return list; } public SimpleProperty findById(String id){ SimpleProperty p = em.find(SimpleProperty.class, id); return p; } }
Finally, we need a front-end for our application. To keep it pretty simple, a basic REST Endpoint will be added:
package com.mastertheboss.rest; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import com.mastertheboss.model.SimpleProperty; import com.mastertheboss.ejb.ServiceBean; /** * JAX-RS Example * <p/> * This class produces a RESTful service to read/write the contents of the members table. */ @Path("/action") @RequestScoped public class RestService { @Inject private ServiceBean ejb; @GET @Produces(MediaType.APPLICATION_JSON) public List<SimpleProperty> listAllMembers() { return ejb.findAll(); } @GET @Path("/id/{id}") @Produces(MediaType.APPLICATION_JSON) public SimpleProperty findById(@PathParam("id") String id) { SimpleProperty p = ejb.findById(id); if (p == null) { throw new WebApplicationException(Response.Status.NOT_FOUND); } return p; } @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response createMember(SimpleProperty member) { Response.ResponseBuilder builder = null; try { ejb.put(member); // Create an "ok" response builder = Response.ok("Saved!"); } catch (Exception e) { // Handle generic exceptions Map<String, String> responseObj = new HashMap<>(); responseObj.put("error", e.getMessage()); builder = Response.status(Response.Status.BAD_REQUEST).entity(responseObj); } return builder.build(); } }
As you can see, the above REST endpoint has some basic methods for creating and querying our Entity objects, returning a JSON view of it.
In order to get it working, we need a REST Activator class:
package com.mastertheboss.rest; import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; @ApplicationPath("/rest") public class RestActivator extends Application { }
Done with the code, we will add a persistence.xml file to declare the mapping for our PersistenceContext objects:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="primary"> <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source> <properties> <!-- Properties for Hibernate --> <property name="hibernate.hbm2ddl.auto" value="create-drop" /> <property name="hibernate.show_sql" value="false" /> </properties> </persistence-unit> </persistence>
As you can see, we rely on the default Datasource which ships with WildFly. Here is the final project tree structure:
src └── main ├── java │ └── com │ └── mastertheboss │ ├── ejb │ │ └── ServiceBean.java │ ├── model │ │ └── SimpleProperty.java │ └── rest │ ├── RestActivator.java │ └── RestService.java ├── resources │ └── META-INF │ └── persistence.xml └── webapp ├── index.html └── WEB-INF └── beans.xml
Now compile the project:
$ mvn clean install
The deploy it on WildFly. We can start by adding some data using a POST with cURL:
$ curl --header "Content-Type: application/json" \ --request POST \ --data '{"key":"xyz","value":"xyz"}' \ http://localhost:8080/jpa-basic/rest/action
We can check that data was inserted with:
$ curl http://localhost:8080/jpa-basic/rest/action [{"key":"xyz","value":"xyz"}]
Much the same, we can query by id. It will return the same id:
$ curl http://localhost:8080/jpa-basic/rest/action/id/xyz [{"key":"xyz","value":"xyz"}]
That’s all! Enjoy your first JPA application example on WildFly!
You can find the source code for this JPA application on: https://github.com/fmarchioni/mastertheboss/tree/master/javaee/jpa-basic