$30 off During Our Annual Pro Sale. View Details »

Workflow engines with Clojure - It's a match!

Tim Zöller
February 23, 2019

Workflow engines with Clojure - It's a match!

With digital processes becoming more complex every year, and the digitalization finally arriving in our companies, workflow engines become more popular in the Java ecosystem. Describing process flows as a graphic model in BPMN (Business Process Model and Notation) makes them readable and enables workflow tools to execute them. When we let these engines keep the state and orchestrate the steps of a process, we gain the possibility to split our software into atomic delegates. We will explore together, how we can integrate a Java BPM engine with Clojure and how both form a love relationship which makes development incredibly fun and rewarding for us.

Tim Zöller

February 23, 2019
Tweet

More Decks by Tim Zöller

Other Decks in Technology

Transcript

  1. IT’s A Match!
    Workflow Engines And Clojure
    Tim Zöller

    View Slide

  2. Workflows are hard
    2

    View Slide

  3. The THEORETICAL Part

    View Slide

  4. Humans Decisions Sequence Time
    Components of a workflow 4

    View Slide

  5. Humans
    Who is completing tasks?
    5

    View Slide

  6. Decisions
    Which tasks are needed?
    6

    View Slide

  7. Sequence
    Which tasks depend on another?
    7

    View Slide

  8. Time
    SLA? How Long Will we wait?
    8

    View Slide

  9. THIS IS NOT SIMPLE
    9

    View Slide

  10. 10
    BPMN
    What if somebody solved this?

    View Slide

  11. 11
    CAMUNDA BPM
    https://github.com/camunda/camunda-bpm-platform
    (Apache License 2.0)

    View Slide

  12. The PRACTICAL Part

    View Slide

  13. 13
    Introducing BPMN 2.0
    EXECUTABLE

    View Slide

  14. 14
    The Camunda Modeler

    View Slide

  15. Process Deployment
    15

    View Slide

  16. 16
    Deploy a Process Definition
    (defn deploy-process [definition-file]
    (let [repo-service (.getRepositoryService camunda)
    name "ServiceDesk.bpmn"
    input-stream (clojure.java.io/input-stream definition-file)]
    (.deploy (.addInputStream (.createDeployment repo-service)
    name
    input-stream))))
    (deploy-process “/my/path/ServiceDesk.bpmn")

    View Slide

  17. 17
    Start a Process Instance
    (defn start-instance-by-key [key variables]
    (.startProcessInstanceByKey (.getRuntimeService camunda) key variables))
    (start-instance-by-key "service-desk"
    {"service-type" "premium"
    "customer-no" "12345"})

    View Slide

  18. GATEWAYS
    18

    View Slide

  19. 19
    GATEWAY EXAMPLE

    View Slide

  20. 20
    Configuring gateways

    View Slide

  21. Delegates
    21

    View Slide

  22. 22
    Delegate Example

    View Slide

  23. 23
    How is it done in Java?
    @Named("mailDelegate")
    public class MailDelegate implements JavaDelegate {
    @Inject
    private MailSender mailSender;
    @Override
    public void execute(DelegateExecution execution) throws Exception {
    String lastName = (String) execution.getVariable("firstName");
    String firstName = (String) execution.getVariable("lastName");
    String emailAddress = (String) execution.getVariable("mailAddress");
    mailSender.sendLowPrioMail(firstName, lastName, emailAddress);
    }
    }
    MEH

    View Slide

  24. 24
    What about Clojure?
    (ns engine-clojure.mail-delegate
    (:gen-class
    :name de.javahippie.camunda.MailDelegate
    :implements [org.camunda.bpm.engine.delegate.JavaDelegate])
    (:require [my-mailer :as mailer]))
    (defn -execute [this execution]
    (let [{firstName "firstName"
    lastName "lastName"
    eMail "mailAddress"} (.getVariables execution)]
    (mailer/send firstName lastName eMail)))

    View Slide

  25. 25
    Configuring Delegates

    View Slide

  26. The TASK List
    26

    View Slide

  27. 27
    USER TASK Example

    View Slide

  28. 28
    Wrap the TASK Service
    (defn get-tasks-for-candidate-group [group]
    (map convert-task
    (.list (.taskCandidateGroup (.createTaskQuery (task-service))
    group))))
    (defn claim-task [id user]
    (.claim (task-service) id user))
    (defn get-task-variables [id]
    (into {} (.getVariables (task-service) id)))
    (defn complete-task [id variables]
    (.complete (task-service) id variables))

    View Slide

  29. 29
    Interact with TASKS
    (get-tasks-for-candidate-group "basic-support")
    (claim-task 12 "tim")
    (get-task-variables 12)
    (complete-task 12 {"completed-at" (now)
    "resolved" true})

    View Slide

  30. TIMERS
    30

    View Slide

  31. 31
    TIMER Example

    View Slide

  32. 32
    Configuring the timer

    View Slide

  33. THERE IS MUCH MORE!
    33

    View Slide

  34. recap

    View Slide

  35. READABLE DELEGATES
    =rand()
    IS IT A MATCH?
    ENGINE INTEGRATION
    TASK ORCHESTRATION
    UNIFIED LANGUAGE
    35

    View Slide

  36. 36

    View Slide

  37. Recommended:
    Camunda User Group Berlin
    Camunda and Clojure
    Hans Hübner & Robert Peckett
    LambadaWerk
    https://www.meetup.com/de-
    DE/Camunda-User-Group-Berlin/
    26
    37

    View Slide

  38. TIM Zöller
    Senior IT Consultant
    ilum:e informatik ag in
    Mainz
    Living in Freiburg
    Developing Java
    applications since 2008
    Co-Founder of JUG Mainz
    Profiles
    About me
    JVM 90 %
    Web 70 %
    Music 100 %
    communication 90 %
    … so, who am i? 38
    javahippie
    @javahippie
    Tim Zöller

    View Slide