# Spring State Machine Explorer Static analysis tool to extract and visualize Spring State Machines with deep code traceability. ## Core Modules - **`state_machine_exporter`**: Java AST analyzer. Scans source code, resolves local Maven/Gradle dependencies, and extracts logic (Lambdas, Actions, Guards) into JSON/PUML. - **`state_machine_exporter_html`**: Generates an interactive HTML portal with SVG diagrams and rich tooltips. ## Usage Analysis is **source-first**: the exporter reads project source and build metadata (`pom.xml`, `settings.gradle`) statically. It does **not** run Maven or Gradle against the project being analyzed. ### 1. Extract Metadata (JSON) ```bash ./gradlew :state_machine_exporter:run --args="-i ./my-project -o ./out -f json" ``` Common options: | Flag | Description | |------|-------------| | `-i, --input` | Project directory to scan (defaults to `.`) | | `-j, --json` | Re-render from an existing JSON export instead of scanning source | | `-o, --output` | Output directory (default `./out`) | | `-f, --format` | Comma-separated formats: `json`, `dot`, `puml`, `scxml` | | `-p, --profiles` | Spring profiles for property placeholder resolution | | `--event`, `--state` | Enum formatting: `fn` (default), `fqn`, `sn` | | `--debug` | Verbose analysis logging and unresolved chain diagnostics | | `--no-diamonds` | Render choice/junction states as regular nodes (default: diamonds) | | `--include-generated-sources` | Also scan `target/` / `build/` generated `.java` trees (default: on) | | `--no-inline-accessors` | Disable accessor indexing/inlining (enabled by default) | ### 2. Generate Interactive Portal (HTML) ```bash ./gradlew :state_machine_exporter_html:run --args="-i ./my-project -o ./out_html" ``` HTML-specific options: | Flag | Description | |------|-------------| | `-f, --flows` | Custom `flows.json` path | | `-m, --machine` | Export only machines whose name contains this filter | | `--open` | Open the generated portal in the default browser | | `--no-metadata-pane` | Hide the left metadata pane (entry points, flows) | | `--no-diamonds` | Render choice pseudostates as normal nodes | | `--debug` | Same diagnostic mode as the core exporter | | `--include-generated-sources` | Same generated-source scanning as the core exporter | | `-p, --profiles` | Spring profiles for property resolution | ## Business Flows Define sequence of events in `src/main/resources/flows.json`: ```json [ { "name": "Order Success", "description": "Happy path for order placement", "steps": ["PAY", "CHECK_AVAILABILITY->PENDING", "SHIP"] } ] ``` ## JSON Structure - `metadata.entryPoints`: REST, WebFlux, and JMS entry points. - `metadata.callChains`: Trace from API call to machine trigger (`sendEvent`). - `transitions.actions[].internalLogic`: Extracted source code/lambdas. - `metadata.properties`: Dictionary of all detected Spring profiles. ## Static analysis: accessor inlining During scan, the exporter builds an **accessor index** of trivial getters, setters, record components, and constant-returning methods. At analysis time, `AccessorResolver` uses this index first (O(1) lookup), then falls back to constructor/field tracing and method-body evaluation. This improves resolution of DTO/event chains such as `request.getPayload().getType()` without running Maven or Gradle on the target project. ```bash # Enabled by default; disable for debugging or A/B comparison ./gradlew :state_machine_exporter:run --args="-i ./my-project -o ./out --no-inline-accessors" ``` Pipeline components live under `analysis/pipeline/` (`AccessorResolver`, `ResolutionBudget`, `MethodInvocationUnwrapper`, `FieldInitializerFinder`, `LibraryUnwrapRegistry`).