io.permazen.annotation.OnCreate Maven / Gradle / Ivy
Show all versions of permazen-main Show documentation
/*
* Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
*/
package io.permazen.annotation;
import io.permazen.DetachedPermazenTransaction;
import io.permazen.PermazenTransaction;
import io.permazen.core.Transaction;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotates Permazen model class methods that are to be invoked whenever a database object is newly created.
*
*
*
*
*
* Overview
*
*
* When a matching object is created, annotated methods are invoked just after the object's creation.
*
*
* For instance methods, the annotated method may take either zero or one parameter (the newly created object).
* Zero is typical, in which case a matching object is any object that is an instance of the method's declaring class,
* i.e., newly created objects receive their own notifications.
*
*
* If the method has one parameter, then newly created objects still notify themselves but only when their types
* match the parameter's type (the new object is both the method receiver and method parameter). The latter case
* is less common but useful for example when a superclass method is only interested in the creation of
* specific sub-types.
*
*
* For static methods, a method parameter is required and a matching object is one whose type is compatible with it.
*
*
* The annotated method may may have any level of access, including {@code private}.
*
*
* A class may have multiple {@link OnCreate @OnCreate} methods, each with a specific purpose.
*
*
* Note that there is a subtle distinction between (a) the creation of objects in the database (i.e., the event that
* this annotation concerns), and (b) the instantiation of an actual Java model object representing a database object.
* These two events are different; in particular, distinct Java objects are created to represent the same database
* object in different transactions. It's even possible for a Java model object to be instantiated even though no
* corresponding database object exists in the database (via
* {@link PermazenTransaction#get(io.permazen.core.ObjId) PermazenTransaction.get()}).
*
*
* As a consequence, any operations specific to the creation of new database instance, such as one-time initialization
* of database fields, should take place in {@link OnCreate @OnCreate}-annotated methods instead of constructors.
*
*
* For example, instead of doing this:
*
*
*
* @PermazenType
* public abstract class Event {
*
* protected Event() {
* this.setCreateTime(Instant.now());
* }
*
* @NotNull
* public abstract Instant getCreateTime();
* public abstract void setCreateTime(Instant createTime);
* }
*
*
*
* do this:
*
* @PermazenType
* public abstract class Event {
*
* @NotNull
* public abstract Instant getCreateTime();
* public abstract void setCreateTime(Instant createTime);
*
* @OnCreate
* private void initializeCreateTime() {
* this.setCreateTime(Instant.now());
* }
* }
*
*
* Notification Delivery
*
*
* Notifications are delivered in the same thread that created the object, immediately after the object is created.
*
*
* Some notifications may need to be ignored by objects in {@linkplain DetachedPermazenTransaction detached} transactions;
* you can use {@code 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 {@link Transaction#addCallback Transaction.addCallback()}.
*
*
Meta-Annotations
*
*
* This annotation may be configured indirectly as a Spring
* meta-annotation
* when {@code spring-core} is on the classpath.
*
* @see OnDelete
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Documented
public @interface OnCreate {
}