Camunda and integrated third party libraries

Hello,

this blog post about the Platform 7.20.0-alpha1 release states

The new expression language API is integrated into the Camunda JUEL library and relocated inside it to avoid any classpath pollution related to the official Jakarta Expression Language API that might be present in your environment.

We’ve had bad experiences with such “contained inside” (relocated or not) libraries because it makes updating the libs very hard. I mean the scenario where camunda is used as a library and not as a ready to use executable. Some security analysis tools might mark the lib as “vulnerable”, and there is no chance to update the libs without a fix from Camunda.

Have you considered to just declare the dependencies but not include them into the lib? For the executable (i.e. for the application servers) you can (and maybe should) then create a fat jar that would contain all the necessary libs.

This applies not only to JUEL but also to other libs.

Thank you.

Hi @fml2,

thanks for this feedback. Your remarks are absolutely valid, we discussed those as well in the respective tracking issue. One of the main reasons for including a relocated Expression Language API inside the JUEL artifact is to make it work in javax.* and jakarta.*-based environments alike. Otherwise, the engine would require the Jakarta EL API as a transitive dependency, which can create issues for javax-based applications down the line. We want to avoid that.

Additionally, consuming Jakarta EL API as a “plain” dependency comes at some development costs:

  1. If we build and test against a specific version of the API, we can only guarantee a certain degree of functionality for that exact version. Allowing an arbitrary version override by users thus comes with a bit more uncertainty. This might however be acceptable, I just wanted to make sure this doesn’t go unnoticed.
  2. Using the EL API as a transitive dependency by default leads to higher maintenance effort with the ready-to-use distributions, especially regarding the javax.* vs jakarta.* considerations. We would need to consume a different artifact in those modules, most probably the one we currently provide (including a relocated EL API). This can lead to further issues down the line since the package names of the EL API classes change with the relocation. Those EL API classes are however used in the consuming modules like the engine core and the DMN engine. I can see two ways of handling this, both coming with quite some maintenance effort:
    a. The package names have to change in the consumers as well in the process. This requires a rewrite of the consumers or using different consumer versions that already use the relocated names. Both ways introduce quite some maintenance effort.
    b. We create a proxy API in the JUEL artifact for the EL API classes in question. Consumers always use this API. That way, the relocation becomes transparent to consumers. However, this also creates maintenance efforts for the proxy API that might need adjustments over time with new versions of the EL API. Furthermore, it might be incompatible with newer versions that users choose by overriding.

In the end, it comes down to weighing impact and effort here, I believe. One question here would be how likely it is that the EL API version needs to be overridden. There have very rarely been patches or minor versions for any of the major versions in the past.

That being said, we’re completely open to any suggestions here as always. There might be ways we haven’t considered yet. We’re still in the early alpha phase of Camunda 7.20 and your feedback here is exactly why we wanted to get this out early.

Hope this is all followable and makes sense to you as well, looking forward to your feedback here!

Cheers,
Tobias

3 Likes

Hello Tobias,

thank you for the explanations. Without having a ready to use solution, I’d just like to ask how other libs do it. E.g. Spring whichis also used in many different environments.

A naive approach off the top of my head would be to have two implementations (using javax.* and jakarta.*) and then, at startup, somehow detect which one is available and use it.

But I must confess that I have not created a lib that must be able to be used everywhere, I’m rather a cosumer :slight_smile: .