diff --git a/kogito-serverless-workflow/kogito-jq-expression/src/main/java/org/kie/kogito/expr/jq/JqExpression.java b/kogito-serverless-workflow/kogito-jq-expression/src/main/java/org/kie/kogito/expr/jq/JqExpression.java index 3930ababfca..6c6785efe74 100644 --- a/kogito-serverless-workflow/kogito-jq-expression/src/main/java/org/kie/kogito/expr/jq/JqExpression.java +++ b/kogito-serverless-workflow/kogito-jq-expression/src/main/java/org/kie/kogito/expr/jq/JqExpression.java @@ -27,6 +27,7 @@ import org.kie.kogito.jackson.utils.FunctionJsonNode; import org.kie.kogito.jackson.utils.JsonObjectUtils; import org.kie.kogito.jackson.utils.ObjectMapperFactory; +import org.kie.kogito.jackson.utils.PrefixJsonNode; import org.kie.kogito.process.expr.Expression; import org.kie.kogito.serverless.workflow.utils.ExpressionHandlerUtils; import org.kie.kogito.serverless.workflow.utils.JsonNodeContext; @@ -151,7 +152,7 @@ public void assign(Object target, Object value, KogitoProcessContext context) { private Scope getScope(KogitoProcessContext processInfo) { Scope childScope = Scope.newChildScope(scope.get()); - childScope.setValue(ExpressionHandlerUtils.SECRET_MAGIC, new FunctionJsonNode(ExpressionHandlerUtils::getSecret)); + childScope.setValue(ExpressionHandlerUtils.SECRET_MAGIC, new PrefixJsonNode<>(ExpressionHandlerUtils::getOptionalSecret)); childScope.setValue(ExpressionHandlerUtils.CONTEXT_MAGIC, new FunctionJsonNode(ExpressionHandlerUtils.getContextFunction(processInfo))); childScope.setValue(ExpressionHandlerUtils.CONST_MAGIC, ExpressionHandlerUtils.getConstants(processInfo)); return childScope; diff --git a/kogito-serverless-workflow/kogito-jq-expression/src/test/java/org/kie/kogito/expr/jq/JqExpressionHandlerTest.java b/kogito-serverless-workflow/kogito-jq-expression/src/test/java/org/kie/kogito/expr/jq/JqExpressionHandlerTest.java index d5c11c6e8a8..9e6578eddd7 100644 --- a/kogito-serverless-workflow/kogito-jq-expression/src/test/java/org/kie/kogito/expr/jq/JqExpressionHandlerTest.java +++ b/kogito-serverless-workflow/kogito-jq-expression/src/test/java/org/kie/kogito/expr/jq/JqExpressionHandlerTest.java @@ -284,7 +284,7 @@ private static Stream provideMagicWordExpressionsToTest() { Arguments.of("$SECRET.none", "null", getContext()), Arguments.of("\"$SECRET.none\"", "$SECRET.none", getContext()), Arguments.of("$SECRET.lettersonly", "secretlettersonly", getContext()), - Arguments.of("$SECRET.dot.secret", "null", getContext()), + Arguments.of("$SECRET.dot.secret", "secretdotsecret", getContext()), Arguments.of("$SECRET.\"dot.secret\"", "secretdotsecret", getContext()), Arguments.of("$SECRET.\"dash-secret\"", "secretdashsecret", getContext()), Arguments.of("$CONST.someconstant", "value", getContext()), diff --git a/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathExpression.java b/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathExpression.java index 5755de6d9cf..57952675962 100644 --- a/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathExpression.java +++ b/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathExpression.java @@ -32,7 +32,6 @@ import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.JsonPathException; import com.jayway.jsonpath.PathNotFoundException; -import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider; public class JsonPathExpression implements Expression { @@ -57,7 +56,7 @@ private static final String replaceMagic(String expr, String magic) { private Configuration getConfiguration(KogitoProcessContext context) { return Configuration .builder() - .mappingProvider(new JacksonMappingProvider()) + .mappingProvider(new JsonPathJacksonProvider()) .jsonProvider(new WorkflowJacksonJsonNodeJsonProvider(context)) .build(); } diff --git a/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathJacksonProvider.java b/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathJacksonProvider.java new file mode 100644 index 00000000000..528b4aa57ba --- /dev/null +++ b/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathJacksonProvider.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.kie.kogito.expr.jsonpath; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider; + +public class JsonPathJacksonProvider extends JacksonMappingProvider { + + @Override + public T map(Object source, Class targetType, Configuration configuration) { + return targetType.isAssignableFrom(source.getClass()) ? targetType.cast(source) : super.map(source, targetType, configuration); + } +} diff --git a/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/WorkflowJacksonJsonNodeJsonProvider.java b/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/WorkflowJacksonJsonNodeJsonProvider.java index 43068ab3dce..f423bc5c9eb 100644 --- a/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/WorkflowJacksonJsonNodeJsonProvider.java +++ b/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/WorkflowJacksonJsonNodeJsonProvider.java @@ -21,6 +21,8 @@ import java.util.function.Function; import org.kie.kogito.internal.process.runtime.KogitoProcessContext; +import org.kie.kogito.jackson.utils.FunctionBaseJsonNode; +import org.kie.kogito.jackson.utils.PrefixJsonNode; import org.kie.kogito.serverless.workflow.utils.ExpressionHandlerUtils; import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider; @@ -37,10 +39,12 @@ public WorkflowJacksonJsonNodeJsonProvider(KogitoProcessContext context) { public Object getMapValue(Object obj, String key) { if (obj instanceof Function) { return ((Function) obj).apply(key); + } else if (obj instanceof FunctionBaseJsonNode) { + return ((FunctionBaseJsonNode) obj).get(key); } else { switch (key) { case "$" + ExpressionHandlerUtils.SECRET_MAGIC: - return (Function) ExpressionHandlerUtils::getSecret; + return new PrefixJsonNode<>(ExpressionHandlerUtils::getOptionalSecret); case "$" + ExpressionHandlerUtils.CONTEXT_MAGIC: return ExpressionHandlerUtils.getContextFunction(context); case "$" + ExpressionHandlerUtils.CONST_MAGIC: @@ -53,6 +57,6 @@ public Object getMapValue(Object obj, String key) { @Override public boolean isMap(Object obj) { - return super.isMap(obj) || obj instanceof Function; + return super.isMap(obj) || obj instanceof Function || obj instanceof FunctionBaseJsonNode; } } diff --git a/kogito-serverless-workflow/kogito-jsonpath-expression/src/test/java/org/kie/kogito/expr/jsonpath/JsonPathExpressionHandlerTest.java b/kogito-serverless-workflow/kogito-jsonpath-expression/src/test/java/org/kie/kogito/expr/jsonpath/JsonPathExpressionHandlerTest.java index 8d3a5720818..7d364f0ba12 100644 --- a/kogito-serverless-workflow/kogito-jsonpath-expression/src/test/java/org/kie/kogito/expr/jsonpath/JsonPathExpressionHandlerTest.java +++ b/kogito-serverless-workflow/kogito-jsonpath-expression/src/test/java/org/kie/kogito/expr/jsonpath/JsonPathExpressionHandlerTest.java @@ -238,8 +238,8 @@ private static Stream provideMagicWordExpressionsToTest() { return Stream.of( Arguments.of("$WORKFLOW.instanceId", "1111-2222-3333", getContext()), Arguments.of("$SECRET.lettersonly", "secretlettersonly", getContext()), - Arguments.of("$SECRET.none", "null", getContext()), - // Arguments.of("$SECRET.dot.secret", "null", getContext()), // exception due to missing object at path .dot + Arguments.of("$SECRET.none", "", getContext()), + Arguments.of("$SECRET.dot.secret", "secretdotsecret", getContext()), Arguments.of("$SECRET[\"dot.secret\"]", "secretdotsecret", getContext()), Arguments.of("$SECRET[\"dash-secret\"]", "secretdashsecret", getContext()), Arguments.of("$CONST.someconstant", "value", getContext()), diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-utils/src/main/java/org/kie/kogito/serverless/workflow/utils/ExpressionHandlerUtils.java b/kogito-serverless-workflow/kogito-serverless-workflow-utils/src/main/java/org/kie/kogito/serverless/workflow/utils/ExpressionHandlerUtils.java index 615eef3d517..e727f96605a 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-utils/src/main/java/org/kie/kogito/serverless/workflow/utils/ExpressionHandlerUtils.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-utils/src/main/java/org/kie/kogito/serverless/workflow/utils/ExpressionHandlerUtils.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.function.Function; import org.jbpm.ruleflow.core.Metadata; @@ -53,8 +54,12 @@ public static JsonNode getConstants(KogitoProcessContext context) { return node == null ? NullNode.instance : node; } + public static Optional getOptionalSecret(String key) { + return ConfigResolverHolder.getConfigResolver().getConfigProperty(key, String.class); + } + public static String getSecret(String key) { - return ConfigResolverHolder.getConfigResolver().getConfigProperty(key, String.class).orElse(null); + return getOptionalSecret(key).orElse(null); } public static Function getContextFunction(KogitoProcessContext context) { diff --git a/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/FunctionBaseJsonNode.java b/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/FunctionBaseJsonNode.java new file mode 100644 index 00000000000..1c5b3a5aa94 --- /dev/null +++ b/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/FunctionBaseJsonNode.java @@ -0,0 +1,133 @@ +/* + * 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.kie.kogito.jackson.utils; + +import java.io.IOException; +import java.util.List; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonPointer; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.jsontype.TypeSerializer; +import com.fasterxml.jackson.databind.node.BaseJsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeType; +import com.fasterxml.jackson.databind.node.MissingNode; + +public class FunctionBaseJsonNode extends BaseJsonNode { + + private static final long serialVersionUID = 1L; + + @Override + public JsonToken asToken() { + return JsonToken.START_OBJECT; + } + + @Override + public boolean isObject() { + return true; + } + + @Override + public T deepCopy() { + return (T) this; + } + + @Override + public JsonNode get(int index) { + return MissingNode.getInstance(); + } + + @Override + public JsonNode path(String fieldName) { + return get(fieldName); + } + + @Override + public JsonNode path(int index) { + return MissingNode.getInstance(); + } + + @Override + protected JsonNode _at(JsonPointer ptr) { + return null; + } + + @Override + public JsonNodeType getNodeType() { + return JsonNodeType.OBJECT; + } + + @Override + public String asText() { + return null; + } + + @Override + public JsonNode findValue(String fieldName) { + return get(fieldName); + } + + @Override + public JsonNode findParent(String fieldName) { + return null; + } + + @Override + public List findValues(String fieldName, List foundSoFar) { + foundSoFar.add(findValue(fieldName)); + return foundSoFar; + } + + @Override + public List findValuesAsText(String fieldName, List foundSoFar) { + foundSoFar.add(findValue(fieldName).asText()); + return foundSoFar; + } + + @Override + public List findParents(String fieldName, List foundSoFar) { + foundSoFar.add(findParent(fieldName)); + return foundSoFar; + } + + @Override + public boolean equals(Object o) { + return true; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException { + // not serialize + } + + @Override + public void serializeWithType(JsonGenerator jgen, + SerializerProvider provider, + TypeSerializer typeSer) throws IOException { + // not serialize + } + +} \ No newline at end of file diff --git a/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/FunctionJsonNode.java b/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/FunctionJsonNode.java index f61d160da50..3d2a67dfdad 100644 --- a/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/FunctionJsonNode.java +++ b/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/FunctionJsonNode.java @@ -18,21 +18,11 @@ */ package org.kie.kogito.jackson.utils; -import java.io.IOException; -import java.util.List; import java.util.function.Function; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonPointer; -import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.jsontype.TypeSerializer; -import com.fasterxml.jackson.databind.node.BaseJsonNode; -import com.fasterxml.jackson.databind.node.JsonNodeType; -import com.fasterxml.jackson.databind.node.MissingNode; -public class FunctionJsonNode extends BaseJsonNode { +public class FunctionJsonNode extends FunctionBaseJsonNode { private static final long serialVersionUID = 1L; private transient Function function; @@ -41,104 +31,8 @@ public FunctionJsonNode(Function function) { this.function = function; } - @Override - public JsonToken asToken() { - return JsonToken.START_OBJECT; - } - - @Override - public boolean isObject() { - return true; - } - - @Override - public T deepCopy() { - return (T) this; - } - - @Override - public JsonNode get(int index) { - return MissingNode.getInstance(); - } - - @Override - public JsonNode path(String fieldName) { - return get(fieldName); - } - - @Override - public JsonNode path(int index) { - return MissingNode.getInstance(); - } - - @Override - protected JsonNode _at(JsonPointer ptr) { - return null; - } - - @Override - public JsonNodeType getNodeType() { - return JsonNodeType.OBJECT; - } - - @Override - public String asText() { - return null; - } - - @Override - public JsonNode findValue(String fieldName) { - return get(fieldName); - } - @Override public JsonNode get(String fieldName) { return JsonObjectUtils.fromValue(function.apply(fieldName)); } - - @Override - public JsonNode findParent(String fieldName) { - return null; - } - - @Override - public List findValues(String fieldName, List foundSoFar) { - foundSoFar.add(findValue(fieldName)); - return foundSoFar; - } - - @Override - public List findValuesAsText(String fieldName, List foundSoFar) { - foundSoFar.add(findValue(fieldName).asText()); - return foundSoFar; - } - - @Override - public List findParents(String fieldName, List foundSoFar) { - foundSoFar.add(findParent(fieldName)); - return foundSoFar; - } - - @Override - public boolean equals(Object o) { - return true; - } - - @Override - public int hashCode() { - return 0; - } - - @Override - public void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException { - // not serialize - } - - @Override - public void serializeWithType(JsonGenerator jgen, - SerializerProvider provider, - TypeSerializer typeSer) throws IOException { - // not serialize - } - -} \ No newline at end of file +} diff --git a/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/PrefixJsonNode.java b/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/PrefixJsonNode.java new file mode 100644 index 00000000000..0793e849d6f --- /dev/null +++ b/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/PrefixJsonNode.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.kie.kogito.jackson.utils; + +import java.util.Optional; +import java.util.function.Function; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeType; + +public class PrefixJsonNode extends FunctionBaseJsonNode { + + private static final long serialVersionUID = 1L; + + private transient final String prefix; + private transient final Function> function; + private transient Optional value; + + public PrefixJsonNode(Function> function) { + this(null, function); + } + + public PrefixJsonNode(String prefix, Function> function) { + this.prefix = prefix; + this.function = function; + this.value = prefix == null ? Optional.empty() : function.apply(prefix); + } + + @Override + public JsonNodeType getNodeType() { + return value.isPresent() ? JsonNodeType.STRING : JsonNodeType.OBJECT; + } + + @Override + public String asText() { + return value.map(Object::toString).orElse(null); + } + + @Override + public JsonNode get(String fieldName) { + return new PrefixJsonNode<>(prefix == null ? fieldName : prefix + "." + fieldName, function); + } +} diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/application.properties b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/application.properties index 464e0b8e6ea..cc89ce64f9c 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/application.properties +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/application.properties @@ -67,7 +67,7 @@ mp.messaging.incoming.event2Exclusive.path=/event2Exclusive mp.messaging.incoming.event3Exclusive.connector=quarkus-http mp.messaging.incoming.event3Exclusive.path=/event3Exclusive -my_name=javierito +expression.my_name=javierito # Kafka configuration for the sw tests that produce events mp.messaging.outgoing.kogito_outgoing_stream.connector=smallrye-kafka diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/expression.sw.json b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/expression.sw.json index b738e603ea6..9a0b96344ea 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/expression.sw.json +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/expression.sw.json @@ -29,7 +29,7 @@ { "name": "secretMessage", "type": "expression", - "operation": ".message |= \"my name is \"+$SECRET.my_name" + "operation": ".message |= \"my name is \"+$SECRET.expression.my_name" }, { "name": "constantMessage",