Skip to content

This project contains boilerplate code to turn simple quarkus rest-api development.

Notifications You must be signed in to change notification settings

Trajy/Quarkus-Base-Architecture

Repository files navigation

Quarkus Base Architecture

Maven Package pages-build-deployment Javadoc Licence MIT

This project contains boilerplate code to turn simple quarkus rest-api development. Uses the Strategy Design Pattern and Template Method Design Pattern to define different behaviors for each application domain.

Note

See How to install guide to add the project maven dependency from github packages.

Summary

Controller Implementation

A Rest controller that provides an end-point with CRUD Operations (http verbs GET, CREATE, UPDATE and DELETE) can be easily implemented just by inserting respectively the types of the Data Transfer Object (DTO), Entity, Service, and Assembly classes as arguments in the diamond operator <>.

@Path("/foos")
public class FooController extends AbstractPanacheController<FooDTO, FooEntity, FooService, FooAssembler> {

}

Note that @Path has /foos as argument, so the end-points will be:

Http Verb Uri
GET /foos
CREATE /foos
UPDATE /foos/{id}
DELETE /foos/{id}

If is necessary implement some code before or after Service bussiness logic, override the before or after methods.

In following exemple a property of object received from CREATE request is changed before it is passed to service layer.

@Path("/foos")
public class FooController extends AbstractPanacheController<FooDTO, FooEntity, FooService, FooAssembler> {

    @Override
    public void beforeCreate(FooDto dto) {
        dto.someProperty = "new value";
    }

}

Note

See JavaDoc to abstract classes details.

Assembly Implementation

The assembler must have overridden methods to perform the mapping between Entity and DTO classes, for UPDATE it must map the object attached to the database to the object with the new data as shown in the example.

@ApplicationScoped
public class FooAssembler extends AbstractPanacheAssembly<FooDTO, FooEntity> {

    @Override
    public FooEntity assembly(FooDTO dto) {
        return FooEntity.builder()
                .name(dto.name)
                .age(dto.age)
                .build();
    }

    @Override
    public FooDTO assembly(FooEntity entity) {
        return FooDTO.builder()
                .id(entity.id)
                .name(entity.name)
                .age(entity.age)
                .build();
    }

    @Override
    public void fillToAttachedEntity(FooEntity attached, FooEntity detached) {
        attached.name = detached.name;
        attached.age = detached.age;
    }

}

Tip

Additionally, the MapStruct dependency can help to automatically assembly code generation.

Service Implementation

Similarly to Controller Implementation, Service class need extends AbstractPanacheService type and passes the Entity type as an argument to the diamond operator <>.

Override methods to call static Hibernate with Panache implementations

However, due to the way quarkus works, to avoid the use of reflection, there are 3 methods that must be overridden with the call to static methods through the entities that inherit from PanacheEntity.

@ApplicationScoped
public class FooService extends AbstractPanacheService<FooEntity> {

    @Override
    protected List<FooEntity> findStaticMethod() {
        return FooEntity.<FooEntity>findAll().stream().toList();
    }

    @Override
    protected FooEntity findByIdStatidMethod(Long id) {
        return FooEntity.findById(id);
    }

    @Override
    protected void deleteByIdStaticMethod(Long id) {
        FooEntity.deleteById(id);
    }

}

Bussiness logic exemple

The bussiness logic can be declared into before and after methods.

@ApplicationScoped
public class FooService extends AbstractPanacheService<FooEntity> {

    @Override
    public beforeUpdade(Long id, FooEntity enitity) {
        // ...some bussiness logic
    }

    @Override
    public afterUpdate(Long id, FooEntity entity) {
        // ...some bussiness logic
    }
    
    // ...Overriden static call methods

}

Entity implementation

Classes annotated with @Entity must extend the PanacheEntity class.

@Entity
@Table(name = "foo")
public class FooEntity extends PanacheEntity {

    public String name;

    public Integer age;

}