Implementing Service Layer

1. Defining Service Responsibilities

ResponsibilityDetail
Use case orchestrationCoordinate domain + repos
Transaction boundaryBegin/commit per use case
Validation (cross-aggregate)Beyond DTO format
Authorization checksMethod-level security
Event publishingDomain events post-commit

2. Implementing Service Interfaces

Example: Interface + impl

public interface OrderService {
    Order place(PlaceOrderCommand cmd);
    Order get(OrderId id);
}

@Service
public class DefaultOrderService implements OrderService { ... }
Note: Skip interface if there's only one impl and no proxy/AOP need — Spring proxies work on classes too (CGLIB).

3. Implementing Service Transaction Boundaries

RuleDetail
Boundary at use caseService method = one transaction
No tx in controllersKeep web layer thin
No tx in reposRepository inherits ambient tx
Read-only flag@Transactional(readOnly = true)

4. Implementing Service Composition

Example: Compose services

@Service
public class CheckoutService {
    private final OrderService orders;
    private final PaymentService payments;
    private final InventoryService inventory;
    @Transactional
    public CheckoutResult checkout(Cart cart) {
        inventory.reserve(cart);
        var order = orders.place(toCommand(cart));
        var receipt = payments.capture(order, cart.payment());
        return new CheckoutResult(order.id(), receipt.id());
    }
}

5. Implementing Service Dependencies

DirectionAllowed
Service → RepositoryYes
Service → DomainYes
Service → ServiceYes (acyclic)
Service → ControllerNever
Domain → ServiceNever

6. Implementing Service Error Handling

StrategyDetail
Throw domain exceptionsTranslated by global handler
Result typesFor expected outcomes
Wrap external errorsDon't leak vendor exceptions
Log with contextcorrelation ID, inputs (no PII)

7. Implementing Service Input Validation

LayerValidates
ControllerFormat (Bean Validation on DTO)
ServiceCross-field, cross-aggregate
DomainInvariants in entity/value object

8. Implementing Service Output Transformation

ApproachDetail
Return domainMap at controller boundary
Return DTOMap inside service
Mapper componentReusable, testable

9. Designing Service Granularity

Too coarseToo fine
God service (everything)One method per service
Hard to testWiring nightmare
Many actorsNo abstraction
Note: One service per use case family (e.g., OrderService) is typically the sweet spot.

10. Understanding Service vs Repository Separation

ServiceRepository
Business workflowPersistence
Multiple repos/servicesOne aggregate
Tx boundaryTx participant

11. Implementing Application Services

TraitDetail
LayerApplication
Knows aboutUse cases, transactions, security
Doesn't haveBusiness rules (those belong to domain)

12. Implementing Domain Services

TraitDetail
LayerDomain
StatelessPure business operations
Use whenLogic doesn't fit a single entity