You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2020/03/25 15:23:02 UTC

[camel] 04/11: Add an init method to Expression / Predicate

This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 7afcecd94288e88df957f3a4f4d0facb1e747b8f
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Mar 18 10:07:45 2020 +0100

    Add an init method to Expression / Predicate
---
 .../apache/camel/language/bean/BeanExpression.java |   4 +
 .../camel/component/mock/MockExpressionClause.java |  34 +-
 .../camel/component/mock/MockValueBuilder.java     |   6 +
 .../apache/camel/language/xpath/XPathBuilder.java  |   4 +
 .../src/main/java/org/apache/camel/Expression.java |   7 +
 .../src/main/java/org/apache/camel/Predicate.java  |   6 +
 .../apache/camel/processor/FilterProcessor.java    |  11 +-
 .../org/apache/camel/builder/ExpressionClause.java |  34 +-
 .../org/apache/camel/builder/SimpleBuilder.java    |  88 ++++--
 .../camel/model/language/ExpressionDefinition.java |  10 +
 .../apache/camel/reifier/ExpressionReifier.java    |   2 +-
 .../org/apache/camel/reifier/FilterReifier.java    |   2 +-
 .../reifier/language/SimpleExpressionReifier.java  |  37 ++-
 .../apache/camel/processor/TryProcessorTest.java   |   5 +
 .../apache/camel/processor/ValidateSimpleTest.java |   4 +-
 .../apache/camel/support/ExpressionSupport.java    |   5 +
 .../support/ExpressionToPredicateAdapter.java      |   5 +
 .../org/apache/camel/support/ScriptHelper.java     |  10 +
 .../support/builder/BinaryPredicateSupport.java    |   7 +
 .../camel/support/builder/ExpressionBuilder.java   | 342 +++++++++++++++++----
 .../apache/camel/support/builder/ValueBuilder.java |   6 +
 21 files changed, 512 insertions(+), 117 deletions(-)

diff --git a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java
index 516c131..3d48bf0 100644
--- a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java
+++ b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java
@@ -110,6 +110,10 @@ public class BeanExpression implements Expression, Predicate, AfterPropertiesCon
     }
 
     @Override
+    public void init(CamelContext context) {
+    }
+
+    @Override
     public String toString() {
         StringBuilder sb = new StringBuilder("BeanExpression[");
         if (bean != null) {
diff --git a/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockExpressionClause.java b/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockExpressionClause.java
index aa3c77d..ba74616b 100644
--- a/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockExpressionClause.java
+++ b/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockExpressionClause.java
@@ -21,6 +21,7 @@ import java.util.function.BiFunction;
 import java.util.function.Function;
 import java.util.function.Supplier;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.ExpressionFactory;
@@ -425,23 +426,32 @@ public class MockExpressionClause<T> implements Expression, Predicate {
         return delegate.getExpressionType();
     }
 
+    private volatile Expression expr;
+
     @Override
-    public <T> T evaluate(Exchange exchange, Class<T> type) {
-        if (getExpressionValue() != null) {
-            return getExpressionValue().evaluate(exchange, type);
-        } else {
-            Expression exp = delegate.getExpressionType().createExpression(exchange.getContext());
-            return exp.evaluate(exchange, type);
+    public void init(CamelContext context) {
+        if (expr == null) {
+            synchronized (this) {
+                if (expr == null) {
+                    expr = getExpressionValue();
+                    if (expr == null) {
+                        expr = getExpressionType().createExpression(context);
+                    }
+                    expr.init(context);
+                }
+            }
         }
     }
 
     @Override
+    public <T> T evaluate(Exchange exchange, Class<T> type) {
+        init(exchange.getContext());
+        return expr.evaluate(exchange, type);
+    }
+
+    @Override
     public boolean matches(Exchange exchange) {
-        if (getExpressionValue() != null) {
-            return new ExpressionToPredicateAdapter(getExpressionValue()).matches(exchange);
-        } else {
-            Expression exp = delegate.getExpressionType().createExpression(exchange.getContext());
-            return new ExpressionToPredicateAdapter(exp).matches(exchange);
-        }
+        init(exchange.getContext());
+        return new ExpressionToPredicateAdapter(expr).matches(exchange);
     }
 }
diff --git a/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockValueBuilder.java b/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockValueBuilder.java
index 551c524..4082a0e 100644
--- a/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockValueBuilder.java
+++ b/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockValueBuilder.java
@@ -21,6 +21,7 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.Predicate;
@@ -44,6 +45,11 @@ public class MockValueBuilder implements Expression, Predicate {
     }
 
     @Override
+    public void init(CamelContext context) {
+        expression.init(context);
+    }
+
+    @Override
     public <T> T evaluate(Exchange exchange, Class<T> type) {
         return expression.evaluate(exchange, type);
     }
diff --git a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java
index 6ff9fef..7adb463 100644
--- a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java
+++ b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java
@@ -171,6 +171,10 @@ public class XPathBuilder extends ServiceSupport implements CamelContextAware, E
     }
 
     @Override
+    public void init(CamelContext context) {
+    }
+
+    @Override
     public boolean configure(CamelContext camelContext, Object target, String name, Object value, boolean ignoreCase) {
         if (target != this) {
             throw new IllegalStateException("Can only configure our own instance !");
diff --git a/core/camel-api/src/main/java/org/apache/camel/Expression.java b/core/camel-api/src/main/java/org/apache/camel/Expression.java
index 4995d0b..6fc0f64 100644
--- a/core/camel-api/src/main/java/org/apache/camel/Expression.java
+++ b/core/camel-api/src/main/java/org/apache/camel/Expression.java
@@ -30,4 +30,11 @@ public interface Expression {
      * @return the value of the expression
      */
     <T> T evaluate(Exchange exchange, Class<T> type);
+
+    /**
+     * Initialize the expression with the given camel context
+     */
+    default void init(CamelContext context) {
+    }
+
 }
diff --git a/core/camel-api/src/main/java/org/apache/camel/Predicate.java b/core/camel-api/src/main/java/org/apache/camel/Predicate.java
index d6a81c0..2f7f3dc 100644
--- a/core/camel-api/src/main/java/org/apache/camel/Predicate.java
+++ b/core/camel-api/src/main/java/org/apache/camel/Predicate.java
@@ -31,4 +31,10 @@ public interface Predicate {
      */
     boolean matches(Exchange exchange);
 
+    /**
+     * Initialize the predicate with the given camel context
+     */
+    default void init(CamelContext context) {
+    }
+
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/processor/FilterProcessor.java b/core/camel-base/src/main/java/org/apache/camel/processor/FilterProcessor.java
index 637cc65..3c472df 100644
--- a/core/camel-base/src/main/java/org/apache/camel/processor/FilterProcessor.java
+++ b/core/camel-base/src/main/java/org/apache/camel/processor/FilterProcessor.java
@@ -17,6 +17,7 @@
 package org.apache.camel.processor;
 
 import org.apache.camel.AsyncCallback;
+import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
@@ -36,17 +37,25 @@ public class FilterProcessor extends DelegateAsyncProcessor implements Traceable
 
     private static final Logger LOG = LoggerFactory.getLogger(FilterProcessor.class);
 
+    private final CamelContext context;
     private String id;
     private String routeId;
     private final Predicate predicate;
     private transient long filtered;
 
-    public FilterProcessor(Predicate predicate, Processor processor) {
+    public FilterProcessor(CamelContext context, Predicate predicate, Processor processor) {
         super(processor);
+        this.context = context;
         this.predicate = predicate;
     }
 
     @Override
+    protected void doInit() throws Exception {
+        super.doInit();
+        predicate.init(context);
+    }
+
+    @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
         boolean matches = false;
 
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/builder/ExpressionClause.java b/core/camel-core-engine/src/main/java/org/apache/camel/builder/ExpressionClause.java
index ff2f968..9dd2f6f 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/builder/ExpressionClause.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/builder/ExpressionClause.java
@@ -20,6 +20,7 @@ import java.util.Map;
 import java.util.function.BiFunction;
 import java.util.function.Function;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.ExpressionFactory;
@@ -939,23 +940,32 @@ public class ExpressionClause<T> implements Expression, Predicate {
         return delegate.getExpressionType();
     }
 
+    private volatile Expression expr;
+
     @Override
-    public <T> T evaluate(Exchange exchange, Class<T> type) {
-        if (getExpressionValue() != null) {
-            return getExpressionValue().evaluate(exchange, type);
-        } else {
-            Expression exp = delegate.getExpressionType().createExpression(exchange.getContext());
-            return exp.evaluate(exchange, type);
+    public void init(CamelContext context) {
+        if (expr == null) {
+            synchronized (this) {
+                if (expr == null) {
+                    expr = getExpressionValue();
+                    if (expr == null) {
+                        expr = delegate.getExpressionType().createExpression(context);
+                    }
+                    expr.init(context);
+                }
+            }
         }
     }
 
     @Override
+    public <T> T evaluate(Exchange exchange, Class<T> type) {
+        init(exchange.getContext());
+        return expr.evaluate(exchange, type);
+    }
+
+    @Override
     public boolean matches(Exchange exchange) {
-        if (getExpressionValue() != null) {
-            return new ExpressionToPredicateAdapter(getExpressionValue()).matches(exchange);
-        } else {
-            Expression exp = delegate.getExpressionType().createExpression(exchange.getContext());
-            return new ExpressionToPredicateAdapter(exp).matches(exchange);
-        }
+        init(exchange.getContext());
+        return new ExpressionToPredicateAdapter(expr).matches(exchange);
     }
 }
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/builder/SimpleBuilder.java b/core/camel-core-engine/src/main/java/org/apache/camel/builder/SimpleBuilder.java
index 894e5e6..d252920 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/builder/SimpleBuilder.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/builder/SimpleBuilder.java
@@ -103,60 +103,90 @@ public class SimpleBuilder implements Predicate, Expression, ExpressionResultTyp
     }
 
     @Override
-    public boolean matches(Exchange exchange) {
+    public void init(CamelContext context) {
         if (predicate == null) {
-            predicate = createPredicate(exchange);
+            predicate = createPredicate(context);
         }
+        predicate.init(context);
+    }
+
+    @Override
+    public boolean matches(Exchange exchange) {
+        init(exchange.getContext());
         return predicate.matches(exchange);
     }
 
     @Override
     public <T> T evaluate(Exchange exchange, Class<T> type) {
         if (expression == null) {
-            expression = createExpression(exchange);
+            expression = createExpression(exchange.getContext());
         }
         return expression.evaluate(exchange, type);
     }
 
-    private Predicate createPredicate(Exchange exchange) {
+    public Predicate createPredicate(CamelContext context) {
         try {
+            Language simple = context.resolveLanguage("simple");
             // resolve property placeholders
-            String resolve = exchange.getContext().resolvePropertyPlaceholders(text);
-            // and optional it be refer to an external script on the
-            // file/classpath
-            resolve = ScriptHelper.resolveOptionalExternalScript(exchange.getContext(), exchange, resolve);
-            Language simple = exchange.getContext().resolveLanguage("simple");
-            return simple.createPredicate(resolve);
-        } catch (Exception e) {
-            throw CamelExecutionException.wrapCamelExecutionException(exchange, e);
-        }
-    }
-
-    private Expression createExpression(Exchange exchange) {
-        try {
-            // resolve property placeholders
-            String resolve = exchange.getContext().resolvePropertyPlaceholders(text);
-            // and optional it be refer to an external script on the
-            // file/classpath
-            resolve = ScriptHelper.resolveOptionalExternalScript(exchange.getContext(), exchange, resolve);
-            Language simple = exchange.getContext().resolveLanguage("simple");
-            return createSimpleExpression(simple, resolve, resultType);
+            String resolve = context.resolvePropertyPlaceholders(text);
+            // and optional it be refer to an external script on the file/classpath
+            if (ScriptHelper.hasExternalScript(resolve)) {
+                return new Predicate() {
+                    @Override
+                    public boolean matches(Exchange exchange) {
+                        String r = ScriptHelper.resolveOptionalExternalScript(context, exchange, resolve);
+                        return simple.createPredicate(r).matches(exchange);
+                    }
+                    @Override
+                    public String toString() {
+                        return text;
+                    }
+                };
+            } else {
+                Predicate pred = simple.createPredicate(resolve);
+                pred.init(context);
+                return pred;
+            }
         } catch (Exception e) {
-            throw CamelExecutionException.wrapCamelExecutionException(exchange, e);
+            throw CamelExecutionException.wrapCamelExecutionException(null, e);
         }
     }
 
-    private static Expression createSimpleExpression(Language simple, String expression, Class<?> resultType) {
+    public Expression createExpression(CamelContext context) {
         if (resultType == Boolean.class || resultType == boolean.class) {
             // if its a boolean as result then its a predicate
-            Predicate predicate = simple.createPredicate(expression);
+            Predicate predicate = createPredicate(context);
             return PredicateToExpressionAdapter.toExpression(predicate);
-        } else {
-            Expression exp = simple.createExpression(expression);
+        }
+        try {
+            // resolve property placeholders
+            Language simple = context.resolveLanguage("simple");
+            String resolve = context.resolvePropertyPlaceholders(text);
+            Expression exp;
+            // and optional it be refer to an external script on the file/classpath
+            if (ScriptHelper.hasExternalScript(resolve)) {
+                exp = new Expression() {
+                    @Override
+                    public <T> T evaluate(Exchange exchange, Class<T> type) {
+                        String r = ScriptHelper.resolveOptionalExternalScript(context, exchange, resolve);
+                        Expression exp = simple.createExpression(r);
+                        return exp.evaluate(exchange, type);
+                    }
+                    @Override
+                    public String toString() {
+                        return text;
+                    }
+                };
+            } else {
+                exp = simple.createExpression(resolve);
+                exp.init(context);
+            }
             if (resultType != null) {
                 exp = ExpressionBuilder.convertToExpression(exp, resultType);
             }
             return exp;
+        } catch (Exception e) {
+            throw CamelExecutionException.wrapCamelExecutionException(null, e);
         }
     }
 
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java b/core/camel-core-engine/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java
index d2326b7..0ea00ef 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java
@@ -225,4 +225,14 @@ public class ExpressionDefinition implements Expression, Predicate, ExpressionFa
         return predicate.matches(exchange);
     }
 
+    @Override
+    public void init(CamelContext context) {
+        if (expressionValue == null) {
+            expressionValue = createExpression(context);
+        }
+        if (predicate == null) {
+            predicate = createPredicate(context);
+        }
+    }
+
 }
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/ExpressionReifier.java b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/ExpressionReifier.java
index 77667eb..672a1b6 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/ExpressionReifier.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/ExpressionReifier.java
@@ -36,7 +36,7 @@ abstract class ExpressionReifier<T extends ExpressionNode> extends ProcessorReif
      */
     protected FilterProcessor createFilterProcessor() throws Exception {
         Processor childProcessor = createOutputsProcessor();
-        return new FilterProcessor(createPredicate(), childProcessor);
+        return new FilterProcessor(camelContext, createPredicate(), childProcessor);
     }
 
     /**
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/FilterReifier.java b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/FilterReifier.java
index 4d070ef..239a82b 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/FilterReifier.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/FilterReifier.java
@@ -37,7 +37,7 @@ public class FilterReifier extends ExpressionReifier<FilterDefinition> {
     protected FilterProcessor createFilterProcessor() throws Exception {
         // filter EIP should have child outputs
         Processor childProcessor = this.createChildProcessor(true);
-        return new FilterProcessor(createPredicate(), childProcessor);
+        return new FilterProcessor(camelContext, createPredicate(), childProcessor);
     }
 
 }
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/SimpleExpressionReifier.java b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/SimpleExpressionReifier.java
index c5f238d..0126cee 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/SimpleExpressionReifier.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/SimpleExpressionReifier.java
@@ -20,6 +20,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.Predicate;
 import org.apache.camel.builder.SimpleBuilder;
@@ -34,13 +35,41 @@ public class SimpleExpressionReifier extends ExpressionReifier<SimpleExpression>
 
     @Override
     public Expression createExpression() {
+        Expression expr = createBuilder().createExpression(camelContext);
+        return new Expression() {
+            @Override
+            public <T> T evaluate(Exchange exchange, Class<T> type) {
+                return expr.evaluate(exchange, type);
+            }
+            @Override
+            public String toString() {
+                return definition.getExpression();
+            }
+        };
+    }
+
+    @Override
+    public Predicate createPredicate() {
+        Predicate pred = createBuilder().createPredicate(camelContext);
+        return new Predicate() {
+            @Override
+            public boolean matches(Exchange exchange) {
+                return pred.matches(exchange);
+            }
+            @Override
+            public String toString() {
+                return definition.getExpression();
+            }
+        };
+    }
+
+    protected SimpleBuilder createBuilder() {
         String exp = parseString(definition.getExpression());
         // should be true by default
         boolean isTrim = parseBoolean(definition.getTrim(), true);
         if (exp != null && isTrim) {
             exp = exp.trim();
         }
-
         SimpleBuilder answer = new SimpleBuilder(exp);
         Map<String, Object> props = new HashMap<>();
         props.put("resultType", or(definition.getResultType(), definition.getResultTypeName()));
@@ -48,10 +77,4 @@ public class SimpleExpressionReifier extends ExpressionReifier<SimpleExpression>
         return answer;
     }
 
-    @Override
-    public Predicate createPredicate() {
-        // SimpleBuilder is also a Predicate
-        return (Predicate) createExpression();
-    }
-
 }
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/TryProcessorTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/TryProcessorTest.java
index 5d81d93..e978d7b 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/TryProcessorTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/TryProcessorTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.processor;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.CamelException;
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Exchange;
@@ -95,6 +96,10 @@ public class TryProcessorTest extends ContextTestSupport {
         public boolean matches(Exchange exchange) {
             throw new RuntimeCamelException(new CamelException("Force to fail"));
         }
+
+        @Override
+        public void init(CamelContext context) {
+        }
     }
 
     private class ProcessorHandle implements Processor {
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ValidateSimpleTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/ValidateSimpleTest.java
index b463006..0498090 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ValidateSimpleTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/ValidateSimpleTest.java
@@ -58,8 +58,8 @@ public class ValidateSimpleTest extends ContextTestSupport {
         } catch (CamelExecutionException e) {
             // expected
             assertIsInstanceOf(PredicateValidationException.class, e.getCause());
-            String s = "Validation failed for Predicate[Simple: ${body} contains 'Camel'].";
-            assertTrue(e.getCause().getMessage().startsWith(s));
+            String s = "Validation failed for Predicate[${body} contains 'Camel'].";
+            assertStringContains(e.getCause().getMessage(), s);
         }
 
         assertMockEndpointsSatisfied();
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ExpressionSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/ExpressionSupport.java
index 322a742..c90810e 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/ExpressionSupport.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/ExpressionSupport.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.support;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.Predicate;
@@ -27,6 +28,10 @@ import org.apache.camel.util.ObjectHelper;
 public abstract class ExpressionSupport implements Expression, Predicate {
 
     @Override
+    public void init(CamelContext context) {
+    }
+
+    @Override
     public boolean matches(Exchange exchange) {
         Object value = evaluate(exchange, Object.class);
         return ObjectHelper.evaluateValuePredicate(value);
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ExpressionToPredicateAdapter.java b/core/camel-support/src/main/java/org/apache/camel/support/ExpressionToPredicateAdapter.java
index 9c8fb6d3..51b4ab5 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/ExpressionToPredicateAdapter.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/ExpressionToPredicateAdapter.java
@@ -58,6 +58,11 @@ public final class ExpressionToPredicateAdapter implements Predicate, CamelConte
     }
 
     @Override
+    public void init(CamelContext context) {
+        expression.init(context);
+    }
+
+    @Override
     public void setCamelContext(CamelContext camelContext) {
         if (expression instanceof CamelContextAware) {
             ((CamelContextAware) expression).setCamelContext(camelContext);
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ScriptHelper.java b/core/camel-support/src/main/java/org/apache/camel/support/ScriptHelper.java
index 0550330..d66d02f 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/ScriptHelper.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/ScriptHelper.java
@@ -89,4 +89,14 @@ public final class ScriptHelper {
 
         return expression;
     }
+
+    public static boolean hasExternalScript(String external) {
+        if (external.startsWith("resource:")) {
+            external = external.substring(9);
+            if (ResourceHelper.hasScheme(external) && LanguageSupport.hasSimpleFunction(external)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/builder/BinaryPredicateSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/builder/BinaryPredicateSupport.java
index b7c49ec..65757c5 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/builder/BinaryPredicateSupport.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/builder/BinaryPredicateSupport.java
@@ -17,6 +17,7 @@
 package org.apache.camel.support.builder;
 
 import org.apache.camel.BinaryPredicate;
+import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.Predicate;
@@ -40,6 +41,12 @@ public abstract class BinaryPredicateSupport implements BinaryPredicate {
     }
 
     @Override
+    public void init(CamelContext context) {
+        left.init(context);
+        right.init(context);
+    }
+
+    @Override
     public String toString() {
         return left + " " + getOperationText() + " " + right;
     }
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java b/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java
index 71f1d68..d9c0a3a 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java
@@ -35,6 +35,7 @@ import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.Message;
 import org.apache.camel.NoSuchLanguageException;
+import org.apache.camel.Predicate;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.RuntimeExchangeException;
 import org.apache.camel.spi.Language;
@@ -65,9 +66,22 @@ public class ExpressionBuilder {
      * @return an expression object which will return the header value
      */
     public static Expression headerExpression(final String headerName) {
+        return headerExpression(simpleExpression(headerName));
+    }
+
+    /**
+     * Returns an expression for the header value with the given name
+     * <p/>
+     * Will fallback and look in properties if not found in headers.
+     *
+     * @param headerName the name of the header the expression will return
+     * @return an expression object which will return the header value
+     */
+    public static Expression headerExpression(final Expression headerName) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
-                String name = simpleExpression(headerName).evaluate(exchange, String.class);
+                String name = headerName.evaluate(exchange, String.class);
                 Object header = exchange.getIn().getHeader(name);
                 if (header == null) {
                     // fall back on a property
@@ -77,6 +91,11 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                headerName.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "header(" + headerName + ")";
             }
@@ -93,22 +112,7 @@ public class ExpressionBuilder {
      * @return an expression object which will return the header value
      */
     public static <T> Expression headerExpression(final String headerName, final Class<T> type) {
-        return new ExpressionAdapter() {
-            public Object evaluate(Exchange exchange) {
-                String name = simpleExpression(headerName).evaluate(exchange, String.class);
-                T header = exchange.getIn().getHeader(name, type);
-                if (header == null) {
-                    // fall back on a property
-                    header = exchange.getProperty(name, type);
-                }
-                return header;
-            }
-
-            @Override
-            public String toString() {
-                return "headerAs(" + headerName + ", " + type + ")";
-            }
-        };
+        return headerExpression(simpleExpression(headerName), constantExpression(type));
     }
 
     /**
@@ -121,17 +125,30 @@ public class ExpressionBuilder {
      * @return an expression object which will return the header value
      */
     public static Expression headerExpression(final String headerName, final String typeName) {
+        return headerExpression(simpleExpression(headerName), simpleExpression(typeName));
+    }
+
+    /**
+     * Returns an expression for the header value with the given name converted to the given type
+     * <p/>
+     * Will fallback and look in properties if not found in headers.
+     *
+     * @param headerName the name of the header the expression will return
+     * @param typeName the type to convert to as a FQN class name
+     * @return an expression object which will return the header value
+     */
+    public static Expression headerExpression(final Expression headerName, final Expression typeName) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 Class<?> type;
                 try {
-                    String text = simpleExpression(typeName).evaluate(exchange, String.class);
+                    String text = typeName.evaluate(exchange, String.class);
                     type = exchange.getContext().getClassResolver().resolveMandatoryClass(text);
                 } catch (ClassNotFoundException e) {
                     throw CamelExecutionException.wrapCamelExecutionException(exchange, e);
                 }
-
-                String text = simpleExpression(headerName).evaluate(exchange, String.class);
+                String text = headerName.evaluate(exchange, String.class);
                 Object header = exchange.getIn().getHeader(text, type);
                 if (header == null) {
                     // fall back on a property
@@ -141,6 +158,12 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                headerName.init(context);
+                typeName.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "headerAs(" + headerName + ", " + typeName + ")";
             }
@@ -276,13 +299,28 @@ public class ExpressionBuilder {
      * @return an expression object which will return the bean
      */
     public static Expression refExpression(final String ref) {
+        return refExpression(simpleExpression(ref));
+    }
+
+    /**
+     * Returns an expression for lookup a bean in the {@link org.apache.camel.spi.Registry}
+     *
+     * @return an expression object which will return the bean
+     */
+    public static Expression refExpression(final Expression ref) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
-                String text = simpleExpression(ref).evaluate(exchange, String.class);
+                String text = ref.evaluate(exchange, String.class);
                 return exchange.getContext().getRegistry().lookupByName(text);
             }
 
             @Override
+            public void init(CamelContext context) {
+                ref.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "ref(" + ref + ")";
             }
@@ -384,13 +422,29 @@ public class ExpressionBuilder {
      * @return an expression object which will return the property value
      */
     public static Expression exchangePropertyExpression(final String propertyName) {
+        return exchangePropertyExpression(simpleExpression(propertyName));
+    }
+
+    /**
+     * Returns an expression for the property value of exchange with the given name
+     *
+     * @param propertyName the name of the property the expression will return
+     * @return an expression object which will return the property value
+     */
+    public static Expression exchangePropertyExpression(final Expression propertyName) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
-                String text = simpleExpression(propertyName).evaluate(exchange, String.class);
+                String text = propertyName.evaluate(exchange, String.class);
                 return exchange.getProperty(text);
             }
 
             @Override
+            public void init(CamelContext context) {
+                propertyName.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "exchangeProperty(" + propertyName + ")";
             }
@@ -440,13 +494,29 @@ public class ExpressionBuilder {
      * @return an expression object which will return the property value
      */
     public static Expression camelContextPropertyExpression(final String propertyName) {
+        return camelContextPropertyExpression(simpleExpression(propertyName));
+    }
+
+    /**
+     * Returns an expression for the property value of the camel context with the given name
+     *
+     * @param propertyName the name of the property the expression will return
+     * @return an expression object which will return the property value
+     */
+    public static Expression camelContextPropertyExpression(final Expression propertyName) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
-                String text = simpleExpression(propertyName).evaluate(exchange, String.class);
+                String text = propertyName.evaluate(exchange, String.class);
                 return exchange.getContext().getGlobalOption(text);
             }
 
             @Override
+            public void init(CamelContext context) {
+                propertyName.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "camelContextProperty(" + propertyName + ")";
             }
@@ -472,16 +542,37 @@ public class ExpressionBuilder {
      */
     public static Expression systemPropertyExpression(final String propertyName,
                                                       final String defaultValue) {
+        Expression exprName = simpleExpression(propertyName);
+        Expression exprDeflt = simpleExpression(defaultValue);
+        return systemPropertyExpression(exprName, exprDeflt);
+    }
+
+    /**
+     * Returns an expression for a system property value with the given name
+     *
+     * @param exprName the name of the system property the expression will return
+     * @param defaultValue default value to return if no system property exists
+     * @return an expression object which will return the system property value
+     */
+    public static Expression systemPropertyExpression(final Expression exprName,
+                                                      final Expression defaultValue) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
-                String text = simpleExpression(propertyName).evaluate(exchange, String.class);
-                String text2 = simpleExpression(defaultValue).evaluate(exchange, String.class);
+                String text = exprName.evaluate(exchange, String.class);
+                String text2 = defaultValue.evaluate(exchange, String.class);
                 return System.getProperty(text, text2);
             }
 
             @Override
+            public void init(CamelContext context) {
+                exprName.init(context);
+                defaultValue.init(context);
+            }
+
+            @Override
             public String toString() {
-                return "systemProperty(" + propertyName + ")";
+                return "systemProperty(" + exprName + ")";
             }
         };
     }
@@ -505,9 +596,24 @@ public class ExpressionBuilder {
      */
     public static Expression systemEnvironmentExpression(final String propertyName,
                                                          final String defaultValue) {
+        Expression exprName = simpleExpression(propertyName);
+        Expression expDeflt = simpleExpression(defaultValue);
+        return systemEnvironmentExpression(exprName, expDeflt);
+    }
+
+    /**
+     * Returns an expression for a system environment value with the given name
+     *
+     * @param propertyName the name of the system environment the expression will return
+     * @param defaultValue default value to return if no system environment exists
+     * @return an expression object which will return the system environment value
+     */
+    public static Expression systemEnvironmentExpression(final Expression propertyName,
+                                                         final Expression defaultValue) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
-                String text = simpleExpression(propertyName).evaluate(exchange, String.class);
+                String text = propertyName.evaluate(exchange, String.class);
                 String answer = null;
                 if (text != null) {
                     // lookup OS env with upper case key
@@ -521,12 +627,18 @@ public class ExpressionBuilder {
                 }
 
                 if (answer == null) {
-                    answer = simpleExpression(defaultValue).evaluate(exchange, String.class);
+                    answer = defaultValue.evaluate(exchange, String.class);
                 }
                 return answer;
             }
 
             @Override
+            public void init(CamelContext context) {
+                propertyName.init(context);
+                defaultValue.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "systemEnvironment(" + propertyName + ")";
             }
@@ -560,22 +672,36 @@ public class ExpressionBuilder {
      */
     public static Expression languageExpression(final String language, final String expression) {
         return new ExpressionAdapter() {
+            private volatile Expression expr;
+            private volatile Predicate pred;
+
             public Object evaluate(Exchange exchange) {
-                Language lan = exchange.getContext().resolveLanguage(language);
-                if (lan != null) {
-                    return lan.createExpression(expression).evaluate(exchange, Object.class);
-                } else {
-                    throw new NoSuchLanguageException(language);
-                }
+                init(exchange.getContext());
+                return expr.evaluate(exchange, Object.class);
             }
 
             @Override
             public boolean matches(Exchange exchange) {
-                Language lan = exchange.getContext().resolveLanguage(language);
-                if (lan != null) {
-                    return lan.createPredicate(expression).matches(exchange);
-                } else {
-                    throw new NoSuchLanguageException(language);
+                init(exchange.getContext());
+                return pred.matches(exchange);
+            }
+
+            @Override
+            public void init(CamelContext context) {
+                if (expr == null) {
+                    synchronized (this) {
+                        if (expr == null) {
+                            Language lan = context.resolveLanguage(language);
+                            if (lan != null) {
+                                pred = lan.createPredicate(expression);
+                                pred.init(context);
+                                expr = lan.createExpression(expression);
+                                expr.init(context);
+                            } else {
+                                throw new NoSuchLanguageException(language);
+                            }
+                        }
+                    }
                 }
             }
 
@@ -698,11 +824,20 @@ public class ExpressionBuilder {
      * to the given type
      */
     public static Expression bodyExpression(final String name) {
+        return bodyExpression(simpleExpression(name));
+    }
+
+    /**
+     * Returns the expression for the exchanges inbound message body converted
+     * to the given type
+     */
+    public static Expression bodyExpression(final Expression name) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
-                String text = simpleExpression(name).evaluate(exchange, String.class);
                 Class<?> type;
                 try {
+                    String text = name.evaluate(exchange, String.class);
                     type = exchange.getContext().getClassResolver().resolveMandatoryClass(text);
                 } catch (ClassNotFoundException e) {
                     throw CamelExecutionException.wrapCamelExecutionException(exchange, e);
@@ -711,6 +846,11 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                name.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "bodyAs[" + name + "]";
             }
@@ -722,6 +862,7 @@ public class ExpressionBuilder {
      */
     public static Expression threadNameExpression() {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 return Thread.currentThread().getName();
             }
@@ -738,6 +879,7 @@ public class ExpressionBuilder {
      */
     public static Expression hostnameExpression() {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 return InetAddressUtil.getLocalHostNameSafe();
             }
@@ -754,6 +896,7 @@ public class ExpressionBuilder {
      */
     public static Expression stepIdExpression() {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 return exchange.getProperty(Exchange.STEP_ID);
             }
@@ -785,6 +928,7 @@ public class ExpressionBuilder {
      */
     public static <T> Expression mandatoryBodyExpression(final Class<T> type, final boolean nullBodyAllowed) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 if (nullBodyAllowed) {
                     if (exchange.getIn().getBody() == null) {
@@ -811,6 +955,7 @@ public class ExpressionBuilder {
      */
     public static Expression bodyTypeExpression() {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 return exchange.getIn().getBody().getClass();
             }
@@ -827,6 +972,7 @@ public class ExpressionBuilder {
      */
     public static Expression exchangeExpression() {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 return exchange;
             }
@@ -843,6 +989,7 @@ public class ExpressionBuilder {
      */
     public static Expression exchangeExpression(final Function<Exchange, Object> function) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 return function.apply(exchange);
             }
@@ -873,6 +1020,7 @@ public class ExpressionBuilder {
      */
     public static Expression inMessageExpression() {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 return exchange.getIn();
             }
@@ -889,6 +1037,7 @@ public class ExpressionBuilder {
      */
     public static Expression inMessageExpression(final Function<Message, Object> function) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 return function.apply(exchange.getIn());
             }
@@ -905,6 +1054,7 @@ public class ExpressionBuilder {
      */
     public static Expression convertToExpression(final Expression expression, final Class<?> type) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 if (type != null) {
                     return expression.evaluate(exchange, type);
@@ -914,6 +1064,11 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                expression.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "" + expression;
             }
@@ -926,6 +1081,7 @@ public class ExpressionBuilder {
      */
     public static Expression convertToExpression(final Expression expression, final Expression type) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 Object result = type.evaluate(exchange, Object.class);
                 if (result != null) {
@@ -936,6 +1092,12 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                expression.init(context);
+                type.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "" + expression;
             }
@@ -948,15 +1110,31 @@ public class ExpressionBuilder {
      */
     public static Expression tokenizeExpression(final Expression expression,
                                                 final String token) {
+        return tokenizeExpression(expression, simpleExpression(token));
+    }
+
+    /**
+     * Returns a tokenize expression which will tokenize the string with the
+     * given token
+     */
+    public static Expression tokenizeExpression(final Expression expression,
+                                                final Expression token) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
-                String text = simpleExpression(token).evaluate(exchange, String.class);
+                String text = token.evaluate(exchange, String.class);
                 Object value = expression.evaluate(exchange, Object.class);
                 Scanner scanner = ExchangeHelper.getScanner(exchange, value, text);
                 return scanner;
             }
 
             @Override
+            public void init(CamelContext context) {
+                expression.init(context);
+                token.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "tokenize(" + expression + ", " + token + ")";
             }
@@ -968,6 +1146,7 @@ public class ExpressionBuilder {
      */
     public static Expression skipFirstExpression(final Expression expression) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 Object value = expression.evaluate(exchange, Object.class);
                 Iterator it = exchange.getContext().getTypeConverter().tryConvertTo(Iterator.class, exchange, value);
@@ -981,6 +1160,11 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                expression.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "skipFirst(" + expression + ")";
             }
@@ -994,6 +1178,7 @@ public class ExpressionBuilder {
     public static Expression regexTokenizeExpression(final Expression expression,
                                                      final String regexTokenizer) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 Object value = expression.evaluate(exchange, Object.class);
                 Scanner scanner = ExchangeHelper.getScanner(exchange, value, regexTokenizer);
@@ -1001,6 +1186,11 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                expression.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "regexTokenize(" + expression + ", " + regexTokenizer + ")";
             }
@@ -1009,6 +1199,7 @@ public class ExpressionBuilder {
 
     public static Expression groupXmlIteratorExpression(final Expression expression, final String group) {
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 // evaluate expression as iterator
                 Iterator<?> it = expression.evaluate(exchange, Iterator.class);
@@ -1025,6 +1216,11 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                expression.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "group " + expression + " " + group + " times";
             }
@@ -1052,6 +1248,11 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                expression.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "group " + expression + " " + group + " times";
             }
@@ -1073,6 +1274,11 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                expression.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "sort(" + expression + " by: " + comparator + ")";
             }
@@ -1096,6 +1302,11 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                expression.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "regexReplaceAll(" + expression + ", " + pattern.pattern() + ")";
             }
@@ -1111,6 +1322,7 @@ public class ExpressionBuilder {
 
         final Pattern pattern = Pattern.compile(regex);
         return new ExpressionAdapter() {
+            @Override
             public Object evaluate(Exchange exchange) {
                 String text = expression.evaluate(exchange, String.class);
                 String replacement = replacementExpression.evaluate(exchange, String.class);
@@ -1121,6 +1333,12 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                expression.init(context);
+                replacementExpression.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "regexReplaceAll(" + expression + ", " + pattern.pattern() + ")";
             }
@@ -1137,6 +1355,12 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                left.init(context);
+                right.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "append(" + left + ", " + right + ")";
             }
@@ -1153,6 +1377,12 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                left.init(context);
+                right.init(context);
+            }
+
+            @Override
             public String toString() {
                 return "prepend(" + left + ", " + right + ")";
             }
@@ -1192,6 +1422,13 @@ public class ExpressionBuilder {
             }
 
             @Override
+            public void init(CamelContext context) {
+                for (Expression expression : expressions) {
+                    expression.init(context);
+                }
+            }
+
+            @Override
             public String toString() {
                 if (description != null) {
                     return description;
@@ -1252,24 +1489,24 @@ public class ExpressionBuilder {
     }
 
     public static Expression simpleExpression(final String expression) {
-        return new ExpressionAdapter() {
-            public Object evaluate(Exchange exchange) {
-                if (LanguageSupport.hasSimpleFunction(expression)) {
+        if (LanguageSupport.hasSimpleFunction(expression)) {
+            return new ExpressionAdapter() {
+                public Object evaluate(Exchange exchange) {
                     // resolve language using context to have a clear separation of packages
                     // must call evaluate to return the nested language evaluate when evaluating
                     // stacked expressions
                     Language language = exchange.getContext().resolveLanguage("simple");
                     return language.createExpression(expression).evaluate(exchange, Object.class);
-                } else {
-                    return expression;
                 }
-            }
 
-            @Override
-            public String toString() {
-                return "simple(" + expression + ")";
-            }
-        };
+                @Override
+                public String toString() {
+                    return "simple(" + expression + ")";
+                }
+            };
+        } else {
+            return constantExpression(expression);
+        }
     }
 
     public static Expression beanExpression(final String expression) {
@@ -1423,4 +1660,5 @@ public class ExpressionBuilder {
             throw new IllegalArgumentException("Failed to set property " + name + " on " + bean + ". Reason: " + e, e);
         }
     }
+
 }
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/builder/ValueBuilder.java b/core/camel-support/src/main/java/org/apache/camel/support/builder/ValueBuilder.java
index 833de82..915a2fa 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/builder/ValueBuilder.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/builder/ValueBuilder.java
@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.Predicate;
@@ -36,6 +37,11 @@ public class ValueBuilder implements Expression, Predicate {
     }
 
     @Override
+    public void init(CamelContext context) {
+        expression.init(context);
+    }
+
+    @Override
     public <T> T evaluate(Exchange exchange, Class<T> type) {
         return expression.evaluate(exchange, type);
     }