Annotation Interface HandleDocument
This is a specialization of HandleMessage for MessageType.DOCUMENT messages. It allows consuming
updates from the document store in near real-time—similar to event tracking. Handlers can either specify a collection
name or a document class, or infer a Model node or logical Graph from the handler parameter.
Document Tracking Semantics
Each time a document is (re)indexed in Fluxzero, it receives a new tracking index. When a handler is subscribed
via @HandleDocument, it will receive the most recent version of the document for each index. If the tracker
is behind (e.g., during a replay), earlier versions of the same document may be skipped—only the latest version is
retained.
Transforming and Updating Documents
A powerful feature of document handlers is that they can return a modified version of the document to update it in-place. This allows document transformations and upcasting to be applied automatically and reliably.
For this behavior to take effect:
- The returned document must have a higher
Revisionthan the one stored - The updated version will be stored in the document collection under the same ID
Ordinary document replacements preserve all metadata embedded in the handled stored version, including when
the payload was upcast. Derived search indexes/exclusions are regenerated from the replacement. Tracking-envelope metadata is not copied into the document. Return a
Message to replace the complete document metadata explicitly; empty metadata removes
it. Only the returned Message's payload and metadata participate in document replacement; its message ID,
message timestamp, routing key and any subclass-specific envelope fields are not used for that write. The
payload must still have a higher revision. The handled document's ID and collection remain unchanged;
indexed start/end times retain the existing values unless the payload declares timestamp/end paths.
A plain null result still deletes the document.
Independent Model values use the stricter schema-only contract described by source().
This mechanism supports fully-automated data migrations: handlers can evolve or patch documents over time,
and changes are persisted across application restarts.
- See Also:
-
Optional Element Summary
Optional ElementsModifier and TypeOptional ElementDescriptionbooleanIftrue, disables this handler during discovery.Class<?> Optional class of the documents to handle.Migration target when this handler returns its complete injected Graph.Determines how the handler responds when referenced protected data is no longer available.Document source to observe.Optional name of the document collection.
-
Element Details
-
onMissingProtectedData
MissingProtectedDataPolicy onMissingProtectedDataDetermines how the handler responds when referenced protected data is no longer available.- Default:
DEFAULT
-
value
String valueOptional name of the document collection. If provided,documentClass()is ignored.If neither documentClass nor value are specified, the first parameter of the method is used to determine the collection:
class OrganisationHandler { @HandleDocument void on(Organisation organisation, Metadata metadata) { ... } }- See Also:
- Default:
""
-
documentClass
Class<?> documentClassOptional class of the documents to handle. If annotated withSearchable, the annotation defines the collection; otherwise the class name is used.If neither documentClass nor value are specified, the first parameter of the method is used to determine the collection:
class OrganisationHandler { @HandleDocument void on(Organisation organisation, Metadata metadata) { ... } }- See Also:
- Default:
java.lang.Void.class
-
source
DocumentSource sourceDocument source to observe.DocumentSource.SEARCHis the default: a Model parameter selects its canonical searchable node, andGraph<Model>selects that root and its included descendants. Ancestor content alone does not trigger the latter. Graph handling works with every projection mode;NONEcomposes the latest indexed nodes when reading an update and does not retain previous Graph snapshots.DocumentSource.MODEL_STATEexplicitly selects maintained internal Model state for observation or schema migration, including non-searchable DOCUMENT Models. It requires a Model value, not a Graph, and cannot be combined with an explicit collection. There is no automatic fallback between sources.Returning an injected Model value may persist a higher-revision schema upcast, but must preserve identity and business state. Use Model commands for business changes. Returning the injected Graph migrates evolved canonical nodes by default, including live Graphs in projection mode NONE; see
graphMigration(). A void handler only observes. Neither route creates historical Graph snapshots that the selected storage does not maintain.- Default:
SEARCH
-
graphMigration
GraphMigrationTarget graphMigrationMigration target when this handler returns its complete injected Graph. The default upcasts the verified current source of each evolved node, preserving business state, identity, relationships and history. Returning a Graph with modified values or topology is rejected. Nodes are migrated individually and idempotently; concurrent changes are re-read, and persistent contention fails handling so the consumer can retry. Custom serializers must implementDocumentSerializer.modelStateSnapshot(Object)for this default route; the PROJECTION override retains the previous serializer contract.Completion confirms node storage. Affected projections follow durably, including for Models configured with AWAIT, whose waiting guarantee applies to ordinary Model commits. Select
GraphMigrationTarget.PROJECTIONto retain projection-only migration; this does not write canonical nodes and is observational for live Graphs.- Default:
MODEL_STATE
-
disabled
boolean disabledIftrue, disables this handler during discovery.- Default:
false
-