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

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


The following commit(s) were added to refs/heads/main by this push:
     new 3404573  CAMEL-16913: convertBodyTo EIP - Allow to turn off mandatory.
3404573 is described below

commit 34045738de92fc58eea935639468b46338d2b577
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Thu Sep 2 15:36:46 2021 +0200

    CAMEL-16913: convertBodyTo EIP - Allow to turn off mandatory.
---
 .../org/apache/camel/model/convertBodyTo.json      |  1 +
 .../org/apache/camel/model/dynamicRouter.json      |  2 +-
 .../apache/camel/model/ConvertBodyDefinition.java  | 22 ++++++++++++++++++++++
 .../camel/model/DynamicRouterDefinition.java       |  1 +
 .../apache/camel/model/ProcessorDefinition.java    | 14 +++++++++++++-
 .../apache/camel/reifier/ConvertBodyReifier.java   |  6 +++++-
 .../apache/camel/processor/ConvertBodyTest.java    | 21 +++++++++++++++++++++
 .../support/processor/ConvertBodyProcessor.java    | 17 ++++++++++++++++-
 .../java/org/apache/camel/xml/in/ModelParser.java  |  1 +
 .../dsl/yaml/deserializers/ModelDeserializers.java |  8 +++++++-
 .../src/generated/resources/camel-yaml-dsl.json    |  5 ++++-
 11 files changed, 92 insertions(+), 6 deletions(-)

diff --git 
a/core/camel-core-model/src/generated/resources/org/apache/camel/model/convertBodyTo.json
 
b/core/camel-core-model/src/generated/resources/org/apache/camel/model/convertBodyTo.json
index 448e03b..4b84803 100644
--- 
a/core/camel-core-model/src/generated/resources/org/apache/camel/model/convertBodyTo.json
+++ 
b/core/camel-core-model/src/generated/resources/org/apache/camel/model/convertBodyTo.json
@@ -12,6 +12,7 @@
   },
   "properties": {
     "type": { "kind": "attribute", "displayName": "Type", "required": true, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "description": "The java type to convert 
to" },
+    "mandatory": { "kind": "attribute", "displayName": "Mandatory", 
"required": false, "type": "boolean", "javaType": "java.lang.Boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "When mandatory then the conversion must return a value (cannot 
be null), if this is not possible then NoTypeConversionAvailableException is 
thrown. Setting this to false could mean conversion is not possible and the 
value is null." },
     "charset": { "kind": "attribute", "displayName": "Charset", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use a specific charset 
when converting" },
     "id": { "kind": "attribute", "displayName": "Id", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the id of this node" 
},
     "description": { "kind": "element", "displayName": "Description", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.model.DescriptionDefinition", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the description of 
this node" }
diff --git 
a/core/camel-core-model/src/generated/resources/org/apache/camel/model/dynamicRouter.json
 
b/core/camel-core-model/src/generated/resources/org/apache/camel/model/dynamicRouter.json
index 67431d9..345f21d 100644
--- 
a/core/camel-core-model/src/generated/resources/org/apache/camel/model/dynamicRouter.json
+++ 
b/core/camel-core-model/src/generated/resources/org/apache/camel/model/dynamicRouter.json
@@ -13,7 +13,7 @@
   "properties": {
     "expression": { "kind": "expression", "displayName": "Expression", 
"required": true, "type": "object", "javaType": 
"org.apache.camel.model.language.ExpressionDefinition", "oneOf": [ "constant", 
"csimple", "datasonnet", "exchangeProperty", "groovy", "header", "hl7terser", 
"joor", "jsonpath", "language", "method", "mvel", "ognl", "ref", "simple", 
"spel", "tokenize", "xpath", "xquery", "xtokenize" ], "deprecated": false, 
"autowired": false, "secret": false, "description": "Expression to [...]
     "uriDelimiter": { "kind": "attribute", "displayName": "Uri Delimiter", 
"required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": ",", 
"description": "Sets the uri delimiter to use" },
-    "ignoreInvalidEndpoints": { "kind": "attribute", "displayName": "Ignore 
Invalid Endpoints", "required": false, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"description": "Ignore the invalidate endpoint exception when try to create a 
producer with that endpoint" },
+    "ignoreInvalidEndpoints": { "kind": "attribute", "displayName": "Ignore 
Invalid Endpoints", "required": false, "type": "boolean", "javaType": 
"java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Ignore the invalidate endpoint exception 
when try to create a producer with that endpoint" },
     "cacheSize": { "kind": "attribute", "displayName": "Cache Size", 
"required": false, "type": "integer", "javaType": "java.lang.Integer", 
"deprecated": false, "autowired": false, "secret": false, "description": "Sets 
the maximum size used by the org.apache.camel.spi.ProducerCache which is used 
to cache and reuse producers when using this dynamic router, when uris are 
reused. Beware that when using dynamic endpoints then it affects how well the 
cache can be utilized. If each dynamic end [...]
     "id": { "kind": "attribute", "displayName": "Id", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the id of this node" 
},
     "description": { "kind": "element", "displayName": "Description", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.model.DescriptionDefinition", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the description of 
this node" }
diff --git 
a/core/camel-core-model/src/main/java/org/apache/camel/model/ConvertBodyDefinition.java
 
b/core/camel-core-model/src/main/java/org/apache/camel/model/ConvertBodyDefinition.java
index e0a387f..9795198 100644
--- 
a/core/camel-core-model/src/main/java/org/apache/camel/model/ConvertBodyDefinition.java
+++ 
b/core/camel-core-model/src/main/java/org/apache/camel/model/ConvertBodyDefinition.java
@@ -34,6 +34,9 @@ public class ConvertBodyDefinition extends 
NoOutputDefinition<ConvertBodyDefinit
     @XmlAttribute(required = true)
     private String type;
     @XmlAttribute
+    @Metadata(javaType = "java.lang.Boolean", defaultValue = "true")
+    private String mandatory;
+    @XmlAttribute
     private String charset;
     @XmlTransient
     private Class<?> typeClass;
@@ -50,6 +53,12 @@ public class ConvertBodyDefinition extends 
NoOutputDefinition<ConvertBodyDefinit
         setType(typeClass.getCanonicalName());
     }
 
+    public ConvertBodyDefinition(Class<?> typeClass, boolean mandatory) {
+        setTypeClass(typeClass);
+        setType(typeClass.getCanonicalName());
+        setMandatory(mandatory ? "true" : "false");
+    }
+
     public ConvertBodyDefinition(Class<?> typeClass, String charset) {
         setTypeClass(typeClass);
         setType(typeClass.getCanonicalName());
@@ -100,4 +109,17 @@ public class ConvertBodyDefinition extends 
NoOutputDefinition<ConvertBodyDefinit
     public void setCharset(String charset) {
         this.charset = charset;
     }
+
+    public String getMandatory() {
+        return mandatory;
+    }
+
+    /**
+     * When mandatory then the conversion must return a value (cannot be 
null), if this is not possible then
+     * NoTypeConversionAvailableException is thrown. Setting this to false 
could mean conversion is not possible and the
+     * value is null.
+     */
+    public void setMandatory(String mandatory) {
+        this.mandatory = mandatory;
+    }
 }
diff --git 
a/core/camel-core-model/src/main/java/org/apache/camel/model/DynamicRouterDefinition.java
 
b/core/camel-core-model/src/main/java/org/apache/camel/model/DynamicRouterDefinition.java
index d70289b..36a85b1 100644
--- 
a/core/camel-core-model/src/main/java/org/apache/camel/model/DynamicRouterDefinition.java
+++ 
b/core/camel-core-model/src/main/java/org/apache/camel/model/DynamicRouterDefinition.java
@@ -42,6 +42,7 @@ public class DynamicRouterDefinition<Type extends 
ProcessorDefinition<Type>> ext
     @Metadata(defaultValue = ",")
     private String uriDelimiter;
     @XmlAttribute
+    @Metadata(javaType = "java.lang.Boolean")
     private String ignoreInvalidEndpoints;
     @XmlAttribute
     @Metadata(javaType = "java.lang.Integer")
diff --git 
a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
 
b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
index 6d2fe06..8efa326 100644
--- 
a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
+++ 
b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
@@ -2747,8 +2747,20 @@ public abstract class ProcessorDefinition<Type extends 
ProcessorDefinition<Type>
     /**
      * Converts the IN message body to the specified type
      *
+     * @param  type      the type to convert to
+     * @param  mandatory whether to use mandatory type conversion or not
+     * @return           the builder
+     */
+    public Type convertBodyTo(Class<?> type, boolean mandatory) {
+        addOutput(new ConvertBodyDefinition(type, mandatory));
+        return asType();
+    }
+
+    /**
+     * Converts the IN message body to the specified type
+     *
      * @param  type    the type to convert to
-     * @param  charset the charset to use by type converters (not all 
converters support specifc charset)
+     * @param  charset the charset to use by type converters (not all 
converters support specific charset)
      * @return         the builder
      */
     public Type convertBodyTo(Class<?> type, String charset) {
diff --git 
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConvertBodyReifier.java
 
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConvertBodyReifier.java
index 78fa218..441600d 100644
--- 
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConvertBodyReifier.java
+++ 
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConvertBodyReifier.java
@@ -35,7 +35,11 @@ public class ConvertBodyReifier extends 
ProcessorReifier<ConvertBodyDefinition>
     public Processor createProcessor() throws Exception {
         Class<?> typeClass = parse(Class.class, or(definition.getTypeClass(), 
parseString(definition.getType())));
         String charset = validateCharset(parseString(definition.getCharset()));
-        return new ConvertBodyProcessor(typeClass, charset);
+        boolean mandatory = true;
+        if (definition.getMandatory() != null) {
+            mandatory = parseBoolean(definition.getMandatory(), true);
+        }
+        return new ConvertBodyProcessor(typeClass, charset, mandatory);
     }
 
     public static String validateCharset(String charset) throws 
UnsupportedCharsetException {
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/processor/ConvertBodyTest.java 
b/core/camel-core/src/test/java/org/apache/camel/processor/ConvertBodyTest.java
index 54d6586..e8a8ab1 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/processor/ConvertBodyTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/processor/ConvertBodyTest.java
@@ -24,6 +24,7 @@ import java.util.Locale;
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Exchange;
 import org.apache.camel.InvalidPayloadException;
+import org.apache.camel.NoTypeConversionAvailableException;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.builder.ExchangeBuilder;
 import org.apache.camel.builder.RouteBuilder;
@@ -100,6 +101,25 @@ public class ConvertBodyTest extends ContextTestSupport {
     }
 
     @Test
+    public void testConvertToIntegerNotMandatory() throws Exception {
+        // mandatory should fail
+        try {
+            template.sendBody("direct:start", Double.NaN);
+            fail();
+        } catch (Exception e) {
+            assertIsInstanceOf(NoTypeConversionAvailableException.class, 
e.getCause().getCause());
+        }
+
+        // optional should cause null body
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+        getMockEndpoint("mock:result").message(0).body().isNull();
+
+        template.sendBody("direct:optional", Double.NaN);
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
     public void testConvertNullBody() throws Exception {
         MockEndpoint result = getMockEndpoint("mock:result");
         result.expectedMessageCount(1);
@@ -189,6 +209,7 @@ public class ConvertBodyTest extends ContextTestSupport {
         return new RouteBuilder() {
             public void configure() {
                 
from("direct:start").convertBodyTo(Integer.class).to("mock:result");
+                from("direct:optional").convertBodyTo(Integer.class, 
false).to("mock:result");
                 
from("direct:invalid").convertBodyTo(Date.class).to("mock:result");
                 from("direct:charset").convertBodyTo(byte[].class, 
"iso-8859-1").to("mock:result");
                 from("direct:charset2").convertBodyTo(byte[].class, 
"utf-16").to("mock:result");
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/processor/ConvertBodyProcessor.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/processor/ConvertBodyProcessor.java
index 259f348..787c0f5 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/processor/ConvertBodyProcessor.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/processor/ConvertBodyProcessor.java
@@ -42,17 +42,27 @@ public class ConvertBodyProcessor extends ServiceSupport 
implements AsyncProcess
     private String routeId;
     private final Class<?> type;
     private final String charset;
+    private final boolean mandatory;
 
     public ConvertBodyProcessor(Class<?> type) {
         ObjectHelper.notNull(type, "type", this);
         this.type = type;
         this.charset = null;
+        this.mandatory = true;
     }
 
     public ConvertBodyProcessor(Class<?> type, String charset) {
         ObjectHelper.notNull(type, "type", this);
         this.type = type;
         this.charset = IOHelper.normalizeCharset(charset);
+        this.mandatory = true;
+    }
+
+    public ConvertBodyProcessor(Class<?> type, String charset, boolean 
mandatory) {
+        ObjectHelper.notNull(type, "type", this);
+        this.type = type;
+        this.charset = IOHelper.normalizeCharset(charset);
+        this.mandatory = mandatory;
     }
 
     @Override
@@ -103,7 +113,12 @@ public class ConvertBodyProcessor extends ServiceSupport 
implements AsyncProcess
             exchange.setProperty(ExchangePropertyKey.CHARSET_NAME, charset);
         }
         // use mandatory conversion
-        Object value = old.getMandatoryBody(type);
+        Object value;
+        if (mandatory) {
+            value = old.getMandatoryBody(type);
+        } else {
+            value = old.getBody(type);
+        }
 
         // create a new message container so we do not drag specialized 
message objects along
         // but that is only needed if the old message is a specialized message
diff --git 
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java 
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index b33981d..3026944 100644
--- 
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ 
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -285,6 +285,7 @@ public class ModelParser extends BaseParser {
         return doParse(new ConvertBodyDefinition(), (def, key, val) -> {
             switch (key) {
                 case "charset": def.setCharset(val); break;
+                case "mandatory": def.setMandatory(val); break;
                 case "type": def.setType(val); break;
                 default: return 
processorDefinitionAttributeHandler().accept(def, key, val);
             }
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index 56ecd7b..e50ac3c 100644
--- 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -2126,6 +2126,7 @@ public final class ModelDeserializers extends 
YamlDeserializerSupport {
             properties = {
                     @YamlProperty(name = "charset", type = "string"),
                     @YamlProperty(name = "inherit-error-handler", type = 
"boolean"),
+                    @YamlProperty(name = "mandatory", type = "boolean"),
                     @YamlProperty(name = "type", type = "string", required = 
true)
             }
     )
@@ -2158,6 +2159,11 @@ public final class ModelDeserializers extends 
YamlDeserializerSupport {
                     
target.setInheritErrorHandler(java.lang.Boolean.valueOf(val));
                     break;
                 }
+                case "mandatory": {
+                    String val = asText(node);
+                    target.setMandatory(val);
+                    break;
+                }
                 case "type": {
                     String val = asText(node);
                     target.setType(val);
@@ -4191,7 +4197,7 @@ public final class ModelDeserializers extends 
YamlDeserializerSupport {
                     @YamlProperty(name = "__extends", type = 
"object:org.apache.camel.model.language.ExpressionDefinition"),
                     @YamlProperty(name = "cache-size", type = "number"),
                     @YamlProperty(name = "expression", type = 
"object:org.apache.camel.model.language.ExpressionDefinition"),
-                    @YamlProperty(name = "ignore-invalid-endpoints", type = 
"string"),
+                    @YamlProperty(name = "ignore-invalid-endpoints", type = 
"boolean"),
                     @YamlProperty(name = "inherit-error-handler", type = 
"boolean"),
                     @YamlProperty(name = "uri-delimiter", type = "string")
             }
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json 
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
index 10e7ac6..d5b780e 100644
--- 
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
@@ -576,6 +576,9 @@
             "inherit-error-handler" : {
               "type" : "boolean"
             },
+            "mandatory" : {
+              "type" : "boolean"
+            },
             "type" : {
               "type" : "string"
             }
@@ -642,7 +645,7 @@
             "$ref" : 
"#/items/definitions/org.apache.camel.model.language.ExpressionDefinition"
           },
           "ignore-invalid-endpoints" : {
-            "type" : "string"
+            "type" : "boolean"
           },
           "inherit-error-handler" : {
             "type" : "boolean"

Reply via email to