Services

Business logic, @ServiceImplementation, constructor injection, and the service lifecycle.

Defining a Service

A service has two parts:

  1. Interface — defined in the core-* module.
  2. Implementation — annotated with @ServiceImplementation. KSP generates the DI wiring.

Interface (in core-* module)

kotlin

Implementation

kotlin

Constructor Injection

Dependencies are injected via the constructor. KSP reads the constructor parameters and generates the provider wiring. You can inject:

  • Repositories@Repository-annotated interfaces
  • Other services — via their interface
  • InfrastructureCacheManager, PubSubService, BoscaApplication, etc.
  • ObjectProvider<T> — for lazy/deferred resolution

Service Responsibilities

A service typically handles:

  1. Cache-through reads — look up in cache first, fall back to repository on miss.
  2. Writes with cache invalidation — perform the repository write, then invalidate all affected caches.
  3. Event dispatch — dispatch domain events after writes for background jobs and subscribers.
  4. Business logic — validation, transformation, orchestration across repositories.
Services should not handle authentication or authorization — that belongs in the controller layer via PermissionEvaluator and GroupEvaluator.

Event Dispatch

Services dispatch domain events after writes using KSP-generated dispatch() extensions:

kotlin

See Messaging & Events for full details.