Search code examples
javaspring-datadomain-driven-designspring-data-jdbc

How to use AbstractAggregateRoot<T> or the annotation DomainEvents with Java Records


I am trying to evolve a domain which it includes and Aggregate-root implemented with Java Records and I am not able to find a way to use the Domain Event concept to propagate events from one Aggregate-root. https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#core.domain-events

Compilation issue with the following syntax:

import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import org.springframework.data.domain.AbstractAggregateRoot;

@Table("BALANCE")
public record Balance extends AbstractAggregateRoot<Balance> (

    @Id
    @Column("ID_BALANCE")
    Long balanceId,

    @Column("BALANCE")
    BigDecimal balance,

    @Column("ID_CUSTOMER")
    Long customerId,

    @Column("LAST_UPDATE")
    Timestamp lastUpdate,

    @Column("WITHDRAW_LIMIT")
    BigDecimal withdrawLimit
) {
//Business logic
}

No problem with this syntax:

import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import org.springframework.data.domain.AbstractAggregateRoot;

public class BalanceDemo extends AbstractAggregateRoot<BalanceDemo> {

    @Id
    @Column("ID_BALANCE")
    Long balanceId;

    @Column("BALANCE")
    BigDecimal balance;

    @Column("ID_CUSTOMER")
    Long customerId;

    @Column("LAST_UPDATE")
    Timestamp lastUpdate;

    @Column("WITHDRAW_LIMIT")
    BigDecimal withdrawLimit;

    //Constructors, Get, HashCode, Equals, toString
    //Business Logic
}

What is wrong? Is it not possible to use Java records in combination with Domain Events?


Solution

  • As Tim Moore wrote in a comment a Java Record cannot extend another class since it already extends java.lang.Record implicitly.

    So you can either copy the relevant code from AbstractAggregateRoot into your record or have an instance of it in your record and delegate to it in the relevant method implementations.