Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Platform Bpm Camunda Bundle Laravel Package

digitalstate/platform-bpm-camunda-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the bundle to your composer.json:

    composer require digitalstate/platform-bpm-camunda-bundle
    

    Register the bundle in config/bundles.php:

    return [
        // ...
        DigitalState\Platform\Bpm\CamundaBundle\DigitalStatePlatformBpmCamundaBundle::class => ['all' => true],
    ];
    
  2. Configuration Publish the default configuration:

    php bin/console digitalstate:bpm:camunda:install
    

    Update config/packages/digitalstate_platform_bpm_camunda.yaml with your Camunda server details (e.g., URL, credentials).

  3. First Use Case: Triggering a Process Use the CamundaClient service to start a process:

    use DigitalState\Platform\Bpm\CamundaBundle\Client\CamundaClientInterface;
    
    class MyService {
        public function __construct(private CamundaClientInterface $camundaClient) {}
    
        public function startProcess(string $processDefinitionKey, array $variables = []): void {
            $this->camundaClient->startProcess($processDefinitionKey, $variables);
        }
    }
    

Implementation Patterns

Core Workflows

  1. Process Interaction

    • Start Processes: Use CamundaClientInterface to kick off workflows:
      $this->camundaClient->startProcess('purchase-order', ['orderId' => 123]);
      
    • Query Processes: Fetch active/inactive processes:
      $processes = $this->camundaClient->getProcessInstances('purchase-order');
      
    • Signal Events: Trigger intermediate events:
      $this->camundaClient->signalEvent('order-approved', ['orderId' => 123]);
      
  2. Variable Management

    • Pass variables when starting processes or use setVariables()/getVariables():
      $this->camundaClient->setVariables('processInstanceId', ['status' => 'approved']);
      $variables = $this->camundaClient->getVariables('processInstanceId');
      
  3. Task Handling

    • Complete tasks with business key or ID:
      $this->camundaClient->completeTask('taskId', ['assignee' => 'user1']);
      
    • Fetch tasks for a user:
      $tasks = $this->camundaClient->getTasksForUser('user1');
      
  4. Event Listeners

    • Subscribe to Camunda events (e.g., process started/completed) via Symfony’s event dispatcher:
      # config/services.yaml
      services:
          App\EventListener\CamundaProcessListener:
              tags:
                  - { name: kernel.event_listener, event: digitalstate.bpm.camunda.process.started, method: onProcessStarted }
      

Integration Tips

  1. OroPlatform Integration

    • Extend DigitalState\Platform\Bpm\CamundaBundle\Entity\CamundaProcess to add custom fields or behaviors.
    • Use Oro’s entity managers to query processes alongside other business entities:
      $processes = $this->entityManager->getRepository(CamundaProcess::class)
          ->findBy(['definitionKey' => 'purchase-order']);
      
  2. Custom Process Definitions

    • Store Camunda BPMN files in config/bpmn/ and reference them in YAML:
      # config/packages/digitalstate_platform_bpm_camunda.yaml
      digitalstate_platform_bpm_camunda:
          process_definitions:
              purchase-order: { file: 'purchase_order.bpmn' }
      
  3. API-Driven Workflows

    • Expose Camunda actions as API endpoints:
      #[Route('/api/processes/{processId}/complete', methods: ['POST'])]
      public function completeProcess(CamundaClientInterface $camundaClient, string $processId): JsonResponse {
          $camundaClient->completeProcess($processId);
          return new JsonResponse(['status' => 'completed']);
      }
      
  4. Testing

    • Use the CamundaClientInterface mock in PHPUnit:
      $mockClient = $this->createMock(CamundaClientInterface::class);
      $mockClient->method('startProcess')->willReturn(['id' => 'test-123']);
      $this->container->set(CamundaClientInterface::class, $mockClient);
      

Gotchas and Tips

Pitfalls

  1. Configuration Overrides

    • Avoid hardcoding Camunda URLs in services. Always use the configured digitalstate_platform_bpm_camunda.client.url.
    • Fix: Inject CamundaClientInterface (which uses the configured URL) instead of raw HTTP clients.
  2. Process Definition Key Mismatches

    • Typos in processDefinitionKey will silently fail. Validate keys against your process_definitions config:
      if (!array_key_exists($processDefinitionKey, $this->config['process_definitions'])) {
          throw new \InvalidArgumentException("Invalid process definition key: $processDefinitionKey");
      }
      
  3. Variable Serialization

    • Camunda expects variables to be JSON-serializable. Avoid passing objects directly:
      // ❌ Avoid
      $this->camundaClient->startProcess('process', ['user' => $userObject]);
      
      // ✅ Do this
      $this->camundaClient->startProcess('process', ['userId' => $userObject->getId()]);
      
  4. Task Assignee Conflicts

    • If multiple users claim the same task, use CamundaClientInterface::claimTask() explicitly:
      $this->camundaClient->claimTask('taskId', 'user1');
      
  5. Rate Limiting

    • High-frequency calls may hit Camunda’s rate limits. Implement retries with exponential backoff:
      use Symfony\Component\Process\Exception\ProcessFailedException;
      
      try {
          $this->camundaClient->startProcess('process');
      } catch (ProcessFailedException $e) {
          if (str_contains($e->getMessage(), 'rate limit')) {
              sleep(2 ** $attempt); // Exponential backoff
              retry();
          }
      }
      

Debugging Tips

  1. Enable API Logging Add this to config/packages/monolog.yaml:

    handlers:
        digitalstate_bpm:
            type: stream
            path: "%kernel.logs_dir%/digitalstate_bpm.log"
            level: debug
            channels: ["digitalstate_bpm"]
    

    Then enable logging in digitalstate_platform_bpm_camunda.yaml:

    digitalstate_platform_bpm_camunda:
        debug: true
    
  2. Camunda Engine Logs

    • Check Camunda’s engine.log (default: logs/camunda-engine.log) for process execution details.
  3. Process Instance IDs

    • Always log processInstanceId when debugging:
      $processInstance = $this->camundaClient->startProcess('process');
      $this->logger->info('Started process', ['instanceId' => $processInstance['id']]);
      

Extension Points

  1. Custom Clients

    • Extend CamundaClient to add domain-specific methods:
      class CustomCamundaClient extends CamundaClient {
          public function approvePurchaseOrder(string $orderId): void {
              $this->signalEvent('order-approved', ['orderId' => $orderId]);
          }
      }
      
    • Register as a service with a higher priority:
      services:
          App\Service\CustomCamundaClient:
              decorates: digitalstate_platform_bpm_camunda.client
              arguments: ['@digitalstate_platform_bpm_camunda.client.inner']
      
  2. Event Subscribers

    • Listen to Camunda events and trigger OroPlatform actions:
      class CamundaToOroSyncListener {
          public function onProcessCompleted(ProcessCompletedEvent $event) {
              $this->entityManager->persist(new ProcessCompletionLog($event->getProcessInstance()));
              $this->entityManager->flush();
          }
      }
      
  3. Custom Process Variables

    • Add metadata to variables using DigitalState\Platform\Bpm\CamundaBundle\Variable\VariableMetadata:
      $metadata = new VariableMetadata('status', 'approved', ['readOnly' => true]);
      $this->camundaClient->setVariables($instanceId, ['status' => 'approved'], [$metadata]);
      
  4. BPMN File Watcher

    • Use Symfony’s FileWatcher to auto-reload BPMN files during development:
      use Symfony\Component\Filesystem\Filesystem;
      
      class BpmnWatcher {
          public function __construct(private Filesystem $fs) {}
      
          public function watch(string $directory): void {
              $files = $this
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
daikazu/eloquent-salesforce-objects
unseen-codes/chat
romalytar/yammi-jobs-monitoring-laravel
kisame76/filament-db-table-state
nqxcode/laravel-lucene-search
dpfx/laravel-livewire-wizards
workos/workos-php-laravel
sofa/laravel-global-scope
nawasara/auth-primitives
adhocrat-io/arkhe-main
make-dev/orca-harpoon
itsemon245/lamet
baks-dev/dashboard
amoifr/pickle-panther-bundle
make-dev/orca
dmstr/symfony-system-resources-bundle
dmstr/symfony-job-queue-bundle
dmstr/openapi-json-schema-bundle
dmstr/keycloak-security-bundle
dmstr/doctrine-audit-log-bundle