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

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

commit 2bcbf94bb53b186508f938ba7afc5a1d123dc16b
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Apr 2 17:27:43 2020 +0200

    CAMEL-14820: rest-dsl - Configuring JSon and JAXB additional properties 
uses reflection. Now they use configurer
---
 .../converter/jaxb/JaxbDataFormatConfigurer.java   |  2 +
 .../org/apache/camel/converter/jaxb/jaxb.json      |  1 +
 .../camel-jaxb/src/main/docs/jaxb-dataformat.adoc  |  3 +-
 .../camel/converter/jaxb/JaxbDataFormat.java       | 31 +++++++++++--
 .../jaxb/JaxbRestBindingJaxbDataFormatFactory.java | 54 ++++++++++++----------
 .../apache/camel/component/rest/RestProducer.java  | 45 ++++++++++--------
 .../rest/RestUndertowProducerGetPojoTest.java      | 16 ++++++-
 .../impl/engine/DefaultBeanIntrospection.java      |  5 ++
 .../org/apache/camel/model/dataformat/jaxb.json    |  1 +
 .../src/main/docs/modules/eips/pages/to-eip.adoc   |  2 +-
 .../camel/model/dataformat/JaxbDataFormat.java     | 14 ++++++
 .../reifier/dataformat/JaxbDataFormatReifier.java  |  1 +
 .../camel/support/PropertyBindingSupport.java      |  5 +-
 .../java/org/apache/camel/xml/in/ModelParser.java  |  1 +
 14 files changed, 127 insertions(+), 54 deletions(-)

diff --git 
a/components/camel-jaxb/src/generated/java/org/apache/camel/converter/jaxb/JaxbDataFormatConfigurer.java
 
b/components/camel-jaxb/src/generated/java/org/apache/camel/converter/jaxb/JaxbDataFormatConfigurer.java
index e33f75c..81546ee 100644
--- 
a/components/camel-jaxb/src/generated/java/org/apache/camel/converter/jaxb/JaxbDataFormatConfigurer.java
+++ 
b/components/camel-jaxb/src/generated/java/org/apache/camel/converter/jaxb/JaxbDataFormatConfigurer.java
@@ -20,6 +20,8 @@ public class JaxbDataFormatConfigurer extends 
PropertyConfigurerSupport implemen
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "contextpath":
         case "contextPath": dataformat.setContextPath(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "contextpathisclassname":
+        case "contextPathIsClassName": 
dataformat.setContextPathIsClassName(property(camelContext, boolean.class, 
value)); return true;
         case "schema": dataformat.setSchema(property(camelContext, 
java.lang.String.class, value)); return true;
         case "schemaseveritylevel":
         case "schemaSeverityLevel": 
dataformat.setSchemaSeverityLevel(property(camelContext, int.class, value)); 
return true;
diff --git 
a/components/camel-jaxb/src/generated/resources/org/apache/camel/converter/jaxb/jaxb.json
 
b/components/camel-jaxb/src/generated/resources/org/apache/camel/converter/jaxb/jaxb.json
index d9e7ddc..37e2bc0 100644
--- 
a/components/camel-jaxb/src/generated/resources/org/apache/camel/converter/jaxb/jaxb.json
+++ 
b/components/camel-jaxb/src/generated/resources/org/apache/camel/converter/jaxb/jaxb.json
@@ -17,6 +17,7 @@
   },
   "properties": {
     "contextPath": { "kind": "attribute", "displayName": "Context Path", 
"required": true, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "secret": false, "description": "Package name where your 
JAXB classes are located." },
+    "contextPathIsClassName": { "kind": "attribute", "displayName": "Context 
Path Is Class Name", "required": false, "type": "boolean", "javaType": 
"java.lang.Boolean", "deprecated": false, "secret": false, "defaultValue": 
false, "description": "This can be set to true to mark that the contextPath is 
referring to a classname and not a package name." },
     "schema": { "kind": "attribute", "displayName": "Schema", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"secret": false, "description": "To validate against an existing schema. Your 
can use the prefix classpath:, file: or http: to specify how the resource 
should by resolved. You can separate multiple schema files by using the ',' 
character." },
     "schemaSeverityLevel": { "kind": "attribute", "displayName": "Schema 
Severity Level", "required": false, "type": "enum", "javaType": 
"java.lang.Integer", "enum": [ "0", "1", "2" ], "deprecated": false, "secret": 
false, "defaultValue": "0", "description": "Sets the schema severity level to 
use when validating against a schema. This level determines the minimum 
severity error that triggers JAXB to stop continue parsing. The default value 
of 0 (warning) means that any error (warning, er [...]
     "prettyPrint": { "kind": "attribute", "displayName": "Pretty Print", 
"required": false, "type": "boolean", "javaType": "java.lang.Boolean", 
"deprecated": false, "secret": false, "defaultValue": false, "description": "To 
enable pretty printing output nicely formatted. Is by default false." },
diff --git a/components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc 
b/components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc
index 66e2f92..8674a82 100644
--- a/components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc
+++ b/components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc
@@ -11,7 +11,7 @@ payload.
 == Options
 
 // dataformat options: START
-The JAXB dataformat supports 18 options, which are listed below.
+The JAXB dataformat supports 19 options, which are listed below.
 
 
 
@@ -19,6 +19,7 @@ The JAXB dataformat supports 18 options, which are listed 
below.
 |===
 | Name | Default | Java Type | Description
 | contextPath |  | String | Package name where your JAXB classes are located.
+| contextPathIsClassName | false | Boolean | This can be set to true to mark 
that the contextPath is referring to a classname and not a package name.
 | schema |  | String | To validate against an existing schema. Your can use 
the prefix classpath:, file: or http: to specify how the resource should by 
resolved. You can separate multiple schema files by using the ',' character.
 | schemaSeverityLevel | 0 | Integer | Sets the schema severity level to use 
when validating against a schema. This level determines the minimum severity 
error that triggers JAXB to stop continue parsing. The default value of 0 
(warning) means that any error (warning, error or fatal error) will trigger 
JAXB to stop. There are the following three levels: 0=warning, 1=error, 2=fatal 
error. The value can be one of: 0, 1, 2
 | prettyPrint | false | Boolean | To enable pretty printing output nicely 
formatted. Is by default false.
diff --git 
a/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java
 
b/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java
index 041d448..5aa4c46 100644
--- 
a/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java
+++ 
b/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java
@@ -83,6 +83,7 @@ public class JaxbDataFormat extends ServiceSupport implements 
DataFormat, DataFo
     private JAXBContext context;
     private JAXBIntrospector introspector;
     private String contextPath;
+    private boolean contextPathIsClassName;
     private String schema;
     private int schemaSeverityLevel; // 0 = warning, 1 = error, 2 = fatal
     private String schemaLocation;
@@ -349,6 +350,14 @@ public class JaxbDataFormat extends ServiceSupport 
implements DataFormat, DataFo
         this.contextPath = contextPath;
     }
 
+    public boolean isContextPathIsClassName() {
+        return contextPathIsClassName;
+    }
+
+    public void setContextPathIsClassName(boolean contextPathIsClassName) {
+        this.contextPathIsClassName = contextPathIsClassName;
+    }
+
     public SchemaFactory getSchemaFactory() {
         if (schemaFactory == null) {
             return getOrCreateSchemaFactory();
@@ -522,17 +531,29 @@ public class JaxbDataFormat extends ServiceSupport 
implements DataFormat, DataFo
     /**
      * Strategy to create JAXB context
      */
-    protected JAXBContext createContext() throws JAXBException {
+    protected JAXBContext createContext() throws Exception {
         if (contextPath != null) {
             // prefer to use application class loader which is most likely to 
be able to
             // load the class which has been JAXB annotated
             ClassLoader cl = camelContext.getApplicationContextClassLoader();
             if (cl != null) {
-                LOG.debug("Creating JAXBContext with contextPath: " + 
contextPath + " and ApplicationContextClassLoader: " + cl);
-                return JAXBContext.newInstance(contextPath, cl);
+                if (contextPathIsClassName) {
+                    LOG.debug("Creating JAXBContext with className: " + 
contextPath + " and ApplicationContextClassLoader: " + cl);
+                    Class clazz = 
camelContext.getClassResolver().resolveMandatoryClass(contextPath, cl);
+                    return JAXBContext.newInstance(clazz);
+                } else {
+                    LOG.debug("Creating JAXBContext with contextPath: " + 
contextPath + " and ApplicationContextClassLoader: " + cl);
+                    return JAXBContext.newInstance(contextPath, cl);
+                }
             } else {
-                LOG.debug("Creating JAXBContext with contextPath: {}", 
contextPath);
-                return JAXBContext.newInstance(contextPath);
+                if (contextPathIsClassName) {
+                    LOG.debug("Creating JAXBContext with className: {}", 
contextPath);
+                    Class clazz = 
camelContext.getClassResolver().resolveMandatoryClass(contextPath);
+                    return JAXBContext.newInstance(clazz);
+                } else {
+                    LOG.debug("Creating JAXBContext with contextPath: {}", 
contextPath);
+                    return JAXBContext.newInstance(contextPath);
+                }
             }
         } else {
             LOG.debug("Creating JAXBContext");
diff --git 
a/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbRestBindingJaxbDataFormatFactory.java
 
b/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbRestBindingJaxbDataFormatFactory.java
index 44f0846..4ec05a0 100644
--- 
a/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbRestBindingJaxbDataFormatFactory.java
+++ 
b/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbRestBindingJaxbDataFormatFactory.java
@@ -19,11 +19,10 @@ package org.apache.camel.converter.jaxb;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.xml.bind.JAXBContext;
-
 import org.apache.camel.CamelContext;
 import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.PropertyConfigurer;
 import org.apache.camel.spi.RestBindingJaxbDataFormatFactory;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.spi.annotations.JdkService;
@@ -37,38 +36,43 @@ public class JaxbRestBindingJaxbDataFormatFactory 
implements RestBindingJaxbData
 
     @Override
     public void setupJaxb(CamelContext camelContext, RestConfiguration config, 
String type, String outType, DataFormat jaxb, DataFormat outJaxb) throws 
Exception {
-        Class<?> clazz = null;
+        // lookup configurer
+        PropertyConfigurer configurer = 
camelContext.adapt(ExtendedCamelContext.class).getConfigurerResolver().resolvePropertyConfigurer("jaxb-dataformat-configurer",
 camelContext);
+        if (configurer == null) {
+            throw new IllegalStateException("Cannot find configurer for 
dataformat: jaxb");
+        }
+
+        PropertyBindingSupport.Builder builder = PropertyBindingSupport.build()
+                .withCamelContext(camelContext)
+                .withConfigurer(configurer)
+                .withTarget(jaxb);
         if (type != null) {
             String typeName = type.endsWith("[]") ? type.substring(0, 
type.length() - 2) : type;
-            clazz = 
camelContext.getClassResolver().resolveMandatoryClass(typeName);
-        }
-        if (clazz != null) {
-            JAXBContext jc = JAXBContext.newInstance(clazz);
-            setJaxbContext(camelContext, jaxb, jc);
+            builder.withProperty("contextPath", typeName);
+            builder.withProperty("contextPathIsClassName", "true");
         }
-        setAdditionalConfiguration(camelContext, config, jaxb, "xml.in.");
+        setAdditionalConfiguration(config, "xml.in.", builder);
+        builder.bind();
 
-        Class<?> outClazz = null;
+        builder = PropertyBindingSupport.build()
+                .withCamelContext(camelContext)
+                .withConfigurer(configurer)
+                .withTarget(outJaxb);
         if (outType != null) {
             String typeName = outType.endsWith("[]") ? outType.substring(0, 
outType.length() - 2) : outType;
-            outClazz = 
camelContext.getClassResolver().resolveMandatoryClass(typeName);
-        }
-        if (outClazz != null) {
-            JAXBContext jc = JAXBContext.newInstance(outClazz);
-            setJaxbContext(camelContext, outJaxb, jc);
-        } else if (clazz != null) {
+            builder.withProperty("contextPath", typeName);
+            builder.withProperty("contextPathIsClassName", "true");
+        } else if (type != null) {
             // fallback and use the context from the input
-            JAXBContext jc = JAXBContext.newInstance(clazz);
-            setJaxbContext(camelContext, outJaxb, jc);
+            String typeName = type.endsWith("[]") ? type.substring(0, 
type.length() - 2) : type;
+            builder.withProperty("contextPath", typeName);
+            builder.withProperty("contextPathIsClassName", "true");
         }
-        setAdditionalConfiguration(camelContext, config, outJaxb, "xml.out.");
-    }
-
-    private void setJaxbContext(CamelContext camelContext, DataFormat jaxb, 
JAXBContext jc) throws Exception {
-        
camelContext.adapt(ExtendedCamelContext.class).getBeanIntrospection().setProperty(camelContext,
 jaxb, "context", jc);
+        setAdditionalConfiguration(config, "xml.out.", builder);
+        builder.bind();
     }
 
-    private void setAdditionalConfiguration(CamelContext camelContext, 
RestConfiguration config, DataFormat dataFormat, String prefix) throws 
Exception {
+    private void setAdditionalConfiguration(RestConfiguration config, String 
prefix, PropertyBindingSupport.Builder builder) throws Exception {
         if (config.getDataFormatProperties() != null && 
!config.getDataFormatProperties().isEmpty()) {
             // must use a copy as otherwise the options gets removed during
             // introspection setProperties
@@ -93,7 +97,7 @@ public class JaxbRestBindingJaxbDataFormatFactory implements 
RestBindingJaxbData
                 }
             }
 
-            PropertyBindingSupport.build().bind(camelContext, dataFormat, 
copy);
+            builder.withProperties(copy);
         }
     }
 
diff --git 
a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestProducer.java
 
b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestProducer.java
index 2c92c4c..2f8be9f 100644
--- 
a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestProducer.java
+++ 
b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestProducer.java
@@ -32,8 +32,8 @@ import org.apache.camel.Exchange;
 import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.Message;
 import org.apache.camel.Producer;
-import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.PropertyConfigurer;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.support.AsyncProcessorConverterHelper;
 import org.apache.camel.support.DefaultAsyncProducer;
@@ -302,29 +302,36 @@ public class RestProducer extends DefaultAsyncProducer {
             throw new IllegalArgumentException("JSon DataFormat " + name + " 
not found.");
         }
 
-        BeanIntrospection beanIntrospection = 
camelContext.adapt(ExtendedCamelContext.class).getBeanIntrospection();
         if (json != null) {
-            Class<?> clazz = null;
+            // lookup configurer
+            PropertyConfigurer configurer = 
camelContext.adapt(ExtendedCamelContext.class).getConfigurerResolver().resolvePropertyConfigurer(name
 + "-dataformat-configurer", camelContext);
+            if (configurer == null) {
+                throw new IllegalStateException("Cannot find configurer for 
dataformat: " + name);
+            }
+
+            PropertyBindingSupport.Builder builder = 
PropertyBindingSupport.build()
+                    .withCamelContext(camelContext)
+                    .withConfigurer(configurer)
+                    .withTarget(json);
             if (type != null) {
                 String typeName = type.endsWith("[]") ? type.substring(0, 
type.length() - 2) : type;
-                clazz = 
camelContext.getClassResolver().resolveMandatoryClass(typeName);
+                builder.withProperty("unmarshalTypeName", typeName);
+                builder.withProperty("useList", type.endsWith("[]"));
             }
-            if (clazz != null) {
-                beanIntrospection.setProperty(camelContext, json, 
"unmarshalType", clazz);
-                beanIntrospection.setProperty(camelContext, json, "useList", 
type.endsWith("[]"));
-            }
-            setAdditionalConfiguration(configuration, camelContext, json, 
"json.in.");
+            setAdditionalConfiguration(configuration, "json.in.", builder);
+            builder.bind();
 
-            Class<?> outClazz = null;
+            builder = PropertyBindingSupport.build()
+                    .withCamelContext(camelContext)
+                    .withConfigurer(configurer)
+                    .withTarget(outJson);
             if (outType != null) {
                 String typeName = outType.endsWith("[]") ? 
outType.substring(0, outType.length() - 2) : outType;
-                outClazz = 
camelContext.getClassResolver().resolveMandatoryClass(typeName);
-            }
-            if (outClazz != null) {
-                beanIntrospection.setProperty(camelContext, outJson, 
"unmarshalType", outClazz);
-                beanIntrospection.setProperty(camelContext, outJson, 
"useList", outType.endsWith("[]"));
+                builder.withProperty("unmarshalTypeName", typeName);
+                builder.withProperty("useList", outType.endsWith("[]"));
             }
-            setAdditionalConfiguration(configuration, camelContext, outJson, 
"json.out.");
+            setAdditionalConfiguration(configuration, "json.out.", builder);
+            builder.bind();
         }
 
         // setup xml data format
@@ -356,8 +363,7 @@ public class RestProducer extends DefaultAsyncProducer {
         return new RestProducerBindingProcessor(producer, camelContext, json, 
jaxb, outJson, outJaxb, mode, skip, outType);
     }
 
-    private void setAdditionalConfiguration(RestConfiguration config, 
CamelContext context,
-                                            DataFormat dataFormat, String 
prefix) throws Exception {
+    private void setAdditionalConfiguration(RestConfiguration config, String 
prefix, PropertyBindingSupport.Builder builder) throws Exception {
         if (config.getDataFormatProperties() != null && 
!config.getDataFormatProperties().isEmpty()) {
             // must use a copy as otherwise the options gets removed during 
introspection setProperties
             Map<String, Object> copy = new HashMap<>();
@@ -381,8 +387,7 @@ public class RestProducer extends DefaultAsyncProducer {
                 }
             }
 
-            // set reference properties first as they use # syntax that fools 
the regular properties setter
-            PropertyBindingSupport.bindProperties(context, dataFormat, copy);
+            builder.withProperties(copy);
         }
     }
 
diff --git 
a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowProducerGetPojoTest.java
 
b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowProducerGetPojoTest.java
index 423a774..61681d1 100644
--- 
a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowProducerGetPojoTest.java
+++ 
b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowProducerGetPojoTest.java
@@ -16,15 +16,25 @@
  */
 package org.apache.camel.component.undertow.rest;
 
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.LoggingLevel;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.undertow.BaseUndertowTest;
 import org.apache.camel.model.rest.RestBindingMode;
+import org.apache.camel.spi.BeanIntrospection;
 import org.junit.Test;
 
 public class RestUndertowProducerGetPojoTest extends BaseUndertowTest {
 
     @Test
     public void testUndertowGetPojoRequest() throws Exception {
+        // should not use reflection when using rest binding in the rest 
producer
+        BeanIntrospection bi = 
context.adapt(ExtendedCamelContext.class).getBeanIntrospection();
+        bi.setLoggingLevel(LoggingLevel.INFO);
+        bi.resetCounters();
+
+        assertEquals(0, bi.getInvokedCounter());
+
         String url = "rest:get:users/lives?outType=" + 
CountryPojo.class.getName();
         Object out = template.requestBody(url, (String) null);
 
@@ -32,6 +42,10 @@ public class RestUndertowProducerGetPojoTest extends 
BaseUndertowTest {
         CountryPojo pojo = assertIsInstanceOf(CountryPojo.class, out);
         assertEquals("EN", pojo.getIso());
         assertEquals("England", pojo.getCountry());
+
+        // TODO: Should be 0, but there are elsewhere things being reflected
+        // assertEquals(0, bi.getInvokedCounter());
+        assertEquals(1, bi.getInvokedCounter());
     }
 
     @Override
@@ -41,7 +55,7 @@ public class RestUndertowProducerGetPojoTest extends 
BaseUndertowTest {
             public void configure() throws Exception {
                 // configure to use undertow on localhost with the given port
                 // and enable auto binding mode
-                
restConfiguration().component("undertow").host("localhost").port(getPort()).bindingMode(RestBindingMode.auto);
+                
restConfiguration().component("undertow").host("localhost").port(getPort()).bindingMode(RestBindingMode.json);
 
                 // use the rest DSL to define the rest services
                 rest("/users/")
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultBeanIntrospection.java
 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultBeanIntrospection.java
index 3db2234..ecbd446 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultBeanIntrospection.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultBeanIntrospection.java
@@ -95,6 +95,11 @@ public class DefaultBeanIntrospection extends ServiceSupport 
implements BeanIntr
             obj = Arrays.asList(args);
         }
 
+        if (target != null) {
+            // use Object.toString as target logging
+            target = target.getClass().getName() + "@" + 
Integer.toHexString(target.hashCode());
+        }
+
         String line;
         if (target == null) {
             line = "Invoked: " + invoked.get() + " times (overall) [Method: " 
+ method + "]";
diff --git 
a/core/camel-core-engine/src/generated/resources/org/apache/camel/model/dataformat/jaxb.json
 
b/core/camel-core-engine/src/generated/resources/org/apache/camel/model/dataformat/jaxb.json
index 1a9d64a..c15f2d0 100644
--- 
a/core/camel-core-engine/src/generated/resources/org/apache/camel/model/dataformat/jaxb.json
+++ 
b/core/camel-core-engine/src/generated/resources/org/apache/camel/model/dataformat/jaxb.json
@@ -13,6 +13,7 @@
   },
   "properties": {
     "contextPath": { "kind": "attribute", "displayName": "Context Path", 
"required": true, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "secret": false, "description": "Package name where your 
JAXB classes are located." },
+    "contextPathIsClassName": { "kind": "attribute", "displayName": "Context 
Path Is Class Name", "required": false, "type": "boolean", "javaType": 
"java.lang.Boolean", "deprecated": false, "secret": false, "defaultValue": 
false, "description": "This can be set to true to mark that the contextPath is 
referring to a classname and not a package name." },
     "schema": { "kind": "attribute", "displayName": "Schema", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"secret": false, "description": "To validate against an existing schema. Your 
can use the prefix classpath:, file: or http: to specify how the resource 
should by resolved. You can separate multiple schema files by using the ',' 
character." },
     "schemaSeverityLevel": { "kind": "attribute", "displayName": "Schema 
Severity Level", "required": false, "type": "enum", "javaType": 
"java.lang.Integer", "enum": [ "0", "1", "2" ], "deprecated": false, "secret": 
false, "defaultValue": "0", "description": "Sets the schema severity level to 
use when validating against a schema. This level determines the minimum 
severity error that triggers JAXB to stop continue parsing. The default value 
of 0 (warning) means that any error (warning, er [...]
     "prettyPrint": { "kind": "attribute", "displayName": "Pretty Print", 
"required": false, "type": "boolean", "javaType": "java.lang.Boolean", 
"deprecated": false, "secret": false, "defaultValue": false, "description": "To 
enable pretty printing output nicely formatted. Is by default false." },
diff --git 
a/core/camel-core-engine/src/main/docs/modules/eips/pages/to-eip.adoc 
b/core/camel-core-engine/src/main/docs/modules/eips/pages/to-eip.adoc
index f9ceb03..fb1c22c 100644
--- a/core/camel-core-engine/src/main/docs/modules/eips/pages/to-eip.adoc
+++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/to-eip.adoc
@@ -19,7 +19,7 @@ The To EIP supports 2 options which are listed below:
 |===
 | Name | Description | Default | Type
 | *uri* | *Required* Sets the uri of the endpoint to send to. |  | String
-| *pattern* | Sets the optional ExchangePattern used to invoke this endpoint | 
 | String
+| *pattern* | Sets the optional ExchangePattern used to invoke this endpoint | 
 | ExchangePattern
 |===
 // eip options: END
 
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java
index e84a2be..05ac1b8 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java
@@ -35,6 +35,9 @@ public class JaxbDataFormat extends DataFormatDefinition {
     @XmlAttribute(required = true)
     private String contextPath;
     @XmlAttribute
+    @Metadata(javaType = "java.lang.Boolean")
+    private String contextPathIsClassName;
+    @XmlAttribute
     private String schema;
     @XmlAttribute
     @Metadata(javaType = "java.lang.Integer", enums = "0,1,2", defaultValue = 
"0")
@@ -97,6 +100,17 @@ public class JaxbDataFormat extends DataFormatDefinition {
         this.contextPath = contextPath;
     }
 
+    public String getContextPathIsClassName() {
+        return contextPathIsClassName;
+    }
+
+    /**
+     * This can be set to true to mark that the contextPath is referring to a 
classname and not a package name.
+     */
+    public void setContextPathIsClassName(String contextPathIsClassName) {
+        this.contextPathIsClassName = contextPathIsClassName;
+    }
+
     public String getSchema() {
         return schema;
     }
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/dataformat/JaxbDataFormatReifier.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/dataformat/JaxbDataFormatReifier.java
index 5c3049c..0f10ee9 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/dataformat/JaxbDataFormatReifier.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/dataformat/JaxbDataFormatReifier.java
@@ -37,6 +37,7 @@ public class JaxbDataFormatReifier extends 
DataFormatReifier<JaxbDataFormat> {
         properties.put("filterNonXmlChars", definition.getFilterNonXmlChars());
         properties.put("fragment", definition.getFragment());
         properties.put("contextPath", definition.getContextPath());
+        properties.put("contextPathIsClassName", 
definition.getContextPathIsClassName());
         properties.put("partClass", definition.getPartClass());
         properties.put("partNamespace", definition.getPartNamespace());
         properties.put("encoding", definition.getEncoding());
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
index 457f53f..add2fe0 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
@@ -232,7 +232,10 @@ public final class PropertyBindingSupport {
             // mandatory parameters
             org.apache.camel.util.ObjectHelper.notNull(camelContext, 
"camelContext");
             org.apache.camel.util.ObjectHelper.notNull(target, "target");
-            org.apache.camel.util.ObjectHelper.notNull(properties, 
"properties");
+
+            if (properties == null || properties.isEmpty()) {
+                return false;
+            }
 
             return doBindProperties(camelContext, target,  removeParameters ? 
properties : new HashMap<>(properties),
                     optionPrefix, ignoreCase, true, mandatory,
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 33f3b43..f3d1c6a 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
@@ -1902,6 +1902,7 @@ public class ModelParser extends BaseParser {
         return doParse(new JaxbDataFormat(), (def, key, val) -> {
             switch (key) {
                 case "contextPath": def.setContextPath(val); break;
+                case "contextPathIsClassName": 
def.setContextPathIsClassName(val); break;
                 case "encoding": def.setEncoding(val); break;
                 case "filterNonXmlChars": def.setFilterNonXmlChars(val); break;
                 case "fragment": def.setFragment(val); break;

Reply via email to