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;
