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