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

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


The following commit(s) were added to refs/heads/camel-3.11.x by this push:
     new b39c8a1  CAMEL-16918: camel-datasonnet - Fix concurrency issue and 
other thread-safety problems.
b39c8a1 is described below

commit b39c8a10edd17c663434242352e5f3bb9bffd0b7
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Fri Sep 3 18:02:52 2021 +0200

    CAMEL-16918: camel-datasonnet - Fix concurrency issue and other 
thread-safety problems.
---
 .../language/datasonnet/DatasonnetExpression.java  | 80 ++++++++++------------
 .../org/apache/camel/builder/BuilderSupport.java   |  2 +
 2 files changed, 37 insertions(+), 45 deletions(-)

diff --git 
a/components/camel-datasonnet/src/main/java/org/apache/camel/language/datasonnet/DatasonnetExpression.java
 
b/components/camel-datasonnet/src/main/java/org/apache/camel/language/datasonnet/DatasonnetExpression.java
index 2d75095..846229b 100644
--- 
a/components/camel-datasonnet/src/main/java/org/apache/camel/language/datasonnet/DatasonnetExpression.java
+++ 
b/components/camel-datasonnet/src/main/java/org/apache/camel/language/datasonnet/DatasonnetExpression.java
@@ -28,7 +28,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Objects;
 
 import com.datasonnet.Mapper;
 import com.datasonnet.MapperBuilder;
@@ -36,8 +35,8 @@ import com.datasonnet.document.DefaultDocument;
 import com.datasonnet.document.Document;
 import com.datasonnet.document.MediaType;
 import com.datasonnet.document.MediaTypes;
+import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
-import org.apache.camel.Expression;
 import org.apache.camel.RuntimeExpressionException;
 import org.apache.camel.spi.ExpressionResultTypeAware;
 import org.apache.camel.support.ExchangeHelper;
@@ -50,43 +49,28 @@ import org.slf4j.LoggerFactory;
 public class DatasonnetExpression extends ExpressionAdapter implements 
ExpressionResultTypeAware {
     private static final Logger LOG = 
LoggerFactory.getLogger(DatasonnetExpression.class);
 
-    private String expression;
-    private Expression metaExpression;
+    private final String expression;
     private MediaType bodyMediaType;
     private MediaType outputMediaType;
     private Class<?> resultType;
     private Collection<String> libraryPaths;
+    private transient DatasonnetLanguage language;
 
     public DatasonnetExpression(String expression) {
         this.expression = expression;
     }
 
-    public DatasonnetExpression(Expression expression) {
-        this.metaExpression = expression;
-    }
-
     public static DatasonnetExpression builder(String expression) {
         DatasonnetExpression answer = new DatasonnetExpression(expression);
         return answer;
     }
 
-    public static DatasonnetExpression builder(Expression expression) {
-        DatasonnetExpression answer = new DatasonnetExpression(expression);
-        return answer;
-    }
-
     public static DatasonnetExpression builder(String expression, Class<?> 
resultType) {
         DatasonnetExpression answer = new DatasonnetExpression(expression);
         answer.setResultType(resultType);
         return answer;
     }
 
-    public static DatasonnetExpression builder(Expression expression, Class<?> 
resultType) {
-        DatasonnetExpression answer = new DatasonnetExpression(expression);
-        answer.setResultType(resultType);
-        return answer;
-    }
-
     @Override
     public boolean matches(Exchange exchange) {
         this.outputMediaType = MediaTypes.APPLICATION_JAVA;
@@ -97,11 +81,8 @@ public class DatasonnetExpression extends ExpressionAdapter 
implements Expressio
     @Override
     public <T> T evaluate(Exchange exchange, Class<T> type) {
         try {
-            if (metaExpression != null) {
-                expression = metaExpression.evaluate(exchange, String.class);
-            }
-
-            Objects.requireNonNull(expression, "String expression property 
must be set!");
+            // pass exchange to CML lib using thread as context
+            CML.getInstance().getExchange().set(exchange);
 
             Document<?> result = doEvaluate(exchange);
             if (!type.equals(Object.class)) {
@@ -119,52 +100,46 @@ public class DatasonnetExpression extends 
ExpressionAdapter implements Expressio
     }
 
     private Document<?> doEvaluate(Exchange exchange) {
-        if (bodyMediaType == null) {
+        MediaType bodyMT = bodyMediaType;
+        if (bodyMT == null) {
             //Try to auto-detect input mime type if it was not explicitly set
             String typeHeader = 
exchange.getProperty(DatasonnetConstants.BODY_MEDIATYPE,
                     exchange.getIn().getHeader(Exchange.CONTENT_TYPE), 
String.class);
             if (typeHeader != null) {
-                bodyMediaType = MediaType.valueOf(typeHeader);
+                bodyMT = MediaType.valueOf(typeHeader);
             }
         }
 
         Document<?> body;
         if (exchange.getMessage().getBody() instanceof Document) {
             body = (Document<?>) exchange.getMessage().getBody();
-        } else if 
(MediaTypes.APPLICATION_JAVA.equalsTypeAndSubtype(bodyMediaType)) {
+        } else if (MediaTypes.APPLICATION_JAVA.equalsTypeAndSubtype(bodyMT)) {
             body = new DefaultDocument<>(exchange.getMessage().getBody());
         } else {
-            body = new 
DefaultDocument<>(MessageHelper.extractBodyAsString(exchange.getMessage()), 
bodyMediaType);
+            body = new 
DefaultDocument<>(MessageHelper.extractBodyAsString(exchange.getMessage()), 
bodyMT);
         }
 
-        Map<String, Document<?>> inputs = Collections.singletonMap("body", 
body);
-
-        DatasonnetLanguage language = (DatasonnetLanguage) 
exchange.getContext().resolveLanguage("datasonnet");
-        Mapper mapper = language.computeIfMiss(expression, () -> new 
MapperBuilder(expression)
-                .withInputNames(inputs.keySet())
-                .withImports(resolveImports(language))
-                .withLibrary(CML.getInstance())
-                .withDefaultOutput(MediaTypes.APPLICATION_JAVA)
-                .build());
+        // the mapper is pre initialized
+        Mapper mapper = language.lookup(expression)
+                .orElseThrow(() -> new IllegalStateException("Datasonnet 
expression not initialized"));
 
-        // pass exchange to CML lib using thread as context
-        CML.getInstance().getExchange().set(exchange);
-
-        if (outputMediaType == null) {
+        MediaType outMT = outputMediaType;
+        if (outMT == null) {
             //Try to auto-detect output mime type if it was not explicitly set
             String typeHeader = 
exchange.getProperty(DatasonnetConstants.OUTPUT_MEDIATYPE,
                     
exchange.getIn().getHeader(DatasonnetConstants.OUTPUT_MEDIATYPE), String.class);
             if (typeHeader != null) {
-                outputMediaType = MediaType.valueOf(typeHeader);
+                outMT = MediaType.valueOf(typeHeader);
             } else {
-                outputMediaType = MediaTypes.ANY;
+                outMT = MediaTypes.ANY;
             }
         }
 
+        Map<String, Document<?>> inputs = Collections.singletonMap("body", 
body);
         if (resultType == null || resultType.equals(Document.class)) {
-            return mapper.transform(body, inputs, outputMediaType, 
Object.class);
+            return mapper.transform(body, inputs, outMT, Object.class);
         } else {
-            return mapper.transform(body, inputs, outputMediaType, resultType);
+            return mapper.transform(body, inputs, outMT, resultType);
         }
     }
 
@@ -201,6 +176,20 @@ public class DatasonnetExpression extends 
ExpressionAdapter implements Expressio
         return answer;
     }
 
+    @Override
+    public void init(CamelContext context) {
+        super.init(context);
+
+        language = (DatasonnetLanguage) context.resolveLanguage("datasonnet");
+        // initialize mapper eager
+        language.computeIfMiss(expression, () -> new MapperBuilder(expression)
+                .withInputNames("body")
+                .withImports(resolveImports(language))
+                .withLibrary(CML.getInstance())
+                .withDefaultOutput(MediaTypes.APPLICATION_JAVA)
+                .build());
+    }
+
     // Getter/Setter methods
     // 
-------------------------------------------------------------------------
 
@@ -272,4 +261,5 @@ public class DatasonnetExpression extends ExpressionAdapter 
implements Expressio
     public String toString() {
         return "datasonnet: " + expression;
     }
+
 }
diff --git 
a/core/camel-core-model/src/main/java/org/apache/camel/builder/BuilderSupport.java
 
b/core/camel-core-model/src/main/java/org/apache/camel/builder/BuilderSupport.java
index 81d9453..8c16137 100644
--- 
a/core/camel-core-model/src/main/java/org/apache/camel/builder/BuilderSupport.java
+++ 
b/core/camel-core-model/src/main/java/org/apache/camel/builder/BuilderSupport.java
@@ -164,6 +164,7 @@ public abstract class BuilderSupport {
     /**
      * Returns a Datasonnet expression value builder
      */
+    @Deprecated
     public ValueBuilder datasonnet(Expression value) {
         DatasonnetExpression exp = new DatasonnetExpression(value);
         return new ValueBuilder(exp);
@@ -181,6 +182,7 @@ public abstract class BuilderSupport {
     /**
      * Returns a Datasonnet expression value builder
      */
+    @Deprecated
     public ValueBuilder datasonnet(Expression value, Class<?> resultType) {
         DatasonnetExpression exp = new DatasonnetExpression(value);
         exp.setResultType(resultType);

Reply via email to