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);