Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Event-driven business automation powered by cloud native Java

Event-driven business automation powered by cloud native Java

2020/01/30 JJUG x JJBUG共催ナイトセミナー「cloud native business automation for Java」のスライドです。

Toshiya Kobayashi

January 31, 2020
Tweet

More Decks by Toshiya Kobayashi

Other Decks in Programming

Transcript

  1. Agenda • What is business automation: introduction to Drools and

    jBPM • Event-Driven Business Automation with Kogito • Cloud-native business automation on Openshift + • Quarkus: an open source stack to write cloud native Java apps
  2. What is Business Automation • Processes Set of activities and

    tasks that, once completed following a specific workflow, will accomplish an organizational goal • Rules Encapsulate domain and define business-specific constraints and behaviors, keeping them separated from the main application flow
  3. What is a Rule • A business rule is a

    piece of logic that captures "what to do" depending on a context (Facts) • Usually captured in natural language first WHEN <CONDITIONS> THEN <ACTIONS>
  4. Introducing Drools • Easier to understand → Requirements can be

    more naturally translated into rules. It is more likely for a technically skilled business analyst to verify, validate or even change a rule than a piece of Java code • Improved maintainability → We don't care about how to implement a solution only what needs to be done to solve a problem • Deals with evolving complexity → It's easier to modify a rule than a Java program and to determine the impact of this change on the rest of the application • Modularity → Each rule models an isolated and small portion of your business logic and is not part of a monolithic program • Clear separation of business logic from the rest of the system → Business and infrastructural code have very different life cycles • Complex Event Processing → Facts can be handled like timestamped events allowing temporal reasoning on them RULES
  5. How a Rule Engine Works • The Rule Base contains

    a computation efficient representation of the set of the defined rules • The Working Memory contains the set of facts inserted into session • The engine matches the fact in the working memory against the rules set • When a match is found it creates an activation and puts it into the agenda • An activation is the tuple of facts matching the conditions of a rule plus the rule itself • When all activations have been created the agenda elects through a conflict resolution strategy the one to be executed first • The elected activation is passed to the execution engine and then fired
  6. A simple rule set rule RaiseAlarm when exists Fire() then

    insert( new Alarm( "house1" ) ); System.out.println( "Raise the Alarm"); end rule CancelAlarm when not Fire() a : Alarm() then delete( a ); System.out.println( "Cancel the Alarm"); end rule TurnSprinklerOn when s : Sprinkler( on == false ) f : Fire( room == s.room ) then modify( s ) { setOn( true ) } System.out.println( "Turn on the sprinkler for room " + f.getRoom().getName() ); end rule TurnSprinklerOff when s : Sprinkler( on == true ) not Fire( room == s.room ) then modify( s ) { setOn( false ) } System.out.println( "Turn off the sprinkler for room " + s.getRoom().getName() ); end rule OK when not Alarm() not Sprinkler( on == true ) then System.out.println( "Everything is ok" ); end Pattern-matching against objects in the Working Memory Code executed when a match is fired
  7. Almost anything in any domain can be expressed as process

    or rule. It’s a matter of recognizing patterns to be able to avoid repetition and mistakes, and by that automating business.
  8. jBPM provides various capabilities that simplify and externalize business logic

    into reusable assets such as cases, processes, decision tables and more. It consists of: • business processes (BPMN2) • case management (BPMN2 and CMMN) • decision management (DMN) • business rules (DRL) A toolkit for building business applications to help automate business processes and decisions
  9. • World around us has changed • New deployment techniques

    • Better usage of machine and cluster resources • Fat application servers vs lean serverless/FaaS architectures The reasons for a change
  10. • If you think about business automation think about the

    cloud as this is where your business logic lives these days • Achieves amazingly fast boot time and low memory footprint by leveraging latest technology ◦ Quarkus ◦ Kubernetes ◦ OpenShift ◦ KNative The reasons for a change
  11. Cogito, ergo sum Pronunciation /ˈko.d ͡ ʒi.to/, [ˈkoː.d ͡ ʒi.to]

    (Don't worry, nobody in the team gets it right, anyway) see also: http://kverlaen.blogspot.com/2019/09/etymology-of-kogito.html René Descartes
  12. Kogito, ergo automate • BTW, this is not Mario •

    Not a pirate • It is a viking • Odin, who sacrificed his eye for knowledge
  13. • A cloud-native development, deployment and execution platform for business

    automation: ◦ Rules and Decisions ◦ Processes and Cases • ... under the covers ◦ the backbone is code generation based on business assets ◦ executable model for the process/rule/decision definitions ◦ type safe data model that encapsulates variables ◦ REST api for each public business process/decision/rule Introducing Kogito
  14. • Adapts to your business domain instead of the other

    way around • No more leaking of abstractions of the platform into your client applications • Stay focused on business requirements instead of implementation technology Focus on business domain instead of technology
  15. • Achieve instant developer efficiency by having ◦ Tooling embeddable

    wherever you need it ◦ Code generation taking care of 80% of the work ◦ Flexibility to customize, only use what you need ◦ Simplified local development with live reload Offers a powerful developer experience
  16. • If you think about business automation think about the

    cloud as this is where your business logic lives these days • Achieves amazingly fast boot time and low memory footprint by leveraging newest technology ◦ Quarkus ◦ Kubernetes/OpenShift/KNative Designed from ground up to run at scale
  17. • A Framework for writing (fast and lightweight) Java applications

    • Code generation reduces startup time and memory footprint (bonus: GraalVM native image) Introducing Quarkus
  18. • A Framework for writing (fast and lightweight) Java applications

    • Code generation reduces startup time and memory footprint (bonus: GraalVM native image) • Exposes existing standard ◦ Servlet ◦ JAX-RS ◦ JPA, JDBC ◦ CDI ◦ Bean Validation ◦ Transactions ◦ Logging ◦ Microprofile Introducing Quarkus
  19. Hot Reload • ./mvn compile quarkus:dev makes Quarkus run in

    dev mode and provide hot-reload capabilities • Changes made to source and configuration files are automatically re-compiled once the browser is refreshed • Thanks to Kogito’s Quarkus extension, also Drools and jBPM files are recognized as hot reloadable artifacts and the corresponding rules and processes are regenerated
  20. Demo Kogito Travel Agency.. the beginning • Travel request handling

    service ◦ deals with Travel requests submitted by travellers ◦ assesses if there is a need for visa ◦ books hotel and flights ◦ awaits confirmation from traveller • Single service that ◦ exposes REST api ◦ provides simple UI
  21. Demo Instructions • install VSCode • install Kogito extension $

    curl -L http://bit.ly/get-kogito-ext | sh • You can also install manually - download vsix from https://github.com/kiegroup/kogito-tooling/releases/tag/0.2.0 - install from vsix in VSCode
  22. Startup Time Optimization • Quarkus and Kogito philosophy is to

    move as much as possible at build-time of what formerly was done at compile-time • Ahead-of-time optimizations ◦ Dead code elimination ◦ Code generation instead of reflection + dynamic class loading • Starts key parts of application ahead-of-time
  23. Executable Model at a Glance • A pure Java DSL

    for rules and processes authoring • A pure Java canonical representation of a rule base • Automatically generated by Maven plugin or Quarkus extension ◦ Can be embedded in jar ◦ Faster boot • Improve Backward/Forward compatibility • Allow for faster prototyping and experimentation of new features
  24. Executable Model at a Glance • Avoid: ◦ unnecessary reflection

    ◦ unnecessary dynamic class loading ◦ process as much info at compile time • Benefits ◦ faster startup-time ◦ enable ahead-of-time native compilation
  25. Executable Model at a Glance • Avoid: ◦ unnecessary reflection

    ◦ unnecessary dynamic class loading ◦ process as much info at compile time • Benefits ◦ faster startup-time ◦ enable ahead-of-time native compilation Shameless Plug: Your Program as a Transpiler: Applying Compiler Design to Everyday Programming Wednesday @ 12:00 -- Room 9 (Edoardo)
  26. Native Mode • Quarkus allows to generate an operating system

    specific (aka native) executable from your Java code • Trade-offs: lack of build-once-run-anywhere and hot reload capabilities VS. lower on-disk footprint and quicker startup time • Perfect fit for serverless/event-driven environments where we need to spin up a service in real time to react to an event • Statically compiled executables benefit from closed-world optimizations, such as fine-grained dead-code elimination, where only the portions of frameworks (including the JDK itself) actually in use by the service are included in the resulting image
  27. • Responsible for building with selected runtime ◦ Quarkus ◦

    Spring Boot • Provision services on demand and remove them when no longer needed • Manage deployed services including their dependencies • Service discovery based on labels • Guarding services of losing their dependants • Security provisioning and propagation Operator
  28. • Deploy and manage your services with operator and intuitive

    CLI tool ◦ kogito new-app travel-agency Create new OpenShift project with default services provisioned ◦ kogito deploy travel-agency https://github.com/.../travelapp Deploys given application from source and attaches to required infrastructure ◦ kogito deploy visas https://github.com/.../visasapp Deploys given application from source and attaches to required infrastructure Designed from ground up to run at scale
  29. Runtime Service • Exposes business logic as service ◦ processes

    ◦ rules ◦ decisions • Lightweight and fast • Allows to build on top of ◦ Quarkus ◦ Spring Boot • Extendable
  30. Persistence • Backed by key value storage - string ->

    byte[] • Infinispan used as default persistent store • Stores ◦ Process Instance and Node Instance information ◦ Process Instance variables ▪ Marshalling of both process/node instance and variables is done by protobuf • Each process definition is stored in its own cache to improve management and concurrency
  31. Data Index • Captures all events related to runtime processing

    ◦ processes ◦ user tasks ◦ decision and rules • Indexes it in domain specific way • Exposes GraphQL based API • Provides unified view on technical aspects of the running services
  32. • Messaging (Kafka and AMQ) • Optionally equipped with monitoring

    and tracing capabilities • Monitoring (Prometheus) • Visualization (Grafana) Uses existing and well known tools
  33. What is GraalVM A polyglot VM with cross-language JIT supporting

    • Java Bytecode and JVM languages • Interop with different languages • Dynamic languages through Truffle API Cross-language interop out of the box • Simple AST-based interpreter • JIT across language boundaries Support for native binary compilation (SubstrateVM) • faster boot-up • lower memory footprint
  34. AoT compilation with GraalVM • Static analysis • Closed world

    assumption • Dead code elimination: classes, fields, methods, branches
  35. Fast process start Less memory Small size on disk AoT

    compilation with GraalVM • Static analysis • Closed world assumption • Dead code elimination: classes, fields, methods, branches
  36. GraalVM Limitations Dynamic Classloading Deploying jars, wars, etc. at runtime

    impossible public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String name, byte[] bytecode ) { return defineClass( name, bytecode, 0, bytecode.length ); } }
  37. GraalVM Limitations Dynamic Classloading Deploying jars, wars, etc. at runtime

    impossible public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String name, byte[] bytecode ) { return defineClass( name, bytecode, 0, bytecode.length ); } }
  38. public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String

    name, byte[] bytecode ) { return defineClass( name, bytecode, 0, bytecode.length ); } } GraalVM Limitations JVMTI, JMX + other native VM interfaces No agents → No JRebel, Byteman, profilers, tracers Dynamic Classloading Deploying jars, wars, etc. at runtime impossible Miscellaneous • Security Manager • finalize() (deprecated anyway) • InvokeDynamic and MethodHandle
  39. public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String

    name, byte[] bytecode ) { return defineClass( name, bytecode, 0, bytecode.length ); } } GraalVM Limitations JVMTI, JMX + other native VM interfaces No agents → No JRebel, Byteman, profilers, tracers Miscellaneous • Security Manager • finalize() (deprecated anyway) • InvokeDynamic and MethodHandle Dynamic Classloading Deploying jars, wars, etc. at runtime impossible
  40. public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String

    name, byte[] bytecode ) { return defineClass( name, bytecode, 0, bytecode.length ); } } GraalVM Limitations JVMTI, JMX + other native VM interfaces No agents → No JRebel, Byteman, profilers, tracers Reflection Requires registration (closed world assumption) Miscellaneous • Security Manager • finalize() (deprecated anyway) • InvokeDynamic and MethodHandle Dynamic Classloading Deploying jars, wars, etc. at runtime impossible
  41. public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String

    name, byte[] bytecode ) { return defineClass( name, bytecode, 0, bytecode.length ); } } GraalVM Limitations JVMTI, JMX + other native VM interfaces No agents → No JRebel, Byteman, profilers, tracers [ { "name" : "org.domain.model.Person", "allPublicConstructors" : true, "allPublicMethods" : true } ] Reflection Requires registration (closed world assumption) -H:ReflectionConfigurationFiles=src/main/resources/reflection.json Miscellaneous • Security Manager • finalize() (deprecated anyway) • InvokeDynamic and MethodHandle Dynamic Classloading Deploying jars, wars, etc. at runtime impossible
  42. public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String

    name, byte[] bytecode ) { throw new UnsupportedOperationException(); } } Drools on GraalVM – other refactors Dynamic class definition is no longer necessary
  43. public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String

    name, byte[] bytecode ) { throw new UnsupportedOperationException(); } } Drools on GraalVM – other refactors Dynamic class definition is no longer necessary <?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> <kbase name="simpleKB" packages="org.drools.simple.project"> <ksession name="simpleKS" default="true"/> </kbase> </kmodule> var m = KieServices.get().newKieModuleModel(); var kb = m.newKieBaseModel("simpleKB"); kb.setEventProcessingMode(CLOUD); kb.addPackage("org.drools.simple.project"); var ks = kb.newKieSessionModel("simpleKS"); ks.setDefault(true); ks.setType(STATEFUL); ks.setClockType(ClockTypeOption.get("realtime"));
  44. public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String

    name, byte[] bytecode ) { throw new UnsupportedOperationException(); } } Drools on GraalVM – other refactors Dynamic class definition is no longer necessary <?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> <kbase name="simpleKB" packages="org.drools.simple.project"> <ksession name="simpleKS" default="true"/> </kbase> </kmodule> var m = KieServices.get().newKieModuleModel(); var kb = m.newKieBaseModel("simpleKB"); kb.setEventProcessingMode(CLOUD); kb.addPackage("org.drools.simple.project"); var ks = kb.newKieSessionModel("simpleKS"); ks.setDefault(true); ks.setType(STATEFUL); ks.setClockType(ClockTypeOption.get("realtime")); org.kie.api.io.KieResources = org.drools.core.io.impl.ResourceFactoryServiceImpl org.kie.api.marshalling.KieMarshallers = org.drools.core.marshalling.MarshallerProviderImpl org.kie.api.concurrent.KieExecutors = org.drools.core.concurrent.ExecutorProviderImpl Map<Class<?>, Object> serviceMap = new HashMap<>(); void wireServices() { serviceMap.put( ServiceInterface.class, Class.forName("org.drools.ServiceImpl") .newInstance()); // … more services here }