Skip to main content

Developer Guide


1. Purpose

This guide explains how to implement and extend the Portal Backend at a code-level. It complements the Architectural Overview and describes how Controllers, Services, Assemblers, Mappers, Repositories, and the Domain Model are instantiated for entities like DataSpace or DataSet.


2. Implementation Flow for a New Entity

Introducing a new entity follows a consistent pattern:

  1. Model (Entity, DTOs, Specifications)
  2. Data access (Repository, Specification wiring)
  3. Mapping (MapStruct Mapper)
  4. Business logic (Service + lifecycle hooks)
  5. Response construction (Assembler)
  6. API exposure (Controller)

Each layer reuses shared base components with minimal entity-specific code.


3. Controllers – API Entry

Controllers are thin REST adapters and delegate all logic to Services and Assemblers.

  • Extend BaseController with generics for: Input DTO, Output DTO, Entity, Specification, ID (usually UUID).

  • Base CRUD endpoints are provided:

    • GET /resource – list + filters/pagination
    • GET /resource/{id} – detail
    • POST /resource – create
    • PUT /resource/{id} – update
    • PATCH /resource/{id} – partial update
    • DELETE /resource/{id} – delete

Most controllers only define type parameters and base path. Custom endpoints are added only when required.


4. Assemblers – Response Construction

Assemblers build Output DTOs from entities.

  • Implement BaseAssembler with a template flow:

    1. Optional pre-processing (e.g. load lazy relations)
    2. Base field mapping via Mapper
    3. Optional enrichment (computed fields, summaries)
    4. Optional post-processing (links, formatting)
  • Responsibilities:

    • Use Mappers for base field mapping
    • Convert relations to Summary DTOs
    • Optionally expose toInput for PATCH workflows

Assemblers isolate all response shaping logic from controllers and services.


5. Services – Business Logic and Hooks

Services orchestrate repositories, transactions, and domain rules.

  • Extend BaseService, which provides all standard operations.
  • Override lifecycle hooks only when needed:

Input:

  • preProcessCreateInput
  • preProcessUpdateInput

Mapping:

  • postConvertToEntity

Persistence:

  • preSave
  • postSave

Queries:

  • preProcessQuery
  • postProcessQueryResult

Load/Delete:

  • preProcessLoad, postLoad
  • preProcessDelete, postDelete

Relation handling always belongs in the service layer, never in mappers.


6. Mappers – DTO ↔ Entity Conversion

Mappers perform field-level transformations.

  • Implement DtoMapper:

    • toEntity
    • toOutput
    • toInput
    • updateEntity
  • MapStruct generates implementations:

    • Relation fields are ignored
    • Create ignores nulls for optional fields
    • Update/PATCH applies explicit nulls

Mappers focus purely on type-safe field copying.


7. Repositories and Specifications – Data Access

Repositories encapsulate all DB operations.

  • Base repositories build on Spring Data JPA and support CRUD + Specifications.

  • Entity-specific repositories extend the base and may define EntityGraph queries for eager loading.

  • Specifications:

    • Shared base specs for id, createdAt, modifiedAt
    • Named-entity specs add name, description, and a q search field
    • Entity-specific specs extend these as needed

Controllers receive specification instances built automatically from query parameters.


8. Domain Model – Entities and DTOs

The domain model defines core structures:

  • Entities:

    • BaseEntity – id, audit fields, validation hook
    • NamedEntity – adds name, description
    • ScopedEntity – adds scope fields
    • Concrete entities extend these and define relations and additional fields
  • DTOs:

    • Input DTOs – client data, relations as IDs
    • Output DTOs – full responses with nested summaries
    • Summary DTOs – minimal representations for nested relations

Validation occurs at the DTO, service, and optional entity level.


9. Implementation Checklist for a New Entity

  1. Model
  • Create entity (extend appropriate base)
  • Define relations and constraints
  • Add Input, Output, Summary DTOs
  1. Data Access
  • Create repository
  • Create Specification interface
  1. Mapping
  • Implement MapStruct mapper
  • Ignore relation fields; define summary mapping
  1. Business Logic
  • Extend service
  • Override hooks for relations/validation only as needed
  1. Response
  • Implement assembler with summary generation
  1. API
  • Create controller extending base controller

This sequence ensures all entities integrate consistently with the platform’s architecture.