Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data Rest - How to prevent PUT/PATCH updates to child entities of aggregate root

I'm building a Spring Data REST / Spring HATEOAS based application and I'm attempting to following the principles of DDD outlined here (and elsewhere):

BRIDGING THE WORLDS OF DDD & REST - Oliver Gierke

In particular the concept of aggregates and complex state changes via dedicated resources.

Also avoid using HTTP PATCH or PUT for (complex) state transitions of your business domain because you are missing out on a lot of information regarding the real business domain event that triggered this update. For example, changing a customer’s mailing address is a POST to a new "ChangeOfAddress" resource, not a PATCH or PUT of a “Customer” resource with a different mailing address field value.

What I'm struggling with is a means of enforcing this while allowing cosmetic changes to the aggregate root.

Using this simplified example:

@Entity
public class Customer
{
   private @Id @GeneratedValue(strategy = GenerationType.AUTO) Long id;

   private String name;

   private String comment;

   @Access(AccessType.PROPERTY)
   @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
   private Set<Address> addresses = new HashSet<>();

   ... getters and setters

    public void addAddress(Address address)
    {
        addresses.add(address);
        ... custom code to raise events etc
    }
}

public interface Customer extends CrudRepository<Customer, Long>
{
}

What is the best/correct way to allow a cosmetic change (e.g. update comment) but but prevent changes that directly update the child collection?

The only thing I can think of doing if having the setter throw an exception if there is an attempt to modify the child collection.

like image 258
Adam Jones Avatar asked Nov 08 '22 14:11

Adam Jones


1 Answers

@Entity
public class Customer
{
   private @Id @GeneratedValue(strategy = GenerationType.AUTO) Long id;

   private String name;

   private String comment;

   @JsonProperty(access = JsonProperty.Access.READ_ONLY)
   @Access(AccessType.PROPERTY)
   @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
   private Set<Address> addresses = new HashSet<>();
}
like image 166
Bogdan Oros Avatar answered Nov 14 '22 23:11

Bogdan Oros