Guia 01 - IA Backend - Aplicacao Nova com Core Canonico Atual

Guia 01 - IA Backend - Aplicacao Nova com Core Canonico Atual

Objetivo

Este guia orienta a criacao de uma nova aplicacao Spring Boot sobre o estado atual do praxis-metadata-starter.

O baseline canonico nao e mais o legado AbstractCrudController. Uma aplicacao nova deve nascer sobre:

Resultado esperado

Uma aplicacao nova deve sair com:

Dependencias minimas

Exemplo base:

<dependency>
  <groupId>io.github.codexrodrigues</groupId>
  <artifactId>praxis-metadata-starter</artifactId>
  <version>5.0.0-rc.2</version>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Observacoes:

Estrutura recomendada

src/main/java/{base-package}/
|-- {App}Application.java
|-- constants/
|   `-- ApiPaths.java
`-- {modulo}/
    |-- controller/
    |-- dto/
    |   `-- filter/
    |-- entity/
    |-- mapper/
    |-- repository/
    `-- service/

Como pensar resourcePath vs resourceKey

Antes de criar o primeiro controller, trate os dois campos como responsabilidades diferentes:

Na plataforma Praxis, resourceKey e a chave usada por discovery e capabilities. Ele alimenta consultas como:

Regra pratica:

Primeiro recurso canonico

O primeiro recurso de uma aplicacao nova deve nascer com:

Se houver um caso real de escrita parcial por intencao:

Se houver um caso real de workflow:

Controller canonico

@RestController
@ApiResource(value = ApiPaths.HumanResources.EMPLOYEES, resourceKey = "human-resources.employees")
@ApiGroup("human-resources")
public class EmployeeController extends AbstractResourceController<
        EmployeeResponseDTO,
        Long,
        EmployeeFilterDTO,
        CreateEmployeeDTO,
        UpdateEmployeeDTO> {

    private final EmployeeService service;

    public EmployeeController(EmployeeService service) {
        this.service = service;
    }

    @Override
    protected EmployeeService getService() {
        return service;
    }

    @Override
    protected Long getResponseId(EmployeeResponseDTO dto) {
        return dto.getId();
    }
}

O exemplo acima deixa explicita a separacao correta:

Read-only canonico

@RestController
@ApiResource(value = ApiPaths.HumanResources.PAYROLL_VIEW, resourceKey = "human-resources.payroll-view")
@ApiGroup("human-resources")
public class PayrollViewController extends AbstractReadOnlyResourceController<
        PayrollViewResponseDTO,
        Long,
        PayrollViewFilterDTO> {

    private final PayrollViewService service;

    public PayrollViewController(PayrollViewService service) {
        this.service = service;
    }

    @Override
    protected PayrollViewService getService() {
        return service;
    }

    @Override
    protected Long getResponseId(PayrollViewResponseDTO dto) {
        return dto.getId();
    }
}

Service canonico

@Service
public class EmployeeService extends AbstractBaseResourceService<
        Employee,
        EmployeeResponseDTO,
        Long,
        EmployeeFilterDTO,
        CreateEmployeeDTO,
        UpdateEmployeeDTO> {

    private final EmployeeMapper mapper;

    public EmployeeService(EmployeeRepository repository, EmployeeMapper mapper) {
        super(repository, Employee.class);
        this.mapper = mapper;
    }

    @Override
    protected ResourceMapper<Employee, EmployeeResponseDTO, CreateEmployeeDTO, UpdateEmployeeDTO, Long> getResourceMapper() {
        return mapper;
    }
}

Resource mapper canonico

@Component
public class EmployeeMapper implements ResourceMapper<
        Employee,
        EmployeeResponseDTO,
        CreateEmployeeDTO,
        UpdateEmployeeDTO,
        Long> {

    @Override
    public EmployeeResponseDTO toResponse(Employee entity) { ... }

    @Override
    public Employee newEntity(CreateEmployeeDTO dto) { ... }

    @Override
    public void applyUpdate(Employee entity, UpdateEmployeeDTO dto) { ... }

    @Override
    public Long extractId(Employee entity) {
        return entity.getId();
    }
}

Discovery que a aplicacao nova deve publicar

No baseline atual, um host novo deve expor pelo menos:

Os catalogos nao compartilham a mesma semantica de ausencia:

O que nao usar em aplicacao nova

Prompt recomendado para IA

Voce esta criando uma nova aplicacao Spring Boot sobre o baseline atual do praxis-metadata-starter.

Use o core canonico atual:
- AbstractResourceController / AbstractReadOnlyResourceController
- AbstractBaseResourceService / AbstractReadOnlyResourceService
- ResourceMapper
- @ApiResource(value=..., resourceKey=...)
- DTOs separados de response, create, update e filter

Gere:
- pom.xml coerente
- classe principal Spring Boot
- ApiPaths local
- modulo inicial resource-oriented completo

Nao gere AbstractCrudController nem BaseCrudService.
Nao gere payload inline em catalogos semanticos.

Checklist minimo

Antes de concluir a aplicacao nova:

Referencias