Hi,
Migrating from 7.9 to 7.13, I encountered a small problem with the way Spring beans are made accessible in scripts and expressions.
I have a process engine plugin which declares custom beans which can be accessed by Groovy scripts. All the other contextual Spring beans should not be accessible in scripts / expressions, but they seem to be. What worse is that they override my custom beans (for 2 beans with identical name).
Camunda version: 7.13
Setup: Spring Boot Application
DB: H2
As stated by the documentation, it should at least not be the case for expressions : https://docs.camunda.org/manual/latest/user-guide/spring-framework-integration/expressions/#using-spring-beans-in-scripting
This change seems to have been introduced in 7.12, which register a SpringBeansResolverFactory
.
I’ve created a repository which reproduce this bug, and give a more detailed analyze in the README : https://github.com/hbeaufils/camunda-limit-exposed-beans-sample
To sum it up, here’s what I do :
Using the lastest simple Camunda Webapp sample, I declare a Spring bean in my application :
@Component
public class SomeBean {
public void printMessage() {
System.out.println("Expression bean: SomeBean");
}
}
I also add a class to represent a custom bean which I’d like to override someBean
with:
public class MyCustomScriptBean {
public void printMessage() {
System.out.println("Expression bean: MyCustomScriptBean");
}
}
Then I declare a process engine plugin to configure my custom beans which should be accessible in scripts and expressions :
@Component
public class MyCustomBeanPlugin extends AbstractProcessEnginePlugin {
@Override
public void postInit(ProcessEngineConfigurationImpl conf) {
conf.getBeans().put("someBean", new MyCustomScriptBean());
conf.getBeans().put("someBeanWithADifferentName", new MyCustomScriptBean());
}
}
Finally, I updated the sample model to contain 2 activies :
- one Groovy script
- one Expression delegate task
The Groovy script does this:
def beanClass = someBean.getClass().getName()
def beanClass2 = someBeanWithADifferentName.getClass().getName()
println("Bean class: " + beanClass)
println("Bean class (when using a different name): " + beanClass2)
And the expression this:
#{someBean.printMessage()}
When I start a process instance, I will see the following logs:
Bean class: org.camunda.bpm.spring.boot.example.autodeployment.SomeBean
Bean class (when using a different name): org.camunda.bpm.spring.boot.example.autodeployment.MyCustomScriptBean
Expression bean: SomeBean
So it appears that the Spring beans are always accessible, and override all custom beans.
This is due to the way the ScriptBindings#get(...)
method works, and the order of the resolver factories.
Is this a known issue ? A problem in the documentation ?
I feel like it would be great to at least be able to override the contextual Spring beans, and maybe to limit their exposure with a property or something.
Of course, there’s still a hack to bypass this, by removing the SpringBeansResolverFactory
, but it’s not really clean / user friendly.