xmolecules / jmolecules-integrations

Technology integration for jMolecules
Apache License 2.0
74 stars 19 forks source link

Only applicable ByteBuddy Plugins should match #245

Closed haisi closed 2 weeks ago

haisi commented 1 month ago

Given a simple Aggregate with only spring-data-jpa as an explicit dependency:

import org.jmolecules.ddd.types.AggregateRoot;
import org.jmolecules.ddd.types.Identifier;

import java.util.UUID;

public class Bestellung
        implements AggregateRoot<Bestellung, Bestellung.BestellungId> {

    private BestellungId id;

    @Override
    public BestellungId getId() {
        return id;
    }

    public record BestellungId(UUID id) implements Identifier {}
}

The jmolecules-bytebuddy plugin generates:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package li.selman.jmoleculesbytebuddy;

import java.io.Serializable;
import java.util.UUID;
import javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.PostLoad;
import javax.persistence.PrePersist;
import org.hibernate.annotations.EmbeddableInstantiator;
import org.jmolecules.ddd.types.AggregateRoot;
import org.jmolecules.ddd.types.Identifier;
import org.jmolecules.jpa.JMoleculesJpa;
import org.jmolecules.spring.data.MutablePersistable;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.relational.core.mapping.Table;

@Entity(
    name = ""
)
@Table( // <--- Why?
    name = ""
    value = "",
    schema = ""
)
@Document( // <--- Why Mongo Dependency
    value = "",
    language = "",
    collection = "",
    collation = ""
)
public class Bestellung implements AggregateRoot<Bestellung, BestellungId>, MutablePersistable<Bestellung, BestellungId> {
    @Id // <--- once for Mongo?
    @Id // <--- once for Spring Data JDBC
// Two times the same Annotation causes issues in ArchUnit!
    @EmbeddedId // <--- once for JPA
    private BestellungId id;
    @Transient
    private boolean __jMolecules__isNew = true;

    public Bestellung() {
    }

    public BestellungId getId() {
        return this.id;
    }

    void __verifyNullability() {
    }

    @PostLoad
    void __jMolecules__PostLoad() {
        JMoleculesJpa.verifyNullability(this);
    }

    @PrePersist
    void __jMolecules__PrePersist() {
        JMoleculesJpa.verifyNullability(this);
    }

    public void __jMolecules__markNotNew() {
        this.__jMolecules__isNew = false;
    }

    public boolean isNew() {
        return this.__jMolecules__isNew;
    }

    public boolean equals(Object var1) {
        if (this == var1) {
            return true;
        } else if (var1 == null) {
            return false;
        } else if (this.getClass() != var1.getClass()) {
            return false;
        } else {
            BestellungId var2 = ((Bestellung)var1).id;
            BestellungId var3 = this.id;
            if (var2 != null) {
                if (var3 == null) {
                    return false;
                }

                if (!var3.equals(var2)) {
                    return false;
                }
            } else if (var3 != null) {
                return false;
            }

            return true;
        }
    }

    public int hashCode() {
        int var10000 = 17 * 31;
        BestellungId var1 = this.id;
        if (var1 != null) {
            var10000 += var1.hashCode();
        }

        return var10000;
    }

    @Embeddable
    @EmbeddableInstantiator(RecordInstantiator.jMolecules.WXQ84pX8.class)
    public static record BestellungId(UUID id) implements Identifier, Serializable {
        public BestellungId(UUID id) {
            this.id = id;
        }

        public UUID id() {
            return this.id;
        }

        public BestellungId() {
        }
    }
}

Firstly, I was surprised that merely adding the jmolecules-bytebuddy dependency, pulls in Spring Data Mongo. Secondly, as JMoleculesSpringDataJdbcPlugin and JMoleculesJpaPlugin is run, the id field is annotated twice with the same @Id annotation. This causes issues when using ArchUnit.

[ERROR] Multiple entries with same key: org.springframework.data.annotation.Id=JavaAnnotation{org.springframework.data.annotation.Id} and org.springframework.data.annotation.Id=JavaAnnotation{org.springframework.data.annotation.Id}

Here is a minimal project reproducing the ArchUnit issue: https://github.com/haisi/jmolecules-bytebuddy-issue

odrotbohm commented 3 weeks ago

Good catch! That's a documentation issue. The JAR that should be used is jmolecules-bytebuddy-nodep as can be seen here. I'll make sure to update the readme.