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 0f8ad1a3a42f1f50e863a8b2ff092cd6df3df43b
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Apr 1 10:07:05 2020 +0200

    CAMEL-14819: rest-dsl - XML binding mode should have JAXB initialization 
done in camel-jaxb
---
 .../camel/rest-binding-jaxb-dataformat-factory     |   2 +
 .../jaxb/JaxbRestBindingJaxbDataFormatFactory.java | 104 +++++++++++++++++++++
 .../org/apache/camel/ExtendedCamelContext.java     |  11 +++
 .../spi/RestBindingJaxbDataFormatFactory.java      |  37 ++++++++
 .../camel/impl/engine/AbstractCamelContext.java    |  19 ++++
 .../camel/impl/engine/SimpleCamelContext.java      |   9 ++
 .../camel/impl/lw/LightweightCamelContext.java     |  11 +++
 .../impl/lw/LightweightRuntimeCamelContext.java    |  11 +++
 .../camel/reifier/rest/RestBindingReifier.java     |  40 +-------
 .../camel/main/ExtendedCamelContextConfigurer.java |   2 +
 10 files changed, 210 insertions(+), 36 deletions(-)

diff --git 
a/components/camel-jaxb/src/generated/resources/META-INF/services/org/apache/camel/rest-binding-jaxb-dataformat-factory
 
b/components/camel-jaxb/src/generated/resources/META-INF/services/org/apache/camel/rest-binding-jaxb-dataformat-factory
new file mode 100644
index 0000000..9855388
--- /dev/null
+++ 
b/components/camel-jaxb/src/generated/resources/META-INF/services/org/apache/camel/rest-binding-jaxb-dataformat-factory
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.converter.jaxb.JaxbRestBindingJaxbDataFormatFactory
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
new file mode 100644
index 0000000..44f0846
--- /dev/null
+++ 
b/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbRestBindingJaxbDataFormatFactory.java
@@ -0,0 +1,104 @@
+/*
+ * 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.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.RestBindingJaxbDataFormatFactory;
+import org.apache.camel.spi.RestConfiguration;
+import org.apache.camel.spi.annotations.JdkService;
+import org.apache.camel.support.PropertyBindingSupport;
+
+/**
+ * JAXB based {@link RestBindingJaxbDataFormatFactory}.
+ */
+@JdkService(RestBindingJaxbDataFormatFactory.FACTORY)
+public class JaxbRestBindingJaxbDataFormatFactory implements 
RestBindingJaxbDataFormatFactory {
+
+    @Override
+    public void setupJaxb(CamelContext camelContext, RestConfiguration config, 
String type, String outType, DataFormat jaxb, DataFormat outJaxb) throws 
Exception {
+        Class<?> clazz = null;
+        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);
+        }
+        setAdditionalConfiguration(camelContext, config, jaxb, "xml.in.");
+
+        Class<?> outClazz = null;
+        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) {
+            // fallback and use the context from the input
+            JAXBContext jc = JAXBContext.newInstance(clazz);
+            setJaxbContext(camelContext, outJaxb, jc);
+        }
+        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);
+    }
+
+    private void setAdditionalConfiguration(CamelContext camelContext, 
RestConfiguration config, DataFormat dataFormat, String prefix) 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<>();
+
+            // filter keys on prefix
+            // - either its a known prefix and must match the prefix parameter
+            // - or its a common configuration that we should always use
+            for (Map.Entry<String, Object> entry : 
config.getDataFormatProperties().entrySet()) {
+                String key = entry.getKey();
+                String copyKey;
+                boolean known = isKeyKnownPrefix(key);
+                if (known) {
+                    // remove the prefix from the key to use
+                    copyKey = key.substring(prefix.length());
+                } else {
+                    // use the key as is
+                    copyKey = key;
+                }
+                if (!known || key.startsWith(prefix)) {
+                    copy.put(copyKey, entry.getValue());
+                }
+            }
+
+            PropertyBindingSupport.build().bind(camelContext, dataFormat, 
copy);
+        }
+    }
+
+    private boolean isKeyKnownPrefix(String key) {
+        return key.startsWith("json.in.") || key.startsWith("json.out.") || 
key.startsWith("xml.in.") || key.startsWith("xml.out.");
+    }
+
+}
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java 
b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
index 5e889cb..b58fb7f 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
@@ -53,6 +53,7 @@ import org.apache.camel.spi.PackageScanResourceResolver;
 import org.apache.camel.spi.ProcessorFactory;
 import org.apache.camel.spi.ReactiveExecutor;
 import org.apache.camel.spi.Registry;
+import org.apache.camel.spi.RestBindingJaxbDataFormatFactory;
 import org.apache.camel.spi.RouteController;
 import org.apache.camel.spi.RouteStartupOrder;
 import org.apache.camel.spi.UnitOfWorkFactory;
@@ -524,6 +525,16 @@ public interface ExtendedCamelContext extends CamelContext 
{
     ModelToXMLDumper getModelToXMLDumper();
 
     /**
+     * Sets a custom {@link RestBindingJaxbDataFormatFactory} to be used.
+     */
+    void setRestBindingJaxbDataFormatFactory(RestBindingJaxbDataFormatFactory 
restBindingJaxbDataFormatFactory);
+
+    /**
+     * Gets the {@link RestBindingJaxbDataFormatFactory} to be used.
+     */
+    RestBindingJaxbDataFormatFactory getRestBindingJaxbDataFormatFactory();
+
+    /**
      * Gets the {@link RuntimeCamelCatalog} if available on the classpath.
      */
     RuntimeCamelCatalog getRuntimeCamelCatalog();
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/RestBindingJaxbDataFormatFactory.java
 
b/core/camel-api/src/main/java/org/apache/camel/spi/RestBindingJaxbDataFormatFactory.java
new file mode 100644
index 0000000..74e91fd
--- /dev/null
+++ 
b/core/camel-api/src/main/java/org/apache/camel/spi/RestBindingJaxbDataFormatFactory.java
@@ -0,0 +1,37 @@
+/*
+ * 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.spi;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * SPI for setting up XML data format (JAXB) for rest-dsl.
+ */
+public interface RestBindingJaxbDataFormatFactory {
+
+    /**
+     * Service factory key.
+     */
+    String FACTORY = "rest-binding-jaxb-dataformat-factory";
+
+    /**
+     * Setup XML data format
+     */
+    void setupJaxb(CamelContext camelContext, RestConfiguration config,
+                   String type, String outType, DataFormat jaxb, DataFormat 
outJaxb) throws Exception;
+
+}
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 83b6b0a..0ebe357 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -130,6 +130,7 @@ import org.apache.camel.spi.PropertiesComponent;
 import org.apache.camel.spi.ReactiveExecutor;
 import org.apache.camel.spi.Registry;
 import org.apache.camel.spi.ReifierStrategy;
+import org.apache.camel.spi.RestBindingJaxbDataFormatFactory;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.spi.RestRegistry;
 import org.apache.camel.spi.RestRegistryFactory;
@@ -258,6 +259,7 @@ public abstract class AbstractCamelContext extends 
BaseService
     private volatile BeanProcessorFactory beanProcessorFactory;
     private volatile XMLRoutesDefinitionLoader xmlRoutesDefinitionLoader;
     private volatile ModelToXMLDumper modelToXMLDumper;
+    private volatile RestBindingJaxbDataFormatFactory 
restBindingJaxbDataFormatFactory;
     private volatile RuntimeCamelCatalog runtimeCamelCatalog;
     private volatile ClassResolver classResolver;
     private volatile PackageScanClassResolver packageScanClassResolver;
@@ -4316,6 +4318,21 @@ public abstract class AbstractCamelContext extends 
BaseService
         this.modelToXMLDumper = doAddService(modelToXMLDumper);
     }
 
+    public RestBindingJaxbDataFormatFactory 
getRestBindingJaxbDataFormatFactory() {
+        if (restBindingJaxbDataFormatFactory == null) {
+            synchronized (lock) {
+                if (restBindingJaxbDataFormatFactory == null) {
+                    
setRestBindingJaxbDataFormatFactory(createRestBindingJaxbDataFormatFactory());
+                }
+            }
+        }
+        return restBindingJaxbDataFormatFactory;
+    }
+
+    public void 
setRestBindingJaxbDataFormatFactory(RestBindingJaxbDataFormatFactory 
restBindingJaxbDataFormatFactory) {
+        this.restBindingJaxbDataFormatFactory = 
restBindingJaxbDataFormatFactory;
+    }
+
     @Override
     public RuntimeCamelCatalog getRuntimeCamelCatalog() {
         if (runtimeCamelCatalog == null) {
@@ -4515,6 +4532,8 @@ public abstract class AbstractCamelContext extends 
BaseService
 
     protected abstract ModelToXMLDumper createModelToXMLDumper();
 
+    protected abstract RestBindingJaxbDataFormatFactory 
createRestBindingJaxbDataFormatFactory();
+
     protected abstract RuntimeCamelCatalog createRuntimeCamelCatalog();
 
     protected abstract Tracer createTracer();
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
index 3f959c7..4bddb7d 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
@@ -63,6 +63,7 @@ import org.apache.camel.spi.ProcessorFactory;
 import org.apache.camel.spi.PropertiesComponent;
 import org.apache.camel.spi.ReactiveExecutor;
 import org.apache.camel.spi.Registry;
+import org.apache.camel.spi.RestBindingJaxbDataFormatFactory;
 import org.apache.camel.spi.RestRegistryFactory;
 import org.apache.camel.spi.RouteController;
 import org.apache.camel.spi.ShutdownStrategy;
@@ -316,6 +317,14 @@ public class SimpleCamelContext extends 
AbstractCamelContext {
     }
 
     @Override
+    protected RestBindingJaxbDataFormatFactory 
createRestBindingJaxbDataFormatFactory() {
+        return new 
BaseServiceResolver<>(RestBindingJaxbDataFormatFactory.FACTORY, 
RestBindingJaxbDataFormatFactory.class)
+                .resolve(getCamelContextReference())
+                .orElseThrow(() -> new IllegalArgumentException("Cannot find 
RestBindingJaxbDataFormatFactory on classpath. "
+                        + "Add camel-jaxb to classpath."));
+    }
+
+    @Override
     protected Tracer createTracer() {
         Tracer tracer = null;
         if (getRegistry() != null) {
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
index 5096769..288b0ed 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
@@ -111,6 +111,7 @@ import org.apache.camel.spi.ProcessorFactory;
 import org.apache.camel.spi.PropertiesComponent;
 import org.apache.camel.spi.ReactiveExecutor;
 import org.apache.camel.spi.Registry;
+import org.apache.camel.spi.RestBindingJaxbDataFormatFactory;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.spi.RestRegistry;
 import org.apache.camel.spi.RouteController;
@@ -1379,6 +1380,16 @@ public class LightweightCamelContext implements 
ExtendedCamelContext, CatalogCam
     }
 
     @Override
+    public void 
setRestBindingJaxbDataFormatFactory(RestBindingJaxbDataFormatFactory 
restBindingJaxbDataFormatFactory) {
+        
getExtendedCamelContext().setRestBindingJaxbDataFormatFactory(restBindingJaxbDataFormatFactory);
+    }
+
+    @Override
+    public RestBindingJaxbDataFormatFactory 
getRestBindingJaxbDataFormatFactory() {
+        return getExtendedCamelContext().getRestBindingJaxbDataFormatFactory();
+    }
+
+    @Override
     public RuntimeCamelCatalog getRuntimeCamelCatalog() {
         return getExtendedCamelContext().getRuntimeCamelCatalog();
     }
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
index 2e616ab..c7843eb 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
@@ -108,6 +108,7 @@ import org.apache.camel.spi.ProcessorFactory;
 import org.apache.camel.spi.PropertiesComponent;
 import org.apache.camel.spi.ReactiveExecutor;
 import org.apache.camel.spi.Registry;
+import org.apache.camel.spi.RestBindingJaxbDataFormatFactory;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.spi.RestRegistry;
 import org.apache.camel.spi.RouteController;
@@ -1515,6 +1516,16 @@ public class LightweightRuntimeCamelContext implements 
ExtendedCamelContext, Cat
     }
 
     @Override
+    public void 
setRestBindingJaxbDataFormatFactory(RestBindingJaxbDataFormatFactory 
restBindingJaxbDataFormatFactory) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public RestBindingJaxbDataFormatFactory 
getRestBindingJaxbDataFormatFactory() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void setRuntimeCamelCatalog(RuntimeCamelCatalog 
runtimeCamelCatalog) {
         throw new UnsupportedOperationException();
     }
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/rest/RestBindingReifier.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/rest/RestBindingReifier.java
index aad39ee..95b9fd6 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/rest/RestBindingReifier.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/rest/RestBindingReifier.java
@@ -19,8 +19,6 @@ package org.apache.camel.reifier.rest;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.xml.bind.JAXBContext;
-
 import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.Route;
 import org.apache.camel.model.rest.RestBindingDefinition;
@@ -65,7 +63,7 @@ public class RestBindingReifier extends AbstractReifier {
         // cors headers
         Map<String, String> corsHeaders = config.getCorsHeaders();
 
-        if (mode == null || "off".equals(mode)) {
+        if ("off".equals(mode)) {
             // binding mode is off, so create a off mode binding processor
             return new RestBindingAdvice(camelContext, null, null, null, null,
                                          
parseString(definition.getConsumes()), parseString(definition.getProduces()), 
mode, skip, validation, cors, corsHeaders,
@@ -122,7 +120,9 @@ public class RestBindingReifier extends AbstractReifier {
             }
 
             if (jaxb != null) {
-                setupJaxb(config, parseString(definition.getType()), 
parseString(definition.getOutType()), jaxb, outJaxb);
+                // to setup JAXB we need to use camel-xml-jaxb
+                
camelContext.adapt(ExtendedCamelContext.class).getRestBindingJaxbDataFormatFactory()
+                        .setupJaxb(camelContext, config, 
parseString(definition.getType()), parseString(definition.getOutType()), jaxb, 
outJaxb);
             }
         }
 
@@ -157,38 +157,6 @@ public class RestBindingReifier extends AbstractReifier {
         setAdditionalConfiguration(config, outJson, "json.out.");
     }
 
-    protected void setupJaxb(RestConfiguration config, String type, String 
outType, DataFormat jaxb, DataFormat outJaxb) throws Exception {
-        Class<?> clazz = null;
-        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(jaxb, jc);
-        }
-        setAdditionalConfiguration(config, jaxb, "xml.in.");
-
-        Class<?> outClazz = null;
-        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(outJaxb, jc);
-        } else if (clazz != null) {
-            // fallback and use the context from the input
-            JAXBContext jc = JAXBContext.newInstance(clazz);
-            setJaxbContext(outJaxb, jc);
-        }
-        setAdditionalConfiguration(config, outJaxb, "xml.out.");
-    }
-
-    private void setJaxbContext(DataFormat jaxb, JAXBContext jc) throws 
Exception {
-        
camelContext.adapt(ExtendedCamelContext.class).getBeanIntrospection().setProperty(camelContext,
 jaxb, "context", jc);
-    }
-
     private void setAdditionalConfiguration(RestConfiguration config, 
DataFormat dataFormat, String prefix) throws Exception {
         if (config.getDataFormatProperties() != null && 
!config.getDataFormatProperties().isEmpty()) {
             // must use a copy as otherwise the options gets removed during
diff --git 
a/core/camel-main/src/generated/java/org/apache/camel/main/ExtendedCamelContextConfigurer.java
 
b/core/camel-main/src/generated/java/org/apache/camel/main/ExtendedCamelContextConfigurer.java
index 04878d3..2702d26 100644
--- 
a/core/camel-main/src/generated/java/org/apache/camel/main/ExtendedCamelContextConfigurer.java
+++ 
b/core/camel-main/src/generated/java/org/apache/camel/main/ExtendedCamelContextConfigurer.java
@@ -103,6 +103,8 @@ public class ExtendedCamelContextConfigurer extends 
org.apache.camel.support.com
         case "ReactiveExecutor": 
target.setReactiveExecutor(property(camelContext, 
org.apache.camel.spi.ReactiveExecutor.class, value)); return true;
         case "registry":
         case "Registry": target.setRegistry(property(camelContext, 
org.apache.camel.spi.Registry.class, value)); return true;
+        case "restbindingjaxbdataformatfactory":
+        case "RestBindingJaxbDataFormatFactory": 
target.setRestBindingJaxbDataFormatFactory(property(camelContext, 
org.apache.camel.spi.RestBindingJaxbDataFormatFactory.class, value)); return 
true;
         case "restconfiguration":
         case "RestConfiguration": 
target.setRestConfiguration(property(camelContext, 
org.apache.camel.spi.RestConfiguration.class, value)); return true;
         case "restregistry":

Reply via email to