You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2021/01/22 21:49:43 UTC

[camel] 01/02: CAMEL-16061 - JSLT-Component: Object-Mapper changes large Decimal-Numbers (to scientific notation)

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

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

commit c8604fd2eec9d66943b409d3d0a0d8ad7785a572
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Fri Jan 22 22:44:05 2021 +0100

    CAMEL-16061 - JSLT-Component: Object-Mapper changes large Decimal-Numbers (to scientific notation)
---
 .../apache/camel/catalog/docs/jslt-component.adoc  |  3 +-
 .../component/jslt/JsltEndpointConfigurer.java     |  6 ++
 .../component/jslt/JsltEndpointUriFactory.java     |  3 +-
 .../org/apache/camel/component/jslt/jslt.json      |  1 +
 .../camel-jslt/src/main/docs/jslt-component.adoc   |  3 +-
 .../apache/camel/component/jslt/JsltEndpoint.java  | 16 +++++
 .../camel/component/jslt/JsltBigDecimalTest.java   | 75 ++++++++++++++++++++++
 .../camel/component/jslt/useBigDecimal/input.json  | 13 ++++
 .../camel/component/jslt/useBigDecimal/output.json | 10 +++
 .../jslt/useBigDecimal/transformation.json         |  3 +
 .../endpoint/dsl/JsltEndpointBuilderFactory.java   | 35 ++++++++++
 .../modules/ROOT/pages/jslt-component.adoc         |  3 +-
 12 files changed, 167 insertions(+), 4 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jslt-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jslt-component.adoc
index 28b75d0..7924a76 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jslt-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jslt-component.adoc
@@ -90,7 +90,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (5 parameters):
+=== Query Parameters (6 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -99,6 +99,7 @@ with the following path and query parameters:
 | *allowContextMapAll* (producer) | Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API. | false | boolean
 | *allowTemplateFromHeader* (producer) | Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential security vulnerability if the header is coming from a malicious user, so use this with care. | false | boolean
 | *contentCache* (producer) | Sets whether to use resource content cache or not | false | boolean
+| *mapBigDecimalAsFloats* (producer) | If true, the mapper will use the USE_BIG_DECIMAL_FOR_FLOATS in serialization features | false | boolean
 | *prettyPrint* (common) | If true, JSON in output message is pretty printed. | false | boolean
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 |===
diff --git a/components/camel-jslt/src/generated/java/org/apache/camel/component/jslt/JsltEndpointConfigurer.java b/components/camel-jslt/src/generated/java/org/apache/camel/component/jslt/JsltEndpointConfigurer.java
index 9492314..f375445 100644
--- a/components/camel-jslt/src/generated/java/org/apache/camel/component/jslt/JsltEndpointConfigurer.java
+++ b/components/camel-jslt/src/generated/java/org/apache/camel/component/jslt/JsltEndpointConfigurer.java
@@ -29,6 +29,8 @@ public class JsltEndpointConfigurer extends PropertyConfigurerSupport implements
         case "contentCache": target.setContentCache(property(camelContext, boolean.class, value)); return true;
         case "lazystartproducer":
         case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+        case "mapbigdecimalasfloats":
+        case "mapBigDecimalAsFloats": target.setMapBigDecimalAsFloats(property(camelContext, boolean.class, value)); return true;
         case "prettyprint":
         case "prettyPrint": target.setPrettyPrint(property(camelContext, boolean.class, value)); return true;
         default: return false;
@@ -46,6 +48,8 @@ public class JsltEndpointConfigurer extends PropertyConfigurerSupport implements
         case "contentCache": return boolean.class;
         case "lazystartproducer":
         case "lazyStartProducer": return boolean.class;
+        case "mapbigdecimalasfloats":
+        case "mapBigDecimalAsFloats": return boolean.class;
         case "prettyprint":
         case "prettyPrint": return boolean.class;
         default: return null;
@@ -64,6 +68,8 @@ public class JsltEndpointConfigurer extends PropertyConfigurerSupport implements
         case "contentCache": return target.isContentCache();
         case "lazystartproducer":
         case "lazyStartProducer": return target.isLazyStartProducer();
+        case "mapbigdecimalasfloats":
+        case "mapBigDecimalAsFloats": return target.isMapBigDecimalAsFloats();
         case "prettyprint":
         case "prettyPrint": return target.isPrettyPrint();
         default: return null;
diff --git a/components/camel-jslt/src/generated/java/org/apache/camel/component/jslt/JsltEndpointUriFactory.java b/components/camel-jslt/src/generated/java/org/apache/camel/component/jslt/JsltEndpointUriFactory.java
index 2ee3518..06d8f7a 100644
--- a/components/camel-jslt/src/generated/java/org/apache/camel/component/jslt/JsltEndpointUriFactory.java
+++ b/components/camel-jslt/src/generated/java/org/apache/camel/component/jslt/JsltEndpointUriFactory.java
@@ -20,12 +20,13 @@ public class JsltEndpointUriFactory extends org.apache.camel.support.component.E
     private static final Set<String> PROPERTY_NAMES;
     private static final Set<String> SECRET_PROPERTY_NAMES;
     static {
-        Set<String> props = new HashSet<>(6);
+        Set<String> props = new HashSet<>(7);
         props.add("allowTemplateFromHeader");
         props.add("lazyStartProducer");
         props.add("prettyPrint");
         props.add("contentCache");
         props.add("allowContextMapAll");
+        props.add("mapBigDecimalAsFloats");
         props.add("resourceUri");
         PROPERTY_NAMES = Collections.unmodifiableSet(props);
         SECRET_PROPERTY_NAMES = Collections.emptySet();
diff --git a/components/camel-jslt/src/generated/resources/org/apache/camel/component/jslt/jslt.json b/components/camel-jslt/src/generated/resources/org/apache/camel/component/jslt/jslt.json
index 434b9cd..e2a5dd2 100644
--- a/components/camel-jslt/src/generated/resources/org/apache/camel/component/jslt/jslt.json
+++ b/components/camel-jslt/src/generated/resources/org/apache/camel/component/jslt/jslt.json
@@ -33,6 +33,7 @@
     "allowContextMapAll": { "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. [...]
     "allowTemplateFromHeader": { "kind": "parameter", "displayName": "Allow Template From Header", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential security vuln [...]
     "contentCache": { "kind": "parameter", "displayName": "Content Cache", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether to use resource content cache or not" },
+    "mapBigDecimalAsFloats": { "kind": "parameter", "displayName": "Map Big Decimal As Floats", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If true, the mapper will use the USE_BIG_DECIMAL_FOR_FLOATS in serialization features" },
     "prettyPrint": { "kind": "parameter", "displayName": "Pretty Print", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If true, JSON in output message is pretty printed." },
     "lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during sta [...]
   }
diff --git a/components/camel-jslt/src/main/docs/jslt-component.adoc b/components/camel-jslt/src/main/docs/jslt-component.adoc
index 28b75d0..7924a76 100644
--- a/components/camel-jslt/src/main/docs/jslt-component.adoc
+++ b/components/camel-jslt/src/main/docs/jslt-component.adoc
@@ -90,7 +90,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (5 parameters):
+=== Query Parameters (6 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -99,6 +99,7 @@ with the following path and query parameters:
 | *allowContextMapAll* (producer) | Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API. | false | boolean
 | *allowTemplateFromHeader* (producer) | Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential security vulnerability if the header is coming from a malicious user, so use this with care. | false | boolean
 | *contentCache* (producer) | Sets whether to use resource content cache or not | false | boolean
+| *mapBigDecimalAsFloats* (producer) | If true, the mapper will use the USE_BIG_DECIMAL_FOR_FLOATS in serialization features | false | boolean
 | *prettyPrint* (common) | If true, JSON in output message is pretty printed. | false | boolean
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 |===
diff --git a/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltEndpoint.java b/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltEndpoint.java
index fd5a926..f188f69 100644
--- a/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltEndpoint.java
+++ b/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltEndpoint.java
@@ -25,6 +25,7 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 
+import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -59,6 +60,8 @@ public class JsltEndpoint extends ResourceEndpoint {
     private boolean allowTemplateFromHeader;
     @UriParam(defaultValue = "false", label = "common")
     private boolean prettyPrint;
+    @UriParam(defaultValue = "false")
+    private boolean mapBigDecimalAsFloats;
 
     public JsltEndpoint() {
     }
@@ -145,6 +148,9 @@ public class JsltEndpoint extends ResourceEndpoint {
         JsonNode input;
 
         ObjectMapper objectMapper = new ObjectMapper();
+        if (isMapBigDecimalAsFloats()) {
+            objectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
+        }
         if (exchange.getIn().getBody() instanceof String) {
             input = objectMapper.readTree(exchange.getIn().getBody(String.class));
         } else if (exchange.getIn().getBody() instanceof InputStream) {
@@ -224,4 +230,14 @@ public class JsltEndpoint extends ResourceEndpoint {
         this.allowTemplateFromHeader = allowTemplateFromHeader;
     }
 
+    public boolean isMapBigDecimalAsFloats() {
+        return mapBigDecimalAsFloats;
+    }
+
+    /**
+     * If true, the mapper will use the USE_BIG_DECIMAL_FOR_FLOATS in serialization features
+     */
+    public void setMapBigDecimalAsFloats(boolean mapBigDecimalAsFloats) {
+        this.mapBigDecimalAsFloats = mapBigDecimalAsFloats;
+    }
 }
diff --git a/components/camel-jslt/src/test/java/org/apache/camel/component/jslt/JsltBigDecimalTest.java b/components/camel-jslt/src/test/java/org/apache/camel/component/jslt/JsltBigDecimalTest.java
new file mode 100644
index 0000000..219c164
--- /dev/null
+++ b/components/camel-jslt/src/test/java/org/apache/camel/component/jslt/JsltBigDecimalTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.component.jslt;
+
+import com.schibsted.spt.data.jslt.Expression;
+import com.schibsted.spt.data.jslt.Parser;
+import com.schibsted.spt.data.jslt.filters.JsltJsonFilter;
+import com.schibsted.spt.data.jslt.filters.JsonFilter;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.apache.camel.util.IOHelper;
+import org.junit.jupiter.api.Test;
+
+public class JsltBigDecimalTest extends CamelTestSupport {
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+
+        context.getPropertiesComponent().setLocation("ref:prop");
+
+        context.getComponent("jslt", JsltComponent.class).setObjectFilter(createObjectFilter());
+
+        return context;
+    }
+
+    @Test
+    public void testJsltAsInputStream() throws Exception {
+        getMockEndpoint("mock:result").expectedMinimumMessageCount(1);
+        getMockEndpoint("mock:result").expectedBodiesReceived(
+                IOHelper.loadText(
+                        ResourceHelper.resolveMandatoryResourceAsInputStream(
+                                context, "org/apache/camel/component/jslt/useBigDecimal/output.json"))
+                        .trim() // Remove the last newline added by IOHelper.loadText()
+        );
+
+        sendBody("direct://start",
+                ResourceHelper.resolveMandatoryResourceAsInputStream(
+                        context, "org/apache/camel/component/jslt/useBigDecimal/input.json"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    private JsonFilter createObjectFilter() {
+        Expression filterExpression = Parser.compileString(". != null and . != {}");
+        return new JsltJsonFilter(filterExpression);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct://start")
+                        .to("jslt:org/apache/camel/component/jslt/useBigDecimal/transformation.json?mapBigDecimalAsFloats=true&prettyPrint=true")
+                        .to("mock:result");
+            }
+        };
+    }
+}
diff --git a/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/useBigDecimal/input.json b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/useBigDecimal/input.json
new file mode 100644
index 0000000..ff12b12
--- /dev/null
+++ b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/useBigDecimal/input.json
@@ -0,0 +1,13 @@
+{
+  "name": {
+    "firstname": "foo"
+  },
+  "list": [
+    {
+      "value": 321321321.123657891234
+    },
+    {
+      "value": 11321321.12
+    }
+  ]
+}
diff --git a/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/useBigDecimal/output.json b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/useBigDecimal/output.json
new file mode 100644
index 0000000..87359c9
--- /dev/null
+++ b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/useBigDecimal/output.json
@@ -0,0 +1,10 @@
+{
+  "name" : {
+    "firstname" : "foo"
+  },
+  "list" : [ {
+    "value" : 321321321.123657891234
+  }, {
+    "value" : 11321321.12
+  } ]
+}
diff --git a/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/useBigDecimal/transformation.json b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/useBigDecimal/transformation.json
new file mode 100644
index 0000000..330d5e1
--- /dev/null
+++ b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/useBigDecimal/transformation.json
@@ -0,0 +1,3 @@
+{
+  * : .
+}
diff --git a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/JsltEndpointBuilderFactory.java b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/JsltEndpointBuilderFactory.java
index 289821d..f15bdb9 100644
--- a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/JsltEndpointBuilderFactory.java
+++ b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/JsltEndpointBuilderFactory.java
@@ -147,6 +147,41 @@ public interface JsltEndpointBuilderFactory {
             return this;
         }
         /**
+         * If true, the mapper will use the USE_BIG_DECIMAL_FOR_FLOATS in
+         * serialization features.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: producer
+         * 
+         * @param mapBigDecimalAsFloats the value to set
+         * @return the dsl builder
+         */
+        default JsltEndpointBuilder mapBigDecimalAsFloats(
+                boolean mapBigDecimalAsFloats) {
+            doSetProperty("mapBigDecimalAsFloats", mapBigDecimalAsFloats);
+            return this;
+        }
+        /**
+         * If true, the mapper will use the USE_BIG_DECIMAL_FOR_FLOATS in
+         * serialization features.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: producer
+         * 
+         * @param mapBigDecimalAsFloats the value to set
+         * @return the dsl builder
+         */
+        default JsltEndpointBuilder mapBigDecimalAsFloats(
+                String mapBigDecimalAsFloats) {
+            doSetProperty("mapBigDecimalAsFloats", mapBigDecimalAsFloats);
+            return this;
+        }
+        /**
          * If true, JSON in output message is pretty printed.
          * 
          * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
diff --git a/docs/components/modules/ROOT/pages/jslt-component.adoc b/docs/components/modules/ROOT/pages/jslt-component.adoc
index ce133e6..245457f 100644
--- a/docs/components/modules/ROOT/pages/jslt-component.adoc
+++ b/docs/components/modules/ROOT/pages/jslt-component.adoc
@@ -92,7 +92,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (5 parameters):
+=== Query Parameters (6 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -101,6 +101,7 @@ with the following path and query parameters:
 | *allowContextMapAll* (producer) | Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API. | false | boolean
 | *allowTemplateFromHeader* (producer) | Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential security vulnerability if the header is coming from a malicious user, so use this with care. | false | boolean
 | *contentCache* (producer) | Sets whether to use resource content cache or not | false | boolean
+| *mapBigDecimalAsFloats* (producer) | If true, the mapper will use the USE_BIG_DECIMAL_FOR_FLOATS in serialization features | false | boolean
 | *prettyPrint* (common) | If true, JSON in output message is pretty printed. | false | boolean
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 |===