This tutorial will teach you how to create an example REST (JAX-RS) CRUD application (to be run on the top of WildFly application server) which uses JPA to store your Resources.
Building the CRUD JAX-RS Service
Our JAX-RS Service will use the following HTTP methods to send and retrieve data from/to the server:
- GET: The GET method is used to retrieve data from the server. This is a read-only method,
- POST: This method sends data to the server and creates a new resource. The resource it creates is subordinate to some other parent resource.
- PUT: This method is most often used to update an existing resource.
- DELETE: This method is used to delete a resource specified by its URI.
Firstly, let’s create a Web project using a Maven archetype:
mvn archetype:generate -DgroupId=com.mastertheboss.jaxrs -DartifactId=jaxrs-DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
Then, we will add the Model object named Customer:
@Entity @NamedQuery(name = "Customers.findAll", query = "SELECT c FROM Customer c ORDER BY c.id") public class Customer { @Id @SequenceGenerator( name = "customerSequence", sequenceName = "customerId_seq", allocationSize = 1, initialValue = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "customerSequence") private Long id; @Column(length = 40) private String name; @Column(length = 40) private String surname; 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; } public String getSurname() { return surname; } public void setSurname(String surname) { this.surname = surname; } }
The interaction with the Customer object is done through a CustomerRepository Class which follows here:
@ApplicationScoped public class CustomerRepository { @PersistenceContext private EntityManager entityManager; public List<Customer> findAll() { return entityManager.createNamedQuery("Customers.findAll", Customer.class) .getResultList(); } public Customer findCustomerById(Long id) { Customer customer = entityManager.find(Customer.class, id); if (customer == null) { throw new WebApplicationException("Customer with id of " + id + " does not exist.", 404); } return customer; } @Transactional public void updateCustomer(Long id, String name, String surname) { Customer customerToUpdate = findCustomerById(id); customerToUpdate.setName(name); customerToUpdate.setSurname(surname); } @Transactional public void createCustomer(Customer customer) { entityManager.persist(customer); } @Transactional public void deleteCustomer(Long customerId) { Customer c = findCustomerById(customerId); entityManager.remove(c); } }
It is worth notice that, since the Repository is a CDI bean and not an EJB (which is by default a Transactional component), we need to specify the @Transactional annotation on the top of methods that execute a Transaction. Next on the list is the CustomerEndpoint class, which exposes to the Front-End a set of GET/POST/PUT and DELETE HTTP methods:
@Path("customers") @ApplicationScoped @Produces("application/json") @Consumes("application/json") public class CustomerEndpoint { @Inject CustomerRepository customerRepository; @GET public List<Customer> getAll() { return customerRepository.findAll(); } @POST public Response create(Customer customer) { customerRepository.createCustomer(customer); return Response.status(201).build(); } @PUT public Response update(Customer customer) { customerRepository.updateCustomer(customer); return Response.status(204).build(); } @DELETE public Response delete(@QueryParam("id") Long customerId) { customerRepository.deleteCustomer(customerId); return Response.status(204).build(); } }
The last Class we need to add is a JaxRsActivator which sets the Web context for the REST Service, activating it as well:
@ApplicationPath("/rest") public class JaxRsActivator extends Application { /* class body intentionally left blank */ }
Our example application will run against the default H2 Database which is provided in WildFly, so our persistence.xml will reference the ExampleDS Datasource for this purpose:
<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>
Within the folder resources we can add as well an import.sql script to have some Customer objects already available:
INSERT INTO customer (id, name, surname) VALUES ( nextval('customerId_seq'), 'Homer','Simpson'); INSERT INTO customer (id, name, surname) VALUES ( nextval('customerId_seq'), 'Bart','Simpson');
In order to build our projects, we can use the super-lean Jakarta EE dependency, which follows here:
<dependencies> <dependency> <groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-api</artifactId> <version>10.0.0</version> <scope>provided</scope> </dependency> </dependencies>
Here is the Project tree:
src └── main ├── java │ └── com │ └── mastertheboss │ └── jaxrs │ ├── CustomerEndpoint.java │ ├── CustomerException.java │ ├── Customer.java │ ├── CustomerRepository.java │ └── JaxRsActivator.java ├── resources │ ├── import.sql │ └── META-INF │ └── persistence.xml └── webapp ├── index.html └── WEB-INF └── beans.xml
Running the project
Start WildFly application server using any available configuration:
$ ./standalone.sh
Then, as our project includes the WildFly Maven plugin (check the source code below), we can simply run it as follows:
mvn install wildfly:deploy
Let’s test the GET method:
curl -s http://localhost:8080/jaxrs-demo/rest/customers | jq [ { "id": 1, "name": "Homer", "surname": "Simpson" }, { "id": 2, "name": "Bart", "surname": "Simpson" } ]
Next, let’s add one more Customer:
curl -d '{"name":"John", "surname":"Smith"}' -H "Content-Type: application/json" -X POST http://localhost:8080/jaxrs-demo/rest/customers
To verify that the Customer has been added:
curl -s http://localhost:8080/jaxrs-demo/rest/customers | jq [ { "id": 1, "name": "Homer", "surname": "Simpson" }, { "id": 2, "name": "Bart", "surname": "Simpson" }, { "id": 3, "name": "John", "surname": "Smith" } ]
Next, we will modify the Customer with id “3”:
curl -d '{"id":"3", "name":"Will", "surname":"Smith"}' -H "Content-Type: application/json" -X PUT http://localhost:8080/jaxrs-demo/rest/customers
Finally, to delete the Customer with id “3”:
curl -H "Content-Type: application/json" -X DELETE http://localhost:8080/jaxrs-demo/rest/customers?id=3
Conclusion
We have learned how to create a JAX-RS application to be deployed on a Jakarta EE application server.
Source code: https://github.com/fmarchioni/mastertheboss/tree/master/jax-rs/crud