Files
spring-state-machine-renderer/plan-extended-anaylis/instance_identification.md

2.8 KiB

State Machine Instance Identification & Persistence Mapping

1. The Multi-SM Problem

In large applications, multiple State Machines often coexist. A "Trigger Point" (like a REST Controller) must be linked to the correct State Machine definition.

Common Identification Patterns:

  • Unique Types: StateMachine<OrderState, OrderEvent> vs StateMachine<UserState, UserEvent>.
  • Bean Qualifiers: @Qualifier("orderStateMachine").
  • Factory IDs: factory.getStateMachine("order-123").
  • Persistence Restoration: persister.restore(sm, orderId).

2. Analysis Strategy: "Instance Tracking"

1. Definition Discovery (Existing)

Identify all configurations (classes with @EnableStateMachineFactory or @EnableStateMachine). Store their Bean Names and Generic Types.

2. Dependency Analysis

When a class (e.g., OrderController) uses a state machine:

  1. Identify the Field/Parameter: Look for StateMachine<S, E>.
  2. Resolve Generic Types: Match S and E against known SM definitions.
  3. Resolve Qualifiers: Check for @Qualifier or variable names that match a SM bean name.

3. Loading & Persistence Analysis

A dedicated "Loading Detector" will look for persistence logic.

Pattern: Persister Restore

persister.restore(stateMachine, id);
stateMachine.sendEvent(E);

Static Strategy:

  • Find calls to Persister.restore(sm, ...) or PersistStateChangeListener.
  • Link the variable sm to the restoration event.
  • Mark the TriggerPoint as "Restored from Persistence".

Pattern: Factory Creation

StateMachine sm = factory.getStateMachine(smId);

Static Strategy:

  • Find factory.getStateMachine(...).
  • If the argument is a literal (e.g., "order"), map it to the SM definition named "order".

3. Implementation: InstanceIdentifier

We will introduce an InstanceIdentifier that works alongside the ValueResolver.

public class InstanceIdentifier {
    public StateMachineReference identify(VariableDeclaration var, CodebaseContext context) {
        // 1. Check type generics
        // 2. Check @Qualifier
        // 3. Trace back to factory or persister calls
    }
}

4. Modeling in AnalysisResult

The TriggerPoint will be enhanced with a stateMachineId or configFqn field.

public record TriggerPoint(
    String className,
    String methodName,
    String event,
    String stateMachineId, // Links back to the specific SM
    boolean isRestoredFromPersistence,
    Map<String, String> metadata
) {}

5. Challenges

  • Generic Controllers: A single base controller that handles multiple SMs via generics. We might need to report "Multiple Potential SMs".
  • Dynamic Factory IDs: factory.getStateMachine(payload.getType()). Hard to resolve statically without data flow analysis.