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":
