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

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


The following commit(s) were added to refs/heads/master by this push:
     new 7b0e75a  CAMEL-15713: camel-joor - Added support for dependency 
injection via #bean:id style and optimized to invoke method without reflection 
via interface.
7b0e75a is described below

commit 7b0e75ae9f637d136df071d552730316047197ca
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Wed Oct 21 07:38:31 2020 +0200

    CAMEL-15713: camel-joor - Added support for dependency injection via 
#bean:id style and optimized to invoke method without reflection via interface.
---
 .../apache/camel/catalog/docs/joor-language.adoc   | 69 ++++++++++++++++++++
 .../camel-joor/src/main/docs/joor-language.adoc    | 69 ++++++++++++++++++++
 .../apache/camel/language/joor/JoorCompiler.java   | 75 +++++++++++++++++-----
 .../apache/camel/language/joor/JoorExpression.java | 23 ++++---
 .../org/apache/camel/language/joor/JoorMethod.java | 30 +++++++++
 .../language/joor/JoorBeanInjectTransformTest.java | 51 +++++++++++++++
 .../camel/language/joor/JoorBeanInjectVarTest.java | 51 +++++++++++++++
 .../org/apache/camel/language/joor/MyEchoBean.java | 28 ++++++++
 .../src/test/resources/log4j2.properties           |  4 +-
 .../modules/languages/pages/joor-language.adoc     | 69 ++++++++++++++++++++
 10 files changed, 441 insertions(+), 28 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/joor-language.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/joor-language.adoc
index f03d480..3d0653c 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/joor-language.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/joor-language.adoc
@@ -91,6 +91,75 @@ And then the function can be shortened:
 var user = bodyAs(MyUser);
 ----
 
+== Dependency Injection
+
+The Camel jOOR language allows dependency injection by referring to beans by 
their id from the Camel registry.
+For optimization purposes then the beans are injected once in the constructor 
and the scopes are _singleton_.
+This requires the injected beans to be _thread safe_ as they will be reused 
for all processing.
+
+In the jOOR script you declare the injected beans using the syntax 
`#bean:beanId`.
+
+For example suppose we have the following bean
+
+[source,java]
+----
+public class MyEchoBean {
+
+    public String echo(String str) {
+        return str + str;
+    }
+
+    public String greet() {
+        return "Hello ";
+    }
+}
+----
+
+And this bean is registered with the name `myBean` in the Camel registry.
+
+The jOOR script can then inject this bean directly in the script where the 
bean is in use:
+
+[source,java]
+----
+from("direct:start")
+    .transform().joor("'Hello ' + #bean:myEcho.echo(bodyAs(String))")
+    .to("mock:result");
+----
+
+Now this code may seem a bit magically, but what happens is that the `myEcho` 
bean is injected via a constructor,
+and then called directly in the script so its as fast as possible.
+
+Under the hod Camel jOOR generates the following source code that is compiled 
once:
+
+[source,java]
+----
+public class JoorScript1 implements org.apache.camel.language.joor.JoorMethod {
+
+    private MyEchoBean myEcho;
+
+    public JoorScript1(CamelContext context) throws Exception {
+        myEcho = context.getRegistry().lookupByNameAndType("myEcho", 
MyEchoBean.class);
+    }
+
+    @Override
+    public Object evaluate(CamelContext context, Exchange exchange, Message 
message, Object body, Optional optionalBody) throws Exception {
+        return "Hello " + myEcho.echo(bodyAs(exchange, String.class));
+    }
+}
+----
+
+You can also store a reference to the bean in a variable which would more 
resemble how you would code in Java
+
+[source,java]
+----
+from("direct:start")
+    .transform().joor("var bean = #bean:myEcho; return 'Hello ' + 
bean.echo(bodyAs(String))")
+    .to("mock:result");
+----
+
+Notice how we declare the bean as if its a local variable via `var bean = 
#bean:myEcho`. When doing this we must use
+a different name as `myEcho` is the variable used by the dependency injection 
and therefore we use _bean_ as name in the script.
+
 == Auto imports
 
 The jOOR language will automatic import from:
diff --git a/components/camel-joor/src/main/docs/joor-language.adoc 
b/components/camel-joor/src/main/docs/joor-language.adoc
index f03d480..3d0653c 100644
--- a/components/camel-joor/src/main/docs/joor-language.adoc
+++ b/components/camel-joor/src/main/docs/joor-language.adoc
@@ -91,6 +91,75 @@ And then the function can be shortened:
 var user = bodyAs(MyUser);
 ----
 
+== Dependency Injection
+
+The Camel jOOR language allows dependency injection by referring to beans by 
their id from the Camel registry.
+For optimization purposes then the beans are injected once in the constructor 
and the scopes are _singleton_.
+This requires the injected beans to be _thread safe_ as they will be reused 
for all processing.
+
+In the jOOR script you declare the injected beans using the syntax 
`#bean:beanId`.
+
+For example suppose we have the following bean
+
+[source,java]
+----
+public class MyEchoBean {
+
+    public String echo(String str) {
+        return str + str;
+    }
+
+    public String greet() {
+        return "Hello ";
+    }
+}
+----
+
+And this bean is registered with the name `myBean` in the Camel registry.
+
+The jOOR script can then inject this bean directly in the script where the 
bean is in use:
+
+[source,java]
+----
+from("direct:start")
+    .transform().joor("'Hello ' + #bean:myEcho.echo(bodyAs(String))")
+    .to("mock:result");
+----
+
+Now this code may seem a bit magically, but what happens is that the `myEcho` 
bean is injected via a constructor,
+and then called directly in the script so its as fast as possible.
+
+Under the hod Camel jOOR generates the following source code that is compiled 
once:
+
+[source,java]
+----
+public class JoorScript1 implements org.apache.camel.language.joor.JoorMethod {
+
+    private MyEchoBean myEcho;
+
+    public JoorScript1(CamelContext context) throws Exception {
+        myEcho = context.getRegistry().lookupByNameAndType("myEcho", 
MyEchoBean.class);
+    }
+
+    @Override
+    public Object evaluate(CamelContext context, Exchange exchange, Message 
message, Object body, Optional optionalBody) throws Exception {
+        return "Hello " + myEcho.echo(bodyAs(exchange, String.class));
+    }
+}
+----
+
+You can also store a reference to the bean in a variable which would more 
resemble how you would code in Java
+
+[source,java]
+----
+from("direct:start")
+    .transform().joor("var bean = #bean:myEcho; return 'Hello ' + 
bean.echo(bodyAs(String))")
+    .to("mock:result");
+----
+
+Notice how we declare the bean as if its a local variable via `var bean = 
#bean:myEcho`. When doing this we must use
+a different name as `myEcho` is the variable used by the dependency injection 
and therefore we use _bean_ as name in the script.
+
 == Auto imports
 
 The jOOR language will automatic import from:
diff --git 
a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorCompiler.java
 
b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorCompiler.java
index 4168ff3..84ad995 100644
--- 
a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorCompiler.java
+++ 
b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorCompiler.java
@@ -16,18 +16,18 @@
  */
 package org.apache.camel.language.joor;
 
-import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.Map;
-import java.util.Optional;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
 import org.apache.camel.StaticService;
+import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.ScriptHelper;
 import org.apache.camel.support.service.ServiceSupport;
 import org.apache.camel.util.StopWatch;
@@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory;
 
 public class JoorCompiler extends ServiceSupport implements StaticService {
 
+    private static final Pattern BEAN_INJECTION_PATTERN = 
Pattern.compile("(#bean:)([A-Za-z0-9-_]*)");
     private static final Pattern BODY_AS_PATTERN = 
Pattern.compile("(optionalBodyAs|bodyAs)\\(([A-Za-z0-9.$]*)(.class)\\)");
     private static final Pattern BODY_AS_PATTERN_NO_CLASS = 
Pattern.compile("(optionalBodyAs|bodyAs)\\(([A-Za-z0-9.$]*)\\)");
     private static final Pattern HEADER_AS_PATTERN
@@ -53,7 +54,7 @@ public class JoorCompiler extends ServiceSupport implements 
StaticService {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(JoorCompiler.class);
     private static final AtomicInteger UUID = new AtomicInteger();
-    private Set<String> imports;
+    private Set<String> imports = new TreeSet<>();
     private Map<String, String> aliases;
     private int counter;
     private long taken;
@@ -82,17 +83,19 @@ public class JoorCompiler extends ServiceSupport implements 
StaticService {
         }
     }
 
-    public Method compile(CamelContext camelContext, String script, boolean 
singleQuotes) {
+    public JoorMethod compile(CamelContext camelContext, String script, 
boolean singleQuotes) {
         StopWatch watch = new StopWatch();
 
-        Method answer;
+        JoorMethod answer;
         String className = nextFQN();
         String code = evalCode(camelContext, className, script, singleQuotes);
         try {
-            LOG.trace(code);
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Compiling code:\n\n" + code + "\n");
+            }
             Reflect ref = Reflect.compile(className, code);
-            answer = ref.type().getMethod("evaluate", CamelContext.class, 
Exchange.class, Message.class, Object.class,
-                    Optional.class);
+            Class<?> clazz = ref.type();
+            answer = (JoorMethod) 
clazz.getConstructor(CamelContext.class).newInstance(camelContext);
         } catch (Exception e) {
             throw new JoorCompilationException(className, code, e);
         }
@@ -112,6 +115,12 @@ public class JoorCompiler extends ServiceSupport 
implements StaticService {
         // trim text
         script = script.trim();
 
+        script = staticHelper(script);
+        script = alias(script);
+        Set<String> scriptImports = new LinkedHashSet<>();
+        Map<String, Class> scriptBeans = new HashMap<>();
+        script = evalDependencyInjection(camelContext, scriptImports, 
scriptBeans, script);
+
         //  wrap text into a class method we can call
         StringBuilder sb = new StringBuilder();
         sb.append("package ").append(qn).append(";\n");
@@ -132,19 +141,38 @@ public class JoorCompiler extends ServiceSupport 
implements StaticService {
             }
             sb.append("\n");
         }
+        for (String i : scriptImports) {
+            sb.append("import ");
+            sb.append(i);
+            sb.append(";\n");
+        }
         sb.append("\n");
-        sb.append("public class ").append(name).append(" {\n");
+        sb.append("public class ").append(name).append(" implements 
org.apache.camel.language.joor.JoorMethod {\n");
         sb.append("\n");
+
+        // local beans variables
+        for (Map.Entry<String, Class> entry : scriptBeans.entrySet()) {
+            sb.append("    private 
").append(entry.getValue().getSimpleName()).append(" 
").append(entry.getKey()).append(";\n");
+        }
+        sb.append("\n");
+
+        // constructor to lookup beans
+        sb.append("    public ").append(name).append("(CamelContext context) 
throws Exception {\n");
+        for (Map.Entry<String, Class> entry : scriptBeans.entrySet()) {
+            sb.append("        ").append(entry.getKey()).append(" = 
").append("context.getRegistry().lookupByNameAndType(\"")
+                    .append(entry.getKey()).append("\", 
").append(entry.getValue().getSimpleName()).append(".class);\n");
+        }
+        sb.append("    }\n");
+        sb.append("\n");
+
+        sb.append("    @Override\n");
         sb.append(
-                "    public static Object evaluate(CamelContext context, 
Exchange exchange, Message message, Object body, Optional optionalBody) throws 
Exception {\n");
+                "    public Object evaluate(CamelContext context, Exchange 
exchange, Message message, Object body, Optional optionalBody) throws Exception 
{\n");
         sb.append("        ");
         if (!script.contains("return ")) {
             sb.append("return ");
         }
 
-        script = staticHelper(script);
-        script = alias(script);
-
         if (singleQuotes) {
             // single quotes instead of double quotes, as its very annoying 
for string in strings
             String quoted = script.replace('\'', '"');
@@ -163,6 +191,21 @@ public class JoorCompiler extends ServiceSupport 
implements StaticService {
         return sb.toString();
     }
 
+    private String evalDependencyInjection(
+            CamelContext camelContext, Set<String> scriptImports, Map<String, 
Class> scriptBeans, String script) {
+        Matcher matcher = BEAN_INJECTION_PATTERN.matcher(script);
+        while (matcher.find()) {
+            String id = matcher.group(2);
+            Object bean = CamelContextHelper.mandatoryLookup(camelContext, id);
+            Class<?> type = bean.getClass();
+            scriptImports.add(type.getName());
+            scriptBeans.put(id, type);
+            script = matcher.replaceFirst(id);
+            matcher = BEAN_INJECTION_PATTERN.matcher(script);
+        }
+        return script;
+    }
+
     private String staticHelper(String script) {
         Matcher matcher = BODY_AS_PATTERN.matcher(script);
         script = matcher.replaceAll("$1(exchange, $2$3)");
@@ -191,7 +234,7 @@ public class JoorCompiler extends ServiceSupport implements 
StaticService {
     }
 
     private static String nextFQN() {
-        return "org.apache.camel.language.joor.compiled.JoorLanguage" + 
UUID.incrementAndGet();
+        return "org.apache.camel.language.joor.compiled.JoorScript" + 
UUID.incrementAndGet();
     }
 
 }
diff --git 
a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorExpression.java
 
b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorExpression.java
index 594d5ec..32e0af4 100644
--- 
a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorExpression.java
+++ 
b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorExpression.java
@@ -16,19 +16,18 @@
  */
 package org.apache.camel.language.joor;
 
-import java.lang.reflect.Method;
 import java.util.Optional;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
+import org.apache.camel.ExpressionEvaluationException;
 import org.apache.camel.support.ExpressionAdapter;
-import org.apache.camel.support.ObjectHelper;
 
 public class JoorExpression extends ExpressionAdapter {
 
     private final String text;
     private JoorCompiler compiler;
-    private Method compiled;
+    private JoorMethod method;
 
     private Class<?> resultType;
     private boolean preCompile = true;
@@ -77,17 +76,21 @@ public class JoorExpression extends ExpressionAdapter {
 
     @Override
     public Object evaluate(Exchange exchange) {
-        Method method = compiled;
-        if (method == null) {
-            method = compiler.compile(exchange.getContext(), text, 
singleQuotes);
+        JoorMethod target = this.method;
+        if (target == null) {
+            target = compiler.compile(exchange.getContext(), text, 
singleQuotes);
         }
         // optimize as we call the same method all the time so we dont want to 
find the method every time as joor would do
         // if you use its call method
         Object body = exchange.getIn().getBody();
         // in the rare case the body is already an optional
-        boolean optional = body instanceof Optional;
-        Object out = ObjectHelper.invokeMethod(method, null, 
exchange.getContext(), exchange, exchange.getIn(),
-                body, optional ? body : Optional.ofNullable(body));
+        Optional<?> optional = body instanceof Optional ? (Optional<?>) body : 
Optional.ofNullable(body);
+        Object out;
+        try {
+            out = target.evaluate(exchange.getContext(), exchange, 
exchange.getIn(), body, optional);
+        } catch (Exception e) {
+            throw new ExpressionEvaluationException(this, exchange, e);
+        }
         if (out != null && resultType != null) {
             return 
exchange.getContext().getTypeConverter().convertTo(resultType, exchange, out);
         } else {
@@ -100,7 +103,7 @@ public class JoorExpression extends ExpressionAdapter {
         super.init(context);
 
         if (preCompile) {
-            this.compiled = compiler.compile(context, text, singleQuotes);
+            this.method = compiler.compile(context, text, singleQuotes);
         }
     }
 
diff --git 
a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorMethod.java
 
b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorMethod.java
new file mode 100644
index 0000000..ade1503
--- /dev/null
+++ 
b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorMethod.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.joor;
+
+import java.util.Optional;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+
+public interface JoorMethod {
+
+    Object evaluate(CamelContext context, Exchange exchange, Message message, 
Object body, Optional<?> optionalBody)
+            throws Exception;
+
+}
diff --git 
a/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorBeanInjectTransformTest.java
 
b/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorBeanInjectTransformTest.java
new file mode 100644
index 0000000..5d7282a
--- /dev/null
+++ 
b/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorBeanInjectTransformTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.joor;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+public class JoorBeanInjectTransformTest extends CamelTestSupport {
+
+    @BindToRegistry("myEcho")
+    private MyEchoBean myEchoBean = new MyEchoBean();
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .transform().joor("#bean:myEcho.greet() + 
#bean:myEcho.echo(bodyAs(String))")
+                        .to("mock:result");
+            }
+        };
+    }
+
+    @Test
+    public void testHello() throws Exception {
+        getMockEndpoint("mock:result").expectedBodiesReceived("Hello 
CamelCamel", "Hello WorldWorld");
+
+        template.sendBody("direct:start", "Camel");
+        template.sendBody("direct:start", "World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+}
diff --git 
a/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorBeanInjectVarTest.java
 
b/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorBeanInjectVarTest.java
new file mode 100644
index 0000000..ab15c01
--- /dev/null
+++ 
b/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorBeanInjectVarTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.joor;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+public class JoorBeanInjectVarTest extends CamelTestSupport {
+
+    @BindToRegistry("myEcho")
+    private MyEchoBean myEchoBean = new MyEchoBean();
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .transform().joor("var bean = #bean:myEcho; return 
'Hello ' + bean.echo(bodyAs(String))")
+                        .to("mock:result");
+            }
+        };
+    }
+
+    @Test
+    public void testHello() throws Exception {
+        getMockEndpoint("mock:result").expectedBodiesReceived("Hello 
CamelCamel", "Hello WorldWorld");
+
+        template.sendBody("direct:start", "Camel");
+        template.sendBody("direct:start", "World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+}
diff --git 
a/components/camel-joor/src/test/java/org/apache/camel/language/joor/MyEchoBean.java
 
b/components/camel-joor/src/test/java/org/apache/camel/language/joor/MyEchoBean.java
new file mode 100644
index 0000000..f484326
--- /dev/null
+++ 
b/components/camel-joor/src/test/java/org/apache/camel/language/joor/MyEchoBean.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.joor;
+
+public class MyEchoBean {
+
+    public String echo(String str) {
+        return str + str;
+    }
+
+    public String greet() {
+        return "Hello ";
+    }
+}
diff --git a/components/camel-joor/src/test/resources/log4j2.properties 
b/components/camel-joor/src/test/resources/log4j2.properties
index e4e6691..0383652 100644
--- a/components/camel-joor/src/test/resources/log4j2.properties
+++ b/components/camel-joor/src/test/resources/log4j2.properties
@@ -24,7 +24,7 @@ appender.out.type = Console
 appender.out.name = out
 appender.out.layout.type = PatternLayout
 appender.out.layout.pattern = [%30.30t] %-30.30c{1} %-5p %m%n
-logger.springframework.name = org.springframework
-logger.springframework.level = WARN
+logger.joor.name = org.apache.camel.language.joor
+logger.joor.level = DEBUG
 rootLogger.level = INFO
 rootLogger.appenderRef.file.ref = file
diff --git a/docs/components/modules/languages/pages/joor-language.adoc 
b/docs/components/modules/languages/pages/joor-language.adoc
index 441f32e..fda65dd 100644
--- a/docs/components/modules/languages/pages/joor-language.adoc
+++ b/docs/components/modules/languages/pages/joor-language.adoc
@@ -93,6 +93,75 @@ And then the function can be shortened:
 var user = bodyAs(MyUser);
 ----
 
+== Dependency Injection
+
+The Camel jOOR language allows dependency injection by referring to beans by 
their id from the Camel registry.
+For optimization purposes then the beans are injected once in the constructor 
and the scopes are _singleton_.
+This requires the injected beans to be _thread safe_ as they will be reused 
for all processing.
+
+In the jOOR script you declare the injected beans using the syntax 
`#bean:beanId`.
+
+For example suppose we have the following bean
+
+[source,java]
+----
+public class MyEchoBean {
+
+    public String echo(String str) {
+        return str + str;
+    }
+
+    public String greet() {
+        return "Hello ";
+    }
+}
+----
+
+And this bean is registered with the name `myBean` in the Camel registry.
+
+The jOOR script can then inject this bean directly in the script where the 
bean is in use:
+
+[source,java]
+----
+from("direct:start")
+    .transform().joor("'Hello ' + #bean:myEcho.echo(bodyAs(String))")
+    .to("mock:result");
+----
+
+Now this code may seem a bit magically, but what happens is that the `myEcho` 
bean is injected via a constructor,
+and then called directly in the script so its as fast as possible.
+
+Under the hod Camel jOOR generates the following source code that is compiled 
once:
+
+[source,java]
+----
+public class JoorScript1 implements org.apache.camel.language.joor.JoorMethod {
+
+    private MyEchoBean myEcho;
+
+    public JoorScript1(CamelContext context) throws Exception {
+        myEcho = context.getRegistry().lookupByNameAndType("myEcho", 
MyEchoBean.class);
+    }
+
+    @Override
+    public Object evaluate(CamelContext context, Exchange exchange, Message 
message, Object body, Optional optionalBody) throws Exception {
+        return "Hello " + myEcho.echo(bodyAs(exchange, String.class));
+    }
+}
+----
+
+You can also store a reference to the bean in a variable which would more 
resemble how you would code in Java
+
+[source,java]
+----
+from("direct:start")
+    .transform().joor("var bean = #bean:myEcho; return 'Hello ' + 
bean.echo(bodyAs(String))")
+    .to("mock:result");
+----
+
+Notice how we declare the bean as if its a local variable via `var bean = 
#bean:myEcho`. When doing this we must use
+a different name as `myEcho` is the variable used by the dependency injection 
and therefore we use _bean_ as name in the script.
+
 == Auto imports
 
 The jOOR language will automatic import from:

Reply via email to