Annotation Interface Model


Marks an independently identified and stored domain model.

Unlike an Aggregate, a model is its own persistence and lifecycle boundary. Loading or updating it does not require loading a parent, sibling, child, or an artificial aggregate root. A model may still contain embedded entities declared with @Member; those members share the model's stream, cache, search document, snapshots, and lifecycle.

Choose this boundary from domain lifecycle first: state that can be created, changed, retained, deleted, or whose history matters independently is a separate model, even when it is normally displayed in a parent's collection. Connect such a child with @Parent. A meaningful domain identity is strong evidence for that boundary, not an additional gate: an independently living child may use a globally unique ID or a parent-scoped ID. Collection shape, searchability, storage format, update frequency, and convenient embedding do not make independently living state a Member.

Model identity is the repository representation of its @EntityId. Applications can use a typed Id, annotation-level prefix/postfix affixes, or both to isolate otherwise equal functional identifiers.

An @Apply method targets a model by returning that model. Returning null deletes the targeted model while retaining the applied event according to the configured publication settings. Returning void is invalid for model applies because it does not identify a stored result. Legacy mutable aggregate applies remain supported.

Persistence

persistence() makes the durable representations and authoritative load path explicit. Event-sourced models are reconstructed from their model stream, optionally from a snapshot. Adding ModelPersistence.DOCUMENT maintains a current document as well; when event sourcing is absent, that document is authoritative. Event storage and publication remain independent and are controlled by eventPublication(), publicationStrategy(), and per-apply overrides. Internal component documents used for Graph composition are likewise orthogonal and never change the selected load path.

Example

@Model(persistence = {
        ModelPersistence.EVENT_SOURCED,
        ModelPersistence.DOCUMENT
})
public record Product(@EntityId ProductId productId, String name) {
    @Apply
    Product rename(RenameProduct command) {
        return new Product(productId, command.name());
    }
}
An update may instead create or update the model from a payload-side @Apply. When both sides define an applicable apply, Fluxzero applies the payload first and invokes the model method against that intermediate state. This lets one instance method consistently enforce model-owned behavior for both creation and later updates.
See Also:
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    Controls whether applies producing this model may be exposed as automatic command handlers.
    boolean
    Whether the latest model state should be stored in the shared application cache.
    int
    Number of older model versions retained in the shared cache.
    int
    Frequency at which intermediate states are checkpointed within one reconstruction session.
    Controls when model changes are committed and whether completion-phase commits may run concurrently.
    io.fluxzero.common.api.modeling.ModelConflictPolicy
    Conflict handling for this model when an apply does not provide an explicit override.
    Advanced configuration for the Model's direct current document.
    Controls whether an applied update produces an event when the returned model is unchanged.
    Advanced configuration for the materialized whole-graph search document.
    boolean
    Whether unknown events should be ignored while reconstructing an event-sourced model.
    boolean
    Whether Fluxzero should asynchronously materialize the complete model graph as a separate search document.
    int
    Maximum number of snapshots retained for this model.
    Durable representations and authoritative load path for this Model.
    Controls whether applied events are stored, published, or both.
    int
    Number of stored model events between snapshots.
  • Element Details

    • conflictPolicy

      io.fluxzero.common.api.modeling.ModelConflictPolicy conflictPolicy
      Conflict handling for this model when an apply does not provide an explicit override.
      Default:
      DEFAULT
    • automaticHandling

      AutomaticModelHandling automaticHandling
      Controls whether applies producing this model may be exposed as automatic command handlers.
      Default:
      DEFAULT
    • persistence

      ModelPersistence[] persistence
      Durable representations and authoritative load path for this Model.

      The set must contain at least one unique value. When EVENT_SOURCED is present, the event stream is authoritative. Otherwise DOCUMENT is authoritative.

      This setting does not suppress storing or publishing events produced by Apply methods. A state-changing event-sourced Model apply must store its reconstructing event; a PUBLISH_ONLY or NEVER transition that would change state is rejected before commit. A publish-only no-op remains a valid domain notification when publication is explicitly set to ALWAYS.

      Default:
      {EVENT_SOURCED}
    • ignoreUnknownEvents

      boolean ignoreUnknownEvents
      Whether unknown events should be ignored while reconstructing an event-sourced model.
      Default:
      false
    • snapshotPeriod

      int snapshotPeriod
      Number of stored model events between snapshots. 0 disables periodic snapshots.
      Default:
      0
    • maxSnapshotCount

      int maxSnapshotCount
      Maximum number of snapshots retained for this model. Values below 1 are treated as 1.
      Default:
      1
    • cached

      boolean cached
      Whether the latest model state should be stored in the shared application cache.

      Models participating in a commit may additionally be retained in a commit-local cache until the commit completes.

      Default:
      true
    • cachingDepth

      int cachingDepth
      Number of older model versions retained in the shared cache. -1 retains all available cached versions; 0 retains only the latest version.

      Independent models retain one previous version by default so event handlers can compare the event-visible model with Entity.previous(). Retaining an unbounded revision chain must be an explicit choice because model caches are expected to contain far more keys than aggregate caches.

      Default:
      1
    • checkpointPeriod

      int checkpointPeriod
      Frequency at which intermediate states are checkpointed within one reconstruction session.

      Checkpoints avoid replaying the same prefix for repeated historical dependency loads. They are bounded by the reconstruction session and are not retained as document revisions.

      Default:
      100
    • commitPolicy

      ModelCommitPolicy commitPolicy
      Controls when model changes are committed and whether completion-phase commits may run concurrently.

      The default value resolves from fluxzero.model.commitPolicy when present and otherwise uses ModelCommitPolicy.ASYNC_AFTER_HANDLER_AWAIT_AFTER_BATCH. Independent models were introduced with this default, so it does not depend on the active defaults version.

      Default:
      DEFAULT
    • eventPublication

      EventPublication eventPublication
      Controls whether an applied update produces an event when the returned model is unchanged.

      Independent models default to IF_MODIFIED, so a no-op apply does not create a model-stream or globally published event. Use ALWAYS when an unchanged apply intentionally represents a domain event. This setting is evaluated before publicationStrategy().

      Default:
      IF_MODIFIED
    • publicationStrategy

      EventPublicationStrategy publicationStrategy
      Controls whether applied events are stored, published, or both.

      PUBLISH_ONLY may mutate a document-loaded model. For an event-sourced model it may only publish an unchanged result, because otherwise the next reconstruction could not reproduce the committed state.

      Default:
      DEFAULT
    • document

      Advanced configuration for the Model's direct current document.

      Include ModelPersistence.DOCUMENT in persistence() to enable this projection. Searchable documents use a public collection that defaults to the Model's simple class name. Reference-only documents use type-isolated private storage while remaining available to Model loads, aliases, relationships and Graph composition. Timestamps default to the applied event timestamp when no paths are configured.

      Default:
      @io.fluxzero.sdk.modeling.DocumentProjection
    • materializeGraph

      boolean materializeGraph
      Whether Fluxzero should asynchronously materialize the complete model graph as a separate search document.

      Fluxzero retains the root's current document in its public direct collection when it has a searchable document projection and otherwise in the same type-isolated private storage used by other Graph-only Models. Only the separately named graph collection is allowed to lag; its high-watermark is exposed through the model repository. The collection defaults to the resolved public direct-model collection plus -graphs when present, or to <simple model name>-graphs otherwise.

      Default:
      false
    • graphProjection

      GraphProjection graphProjection
      Advanced configuration for the materialized whole-graph search document.

      This configuration does not enable materialization by itself; set materializeGraph() to true.

      Default:
      @io.fluxzero.sdk.modeling.GraphProjection