Making a Claims Pipeline Executable on Two fUML Engines with Alf Editing
A claims pipeline is modelled as 60 UML activities and about 300 actions, and must execute on two different fUML engines and be edited as text by actuarial analysts. Current state: 40 actions are OpaqueActions whose bodies are Java snippets; the claim lifecycle (New, Assessing, Pending, Settled) is a StateMachine; a DecisionNode branches on three guards but has no [else]; and one branch uses an ActivityFinalNode inside a loop body to "return the result early". The first engine runs the model but the second rejects it; the Alf round trip produces a model that no longer matches the diagram; and analysts' text edits overwrite the Java snippets. The team wants one normative model, executable identically on both engines, with a textual editing surface and no behaviour defined outside the standard.
1. State what fUML 1.x actually defines, and explain why the current model is not portable across the two engines.
Read the worked answer
fUML 1.x defines an executable subset of UML: Classes, DataTypes, Packages, Activities with token-flow semantics, value and event semantics, and the execution model needed to run them. It does not define StateMachines, Interactions, UseCases, Components or Deployments - a state machine in the model has no fUML semantics at all, so an engine that "runs" it is running its own interpretation.
Portability also fails for the Java OpaqueActions: fUML defines that an OpaqueAction exists, but its behaviour is explicitly outside the standard. Each engine calls its own host code, so the two engines are executing different programs. The same applies to OpaqueBehaviors used as method bodies.
What to do:
- Keep the StateMachine if it communicates stakeholder intent, but treat it as non-normative documentation and implement the lifecycle as an Activity over a claim-status value (an enumeration). The state machine becomes a view of the activity, not the executor.
- Replace Java OpaqueActions with fUML-defined behaviour: primitive functions, structured activities, or Alf bodies that compile to activities. Anything needing host code becomes one named, documented service boundary, not 40 scattered snippets.
- Pin engine versions and record which ordering choices fUML leaves to the runtime, so differences are attributable.
Test by running the same activity with the same inputs on both engines and comparing output parameter values and the action-execution trace - not the diagrams.
2. Explain what happens to a token at a DecisionNode with no [else] when no guard is true, and why the ActivityFinalNode inside the loop body is wrong. Give the correct constructs, including how a result is returned.
Read the worked answer
DecisionNode without [else]: tokens arriving at a decision node are offered to the outgoing edges whose guards evaluate true. If none evaluates true and no [else] edge exists, no edge accepts the token; it remains unconsumed at the node, and the activity hangs or ends with an incomplete result depending on the engine's implementation. That is exactly the class of difference that makes one engine "work" and the other stall. Fix: add an explicit [else] edge (guard true) to a diagnostic path or a well-defined default, make the guards exhaustive and mutually exclusive by construction, and add a test that checks coverage of the guard set.
ActivityFinalNode inside a loop body: an ActivityFinalNode terminates the entire activity and destroys all remaining tokens, not just the current iteration. Using it to "return early" kills concurrent branches, discards in-flight object-flow values, and makes the result depend on scheduling. Replace with:
- a MergeNode plus DecisionNode to leave the loop and continue to the result-producing action, or
- a FlowFinalNode if only that single flow should end while the rest of the activity continues.
Returning a result: put the value on an OutputPin of the final action and route it by object flow to the Activity's output Parameter. The Parameter is the contract the engine and the caller agree on; do not rely on side effects or on a final node "seeing" the token.
3. The analysts need a textual editing surface with standard semantics, and the Alf round trip currently diverges from the diagram. Propose a governance and modelling approach that keeps one normative model.
Read the worked answer
Alf (Action Language for fUML) is the standard textual concrete syntax for the fUML subset: Alf text maps to fUML activities, so it gives analysts an editing surface without inventing semantics. Practical rules:
- Normative text, derived model. Keep Alf as the source of truth for activity bodies and generate the fUML activities from it. Keeping hand-edited diagrams and hand-edited text as peers guarantees divergence; the broken round trip is the symptom, not the cause.
- Only Alf-expressible behaviour goes into Alf. State machines, interactions and OpaqueAction host code have no Alf form - that is a semantic boundary, not a tool limitation. Anything outside it must be modelled as data plus activities, or exposed as a named service with a documented signature and pre/postconditions.
- Rework the 40 Java snippets into either (a) Alf statements over model types, or (b) calls to one «service» operation whose behaviour is declared opaque but whose signature, contract and error modes live in the model. Count the opaque bodies; if the number grows, the scope decision was wrong.
- Mapping and tests. Every Alf body attaches to a named activity with declared parameters, so a text diff maps to model elements. Validate with an fUML conformance suite and a golden-output test on both engines.
If analysts need free-form procedural code beyond Alf's subset, record that as an explicit scope decision rather than hiding it in an opaque body.