REST API and execution engine for NexFlow — a no-code workflow automation platform. Built with Spring Boot and Java 17.
- Framework: Spring Boot 3.2.x
- Java: 17
- Data: Spring Data JPA (Hibernate), H2 (default) / configurable DB
- Web: Spring Web, STOMP over WebSocket for execution events
- Java 17+
- Maven 3.6+
# Compile
mvn compile
# Run
mvn spring-boot:runServer runs by default on http://localhost:8090.
Edit src/main/resources/application.properties:
- Server port:
server.port=8090 - Database: Default is H2 (in-memory or file). Change URL/driver for PostgreSQL, etc.
- CORS: Allowed origins are configured for the frontend (see
config/CorsConfig.java).
| Method | Path | Description |
|---|---|---|
| GET | /api/flows |
List all flows |
| POST | /api/flows |
Create flow |
| GET | /api/flows/{flowId} |
Get one flow |
| GET | /api/flows/{flowId}/canvas |
Load canvas (nodes + edges) |
| POST | /api/flows/{flowId}/canvas |
Save canvas (body: { "nodes": [], "edges": [] }) |
| GET | /api/flows/{flowId}/executions |
List executions |
| POST | /api/pulse/{flowId} |
Trigger execution (body: JSON payload) |
- Request body:
CanvasSaveDtowithnodes(array ofFlowNodeDto) andedges(array ofFlowEdgeDto). - Node IDs and edge IDs are provided by the frontend (UUIDs). The backend must not overwrite them (see
FlowNodeandFlowEdgeentities:@Idonly, no@GeneratedValue). - Edges reference nodes by
sourceNodeIdandtargetNodeId; these must match stored node IDs.
nexflow-backend/
├── pom.xml
├── src/main/java/com/nexflow/nexflow_backend/
│ ├── NexflowBackendApplication.java
│ ├── EdgeCondition.java # Enum: SUCCESS, FAILURE, DEFAULT, CUSTOM
│ ├── FlowStatus.java
│ ├── controller/
│ │ ├── FlowController.java # Flows + canvas + executions
│ │ └── PulseController.java # Trigger execution
│ ├── model/
│ │ ├── domain/ # JPA entities
│ │ │ ├── Flow.java
│ │ │ ├── FlowNode.java
│ │ │ ├── FlowEdge.java
│ │ │ ├── Execution.java
│ │ │ └── NodeType.java
│ │ ├── dto/
│ │ │ ├── CanvasSaveDto.java
│ │ │ ├── FlowNodeDto.java
│ │ │ └── FlowEdgeDto.java
│ │ └── nco/ # Execution context types
│ ├── repository/
│ │ ├── FlowRepository.java
│ │ ├── FlowNodeRepository.java
│ │ ├── FlowEdgeRepository.java
│ │ └── ExecutionRepository.java
│ ├── service/
│ │ └── FlowService.java
│ ├── engine/ # Flow execution
│ │ ├── FlowExecutionEngine.java
│ │ └── ExecutionEventPublisher.java
│ ├── executor/ # Node executors (START, PULSE, etc.)
│ │ ├── NodeExecutor.java
│ │ ├── NodeExecutorRegistry.java
│ │ └── ...
│ └── config/
│ ├── AppConfig.java
│ └── CorsConfig.java
└── src/main/resources/
└── application.properties
- IDs:
FlowNodeandFlowEdgeuse@Idwithout@GeneratedValue. The frontend sends UUIDs for nodes and edges; the backend persists them as-is. Do not add@GeneratedValueor canvas edges will no longer match nodes after reload. - Canvas save: Uses DTOs (
CanvasSaveDto,FlowNodeDto,FlowEdgeDto) and@Transactional. Invalid edges (e.g. null source/target) are skipped; valid ones are saved.
Pipeline: GitHub Actions → Railway
| Branch event | What happens |
|---|---|
Push to main |
CI runs (compile + test) → if passes → deploys to Railway |
Pull request to main |
CI runs as a check → no deployment |
| Push to any other branch | Nothing (pipeline does not trigger) |
GitHub Secrets required (Settings → Secrets and variables → Actions):
| Secret | How to get it |
|---|---|
RAILWAY_DEPLOY_HOOK_URL |
Railway → Project → Settings → Deploy Hook → Generate |
RAILWAY_APP_URL |
Railway → Project → Settings → Domains (just the domain, no https://) |
Railway Environment Variables (set in Railway dashboard):
| Variable | Value |
|---|---|
DATABASE_URL |
Auto-injected by Railway when you add a PostgreSQL service |
PORT |
Auto-injected by Railway |
CORS_ALLOWED_ORIGINS |
Your Vercel frontend URL e.g. https://nexflow.vercel.app |
Running locally:
No changes needed. All environment variables in application.yml have localhost fallback values, so local development works exactly as before.
Private / as per project.