Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

27 Commits

Folders and files

Repository files navigation

SpringShelf

API REST para registrar livros que estou estudando, com seus capítulos e anotações. O foco do projeto não é o produto, e sim aplicar Domain-Driven Design de forma concreta em Spring: modelar Book como aggregate root e fazer a persistência refletir essa fronteira, em vez de tratar as três entidades como tabelas soltas.

É a reescrita em Java/Spring do book_queue, onde Chapter e Note eram entidades independentes, sem invariantes garantidas pelo domínio. Baseado no livro Domain Driven Design Quickly (versão digital gratuita).

Decisão central: Book como aggregate root

O modelo tem três entidades numa hierarquia estrita — Book → Chapter → Note — e Book é a única acessível diretamente de fora. Isso está imposto em três camadas:

  • Persistência. Existe um único repositório: BookRepository. Não há ChapterRepository nem NoteRepository. Capítulos e notas só são carregados e persistidos através do Book, com cascade = ALL e orphanRemoval = true controlando o ciclo de vida. A fronteira de persistência é a fronteira do agregado.

  • Comportamento no domínio. As entidades são ricas. Criar um capítulo é book.addChapter(...), que recusa título vazio ou duplicado no mesmo livro; adicionar uma nota é chapter.addNote(...). Atualizações passam por métodos de domínio (updateDescription, updateSummary, updateContent) que validam antes de mutar. As regras vivem na entidade, não no service.

  • Orquestração fina nos services. Os services carregam a raiz, delegam a operação ao domínio e salvam pela raiz — sem regra de negócio própria. ChapterService e NoteService dependem apenas de BookRepository, então não existe caminho para manipular um capítulo ou nota fora do seu livro.

A hierarquia aparece também nas rotas, sempre aninhadas:

/books/{bookId}/chapters/{chapterId}/notes/{noteId}

Autenticação

A aplicação emite e valida os próprios tokens JWT — não é um resource server que confia em um provedor externo. No POST /auth/login, o AuthenticationManager valida usuário e senha (BCrypt) e o JwtService assina um JWT RS256 com uma chave RSA privada e validade de 1 hora. A validação usa o oauth2-resource-server apenas como mecanismo: um JwtDecoder verifica a assinatura com a chave pública do mesmo par RSA. A sessão é stateless.

Autorização atual: GET é público, assim como /auth/login; qualquer outra requisição exige JWT válido.

Tratamento de erros

Um @RestControllerAdvice traduz exceções em respostas HTTP padronizadas (timestamp, status, error, path), separando erros de domínio de infraestrutura:

Exceção HTTP Origem
ResourceNotFoundException 404 Raiz do agregado não encontrada
EntityNotFoundException 404 Capítulo/nota inexistente no agregado
DomainValidationException 400 Invariante de domínio violada
BusinessRuleException 409 Regra de negócio (ex.: título duplicado)
MethodArgumentNotValidException 422 Falha na validação dos DTOs, com erros por campo

Os DTOs são validados com Bean Validation na entrada; o domínio revalida suas próprias invariantes de forma independente.

Stack

Java 17 · Spring Boot 3.5.11 (Web, Data JPA, Security) · Hibernate/JPA · PostgreSQL · OAuth2 Resource Server com assinatura RS256 (Nimbus) · Bean Validation · Lombok · springdoc/OpenAPI.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages