poniedziałek, 2 września 2013

jBPM6 samples with RuntimeManager

jBPM6 introduces new module - jbpm-runtime-manager - that aims at significantly simplify management of:

  • KnowledgeBase (KieBase)
  • KnowledgeSession (KieSession)
Moreover it allows to use predefined strategies for handling knowledge sessions and its relation to process instance. By default jBPM6 comes with three strategies:
  • Singleton - single knowledge session that will execute all process instances
  • Per Request - every request (which is in fact call to getRuntimeEngine) will get new knowledge session
  • Per Process Instance - every process instance will have its dedicated knowledge session for the entire life time
To make use of the strategy it's enough to create proper type of RuntimeManager. jBPM6 allows to obtain instance of the RuntimeManager in various ways, this article will provide hands on information on how it can be achieved. 
With jBPM6 a whole new way of building application has been provided - Context and Dependency Injection is now available for users to build application and bring the power of jBPM to next level. Obviously CDI is not the only way to make use of jBPM - the regular API based approach is still available and fully functional.

CDI integration

jBPM6 tooling (like jbpm console or kie-wb) is built on CDI and thanks to that set of services has been provided to ease the development for custom applications that are based on CDI. These services are bundled as part of jbpm-kie-services and provides compact solution to most of the required operations to put BPM into your application:
  • deployment service - deploys and undeploys units (kjars) into the process engine
  • runtime service - gives access to state of the process engine, like retrieve process definitions, process instances, history log, etc
  • bpmn2 data service - gives access to details of the process definition taken from BPMN2 xml
  • form provider service - gives access to forms for processes and tasks
So whenever custom application is built with CDI these services are recommended way to go to get most of the power of CDI and jBPM. Moreover it's the safest way too as it is used in jBPM tooling so it got fair amount of testing to secure it does what is expected.

Using jbpm-kie-services is not a mandatory to be able to use jBPM6 in CDI environment but it does have some advantages:
- allow to maintain multiple RuntimeManagers within single execution environment
- allow independent deploy and undeploy of units (kjar) without server/application restart
- allow to select different strategies for different units

See jbpm-sample-cdi-services project for details.

while these are all appealing add-ons they are not always needed, especially if application requires only single RuntimeManager instance to be included in the application. If that's the case we can let CDI container to create the RuntimeManager instance for us. That is considered second approach to CDI integration where only single instance of RuntimeManager is active and it's managed completely by the CDI container. Application needs to provide environment that RuntimeManager will be based on. 

See jbpm-sample-cdi project for details.

API approach

Last but not least is the regular API based approach to jBPM6 and RuntimeManager. It expects to be built by the application and in fact provides all configuration options. Moreover this is the simplest way to extend the functionality of RuntimeManager that comes out of the box.

See jbpm-sample project for details.

This article is just an introduction to the way jBPM6 and RuntimeManager can be used. More detailed articles will follow to provide in-depth information on every option given here (cdi with services, pure cdi, api).

If you have any aspects that you would like to see in next articles (regarding runtime manager and CDI) just drop a comment here and I'll do by best to include them.

31 komentarzy:

  1. Thank you Marciej, i finally found an information i still missing in the JPBM6 documentation! go on writing(;)

    OdpowiedzUsuń
  2. Glad it you find it useful. Documentation will soon start coming we are closing last bits of the work so stay tuned.

    OdpowiedzUsuń
  3. Hi Maciejs, thanks, very informative article..

    By the way, will JBPM 6 still support integration with Spring ?

    OdpowiedzUsuń
  4. Thanks Thomas!

    Of course that jBPM 6 supports Spring. I just did not have time yet to produce an example for it. An in fact you should be able to do that in two ways - similar to what is in jbpm-sample project - meaning do it sort of manually using spring config files or use lie-spring module, see details here:
    https://github.com/droolsjbpm/droolsjbpm-integration/tree/master/kie-spring
    https://github.com/droolsjbpm/droolsjbpm-integration/blob/master/kie-aries-blueprint

    in the later you can check out an example that allows you to direct configure runtime manager
    https://github.com/droolsjbpm/droolsjbpm-integration/blob/master/kie-aries-blueprint/src/test/resources/org/kie/aries/blueprint/bpmn.xml

    OdpowiedzUsuń
  5. Hey Maciej,

    great to see some more information on jbpm6 :) Great post!
    I have some trouble getting the RuntimeManager to work with Spring persistence (https://community.jboss.org/thread/231759), as I didn't see any test cases or the like with the Runtime Manager in Kie-Spring. Didn't know that there seems to be some spring stuff in the blueprint module, though...
    Anyway it would be great if you could make a small blog post about Spring integration and runtime manager (especially regarding my transactions problem).

    Cheers, Alex

    OdpowiedzUsuń
  6. noticed that you use local transactions which is always tricky to support, I mean both JTA and then local. I l made a comment on community forum as well. I'll try to work on some sample application with spring as well. Contribution always more than welcome :)

    OdpowiedzUsuń
  7. Hey Maciej,

    it's me again ;) After working with runtimeManager for the last few days, I have to say: great job :)
    Anyhow, I'm working on a grails plugin for drools integration and I would love to pick your brain on a small design decision around the runtimeManager.
    I have basically wrote a new RuntimeManagerFactory which produces RuntimeManagers tailored to my environment, in concept pretty similar to the CDI stuff you guys use. Anyway, I'm indecisive as to how to provide these RuntimeManagers to my client application. The easiest approach would be to set up singletons for the different types of RuntimeManagers via Spring and make them available for injection. These would be set up with a default RuntimeEnvironment, however when customisation would be needed it should be trivial to set up a manager backed by a customized runtimeEnvironment.
    Do you think that's a valid approach? And do you maybe know of any pitfalls that I would need to be aware of when settings things up this way?

    Cheers, Alex

    OdpowiedzUsuń
  8. Glad to hear it meets expectations that was whole idea of providing such component :)

    Would be nice to hear what is missing in the default RuntimeManagerFactory that puts you in position to create your own. So if you could elaborate a bit on this that would be helpful.

    When it comes to the delivery of RuntimeManager to the clients code that depends on the actual needs, is it only a predefined set of RuntimeManagers that application will need or is it dynamic and RuntimeManagers will be created and closed on demand?

    What you could think of is to have sort of cached factory for runtime manager that might keep track of already created RuntimeManagers and if there is request for new one that meets criteria of one that has been already created you could simply resuse it.

    Described approach is completely valid one. Especially if you have fixed number of RuntimeManagers to manage. Most important when using RuntimeManagers and RuntimeEngine is proper selection of what strategy fits best to your environment as in some case when you select not the right one you might experience unexpected issues like performance degradation, concurrency issues etc.

    Bit of background of what exactly you're trying to achieve might help here too.

    OdpowiedzUsuń
  9. Hey Maciej,

    first of all thanks for your valuable input! :)

    At the moment I'm building a droolsjbpm 'core' plugin for grails, which is supposed to be extended by several other grails plugins which integrate their own functionality (e.g. a plugin can provide a custom HT service component, or implement a workflow). Basically a hopefully simpler 'mini' kie-wb based on grails rather than uberfire with a predefined number of RuntimeManagers (based on the number of plugins installed). Hope that makes sense :)

    The reason I rewrote the RuntimeManagerFactory was to make it a little bit easier to manage in the spring environment and have it be more extensible for new RuntimeManagers. So I basically made the existing RuntimeManagerFactory generic and created simple RuntimeManagerFactories for the different runtimeManager types. So now I set up the generic stuff in a factory and can simply register a new runtimeManager type with that generic factory. So a plugin can basically just use that generic factory to set up any kind of runtimeManager (even self implemented ones).

    The idea with the cache is certainly appealing, but that leads me to a question: what could be criteria for runtimeManagers, which would make it sensible to be cached?
    As I understand it a runtimeManager is tied to a specific KieBase and sessionConfiguration that's set up in the runtimeEnvironment. So if I relate this to the plugin paradigm that I'm after that means I would probably need to have (at least one) runtimeManager for every plugin as the plugins won't (shouldn't) be coupled and have different kieBases? This would also mean that caching wouldn't be necessary?

    Or is there a reasonable way to set up a classpath KieBase (similar in spirit to the Classpath kieContainer) so that everything can be called from one runtimeManger thats shared by all plugins?

    Another question would be: what is the best runtimeManager to use for a long running process scenario? I would argue that the PerProcessInstance should be the best solution, as it mitigates the scaling problems posed by a singleton runtimeManager and PerRequest approach doesn't seem to make any sense for long running processes (no way to dispose of the session until the process finished).

    Cheers, Alex

    OdpowiedzUsuń
  10. Alright now its clear :). if you have predefined number of runtime managers - like single runtime manager per plugin then that makes perfectly sense to preload them on start and make them available for injection. So that's the main difference compared to lie-wb as kie-wb allows to have the runtime managers to be created/disposed dynamically - kjar will always get its dedicated RuntimeManager.

    The RuntimeManagerFactory was intentionally done as limited to only supported strategies and you should be capable to provide your own if there is a need for it (and you have already done that). For spring based application you most likely could directly use RuntimeManagerFactoryImpl or an extension of this class as it has some valuable pieces of code. But of course that is not mandatory. Would be good to integrate what you have done at some point...

    Caching for RuntimeManagers I was considering if there is a need to for example have code that uses different plugins at the same time and would like to have central place to ask for RuntimeManagers so that "runtime manager registry" could cache them instead of asking factories to create new instances. Anyway looks like that is not the case here.

    I think that best is to rely on kjar approach where you have mavenized jars that comes with all is needed (process definitions, rules, data model, etc) and you build kbase out of it. Same as kie-wb does it. Again might not be what is required in your case.

    Regarding strategy, it pretty much depends if you use rules or in other words if you keep state in the ksession such as facts. If so then the best would be Per Process Instance. If you don't then any of these three strategies might be used. Per Request does not affect the actual execution of long running processes as the process instance is stored in be and whenever new request comes in new ksession will be created and that ksession will load the process instance so it is still valid.
    Singleton has obviously its limitation in terms of concurrent processing as it is only single ksession that does the work so it will be synchronized reducing the actual throughput.

    OdpowiedzUsuń
  11. Thanks, for your detailed and helpful answer! :)

    I have just 'discovered' the abstractDeploymentService and KModuleDeploymentService, which seems to be the kie-wb "runtimeManager registry" or dynamic deployment which you spoke of, correct? I have to say after a first look and some thinking it does look appealing to go this totally dynamic route. However, my idea was a little bit different:

    I totally agree that a mavenized (k)jar is definitely the right way to go. I thought about setting up grails plugins (which are basically a complete web-app themselves that can be distributed as maven artifacts) as kmodules. Either by providing a kmodule.xml explicitly or even dynamically building a kbase based on conventions. To avoid tight coupling between plugins/kjars (and the need to use 'outside' runtimeManagers) I wanted to use a WIH Registry provided by the core plugin and completly depend on WIH (and if needed an extenal Eventbus) for inter plugin/kjar communication. So on installation a plugin/kjar registers its 'Interface' (WIH) which will be added to every new KieSession so that other plugins 'just work'(TM).

    Does this sound possible/reasonable to you? Do you maybe see limits to what is possible with this approach?

    So if I didn't miss something I think I could do without a full fledged dynamic DeploymentService, though I do have a use case where I need to automatically redeploy a changed kbase. My idea would be to use the a new kbase/runtimeManager for all new operations and dispose of the old one as soon as no processes are running anymore. Is there a convient way to check if there is anything still running in a RuntimeManager? I have seen the RuntimeDataService but this seems to work solely with events and not check the runtimeManager directly... Or can I use the KieScanner to achieve this somehow?

    Thanks again for all your Feedback, I really do appreciate it :)

    Cheers, Alex

    OdpowiedzUsuń
  12. Just to clarify: with WIH I mean WorkItemHandlers ;)

    Cheers, Alex

    OdpowiedzUsuń
  13. You can treat DeploymentService as sort of single point of contact about deployments (kind of registry) although it fires events for every deploy or undeply operation so you could have independent registry for that too if you like.

    Building web apps that shall be considered as kmodules is bit an overkill in my opinion. kmodule jars (kjars) should be self contained and provides business logic to the application that requires it.
    Not sure I got your point about work item handlers.... in general when you look at the RuntimeEnvironment it allows you to set some implementation of RegisterableItemsFactory which in fact is responsible for providing work item handlers for kie session of that particular RuntimeManager. So whenever RuntimeManager creates/loads a ksession it will register all work item handlers defined in the RegisterableItemsFactory configured for it. With that you don't need any other thing to keep track of handlers per runtime manager. So they are scoped to that given runtime manager so no risk of registering more then is needed. Would that cover the case?

    You can use AuditLogService to check if there are any active processes for given deployment this is already done by default when using DeploymentService so you would need to do something similar if you don't want to use DeploymentService.

    OdpowiedzUsuń
  14. Ten komentarz został usunięty przez autora.

    OdpowiedzUsuń
  15. Hey Maciej,

    yeah what I was talking about is pretty project specific, so nevermind :)

    I know about the RegisterableItemsFactory and the WIH registry I was talking about is a customisation of it, to make it play nice with my plugin approach. And I'm pretty sure it covers the case :) Just wanted to check if you liked my general approach as I am not the most experienced in the field of jbpm.

    Anyway, thanks to you I really have better picture of how everything works together and I'm pretty sure I can achieve what I want. I'm totally greatful for all your answers :)

    Droolsjbpm is an excellent piece of software and I'm really excited about all of the possibilities it extends to the community.

    Cheers, Alex.

    OdpowiedzUsuń
  16. Hi
    great job, first of all !!
    second, a questionr
    right now, i can access the runtime engine using a RemoteRestRuntimeFactory (the runtime engine can later be used to access the KieSession or the TaskService) but there is no visible way to access the other components:
    -bpmn2 data service
    -form provider service
    and also, i dont find any methods that can be used to access the history logs
    Is there any plans to include these in the remote runtime engine implementation ?

    OdpowiedzUsuń
  17. bpmn2 data service and form provider service are cdi services only and they are not meant (at least at the moment) to be exposed remotely. For history logs the remote runtime engine should be capable of providing the right information via: RemoteRuntimeEngine.getAuditLogService()

    OdpowiedzUsuń
  18. hi Maciej,
    Can jBPM 6 run seamlessly in Cloud environment?

    OdpowiedzUsuń
  19. yes, it should work in cloud without any problems

    OdpowiedzUsuń
  20. Hi,
    Nice article! I got most of the things running in spring. I was wondering if it is possible to use Spring DI in a custom service task or custom workitemhandlers?
    And also what i now see is when i have a spring component and a process in started the runtimemanager creates a new instance of that spring component. I actually want to use the one from the spring context if possible.
    Do you have an example for that?

    Thanks, cheers!
    Martijn

    OdpowiedzUsuń
  21. To use Spring DI in your custom handlers you would need to provide custom implementation of RegisterableItemsFactory (or extend the DefaultRegisterableItemsFactory) that makes use of Spring context to provide beans when required. Unfortunately don't have any concrete example but feel free to create one (like on github) so we can collaborate.

    Not sure what you mean that start process creates new component, could you elaborate bit on this?

    OdpowiedzUsuń
  22. Well wrong terminology :) The runtime manager creates a new instance of a bean which i defined in spring . An example:
    @Component
    public class HelloService {

    @Autowired
    EmailManager emailManager;

    public HelloService() {
    System.out.println("INSTANTIATING HELLOSERVICE COMPONENT");
    }

    public DataOutput hello(com.test.DataInput name) throws InterruptedException {
    .....
    }
    public DataOutput hello_insert(com.test.DataOutput name) {
    .....
    }

    }

    and use it like this in the bpmn2 xml:


    inputMessage



    What i saw in the log console that spring instantiates the HelloService because it was annotated with @component. Then when the runtimemanager starts it will create a new instance of HelloService instead of using the one in spring context.

    I hope its clear enough :)

    Thanks for the quick reply btw!

    Cheers,
    Martijn

    OdpowiedzUsuń
  23. so how do you pass that HelloService into the process? Is it like service task with interface and operation that points to this HelloService class? If so then that is expected as it will use simply reflection to instantiate the class instance as it does not know if that's spring class or even does know nothing about spring context. For that you would need to extend implementation of ServiceTaskHandler to be context aware.

    https://github.com/droolsjbpm/jbpm/blob/master/jbpm-workitems/src/main/java/org/jbpm/process/workitem/bpmn2/ServiceTaskHandler.java

    OdpowiedzUsuń
  24. Ah it was stripped from my comment but i defined it in the bpmn2 file like this:
    "<bpmn2:interface id="myInterface2" name="com.test.HelloService">
    <bpmn2:operation id="myOperation2" name="hello">
    <bpmn2:inMessageRef>inputMessage2</bpmn2:inMessageRef>
    </bpmn2:operation>"

    OdpowiedzUsuń
    Odpowiedzi
    1. Hi,holle,Can you give me jbpm6 spring DI example?Thanks, cheers!
      ChangLuo

      Usuń
  25. Extending the ServiceTaskHandler to be context aware did the trick! thanks!

    OdpowiedzUsuń
  26. Hi, Thanks for the detailed article. I integrated the JBPM in my non maven application via spring using and bean as explained http://docs.jboss.org/drools/release/latest/drools-docs/html/ch.kie.spring.html#d0e12511.

    The problem is when deployed in wbesphere in .ear format it fails to load the .bpmn and .drl files. Looks like KModuleBeanFactoryPostProcessor loads the files using File lookup and not from classpath as input Stream. How can i load the files from classspath in spring Integration for my KieBase. Will the RuntimeManager help when integrated with spring?
    Any input will be appreciated.

    Thanks,
    Deepak

    OdpowiedzUsuń
  27. Hi , can you help to understand how can i use a KieBase withe the runtime engine ! , I'm a beginner in developing with JBPM , can you help me !

    OdpowiedzUsuń
    Odpowiedzi
    1. you can create kbase manually and set it on RuntimeEnvironment that is then used to create runtime manager

      Usuń
  28. Hi can you help me to understand how to use a Remote API to connect my application web with the jbpm application

    OdpowiedzUsuń
    Odpowiedzi
    1. look at using kie server as your execution server that can be easily accessed remotely http://mswiderski.blogspot.com/2015/09/unified-kie-execution-server-part-1.html

      Usuń