AnsweredAssumed Answered

Dynamic JavaDelegates

Question asked by mmaker1234 on Nov 6, 2013
Latest reply on Nov 15, 2013 by pmsevestre
Hello Activiti developers, community,

We have a requirement to provide the ability to load new and update workflow process definitions and their corresponding JavaDelegates during the application run. And before you to send me to the forum search let me note that I already read the following:
  1. Deploying delegate classes
  2. Multiple Classloaders per Engine
  3. Support Deployment-specific Classloaders
  4. Add business archive classloading for delegation classes
  5. Deploying current version of classes with process definition
  6. ReflectUtil.loadClass() and custom classloader
  7. JavaDelegate instances should not be cached
  8. Setting a context classloader when calling client code
  9. Activiti Classloading
  10. Activiti 5.13 User Guide
Unfortunately I did not found a solution to our problem - there are lot of questions and approaches but I can not see a solution. Did I miss or overlook some solution already provided in the forum?

Our environment is the following:
  • Enterprise application (EAR) running in WebLogic application server;
  • Activiti Engine 5.13 provided as a library in the EAR;
  • Activiti Engine configuration file (activiti.cfg.xml) provided in the EAR;
  • We do not use Spring;
  • Due to security reasons we have to expose the minimum possible web interfaces, therefore we can use neither the engine REST API nor the Aciviti Explorer;
  • We have a separate, command line application to upload the process definitions to the database. It actually invokes a separate, standalone Activiti Engine instance connected to the same database that the enterprise application uses;
What we need to achieve is:
  • To be able to add or update a process definition at any time during the enterprise application run;
  • To be able to change/update the JavaDelegates at any time during the enterprise application run;
  • The changes in the JavaDelegates must apply immediately. Preferably immediate after the (re-) deployment (i.e. for the already existing process instances) but latest with the next created process instance;
  • We are not allowed to restart the application (as this is the only way to restart the Activiti Engine) to apply the changes.
We mainly elaborated on Daniel's tips. Unfortunately
  • "deactivate the deployment cache (implement a subclass which does not cache anything)" is not possible because the
    DeploymentManagerresolveProcessDefinition(ProcessDefinitionEntity)
    heavily relays on cache. We tried with an analog of
    org.activiti.standalone.deploy.CustomDeploymentCache
    but in our test with a single definition the changes in the JavaDelegates were not reflected (until engine restart). The test result draws this solution as at least unreliable - we can not guarantee that instances of other process definitions will be served in order to force the cache update;
  • "use proxy delegates (a delegate which loads the "actual" delegate)" is not quite applicable as we should loose or at least have big headaches with the transfer of the fields of the JavaDelegate;
  • "do not use java delegates (but lookup objects the lifecycle of which is managed by some other container like EJB/CDI, OSGi, Spring, … )" To be honest we do not understand this proposal quite good. We tried with DelegateExpression but it seems there is no big difference with the JavaDelegate - instead to provide the delegate class name in the process definition, one should provide that class name in the engine configuration (which is read only once - at the engine start)
  • "You have to garbage collect the classloader that loaded a class / create a new instance of your classloader" How to garbage collect the class loader when
    ReflectUtil.getCustomClassLoader()
    returns the result of
    processEngineConfiguration.getClassLoader()
    which always provides the same object?!
  • In regard to JavaDelegate instances should not be cached: "I propose that we do not cache DelegateInstances in ClassDelegate", Resolved, Fixed in 5.9. I do not observe this fix in 5.13 - the javadoc for
    DefaultDeploymentCache
    states "keep everything in memory, unless a limit is set".
Currently we did the following to satisfy the requirements:
  • Created a custom class loader;
  • Provided the class loader in the Activiti Engine configuration;
  • Provided for each process definition a deployment package (.jar) containing all JavaDelegates referred by the process definition. These packages are deployed in the application server as separate applications;
  • Forced
    ClassDelegate.execute(ActivityExecution)
    and
    ClassDelegate.signal(ActivityExecution)
    to always call
    getActivityBehaviorInstance(execution)
    ;
What we achieved is:
  • We can add or update the process definition at any time and it applies with the next process instantiation;
  • We can add (deploy) the corresponding JavaDelegates and they apply with their reference by the process instance;
What we still miss is the update of the JavaDelegates to take place immediately and not only after the Activiti Engine restart.

Now the question is (phew, at last!): (again) How to achieve dynamic JavaDelegates update (in an application server environment)?

By the way, anyone to see a feasible or promising approach we miss?

Thank you in advance for your efforts to answer,
Monique

Outcomes