From 6c5b934c0b0fa8b33a3612a11f503c06b81a369a Mon Sep 17 00:00:00 2001 From: Filip Hrisafov Date: Mon, 25 Sep 2023 14:59:01 +0200 Subject: [PATCH] Add support for configuring the bean and json node EL Resolvers --- .../app/engine/AppEngineConfiguration.java | 19 +++++++++++ .../cmmn/engine/CmmnEngineConfiguration.java | 19 +++++++++++ .../dmn/engine/DmnEngineConfiguration.java | 19 +++++++++++ ...sExpressionManagerEngineConfiguration.java | 4 +++ .../impl/el/DefaultExpressionManager.java | 34 +++++++++++++++++-- .../engine/impl/javax/el/BeanELResolver.java | 10 ++++-- .../cfg/ProcessEngineConfigurationImpl.java | 20 +++++++++++ .../EventRegistryEngineConfiguration.java | 19 +++++++++++ 8 files changed, 138 insertions(+), 6 deletions(-) diff --git a/modules/flowable-app-engine/src/main/java/org/flowable/app/engine/AppEngineConfiguration.java b/modules/flowable-app-engine/src/main/java/org/flowable/app/engine/AppEngineConfiguration.java index 617dd15a736..ae3d4a4ab25 100644 --- a/modules/flowable-app-engine/src/main/java/org/flowable/app/engine/AppEngineConfiguration.java +++ b/modules/flowable-app-engine/src/main/java/org/flowable/app/engine/AppEngineConfiguration.java @@ -17,6 +17,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.function.Consumer; import javax.sql.DataSource; @@ -134,6 +135,7 @@ public class AppEngineConfiguration extends AbstractEngineConfiguration implemen protected DeploymentCache appDefinitionCache; protected ExpressionManager expressionManager; + protected Collection> expressionManagerConfigurers; protected SchemaManager identityLinkSchemaManager; protected SchemaManager variableSchemaManager; @@ -284,6 +286,10 @@ public void initMybatisTypeHandlers(Configuration configuration) { public void initExpressionManager() { if (expressionManager == null) { expressionManager = new DefaultExpressionManager(beans); + + if (expressionManagerConfigurers != null) { + expressionManagerConfigurers.forEach(configurer -> configurer.accept(expressionManager)); + } } } @@ -688,6 +694,19 @@ public AppEngineConfiguration setExpressionManager(ExpressionManager expressionM return this; } + public Collection> getExpressionManagerConfigurers() { + return expressionManagerConfigurers; + } + + @Override + public AbstractEngineConfiguration addExpressionManagerConfigurer(Consumer configurer) { + if (this.expressionManagerConfigurers == null) { + this.expressionManagerConfigurers = new ArrayList<>(); + } + this.expressionManagerConfigurers.add(configurer); + return this; + } + public SchemaManager getIdentityLinkSchemaManager() { return identityLinkSchemaManager; } diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/CmmnEngineConfiguration.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/CmmnEngineConfiguration.java index e8308fd9ea8..12b023b307e 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/CmmnEngineConfiguration.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/CmmnEngineConfiguration.java @@ -28,6 +28,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; +import java.util.function.Consumer; import javax.sql.DataSource; @@ -418,6 +419,7 @@ public class CmmnEngineConfiguration extends AbstractEngineConfiguration impleme protected boolean enableCaseDefinitionHistoryLevel; protected ExpressionManager expressionManager; + protected Collection> expressionManagerConfigurers; protected List flowableFunctionDelegates; protected List customFlowableFunctionDelegates; protected List astFunctionCreators; @@ -949,6 +951,10 @@ public void initExpressionManager() { cmmnExpressionManager.setExpressionCache(new DefaultDeploymentCache<>(expressionCacheSize)); cmmnExpressionManager.setExpressionTextLengthCacheLimit(expressionTextLengthCacheLimit); } + + if (expressionManagerConfigurers != null) { + expressionManagerConfigurers.forEach(configurer -> configurer.accept(cmmnExpressionManager)); + } expressionManager = cmmnExpressionManager; } @@ -2638,6 +2644,19 @@ public CmmnEngineConfiguration setExpressionManager(ExpressionManager expression return this; } + public Collection> getExpressionManagerConfigurers() { + return expressionManagerConfigurers; + } + + @Override + public AbstractEngineConfiguration addExpressionManagerConfigurer(Consumer configurer) { + if (this.expressionManagerConfigurers == null) { + this.expressionManagerConfigurers = new ArrayList<>(); + } + this.expressionManagerConfigurers.add(configurer); + return this; + } + public boolean isExpressionCacheEnabled() { return isExpressionCacheEnabled; } diff --git a/modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/DmnEngineConfiguration.java b/modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/DmnEngineConfiguration.java index befb2069b89..bb8f4b929c2 100755 --- a/modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/DmnEngineConfiguration.java +++ b/modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/DmnEngineConfiguration.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; import javax.sql.DataSource; @@ -149,6 +150,7 @@ public class DmnEngineConfiguration extends AbstractEngineConfiguration // EXPRESSION MANAGER ///////////////////////////////////////////// protected ExpressionManager expressionManager; + protected Collection> expressionManagerConfigurers; protected List flowableFunctionDelegates; protected List customFlowableFunctionDelegates; protected Collection preDefaultELResolvers; @@ -451,6 +453,10 @@ public void initExpressionManager() { postDefaultELResolvers.forEach(dmnExpressionManager::addPostDefaultResolver); } + if (expressionManagerConfigurers != null) { + expressionManagerConfigurers.forEach(configurer -> configurer.accept(dmnExpressionManager)); + } + expressionManager = dmnExpressionManager; } @@ -819,6 +825,19 @@ public DmnEngineConfiguration setExpressionManager(ExpressionManager expressionM return this; } + public Collection> getExpressionManagerConfigurers() { + return expressionManagerConfigurers; + } + + @Override + public AbstractEngineConfiguration addExpressionManagerConfigurer(Consumer configurer) { + if (this.expressionManagerConfigurers == null) { + this.expressionManagerConfigurers = new ArrayList<>(); + } + this.expressionManagerConfigurers.add(configurer); + return this; + } + public List getFlowableFunctionDelegates() { return flowableFunctionDelegates; } diff --git a/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/HasExpressionManagerEngineConfiguration.java b/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/HasExpressionManagerEngineConfiguration.java index 378e5a23ed3..201287e77d2 100644 --- a/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/HasExpressionManagerEngineConfiguration.java +++ b/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/HasExpressionManagerEngineConfiguration.java @@ -12,6 +12,8 @@ */ package org.flowable.common.engine.impl; +import java.util.function.Consumer; + import org.flowable.common.engine.impl.el.ExpressionManager; /** @@ -22,4 +24,6 @@ public interface HasExpressionManagerEngineConfiguration { ExpressionManager getExpressionManager(); AbstractEngineConfiguration setExpressionManager(ExpressionManager expressionManager); + + AbstractEngineConfiguration addExpressionManagerConfigurer(Consumer configurer); } diff --git a/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/el/DefaultExpressionManager.java b/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/el/DefaultExpressionManager.java index ff0dc1ad41d..7a13759c7fa 100644 --- a/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/el/DefaultExpressionManager.java +++ b/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/el/DefaultExpressionManager.java @@ -57,8 +57,10 @@ public class DefaultExpressionManager implements ExpressionManager { protected int expressionTextLengthCacheLimit = -1; protected List preDefaultResolvers; + protected ELResolver jsonNodeResolver; protected List postDefaultResolvers; protected List preBeanResolvers; + protected ELResolver beanResolver; protected ELResolver staticElResolver; @@ -134,7 +136,10 @@ protected List createDefaultElResolvers() { elResolvers.add(new ArrayELResolver()); elResolvers.add(new ListELResolver()); elResolvers.add(new MapELResolver()); - elResolvers.add(new JsonNodeELResolver()); + ELResolver jsonNodeElResolver = createJsonNodeElResolver(); + if (jsonNodeElResolver != null) { + elResolvers.add(jsonNodeElResolver); + } if (preBeanResolvers != null) { elResolvers.addAll(preBeanResolvers); } @@ -156,9 +161,13 @@ protected List createDefaultElResolvers() { protected ELResolver createVariableElResolver() { return new VariableContainerELResolver(); } + + protected ELResolver createJsonNodeElResolver() { + return jsonNodeResolver == null ? new JsonNodeELResolver() : jsonNodeResolver; + } protected ELResolver createBeanElResolver() { - return new BeanELResolver(); + return beanResolver == null ? new BeanELResolver() : beanResolver; } @Override @@ -243,6 +252,16 @@ public void addPreDefaultResolver(ELResolver elResolver) { this.preDefaultResolvers.add(elResolver); } + public ELResolver getJsonNodeResolver() { + return jsonNodeResolver; + } + + public void setJsonNodeResolver(ELResolver jsonNodeResolver) { + // When the bean resolver is modified we need to reset the el resolver + this.staticElResolver = null; + this.jsonNodeResolver = jsonNodeResolver; + } + public void addPostDefaultResolver(ELResolver elResolver) { if (this.postDefaultResolvers == null) { this.postDefaultResolvers = new ArrayList<>(); @@ -258,5 +277,14 @@ public void addPreBeanResolver(ELResolver elResolver) { this.preBeanResolvers.add(elResolver); } - + + public ELResolver getBeanResolver() { + return beanResolver; + } + + public void setBeanResolver(ELResolver beanResolver) { + // When the bean resolver is modified we need to reset the el resolver + this.staticElResolver = null; + this.beanResolver = beanResolver; + } } diff --git a/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/javax/el/BeanELResolver.java b/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/javax/el/BeanELResolver.java index cc6b23a83b4..4e73cfbd31a 100644 --- a/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/javax/el/BeanELResolver.java +++ b/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/javax/el/BeanELResolver.java @@ -284,7 +284,7 @@ public Object getValue(ELContext context, Object base, Object property) { Method method = beanProperty.getReadMethod(base); if (method != null) { try { - result = method.invoke(base); + result = invoke(method, base); } catch (InvocationTargetException e) { throw new ELException(e.getCause()); } catch (Exception e) { @@ -385,7 +385,7 @@ public void setValue(ELContext context, Object base, Object property, Object val throw new PropertyNotWritableException("Cannot write property: " + property); } try { - method.invoke(base, value); + invoke(method, base, value); } catch (InvocationTargetException e) { throw new ELException("Cannot write property: " + property, e.getCause()); } catch (IllegalArgumentException e) { @@ -473,7 +473,7 @@ public Object invoke(ELContext context, Object base, Object method, Class[] p Object[] parameters = Util.buildParameters(target.getParameterTypes(), target.isVarArgs(), params, factory); try { - result = target.invoke(base, parameters); + result = invoke(target, base, parameters); } catch (InvocationTargetException e) { throw new ELException(e.getCause()); } catch (IllegalAccessException e) { @@ -484,6 +484,10 @@ public Object invoke(ELContext context, Object base, Object method, Class[] p return result; } + protected Object invoke(Method target, Object base, Object... parameters) throws InvocationTargetException, IllegalAccessException { + return target.invoke(base, parameters); + } + /** * Lookup an expression factory used to coerce method parameters in context under key * "javax.el.ExpressionFactory". diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cfg/ProcessEngineConfigurationImpl.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cfg/ProcessEngineConfigurationImpl.java index 3afeee0fd2f..1ac24575bae 100755 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cfg/ProcessEngineConfigurationImpl.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cfg/ProcessEngineConfigurationImpl.java @@ -31,6 +31,7 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; +import java.util.function.Consumer; import javax.xml.namespace.QName; @@ -47,6 +48,7 @@ import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher; import org.flowable.common.engine.api.delegate.event.FlowableEventListener; import org.flowable.common.engine.api.scope.ScopeTypes; +import org.flowable.common.engine.impl.AbstractEngineConfiguration; import org.flowable.common.engine.impl.EngineConfigurator; import org.flowable.common.engine.impl.EngineDeployer; import org.flowable.common.engine.impl.HasExpressionManagerEngineConfiguration; @@ -721,6 +723,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig protected boolean parallelMultiInstanceAsyncLeave = true; protected ExpressionManager expressionManager; + protected Collection> expressionManagerConfigurers; protected Collection preDefaultELResolvers; protected Collection preBeanELResolvers; protected Collection postDefaultELResolvers; @@ -2367,6 +2370,10 @@ public void initExpressionManager() { postDefaultELResolvers.forEach(processExpressionManager::addPostDefaultResolver); } + if (expressionManagerConfigurers != null) { + expressionManagerConfigurers.forEach(configurer -> configurer.accept(processExpressionManager)); + } + expressionManager = processExpressionManager; } expressionManager.setFunctionDelegates(flowableFunctionDelegates); @@ -3261,6 +3268,19 @@ public ProcessEngineConfigurationImpl setExpressionManager(ExpressionManager exp return this; } + public Collection> getExpressionManagerConfigurers() { + return expressionManagerConfigurers; + } + + @Override + public AbstractEngineConfiguration addExpressionManagerConfigurer(Consumer configurer) { + if (this.expressionManagerConfigurers == null) { + this.expressionManagerConfigurers = new ArrayList<>(); + } + this.expressionManagerConfigurers.add(configurer); + return this; + } + public boolean isExpressionCacheEnabled() { return isExpressionCacheEnabled; } diff --git a/modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/EventRegistryEngineConfiguration.java b/modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/EventRegistryEngineConfiguration.java index dbed8b3d5f1..894d2f6c12d 100755 --- a/modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/EventRegistryEngineConfiguration.java +++ b/modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/EventRegistryEngineConfiguration.java @@ -18,6 +18,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Consumer; import org.flowable.common.engine.api.scope.ScopeTypes; import org.flowable.common.engine.impl.AbstractEngineConfiguration; @@ -123,6 +124,7 @@ public class EventRegistryEngineConfiguration extends AbstractEngineConfiguratio protected EventResourceEntityManager resourceEntityManager; protected ExpressionManager expressionManager; + protected Collection> expressionManagerConfigurers; protected Collection preDefaultELResolvers; protected Collection preBeanELResolvers; protected Collection postDefaultELResolvers; @@ -291,6 +293,10 @@ public void initExpressionManager() { postDefaultELResolvers.forEach(eventRegistryExpressionManager::addPostDefaultResolver); } + if (expressionManagerConfigurers != null) { + expressionManagerConfigurers.forEach(configurer -> configurer.accept(eventRegistryExpressionManager)); + } + expressionManager = eventRegistryExpressionManager; } } @@ -906,6 +912,19 @@ public EventRegistryEngineConfiguration setExpressionManager(ExpressionManager e return this; } + public Collection> getExpressionManagerConfigurers() { + return expressionManagerConfigurers; + } + + @Override + public AbstractEngineConfiguration addExpressionManagerConfigurer(Consumer configurer) { + if (this.expressionManagerConfigurers == null) { + this.expressionManagerConfigurers = new ArrayList<>(); + } + this.expressionManagerConfigurers.add(configurer); + return this; + } + public Collection getPreDefaultELResolvers() { return preDefaultELResolvers; }