camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From davscl...@apache.org
Subject [camel] 01/02: CAMEL-12309: Support SpEL in non spring runtimes. Thanks to Jens Kleine-Herzbruch for the patch.
Date Mon, 05 Mar 2018 09:50:27 GMT
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

commit cbc223bebf75f3afbef16040efe981865f6316bf
Author: Claus Ibsen <claus.ibsen@gmail.com>
AuthorDate: Mon Mar 5 10:18:29 2018 +0100

    CAMEL-12309: Support SpEL in non spring runtimes. Thanks to Jens Kleine-Herzbruch for
the patch.
---
 .../camel-spring/src/main/docs/spel-language.adoc  | 90 ++++++++++------------
 .../apache/camel/language/spel/SpelExpression.java |  3 +
 .../camel/spring/util/RegistryBeanResolver.java    | 50 ++++++++++++
 .../camel/language/spel/SpelNonSpringTest.java     | 59 ++++++++++++++
 4 files changed, 153 insertions(+), 49 deletions(-)

diff --git a/components/camel-spring/src/main/docs/spel-language.adoc b/components/camel-spring/src/main/docs/spel-language.adoc
index 0598556..f5c19f0 100644
--- a/components/camel-spring/src/main/docs/spel-language.adoc
+++ b/components/camel-spring/src/main/docs/spel-language.adoc
@@ -4,21 +4,21 @@
 *Available as of Camel version 2.7*
 
 Camel allows
-http://static.springsource.org/spring/docs/current/spring-framework-reference/htmlsingle/spring-framework-reference.html#expressions[SpEL]
-to be used as an Expression or
-Predicate in the DSL or
-Xml Configuration.
+https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions[Spring
Expression Language (SpEL)]
+to be used as an Expression or Predicate in the DSL or XML Configuration.
 
-### Variables
+NOTE: It is recommended to use SpEL in Spring runtimes. However from Camel 2.21 onwards you
can
+use SpEL in other runtimes (there may be functionality SpEL cannot do when not running in
a Spring runtime)
 
-The following variables are available in expressions and predicates
-written in SpEL:
+=== Variables
+
+The following variables are available in expressions and predicates written in SpEL:
 
 [width="100%",cols="10%,10%,80%",options="header",]
-|=======================================================================
+|===
 |Variable |Type |Description
 
-|*this* |Exchange |the Exchange is the root object
+|this |Exchange |the Exchange is the root object
 
 |exchange |Exchange |the Exchange object
 
@@ -28,7 +28,7 @@ written in SpEL:
 
 |fault |Message |the Fault message (if any)
 
-|body |Object |Camel 2.11: The IN message body.
+|body |Object | The IN message body.
 
 |request |Message |the exchange.in message
 
@@ -39,9 +39,9 @@ written in SpEL:
 |property(name) |Object |the property by the given name
 
 |property(name, type) |Type |the property by the given name as the given type
-|=======================================================================
+|===
 
-### Options
+=== Options
 
 // language options: START
 The SpEL language supports 1 options which are listed below.
@@ -55,9 +55,9 @@ The SpEL language supports 1 options which are listed below.
 |===
 // language options: END
 
-### Samples
+=== Samples
 
-#### Expression templating
+==== Expression templating
 
 SpEL expressions need to be surrounded by `#{` `}` delimiters since
 expression templating is enabled. This allows you to combine SpEL
@@ -67,9 +67,11 @@ template language.
 For example if you construct the following route:
 
 [source,java]
------------------------------------------------------------------------------------------------------------------------------------
-from("direct:example").setBody(spel("Hello #{request.body}! What a beautiful #{request.headers['dayOrNight']}")).to("mock:result");
------------------------------------------------------------------------------------------------------------------------------------
+----
+from("direct:example")
+    .setBody(spel("Hello #{request.body}! What a beautiful #{request.headers['dayOrNight']}"))
+    .to("mock:result");
+----
 
 In the route above, notice spel is a static method which we need to
 import from `org.apache.camel.language.spel.SpelExpression.spel`, as we
@@ -78,9 +80,11 @@ to the `setBody` method. Though if we use the fluent API we can do this
 instead:
 
 [source,java]
-------------------------------------------------------------------------------------------------------------------------------------
-from("direct:example").setBody().spel("Hello #{request.body}! What a beautiful #{request.headers['dayOrNight']}").to("mock:result");
-------------------------------------------------------------------------------------------------------------------------------------
+----
+from("direct:example")
+    .setBody().spel("Hello #{request.body}! What a beautiful #{request.headers['dayOrNight']}")
+    .to("mock:result");
+----
 
 Notice we now use the `spel` method from the `setBody()` method. And
 this does not require us to static import the spel method from
@@ -90,33 +94,33 @@ And sent a message with the string "World" in the body, and a header
 "dayOrNight" with value "day":
 
 [source,java]
----------------------------------------------------------------------------
+----
 template.sendBodyAndHeader("direct:example", "World", "dayOrNight", "day");
----------------------------------------------------------------------------
+----
 
 The output on `mock:result` will be _"Hello World! What a beautiful
 day"_
 
-#### Bean integration
+==== Bean integration
 
 You can reference beans defined in the Registry
 (most likely an `ApplicationContext`) in your SpEL expressions. For
 example if you have a bean named "foo" in your `ApplicationContext` you
 can invoke the "bar" method on this bean like this:
 
-[source,java]
---------------------
+[source,text]
+----
 #{@foo.bar == 'xyz'}
---------------------
+----
 
-#### SpEL in enterprise integration patterns
+==== SpEL in enterprise integration patterns
 
 You can use SpEL as an expression for link:recipient-list.html[Recipient
 List] or as a predicate inside a link:message-filter.html[Message
 Filter]:
 
 [source,xml]
----------------------------------------------------
+----
 <route>
   <from uri="direct:foo"/>
   <filter>
@@ -124,16 +128,18 @@ Filter]:
     <to uri="direct:bar"/>
   </filter>
 </route>
----------------------------------------------------
+----
 
 And the equivalent in Java DSL:
 
 [source,java]
--------------------------------------------------------------------------------------------
-   from("direct:foo").filter().spel("#{request.headers['foo'] == 'bar'}").to("direct:bar");
--------------------------------------------------------------------------------------------
+----
+from("direct:foo")
+    .filter().spel("#{request.headers['foo'] == 'bar'}")
+    .to("direct:bar");
+----
 
-### Loading script from external resource
+=== Loading script from external resource
 
 *Available as of Camel 2.11*
 
@@ -143,21 +149,7 @@ such as `"classpath:"`, `"file:"`, or `"http:"`. +
 eg to refer to a file on the classpath you can do:
 
 [source,java]
-------------------------------------------------------------
+----
 .setHeader("myHeader").spel("resource:classpath:myspel.txt")
-------------------------------------------------------------
+----
 
-### Dependencies
-
-You need Spring 3.0 or higher to use Spring Expression Language. If you
-use Maven you could just add the following to your `pom.xml`:
-
-[source,xml]
-----------------------------------------------------------
-<dependency>
-  <groupId>org.apache.camel</groupId>
-  <artifactId>camel-spring</artifactId>
-  <version>xxx</version>
-  <!-- use the same version as your Camel core version -->
-</dependency>
-----------------------------------------------------------
\ No newline at end of file
diff --git a/components/camel-spring/src/main/java/org/apache/camel/language/spel/SpelExpression.java
b/components/camel-spring/src/main/java/org/apache/camel/language/spel/SpelExpression.java
index 7c7642a..e410e1d 100644
--- a/components/camel-spring/src/main/java/org/apache/camel/language/spel/SpelExpression.java
+++ b/components/camel-spring/src/main/java/org/apache/camel/language/spel/SpelExpression.java
@@ -20,6 +20,7 @@ import org.apache.camel.Exchange;
 import org.apache.camel.ExpressionEvaluationException;
 import org.apache.camel.impl.ExpressionSupport;
 import org.apache.camel.spring.SpringCamelContext;
+import org.apache.camel.spring.util.RegistryBeanResolver;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.expression.BeanFactoryResolver;
 import org.springframework.expression.EvaluationContext;
@@ -71,6 +72,8 @@ public class SpelExpression extends ExpressionSupport {
             // Support references (like @foo) in expressions to beans defined in the Registry/ApplicationContext
             ApplicationContext applicationContext = ((SpringCamelContext) exchange.getContext()).getApplicationContext();
             evaluationContext.setBeanResolver(new BeanFactoryResolver(applicationContext));
+        } else {
+            evaluationContext.setBeanResolver(new RegistryBeanResolver(exchange.getContext().getRegistry()));
         }
         return evaluationContext;
     }
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/util/RegistryBeanResolver.java
b/components/camel-spring/src/main/java/org/apache/camel/spring/util/RegistryBeanResolver.java
new file mode 100644
index 0000000..63b45d8
--- /dev/null
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/util/RegistryBeanResolver.java
@@ -0,0 +1,50 @@
+/**
+ * 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.spring.util;
+
+import org.apache.camel.NoSuchBeanException;
+import org.apache.camel.spi.Registry;
+import org.springframework.expression.AccessException;
+import org.springframework.expression.BeanResolver;
+import org.springframework.expression.EvaluationContext;
+
+/**
+ * EL bean resolver that operates against a Camel {@link Registry}.
+ */
+public final class RegistryBeanResolver implements BeanResolver {
+
+    private final Registry registry;
+
+    public RegistryBeanResolver(Registry registry) {
+        this.registry = registry;
+    }
+
+    @Override
+    public Object resolve(EvaluationContext context, String beanName) throws AccessException
{
+        Object bean = null;
+        try {
+            bean = registry.lookupByName(beanName);
+        } catch (NoSuchBeanException e) {
+            // ignore
+        }
+        if (bean == null) {
+            throw new AccessException("Could not resolve bean reference against Registry");
+        }
+        return bean;
+    }
+
+}
diff --git a/components/camel-spring/src/test/java/org/apache/camel/language/spel/SpelNonSpringTest.java
b/components/camel-spring/src/test/java/org/apache/camel/language/spel/SpelNonSpringTest.java
new file mode 100644
index 0000000..2122f26
--- /dev/null
+++ b/components/camel-spring/src/test/java/org/apache/camel/language/spel/SpelNonSpringTest.java
@@ -0,0 +1,59 @@
+/**
+ * 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.spel;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExpressionEvaluationException;
+import org.apache.camel.LanguageTestSupport;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.SimpleRegistry;
+import org.apache.camel.language.spel.bean.Dummy;
+
+/**
+ * Test access to beans defined in non-Spring context from SpEL expressions/predicates.
+ */
+public class SpelNonSpringTest extends LanguageTestSupport {
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        SimpleRegistry registry = new SimpleRegistry();
+        registry.put("myDummy", new Dummy());
+        return new DefaultCamelContext(registry);
+    }
+
+    public void testSpelBeanExpressions() throws Exception {
+        assertExpression("#{@myDummy.foo == 'xyz'}", true);
+        assertExpression("#{@myDummy.bar == 789}", true);
+        assertExpression("#{@myDummy.bar.toString()}", "789");
+        try {
+            assertExpression("#{@notFound}", null);
+        } catch (ExpressionEvaluationException ex) {
+            assertStringContains(ex.getMessage(), "Could not resolve bean reference against
Registry");
+        }
+    }
+    
+    public void testSpelBeanPredicates() throws Exception {
+        assertPredicate("@myDummy.foo == 'xyz'");
+        assertPredicate("@myDummy.bar == 789");
+        assertPredicate("@myDummy.bar instanceof T(Integer)");
+    }
+
+    @Override
+    protected String getLanguageName() {
+        return "spel";
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
davsclaus@apache.org.

Mime
View raw message