A Java implementation of the State design pattern for approval workflows. The project models a document approval pipeline where behavior changes based on the document's current state: DRAFT, REVIEW, REJECTED, or APPROVED.
The goal is to keep workflow rules encapsulated inside state classes instead of scattering conditional logic throughout the application.
Approval workflows often need to enforce rules such as:
- Draft documents can be edited and submitted for review.
- Documents under review cannot be edited.
- Rejected documents can be revised and resubmitted.
- Approved documents are final and cannot be changed.
This project demonstrates how those rules can be implemented cleanly with object-oriented design. The Document class delegates each action to the active state object, and each state decides whether the action is allowed, blocked, or should trigger a transition.
- State-driven workflow behavior using the State pattern
- Clear separation between workflow context and state-specific rules
- Prevention of invalid transitions
- Audit logging with timestamps in
workflow.log - Console-based demonstration scenario
- Lightweight transition regression test
DRAFT -> REVIEW -> APPROVED
|
v
REJECTED -> REVIEW
state-driven-workflow-engine/
├── Main.java
├── README.md
├── scenario.txt
├── state/
│ ├── ApprovedState.java
│ ├── DraftState.java
│ ├── RejectedState.java
│ ├── ReviewState.java
│ └── State.java
├── tests/
│ └── WorkflowTest.java
├── util/
│ └── LoggerUtil.java
└── workflow/
└── Document.java
The implementation uses four main concepts:
| Concept | Implementation |
|---|---|
| Abstraction | State interface defines supported workflow actions |
| Polymorphism | Each state implements actions differently |
| Encapsulation | State-specific rules stay inside state classes |
| Delegation | Document delegates behavior to its current state |
The Document starts in DraftState. Public actions such as edit(), submit(), approve(), and reject() are delegated to the current state.
When an action causes a valid transition, the state returns the next state. The Document applies the transition internally, keeping direct state changes hidden from external callers.
Compile the source files:
javac Main.java workflow/*.java state/*.java util/*.javaRun the demo workflow:
java MainCompile the application and test classes into an output directory:
javac -d out Main.java workflow/*.java state/*.java util/*.java tests/*.javaRun the transition test:
java -cp out tests.WorkflowTestThe included demo models a company policy approval flow:
- An employee creates a policy document.
- The employee edits the draft.
- The employee submits it for review.
- The manager rejects it.
- The employee revises and resubmits it.
- The manager approves it.
- Further edits are blocked after approval.
Workflow activity is written to workflow.log with timestamps. Logged events include document creation, successful state transitions, approvals, rejections, edits, resubmissions, and blocked actions.
Example:
[2026-06-28 23:32:33] Document approved from REVIEW state.
- Add a formal build tool such as Maven or Gradle
- Add JUnit-based automated tests
- Support role-based access control
- Persist workflow history in a database
- Add a web or desktop interface
Archita Thakur
Computer Science & AI Student