Lesson 6 Complete Solution
This lesson demonstrates clean workflow and activity separation through a comprehensive user onboarding process with multiple coordinated activities.
What's Included
Workflow Architecture
workflow/UserOnboardingWorkflow.kt
- Main workflow interfaceworkflow/UserOnboardingWorkflowImpl.kt
- Orchestration logic with proper error handling
Activity Components
activity/UserValidationActivity.kt
+UserValidationActivityImpl.kt
- Email validationactivity/AccountCreationActivity.kt
+AccountCreationActivityImpl.kt
- Account creationactivity/NotificationActivity.kt
+NotificationActivityImpl.kt
- Welcome notifications
Key Learning Points
Clean Separation of Concerns
Each activity has a single, well-defined responsibility:
- Validation: Input validation and business rules
- Account Creation: Database operations and ID generation
- Notification: External service integration
Proper Error Handling
- Validation failures stop the process early
- Account creation failures are critical errors
- Notification failures are treated as non-critical (best effort)
Activity Configuration
Different activities have different timeout configurations based on their expected behavior:
// Quick validation - 10 seconds
val validationActivity = Workflow.newActivityStub(..., 10 seconds)
// Database operations - 30 seconds
val accountCreationActivity = Workflow.newActivityStub(..., 30 seconds)
// External services - 1 minute
val notificationActivity = Workflow.newActivityStub(..., 1 minute)
Data Flow Architecture
UserOnboardingWorkflow
│
├── ValidationActivity
│ ├── Email format validation
│ ├── Duplicate email checking
│ └── Business rule validation
│
├── AccountCreationActivity
│ ├── User ID generation
│ ├── Database record creation
│ └── Default settings initialization
│
└── NotificationActivity
├── Email composition
├── External service calls
└── Delivery confirmation
Running This Code
1. Register Components
worker.registerWorkflowImplementationTypes(UserOnboardingWorkflowImpl::class.java)
worker.registerActivitiesImplementations(
UserValidationActivityImpl(),
AccountCreationActivityImpl(),
NotificationActivityImpl()
)
2. Execute Workflow
val workflow = workflowClient.newWorkflowStub(
UserOnboardingWorkflow::class.java,
WorkflowOptions.newBuilder()
.setTaskQueue("onboarding-queue")
.setWorkflowId("onboard-${System.currentTimeMillis()}")
.build()
)
val result = workflow.onboardUser("newuser@example.com")
println("Onboarding result: $result")
3. Expected Output
Starting user onboarding for: newuser@example.com
Step 1: Validating user data
Validating user: newuser@example.com
✅ User validation passed for: newuser@example.com
Step 2: Creating user account
Creating account for: newuser@example.com
✅ Account created successfully with ID: user_abc12345
Step 3: Sending welcome notification
📧 Welcome email sent successfully to: newuser@example.com
User onboarding completed successfully
Best Practices Demonstrated
✅ Single Responsibility Principle
Each activity does one thing well and can be tested independently.
✅ Proper Error Handling
- Critical vs non-critical failures
- Graceful degradation for notification failures
- Detailed error messages and logging
✅ Activity Timeouts
Different timeout strategies based on expected operation duration.
✅ Data Modeling
Clear, typed data structures for communication between workflow and activities.
✅ Logging Strategy
- Workflow logs track orchestration decisions
- Activity logs show detailed operation progress
- Emojis and clear formatting for easy debugging
Next Steps
Lesson 7 will explore workflow input/output patterns and more complex data handling scenarios!