Java Classloading problem

Hi guys, I need to support for this scenario. I describe the stept to explain my problem. Could you please help me?

  1. I have a first.war that contains
  • hello1.bpmn (User Task, Service Task 1, User Task)
  • hello.java - linked to service task 1 with log a simple message “Hello mom”
  1. I have a second.war that contains
  • hello2.bpmn (User Task, Service Task 1, User Task, Service Task 2)
  • hello.java - linked to service task 1 with log a simple message “Hello dad”
  • byebye.java - linked to service task 1 with log a simple message “Hello kevin”
  1. I deploy a first.war

  2. I start 3 instances

  3. camunda create 3 process instances

  4. I claim and I complete a first user task and a service task 1 will be runned. I see “Hello mom” into log

  5. ATTENTION!!! I deploy second.war

  6. I claim and I complete a first user task and a service task 1 will be runned. I see “Hello dad” into log.
    I waited to see “Hello mom” but I see “Hello dad”. JAVA CLASS OVERRIDED

How Can I isolate the package?

Regards
Luca

Hi Luca,

Do the BPMN processes hello1 and hello2 have different IDs (i.e. in the XML)?

Cheers,
Thorben

1 Like

No, The ID is the same, I changed only Version Tag

Camunda’s mechanism for registering applications with prior process deployments is by default based on the IDs. See https://docs.camunda.org/manual/7.6/user-guide/process-applications/the-processes-xml-deployment-descriptor/#process-application-deployment for a details. The application server log should also show relevant entries when you deploy the second WAR.

You can try giving the deployments distinct names (use the name attribute of the process-archive element in processes.xml) and set the resumeBy property to deployment-name.

Cheers,
Thorben

1 Like

Thank. Only one note: I use Camunda 7.5 Release. Do This release use the same approch?

Tks

Yup, should work the same there.

1 Like

For model versions ([filename].bpmn), Thorben mentioned above, Camunda does support concurrent, multi-version execution. In-other-words, you could start a process per one if its many versions. And, a process version shouldn’t jump (or self upgrade) unless specifically directed to do so.

Regarding calling on the specific Java class versions: a few options -

  1. Wouldn’t Java naming (CDI) and inheritance (extends) work?

Have a base class define your core behaviour. For example class HelloBase manages core methods required of all descendants. Then, extend this class to a new type HelloExtendedV1, give it an appropriate name such as @Named(“helloExtendedV1”), and use this in hello1.bpmn model.

For hello2.bpmn (model), we also extend HelloBase but give it a different class name such as HelloExtendedV2 and name it @Named(“helloExtendedV2”). Now you have two distinct
class types/versions, with appropriate class and CDI names - essentially allowing reuse of base behaviour with opportunities for extension per model version requirements.

  1. Java interfaces provide similar features - but, going at the problem with a different angle. I was thinking of a factory pattern whereby an instance is created per specific model requirements. In this way you could logically call on specific implementations per model or task-instance requirements.

  2. Aspect Oriented Programming? This approach cross-cuts classes, looking for specific “concerns” (i.e. business requirements), and assembles them per expressed configuration and application.
    see: JBoss documentation (briefly - there are likely more detailed words on this). Case management, alongside a document-oriented approach, follows this methodology. Meaning that the Case model (CMMN) definition provides very specific features per business requirements… as they are defined by user/subject, object-document, and predicate (task) requirements.

  3. Forgot to mention OSGi - this provides very tight controls on class loading. Excellent fit for BPM/Case. But, this can be somewhat complicated.

NOTE: Apologies for shamelessly linking to my blog…

1 Like

@garysamuelson,
clear your points and the options you are explained about.
The pattern suggested can be the solution to have process instances coexistence and belonging to different process definitions. In the use case @lsantaniello showed, it is supposed to be used the class loader isolation of a process engine application (packaged usuallly as a .war) and then it seems like this mechanism is “overriden” by Camunda deployment registration where the last loaded resources win in the .classes loading.
My point is, this is an not desidered behavior from my side and has the following downside:

  1. whereas process definition version is managed for you by Camunda, this is not the case for .classes.
  2. Very often we need to have at max two ot three process definition coexisting in the same Camunda Container, and we need to deploy, as @lsantaniello said, first.war and second.war, where second.war (based on the pattern suggested) need to provide HelloExtendedV1.java and aldo HelloExtendedV2.java (all descendants of the HelloBaseClass used so far by all process istances belonging to the different process version supported);
  3. based on the 1) and 2) points we need also to take care of, at a some point in the time (for sure after the hot deployment of the second.war is completed), to delete first.war before a Camunda container restart, because is not guaranteed in which order the .wars are loaded, and a Class Not Exception can occurs if first.war is loaded as last durint the startup;

Can We definitely say Camunda does not support class loading isolation for same process engine applications with process definition with same id?

What about for third library when we need to update them because a well know bug was solved and but we cannot have the chance to apply this pattern?

Thanks
Elmiro

Sounds like you need OSGi or a micro-service pattern - thinking in terms of utilizing boundaries established by SCA/SwitchYard, ReST, WS interfaces (etc).

Camunda provides the flexibility supporting the necessary pattern per your requirements (tight class-loading controls) - as a BPM/Case engine should.

We’re now taking a closer look at service-implementation (application server) patterns supporting modularity: OSGi and micro-service?

Not sure if this information helps - a while ago I spent some time on OSGi. Micro-services though looks like the emerging leader.

My concern though is the complexity associated with managing versions, configuration, and complex deployments.

Did you try out what I wrote here? Java Classloading problem - #4 by thorben

1 Like