In this tutorial we will learn how to create a REST CRUD application in Quarkus, starting from a Hibernate Panache Entity. We will show two different approaches: in the first one we will create a REST Resources to map the CRUD methods. Then, we will show how to use REST Data Panache to generate automatically a REST Endpoint for an Entity.
Firstly, if you are new to Panache, we recommend checking this tutorial for some background on Hibernate Panache: Managing Data Persistence with Quarkus and Hibernate Panache
Setting up the Quarkus project
The first step is obviously to create a new Project with your favourite tool. If you are using the Quarkus CLI, then you can initialize a project “crud-demo” as follows:
quarkus create app crud-demo
Then, enter the project crud-demo and add the following extensions:
quarkus ext add hibernate-orm-panache jdbc-postgresql resteasy-reactive-jackson
Coding the Basic Crud Application
We will be using Panache Repository Pattern for our application, therefore, our Model will be a plain and simple Entity with just the field definition in it.
@Entity public class Ticket { @Id @GeneratedValue() Long id; @Column(length = 20) public String name; @Column(length = 3) public String seat; }
Our Repository Class will implement the PanacheRepository Interface. Therefore, we will be able to use the built-in CRUD methods on the Ticket Entity:
@ApplicationScoped public class TicketRepository implements PanacheRepository<Ticket> { }
Finally, the TicketResource is the REST Endpoint that wraps the standard GET, POST, PUT and DELETE methods with the corresponding TicketRepository methods:
@Path("crud/ticket") @ApplicationScoped @Produces("application/json") @Consumes("application/json") public class TicketResource { @Inject TicketRepository repository; @GET @Produces("application/json") public List<Ticket> get() { return repository.listAll(Sort.by("name")); } @GET @Path("{id}") public Response getTicketById(@PathParam("id") Long id) { return repository .findByIdOptional(id) .map(d -> Response.ok(d).build()) .orElse(Response.status(204).build()); } @POST @Transactional public Response create(Ticket ticket) { if (ticket.id != null) { throw new WebApplicationException("Id was invalidly set on request.", 422); } repository.persist(ticket); return Response.ok(ticket).status(201).build(); } @PUT @Path("{id}") @Transactional public Response update(@PathParam("id") Long id, Ticket ticket) { return repository .findByIdOptional(id) .map( t -> { t.name = ticket.name; t.seat = ticket.seat; return Response.status(204).build(); }) .orElse(Response.status(Status.NOT_FOUND).build()); } @DELETE @Path("{id}") @Transactional public Response delete(@PathParam("id") Long id) { repository.delete("id", id); return Response.status(204).build(); } }
Testing the CRUD Endpoint
To test our TicketResource you can use any tool such as curl or Postman. Since our application also includes an import.sql file to have some initial Tickets, we can test the HTTP GET method as follows:
Then, checkout the JSON Response:
[ { "name": "Chorus Line", "seat": "5B" }, { "name": "Mamma mia", "seat": "21A" }, { "name": "Phantom of the Opera", "seat": "11A" } ]
Then, try to insert some new data with the HTTP POST method:
Then, by including the Ticket id in the Path, we can update an existing Ticket via the HTTP PUT Method:
Finally, the HTTP DELETE method will delete a Ticket by including the id in the Path:
Generating Rest Endpoints with Panache
REST Data with Panache automatically creates REST resources based on the interfaces available in your application. To do that, you just need to provide a Resource Interface for each Entity and Repository Classes of your domain.
Firstly, let’s add the quarkus-hibernate-orm-rest-data-panache extension to the initial project:
quarkus ext add hibernate-orm-rest-data-panache smallrye-openapi
We also have added the smallrye-openapi to view all REST Endpoints available when we enable Panache REST Data.
Next, just add an Interface which extends Panache RepositoryResource:
public interface TicketResourcePanache extends PanacheRepositoryResource<TicketRepository, Ticket, Long> { }
The above interface will automatically create a REST Endpoint which naps the TicketRepository methods:
If you head to the Swagger UI (http://localhost:8080/q/swagger-ui/) you will see that your application now includes two REST Endpoints:
- The /crud/ticket Endpoint which maps the classic TicketResource Endpoint
- The /ticket-resource-panache which maps the Endpoint automatically generated by Panache REST:
You can test the above methods with the Postman script available in the tutorial’s source code. (See bottom of the article).
Conclusion
This article was a walk through the creation of REST CRUD Endpoints to map a Panache Respisitory of Data. In the first part of the article we have discussed how to create a standard REST CRUD Endpoint by injecting the Panache Repository in it. In the second part of the article we have discussed how to generate automatically the REST Endpoint by adding a PanacheRepositoryResource which maps your Repository.
Source code: https://github.com/fmarchioni/mastertheboss/tree/master/quarkus/panache-rest-demo