Annotation Interface OnDelete


Annotates Permazen model class methods that are to be invoked whenever an object is about to be deleted.

Overview

When a matching object is deleted, annotated methods are invoked just prior to actual deletion.

Methods must return void and normally take one parameter. A matching object is one whose type is compatible with the method parameter and which is found at the end of the reference path specified by path(), starting from the object to be notified. See ReferencePath for more information about reference paths.

In the case of an instance method where path() is empty (the default), the method is allowed to take zero parameters; in this case, the object monitors itself.

For static methods, path() must be empty and every object whose type is compatible with the method's parameter is a matching object and can produce notifications.

The annotated method may may have any level of access, including private.

A class may have multiple @OnDelete methods, each with a specific purpose.

Examples

This example shows various ways an annotated method can be matched:


   @PermazenType
   public abstract class User implements PermazenObject {

       public abstract Account getAccount();
       public abstract void setAccount(Account account);

       @OnDelete(path = "->account")
       private void handleDeletion1(Account account) {
           // Invoked when MY Account is deleted
       }
   }

   @PermazenType
   public abstract class Feature implements PermazenObject {

       public abstract Account getAccount();
       public abstract void setAccount(Account account);

       @OnDelete(path = "->account<-User.account")
       private void handleDeletion1(User user) {
           // Invoked when ANY User associated with MY Account is deleted
       }
   }

   @PermazenType
   public abstract class Account implements PermazenObject {

       @NotNull
       public abstract String getName();
       public abstract void setName(String name);

   // Non-static @OnDelete methods

       @OnDelete
       private void handleDeletion1() {
           // Invoked when THIS Account is deleted
       }

       @OnDelete
       private void handleDeletion2(SpecialAccount self) {
           // Invoked when THIS Account is deleted IF it's also a SpecialAccount
       }

       @OnDelete(path = "<-User.account")
       private void handleDeletion3(User user) {
           // Invoked when ANY User associated with THIS Account is deleted
       }

       @OnDelete(path = "<-User.account")
       private void handleDeletion4(Object obj) {
           // Invoked when ANY User OR Feature associated with THIS Account is deleted
       }

       @OnDelete(path = "<-Feature.account->account<-User.account")
       private void handleDeletion5(User user) {
           // Invoked when ANY User associated with the same Account
           // as ANY Feature associated with THIS Account is deleted
       }

  // Static @OnDelete methods

       @OnDelete
       private static void handleDeletion5(Object obj) {
           // Invoked when ANY object is deleted
       }

       @OnDelete
       private static void handleDeletion6(Account account) {
           // Invoked when ANY Account is deleted
       }
   }
 

Instance vs. Static Methods

An instance method will be invoked on each object for which the deleted object is found at the end of the specified reference path, starting from that object. For example, if there are three child Node's pointing to the same parent Node, and the Node class has an instance method annotated with @OnDelete(path = "parent"), then all three child Node's will be notified when the parent is deleted.

A static method is invoked once for any matching object; the path() is ignored and must be empty.

Notification Delivery

Notifications are delivered in the same thread that deletes the object, before the deletion actually occurs. At most one delete notification will ever be delivered for any object deletion event. In particular, if an annotated method attempts to re-entrantly delete the same object again, no new notification is delivered.

Some notifications may need to be ignored by objects in detached transactions; you can use this.isDetached() to detect that situation.

Actions that have effects visible to the outside world should be made contingent on successful transaction commit, for example, via Transaction.addCallback().

Meta-Annotations

This annotation may be configured indirectly as a Spring meta-annotation when spring-core is on the classpath.

See Also:
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    Specify the reference path to the target object(s) that should be monitored for deletion.
  • Element Details

    • path

      String path
      Specify the reference path to the target object(s) that should be monitored for deletion. See ReferencePath for information on reference paths and their proper syntax.

      The default empty path means the monitored object and the notified object are the same. In that case, the type of the parameter (if any) restricts notifications to compatible subclasses.

      When annotating static methods, this property is unused and must be left unset.

      Returns:
      reference path leading to monitored objects
      See Also:
      Default:
      ""