This is an automated email from the ASF dual-hosted git repository. ggrzybek pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
commit 15eafddc601d6f74c31d83e30ed136733b99affe Author: Grzegorz Grzybek <gr.grzy...@gmail.com> AuthorDate: Fri May 5 13:54:32 2023 +0200 [CAMEL-18189] camel-xml-io-dsl supports top-level <beans> element --- .../org/apache/camel/catalog/models.properties | 2 + .../org/apache/camel/catalog/models}/beans.json | 0 .../apache/camel/catalog/models}/camel-app.json | 1 + .../org/apache/camel/model/app/beans.json | 3 +- .../org/apache/camel/model/app/camel-app.json | 2 + .../org/apache/camel/model/app/jaxb.index | 4 + .../java/org/apache/camel/model/Constants.java | 1 + .../camel/model/app/ApplicationDefinition.java | 5 +- .../camel/model/app/BeanPropertiesAdapter.java | 62 ++++++++ ...finition.java => BeanPropertiesDefinition.java} | 29 ++-- .../camel/model/app/BeanPropertyDefinition.java | 60 +++++++ .../apache/camel/model/app/BeansDefinition.java | 90 +++++++++-- .../camel/model/app/ComponentScanDefinition.java | 23 +-- ...Definition.java => RegistryBeanDefinition.java} | 56 ++++--- .../org/apache/camel/model/app/package-info.java | 6 +- .../java/org/apache/camel/main/MainRegistry.java | 5 + core/camel-support/pom.xml | 6 + .../java/org/apache/camel}/support/DIRegistry.java | 10 +- .../org/apache/camel}/support/DIRegistryTest.java | 2 +- .../java/org/apache/camel/xml/in/ModelParser.java | 51 ++++++ .../java/org/apache/camel/xml/out/ModelWriter.java | 46 ++++++ .../java/org/apache/camel/xml/in/ParserTest.java | 4 + .../camel/dsl/xml/io/XmlRoutesBuilderLoader.java | 109 ++++++++++++- .../apache/camel/dsl/xml/io/XmlLoadAppTest.java | 67 ++++++++ .../org/apache/camel/dsl/xml/io/beans/Greeter.java | 35 +++-- .../camel/dsl/xml/io/beans/GreeterMessage.java | 17 +- .../org/apache/camel/dsl/xml/io/camel-app1.xml | 30 ++++ .../org/apache/camel/dsl/xml/io/camel-app2.xml | 30 ++++ .../dsl/yaml/deserializers/ModelDeserializers.java | 173 +++++++++++++++++++++ .../deserializers/ModelDeserializersResolver.java | 5 + .../generated/resources/schema/camel-yaml-dsl.json | 93 +++++++++++ .../generated/resources/schema/camelYamlDsl.json | 93 +++++++++++ tooling/camel-tooling-maven/pom.xml | 6 - .../camel/tooling/maven/MavenDownloaderImpl.java | 2 +- .../camel/tooling/maven/MavenResolverTest.java | 2 +- .../packaging/ModelXmlParserGeneratorMojo.java | 20 +++ 36 files changed, 1040 insertions(+), 110 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties index da7f83bbcca..9322ce4c9e6 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties @@ -7,10 +7,12 @@ base64 basicAuth batch-config bean +beans bearerToken bindy blacklistServiceFilter cachingServiceDiscovery +camel-app cbor choice circuitBreaker diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/beans.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/beans.json similarity index 100% copy from core/camel-core-model/src/generated/resources/org/apache/camel/model/app/beans.json copy to catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/beans.json diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/camel-app.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/camel-app.json similarity index 98% copy from core/camel-core-model/src/generated/resources/org/apache/camel/model/app/camel-app.json copy to catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/camel-app.json index e941602f7e0..6c74dcaa7c7 100644 --- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/camel-app.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/camel-app.json @@ -5,6 +5,7 @@ "title": "Camel-app", "description": "If beans reminds Spring application too much, we can use camel-app (similar to web-app from Servlet API specification).", "deprecated": false, + "label": "configuration", "javaType": "org.apache.camel.model.app.ApplicationDefinition", "abstract": false, "input": false, diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/beans.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/beans.json index e55cd059c1f..080094084dc 100644 --- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/beans.json +++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/beans.json @@ -3,7 +3,7 @@ "kind": "model", "name": "beans", "title": "Beans", - "description": "A groupping POJO (and related XML root element) that's historically associated with entire application (or its distinguished fragment). beans root element to define the application comes from Spring Framework and it can be treated as de-facto standard.", + "description": "A groupping POJO (and related XML root element) that's historically associated with entire application (or its distinguished fragment). This class is not meant to be used with Camel Java DSL, but it's needed to generate XML Schema and MX parser methods.", "deprecated": false, "label": "configuration", "javaType": "org.apache.camel.model.app.BeansDefinition", @@ -13,6 +13,7 @@ }, "properties": { "component-scan": { "kind": "element", "displayName": "Component-scan", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.app.ComponentScanDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Component scanning definition(s). But unlike package\/packageScan\/contextScan, we're not scanning only for org.apache.camel.builder.RouteBuilder." }, + "bean": { "kind": "element", "displayName": "Bean", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.app.RegistryBeanDefinition>", "deprecated": false, "autowired": false, "secret": false }, "rest": { "kind": "element", "displayName": "Rest", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.rest.RestDefinition>", "deprecated": false, "autowired": false, "secret": false }, "routeConfiguration": { "kind": "element", "displayName": "Route Configuration", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteConfigurationDefinition>", "deprecated": false, "autowired": false, "secret": false }, "routeTemplate": { "kind": "element", "displayName": "Route Template", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteTemplateDefinition>", "deprecated": false, "autowired": false, "secret": false }, diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/camel-app.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/camel-app.json index e941602f7e0..faea5faeddd 100644 --- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/camel-app.json +++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/camel-app.json @@ -5,6 +5,7 @@ "title": "Camel-app", "description": "If beans reminds Spring application too much, we can use camel-app (similar to web-app from Servlet API specification).", "deprecated": false, + "label": "configuration", "javaType": "org.apache.camel.model.app.ApplicationDefinition", "abstract": false, "input": false, @@ -12,6 +13,7 @@ }, "properties": { "component-scan": { "kind": "element", "displayName": "Component-scan", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.app.ComponentScanDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Component scanning definition(s). But unlike package\/packageScan\/contextScan, we're not scanning only for org.apache.camel.builder.RouteBuilder." }, + "bean": { "kind": "element", "displayName": "Bean", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.app.RegistryBeanDefinition>", "deprecated": false, "autowired": false, "secret": false }, "rest": { "kind": "element", "displayName": "Rest", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.rest.RestDefinition>", "deprecated": false, "autowired": false, "secret": false }, "routeConfiguration": { "kind": "element", "displayName": "Route Configuration", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteConfigurationDefinition>", "deprecated": false, "autowired": false, "secret": false }, "routeTemplate": { "kind": "element", "displayName": "Route Template", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteTemplateDefinition>", "deprecated": false, "autowired": false, "secret": false }, diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/jaxb.index b/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/jaxb.index index 63678282437..5a0a73a15d0 100644 --- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/jaxb.index +++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/jaxb.index @@ -1,3 +1,7 @@ # Generated by camel build tools - do NOT edit this file! ApplicationDefinition +BeanPropertiesDefinition +BeanPropertyDefinition BeansDefinition +ComponentScanDefinition +RegistryBeanDefinition diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/Constants.java b/core/camel-core-model/src/main/java/org/apache/camel/model/Constants.java index cf7fefb18f0..fa209e8bc77 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/Constants.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/Constants.java @@ -23,6 +23,7 @@ public final class Constants { public static final String JAXB_CONTEXT_PACKAGES = "org.apache.camel:" + "org.apache.camel.model:" + + "org.apache.camel.model.app:" + "org.apache.camel.model.cloud:" + "org.apache.camel.model.config:" + "org.apache.camel.model.dataformat:" diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/ApplicationDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/ApplicationDefinition.java index 96733157ab9..e416c7cc3cc 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/app/ApplicationDefinition.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/ApplicationDefinition.java @@ -17,11 +17,12 @@ package org.apache.camel.model.app; import jakarta.xml.bind.annotation.XmlRootElement; + import org.apache.camel.spi.Metadata; /** - * If "beans" reminds Spring application too much, we can use "camel-app" (similar to - * "web-app" from Servlet API specification). + * If "beans" reminds Spring application too much, we can use "camel-app" (similar to "web-app" from Servlet API + * specification). */ @Metadata(label = "configuration") @XmlRootElement(name = "camel-app") diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanPropertiesAdapter.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanPropertiesAdapter.java new file mode 100644 index 00000000000..4a1091c8256 --- /dev/null +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanPropertiesAdapter.java @@ -0,0 +1,62 @@ +/* + * 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.model.app; + +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; +import jakarta.xml.bind.annotation.adapters.XmlAdapter; + +public class BeanPropertiesAdapter extends XmlAdapter<BeanPropertiesDefinition, Map<String, Object>> { + + @Override + public Map<String, Object> unmarshal(BeanPropertiesDefinition v) { + Map<String, Object> result = new LinkedHashMap<>(); + for (BeanPropertyDefinition pd : v.getProperties()) { + if (pd.getProperties() != null) { + result.put(pd.getKey(), unmarshal(pd.getProperties())); + } else { + result.put(pd.getKey(), pd.getValue()); + } + } + + return result; + } + + @Override + @SuppressWarnings("unchecked") + public BeanPropertiesDefinition marshal(Map<String, Object> v) { + final BeanPropertyDefinition[] result = new BeanPropertyDefinition[v.size()]; + int pos = 0; + for (Map.Entry<String, Object> entry : v.entrySet()) { + String k = entry.getKey(); + Object value = entry.getValue(); + BeanPropertyDefinition pd = new BeanPropertyDefinition(); + pd.setKey(k); + if (value instanceof Map) { + pd.setProperties(marshal((Map<String, Object>) value)); + } else { + pd.setValue(value.toString()); + } + result[pos++] = pd; + } + BeanPropertiesDefinition propertiesDefinition = new BeanPropertiesDefinition(); + propertiesDefinition.setProperties(Arrays.asList(result)); + return propertiesDefinition; + } + +} diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/ApplicationDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanPropertiesDefinition.java similarity index 58% copy from core/camel-core-model/src/main/java/org/apache/camel/model/app/ApplicationDefinition.java copy to core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanPropertiesDefinition.java index 96733157ab9..9ef586e7605 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/app/ApplicationDefinition.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanPropertiesDefinition.java @@ -16,14 +16,25 @@ */ package org.apache.camel.model.app; -import jakarta.xml.bind.annotation.XmlRootElement; -import org.apache.camel.spi.Metadata; +import java.util.List; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlType; + +@XmlType +@XmlAccessorType(XmlAccessType.FIELD) +public class BeanPropertiesDefinition { + + @XmlElement(name = "property") + private List<BeanPropertyDefinition> properties; + + public List<BeanPropertyDefinition> getProperties() { + return properties; + } + + public void setProperties(List<BeanPropertyDefinition> properties) { + this.properties = properties; + } -/** - * If "beans" reminds Spring application too much, we can use "camel-app" (similar to - * "web-app" from Servlet API specification). - */ -@Metadata(label = "configuration") -@XmlRootElement(name = "camel-app") -public class ApplicationDefinition extends BeansDefinition { } diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanPropertyDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanPropertyDefinition.java new file mode 100644 index 00000000000..39f28f2abdc --- /dev/null +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanPropertyDefinition.java @@ -0,0 +1,60 @@ +/* + * 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.model.app; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlType; + +@XmlType +@XmlAccessorType(XmlAccessType.FIELD) +public class BeanPropertyDefinition { + + @XmlAttribute + private String key; + @XmlAttribute + private String value; + @XmlElement(name = "properties") + private BeanPropertiesDefinition properties; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public BeanPropertiesDefinition getProperties() { + return properties; + } + + public void setProperties(BeanPropertiesDefinition properties) { + this.properties = properties; + } + +} diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeansDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeansDefinition.java index b89600bb7ee..a27b81b953e 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeansDefinition.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeansDefinition.java @@ -21,37 +21,57 @@ import java.util.List; import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlAnyElement; import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlRootElement; import jakarta.xml.bind.annotation.XmlType; + import org.apache.camel.model.RouteConfigurationDefinition; import org.apache.camel.model.RouteDefinition; import org.apache.camel.model.RouteTemplateDefinition; import org.apache.camel.model.TemplatedRouteDefinition; import org.apache.camel.model.rest.RestDefinition; import org.apache.camel.spi.Metadata; +import org.w3c.dom.Element; /** - * A groupping POJO (and related XML root element) that's historically associated with "entire application" - * (or its distinguished fragment). "beans" root element to define "the application" comes from Spring - * Framework and it can be treated as de-facto standard. + * <p>A groupping POJO (and related XML root element) that's historically associated with "entire application" (or its + * distinguished fragment).</p> + * <p>This class is not meant to be used with Camel Java DSL, but it's needed to generate XML Schema and MX + * parser methods.</p> */ @Metadata(label = "configuration") @XmlRootElement(name = "beans") +@XmlType(propOrder = { + "componentScanning", + "beans", + "springBeans", + "rests", + "routeConfigurations", + "routeTemplates", + "templatedRoutes", + "routes" +}) @XmlAccessorType(XmlAccessType.FIELD) public class BeansDefinition { /** - * Component scanning definition(s). But unlike package/packageScan/contextScan, - * we're not scanning only for org.apache.camel.builder.RouteBuilder. + * Component scanning definition(s). But unlike package/packageScan/contextScan, we're not scanning only for + * org.apache.camel.builder.RouteBuilder. */ @XmlElement(name = "component-scan") - private final List<ComponentScanDefinition> componentScanning = new ArrayList<>(); + private List<ComponentScanDefinition> componentScanning = new ArrayList<>(); + + // this is a place for <bean> element definition, without conflicting with <bean> elements referring + // to "bean processors" + + @XmlElement(name = "bean") + private List<RegistryBeanDefinition> beans = new ArrayList<>(); - // this is a place for <bean> element definition, but there's already org.apache.camel.model.BeanDefinition - // model. However it is for "bean processor", not "bean definition". - // also, it'd be nice to support all that Spring's <bean> can support (constructor args, maps/lists/constants) - // for now let's stick to package scanning for JSR330 annotations and SupplierRegistry + // this is the only way I found to generate usable Schema without imports, while allowing elements + // from different namespaces + @XmlAnyElement(lax = true) + private List<Element> springBeans = new ArrayList<>(); // the order comes from <camelContext> (org.apache.camel.spring.xml.CamelContextFactoryBean) // to make things less confusing, as it's not easy to simply tell JAXB to use <xsd:choice maxOccurs="unbounded"> @@ -61,38 +81,78 @@ public class BeansDefinition { // org.apache.camel.dsl.xml.io.XmlRoutesBuilderLoader in camel-xml-io-dsl @XmlElement(name = "rest") - private final List<RestDefinition> rests = new ArrayList<>(); + private List<RestDefinition> rests = new ArrayList<>(); @XmlElement(name = "routeConfiguration") - private final List<RouteConfigurationDefinition> routeConfigurations = new ArrayList<>(); + private List<RouteConfigurationDefinition> routeConfigurations = new ArrayList<>(); @XmlElement(name = "routeTemplate") - private final List<RouteTemplateDefinition> routeTemplates = new ArrayList<>(); + private List<RouteTemplateDefinition> routeTemplates = new ArrayList<>(); @XmlElement(name = "templatedRoute") - private final List<TemplatedRouteDefinition> templatedRoutes = new ArrayList<>(); + private List<TemplatedRouteDefinition> templatedRoutes = new ArrayList<>(); @XmlElement(name = "route") - private final List<RouteDefinition> routes = new ArrayList<>(); + private List<RouteDefinition> routes = new ArrayList<>(); public List<ComponentScanDefinition> getComponentScanning() { return componentScanning; } + public void setComponentScanning(List<ComponentScanDefinition> componentScanning) { + this.componentScanning = componentScanning; + } + + public List<RegistryBeanDefinition> getBeans() { + return beans; + } + + public void setBeans(List<RegistryBeanDefinition> beans) { + this.beans = beans; + } + + public List<Element> getSpringBeans() { + return springBeans; + } + + public void setSpringBeans(List<Element> springBeans) { + this.springBeans = springBeans; + } + public List<RestDefinition> getRests() { return rests; } + public void setRests(List<RestDefinition> rests) { + this.rests = rests; + } + public List<RouteConfigurationDefinition> getRouteConfigurations() { return routeConfigurations; } + public void setRouteConfigurations(List<RouteConfigurationDefinition> routeConfigurations) { + this.routeConfigurations = routeConfigurations; + } + public List<RouteTemplateDefinition> getRouteTemplates() { return routeTemplates; } + public void setRouteTemplates(List<RouteTemplateDefinition> routeTemplates) { + this.routeTemplates = routeTemplates; + } + public List<TemplatedRouteDefinition> getTemplatedRoutes() { return templatedRoutes; } + public void setTemplatedRoutes(List<TemplatedRouteDefinition> templatedRoutes) { + this.templatedRoutes = templatedRoutes; + } + public List<RouteDefinition> getRoutes() { return routes; } + public void setRoutes(List<RouteDefinition> routes) { + this.routes = routes; + } + } diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/ComponentScanDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/ComponentScanDefinition.java index a9e04d06e92..fca0594f3f4 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/app/ComponentScanDefinition.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/ComponentScanDefinition.java @@ -19,31 +19,30 @@ package org.apache.camel.model.app; import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlType; + import org.apache.camel.spi.Metadata; import org.apache.camel.support.DefaultRegistry; /** * <p> - * An equivalent of Spring's {@code <context:component-scan>} element that can be used to populate underlying - * bean registry. + * An equivalent of Spring's {@code <context:component-scan>} element that can be used to populate underlying bean + * registry. * </p> * <p> - * With Spring application, the bean registry is provided by Spring itself, but if we want to use Camel without - * Spring, we have an option to use {@link DefaultRegistry} with underlying, supporting bean + * With Spring application, the bean registry is provided by Spring itself, but if we want to use Camel without Spring, + * we have an option to use {@link DefaultRegistry} with underlying, supporting bean * {@link org.apache.camel.spi.Registry registries} and {@link org.apache.camel.spi.BeanRepository repositories}. * </p> */ @Metadata(label = "configuration") +@XmlType @XmlAccessorType(XmlAccessType.FIELD) public class ComponentScanDefinition { @XmlAttribute(name = "base-package") private String basePackage; - /** Whether to use {@code jakarta.inject} annotations like {@code @Inject} or {@code @Named} */ - @XmlAttribute(name = "use-jsr-330") - private boolean useJsr330 = true; - public String getBasePackage() { return basePackage; } @@ -52,12 +51,4 @@ public class ComponentScanDefinition { this.basePackage = basePackage; } - public void setUseJsr330(boolean useJsr330) { - this.useJsr330 = useJsr330; - } - - public boolean isJsr330Enabled() { - return useJsr330; - } - } diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/ComponentScanDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/RegistryBeanDefinition.java similarity index 50% copy from core/camel-core-model/src/main/java/org/apache/camel/model/app/ComponentScanDefinition.java copy to core/camel-core-model/src/main/java/org/apache/camel/model/app/RegistryBeanDefinition.java index a9e04d06e92..48863226933 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/app/ComponentScanDefinition.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/RegistryBeanDefinition.java @@ -16,48 +16,56 @@ */ package org.apache.camel.model.app; +import java.util.Map; + import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlType; +import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.apache.camel.spi.Metadata; -import org.apache.camel.support.DefaultRegistry; /** - * <p> - * An equivalent of Spring's {@code <context:component-scan>} element that can be used to populate underlying - * bean registry. - * </p> - * <p> - * With Spring application, the bean registry is provided by Spring itself, but if we want to use Camel without - * Spring, we have an option to use {@link DefaultRegistry} with underlying, supporting bean - * {@link org.apache.camel.spi.Registry registries} and {@link org.apache.camel.spi.BeanRepository repositories}. - * </p> + * A Pojo representing simplified "bean" element to declare registry beans using any DSL. This is not the same + * as "bean processor". */ @Metadata(label = "configuration") +@XmlType @XmlAccessorType(XmlAccessType.FIELD) -public class ComponentScanDefinition { +public class RegistryBeanDefinition { + + @XmlAttribute + private String name; + @XmlAttribute + private String type; - @XmlAttribute(name = "base-package") - private String basePackage; + @XmlElement(name = "properties") + @XmlJavaTypeAdapter(BeanPropertiesAdapter.class) + private Map<String, Object> properties; - /** Whether to use {@code jakarta.inject} annotations like {@code @Inject} or {@code @Named} */ - @XmlAttribute(name = "use-jsr-330") - private boolean useJsr330 = true; + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } - public String getBasePackage() { - return basePackage; + public String getType() { + return type; } - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; + public void setType(String type) { + this.type = type; } - public void setUseJsr330(boolean useJsr330) { - this.useJsr330 = useJsr330; + public Map<String, Object> getProperties() { + return properties; } - public boolean isJsr330Enabled() { - return useJsr330; + public void setProperties(Map<String, Object> properties) { + this.properties = properties; } } diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/package-info.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/package-info.java index bf2e2bcd2e6..ef60d6c73d8 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/app/package-info.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/package-info.java @@ -16,9 +16,9 @@ */ /** - * The JAXB POJOs representing the part of the model, which can be used to create a view of Camel application. - * This model can be used to group some Camel definitions (routes, templates) without using full Spring - * application context, but when Spring's {@code <beans>} concept feels appropriate. + * The JAXB POJOs representing the part of the model, which can be used to create a view of Camel application. This + * model can be used to group some Camel definitions (routes, templates) without using full Spring application context, + * but when Spring's {@code <beans>} concept feels appropriate. */ @jakarta.xml.bind.annotation.XmlSchema(namespace = "http://camel.apache.org/schema/spring", elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED) diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainRegistry.java b/core/camel-main/src/main/java/org/apache/camel/main/MainRegistry.java index 14928c99e7c..727f49ad7f8 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/MainRegistry.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/MainRegistry.java @@ -18,6 +18,7 @@ package org.apache.camel.main; import java.util.Set; +import org.apache.camel.spi.BeanRepository; import org.apache.camel.support.DefaultRegistry; /** @@ -25,6 +26,10 @@ import org.apache.camel.support.DefaultRegistry; */ public final class MainRegistry extends DefaultRegistry { + public MainRegistry(BeanRepository... repositories) { + super(repositories); + } + /** * Finds beans in the registry by their type. * diff --git a/core/camel-support/pom.xml b/core/camel-support/pom.xml index ab29756f251..bdab2c3a19b 100644 --- a/core/camel-support/pom.xml +++ b/core/camel-support/pom.xml @@ -56,6 +56,12 @@ <artifactId>camel-util-json</artifactId> </dependency> + <dependency> + <groupId>jakarta.inject</groupId> + <artifactId>jakarta.inject-api</artifactId> + <version>${jakarta-inject-version}</version> + </dependency> + <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> diff --git a/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/support/DIRegistry.java b/core/camel-support/src/main/java/org/apache/camel/support/DIRegistry.java similarity index 96% rename from tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/support/DIRegistry.java rename to core/camel-support/src/main/java/org/apache/camel/support/DIRegistry.java index db7af48cb0a..83a94967582 100644 --- a/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/support/DIRegistry.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/DIRegistry.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.tooling.maven.support; +package org.apache.camel.support; import java.lang.annotation.Annotation; import java.lang.reflect.Array; @@ -39,7 +39,6 @@ import java.util.function.Supplier; import jakarta.inject.Inject; import jakarta.inject.Named; -import org.apache.camel.support.SupplierRegistry; import org.apache.camel.util.StringHelper; import org.apache.camel.util.function.Suppliers; @@ -53,13 +52,6 @@ import org.apache.camel.util.function.Suppliers; * Such requirement was found when trying to configure maven-resolver without using the deprecated service locator * helpers (see <a href="https://issues.apache.org/jira/browse/MRESOLVER-157">MRESOLVER-157</a>). * </p> - * - * <p> - * While this is quite thin extension of {@link SupplierRegistry} and thin implementation of JSR-330 style of dependency - * injection and could potentially be used in many places, for now it's used <em>only</em> to configure - * <em>beans/services</em> required by {@link org.eclipse.aether.RepositorySystem}. If there's a need to use this - * registry in other places, we can move it from {@code camel-tooling-maven} module. - * </p> */ public class DIRegistry extends SupplierRegistry { diff --git a/tooling/camel-tooling-maven/src/test/java/org/apache/camel/tooling/maven/support/DIRegistryTest.java b/core/camel-support/src/test/java/org/apache/camel/support/DIRegistryTest.java similarity index 99% rename from tooling/camel-tooling-maven/src/test/java/org/apache/camel/tooling/maven/support/DIRegistryTest.java rename to core/camel-support/src/test/java/org/apache/camel/support/DIRegistryTest.java index f3c619d0899..cb7bad6070d 100644 --- a/tooling/camel-tooling-maven/src/test/java/org/apache/camel/tooling/maven/support/DIRegistryTest.java +++ b/core/camel-support/src/test/java/org/apache/camel/support/DIRegistryTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.tooling.maven.support; +package org.apache.camel.support; import java.io.FilenameFilter; import java.io.IOException; 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 3817d6e971a..210dcde035e 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 @@ -30,6 +30,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.apache.camel.model.*; +import org.apache.camel.model.app.ApplicationDefinition; +import org.apache.camel.model.app.BeansDefinition; +import org.apache.camel.model.app.ComponentScanDefinition; import org.apache.camel.model.cloud.*; import org.apache.camel.model.config.BatchResequencerConfig; import org.apache.camel.model.config.ResequencerConfig; @@ -1556,6 +1559,54 @@ public class ModelParser extends BaseParser { return true; }, optionalIdentifiedDefinitionElementHandler(), noValueHandler()); } + public Optional<ApplicationDefinition> parseApplicationDefinition() + throws IOException, XmlPullParserException { + String tag = getNextTag("beans", "camel-app"); + if (tag != null) { + return Optional.of(doParseApplicationDefinition()); + } + return Optional.empty(); + } + protected ApplicationDefinition doParseApplicationDefinition() throws IOException, XmlPullParserException { + return doParse(new ApplicationDefinition(), + noAttributeHandler(), beansDefinitionElementHandler(), noValueHandler()); + } + public Optional<BeansDefinition> parseBeansDefinition() + throws IOException, XmlPullParserException { + String tag = getNextTag("beans", "camel-app"); + if (tag != null) { + return Optional.of(doParseBeansDefinition()); + } + return Optional.empty(); + } + protected <T extends BeansDefinition> ElementHandler<T> beansDefinitionElementHandler() { + return (def, key) -> { + switch (key) { + case "component-scan": doAdd(doParseComponentScanDefinition(), def.getComponentScanning(), def::setComponentScanning); break; + case "rest": doAdd(doParseRestDefinition(), def.getRests(), def::setRests); break; + case "routeConfiguration": doAdd(doParseRouteConfigurationDefinition(), def.getRouteConfigurations(), def::setRouteConfigurations); break; + case "routeTemplate": doAdd(doParseRouteTemplateDefinition(), def.getRouteTemplates(), def::setRouteTemplates); break; + case "route": doAdd(doParseRouteDefinition(), def.getRoutes(), def::setRoutes); break; + case "templatedRoute": doAdd(doParseTemplatedRouteDefinition(), def.getTemplatedRoutes(), def::setTemplatedRoutes); break; + default: return false; + } + return true; + }; + } + protected BeansDefinition doParseBeansDefinition() throws IOException, XmlPullParserException { + return doParse(new BeansDefinition(), + noAttributeHandler(), beansDefinitionElementHandler(), noValueHandler()); + } + protected ComponentScanDefinition doParseComponentScanDefinition() throws IOException, XmlPullParserException { + return doParse(new ComponentScanDefinition(), (def, key, val) -> { + switch (key) { + case "base-package": def.setBasePackage(val); break; + case "use-jsr-330": def.setUseJsr330(val); break; + default: return false; + } + return true; + }, noElementHandler(), noValueHandler()); + } protected BlacklistServiceCallServiceFilterConfiguration doParseBlacklistServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException { return doParse(new BlacklistServiceCallServiceFilterConfiguration(), identifiedTypeAttributeHandler(), (def, key) -> { diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java index c9c248c3faa..0f513b54d1a 100644 --- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java +++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java @@ -29,6 +29,9 @@ import java.util.ArrayList; import java.util.Base64; import java.util.List; import org.apache.camel.model.*; +import org.apache.camel.model.app.ApplicationDefinition; +import org.apache.camel.model.app.BeansDefinition; +import org.apache.camel.model.app.ComponentScanDefinition; import org.apache.camel.model.cloud.*; import org.apache.camel.model.config.BatchResequencerConfig; import org.apache.camel.model.config.ResequencerConfig; @@ -482,6 +485,14 @@ public class ModelWriter extends BaseWriter { public void writeWireTapDefinition(WireTapDefinition def) throws IOException { doWriteWireTapDefinition("wireTap", def); } + public void writeApplicationDefinition( + ApplicationDefinition def) + throws IOException { + doWriteApplicationDefinition("camel-app", def); + } + public void writeBeansDefinition(BeansDefinition def) throws IOException { + doWriteBeansDefinition("beans", def); + } public void writeBlacklistServiceCallServiceFilterConfiguration( BlacklistServiceCallServiceFilterConfiguration def) throws IOException { @@ -2557,6 +2568,41 @@ public class ModelWriter extends BaseWriter { doWriteOptionalIdentifiedDefinitionElements(def); endElement(); } + protected void doWriteApplicationDefinition( + String name, + ApplicationDefinition def) + throws IOException { + startElement(name); + doWriteBeansDefinitionElements(def); + endElement(); + } + protected void doWriteBeansDefinitionElements( + BeansDefinition def) + throws IOException { + doWriteList(null, "route", def.getRoutes(), this::doWriteRouteDefinition); + doWriteList(null, "component-scan", def.getComponentScanning(), this::doWriteComponentScanDefinition); + doWriteList(null, "rest", def.getRests(), this::doWriteRestDefinition); + doWriteList(null, "routeConfiguration", def.getRouteConfigurations(), this::doWriteRouteConfigurationDefinition); + doWriteList(null, "routeTemplate", def.getRouteTemplates(), this::doWriteRouteTemplateDefinition); + doWriteList(null, "templatedRoute", def.getTemplatedRoutes(), this::doWriteTemplatedRouteDefinition); + } + protected void doWriteBeansDefinition( + String name, + BeansDefinition def) + throws IOException { + startElement(name); + doWriteBeansDefinitionElements(def); + endElement(); + } + protected void doWriteComponentScanDefinition( + String name, + ComponentScanDefinition def) + throws IOException { + startElement(name); + doWriteAttribute("base-package", def.getBasePackage()); + doWriteAttribute("use-jsr-330", def.getUseJsr330()); + endElement(); + } protected void doWriteBlacklistServiceCallServiceFilterConfiguration( String name, BlacklistServiceCallServiceFilterConfiguration def) diff --git a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ParserTest.java b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ParserTest.java index b5e2c44050e..4f75720b63b 100644 --- a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ParserTest.java +++ b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ParserTest.java @@ -21,10 +21,12 @@ import java.io.StringReader; import org.apache.camel.xml.io.MXParser; import org.apache.camel.xml.io.XmlPullParserException; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +@Disabled("Run manually to check how the MX parser works") public class ParserTest { @Test @@ -118,6 +120,8 @@ public class ParserTest { } case MXParser.DOCDECL -> { } + default -> { + } } eventType = xpp.next(); } diff --git a/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java b/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java index eefb5744794..917d51c0843 100644 --- a/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java +++ b/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java @@ -16,7 +16,12 @@ */ package org.apache.camel.dsl.xml.io; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; +import java.util.Set; + +import jakarta.inject.Named; import org.apache.camel.CamelContextAware; import org.apache.camel.api.management.ManagedResource; @@ -26,10 +31,22 @@ import org.apache.camel.dsl.support.RouteBuilderLoaderSupport; import org.apache.camel.model.RouteConfigurationDefinition; import org.apache.camel.model.RouteConfigurationsDefinition; import org.apache.camel.model.RouteDefinition; +import org.apache.camel.model.RouteTemplateDefinition; +import org.apache.camel.model.RouteTemplatesDefinition; import org.apache.camel.model.RoutesDefinition; +import org.apache.camel.model.TemplatedRouteDefinition; +import org.apache.camel.model.TemplatedRoutesDefinition; +import org.apache.camel.model.app.BeansDefinition; +import org.apache.camel.model.rest.RestDefinition; +import org.apache.camel.model.rest.RestsDefinition; +import org.apache.camel.spi.BeanRepository; +import org.apache.camel.spi.PackageScanClassResolver; import org.apache.camel.spi.Resource; import org.apache.camel.spi.annotations.RoutesLoader; import org.apache.camel.support.CachedResource; +import org.apache.camel.support.CamelContextHelper; +import org.apache.camel.support.DIRegistry; +import org.apache.camel.support.DefaultRegistry; import org.apache.camel.xml.in.ModelParser; import org.apache.camel.xml.io.util.XmlStreamDetector; import org.apache.camel.xml.io.util.XmlStreamInfo; @@ -72,6 +89,10 @@ public class XmlRoutesBuilderLoader extends RouteBuilderLoaderSupport { @Override public void configure() throws Exception { switch (xmlInfo.getRootElementName()) { + case "beans", "camel-app" -> + new ModelParser(resource, xmlInfo.getRootElementNamespace()) + .parseBeansDefinition() + .ifPresent(this::allInOne); case "routeTemplate", "routeTemplates" -> new ModelParser(resource, xmlInfo.getRootElementNamespace()) .parseRouteTemplatesDefinition() @@ -88,6 +109,8 @@ public class XmlRoutesBuilderLoader extends RouteBuilderLoaderSupport { new ModelParser(resource, xmlInfo.getRootElementNamespace()) .parseRoutesDefinition() .ifPresent(this::addRoutes); + default -> { + } } } @@ -95,10 +118,90 @@ public class XmlRoutesBuilderLoader extends RouteBuilderLoaderSupport { public void configuration() throws Exception { switch (xmlInfo.getRootElementName()) { case "routeConfigurations", "routeConfiguration" -> - new ModelParser(resource, xmlInfo.getRootElementNamespace()) - .parseRouteConfigurationsDefinition() - .ifPresent(this::addConfigurations); + new ModelParser(resource, xmlInfo.getRootElementNamespace()) + .parseRouteConfigurationsDefinition() + .ifPresent(this::addConfigurations); + default -> { + } + } + } + + private void allInOne(BeansDefinition app) { + // selected elements which can be found in camel-spring-xml's <camelContext> + + List<String> packagesToScan = new ArrayList<>(); + app.getComponentScanning().forEach(cs -> { + Boolean useJakartaInject = CamelContextHelper.parseBoolean(getCamelContext(), cs.getUseJsr330()); + if (useJakartaInject != null && useJakartaInject) { + packagesToScan.add(cs.getBasePackage()); + } + }); + if (!packagesToScan.isEmpty()) { + DIRegistry registry = null; + DefaultRegistry camelRegistry = getCamelContext().getRegistry(DefaultRegistry.class); + if (camelRegistry != null) { + List<BeanRepository> repos = camelRegistry.getRepositories(); + if (repos != null) { + Optional<BeanRepository> diRegistry + = repos.stream().filter(r -> DIRegistry.class.isAssignableFrom(r.getClass())).findAny(); + if (diRegistry.isPresent()) { + registry = (DIRegistry) diRegistry.get(); + } + } + } + if (registry != null) { + PackageScanClassResolver scanner + = getCamelContext().getCamelContextExtension().getContextPlugin(PackageScanClassResolver.class); + if (scanner != null) { + for (String pkg : packagesToScan) { + Set<Class<?>> classes = scanner.findAnnotated(Named.class, pkg); + for (Class<?> c : classes) { + registry.bind(c, c); + } + } + } + } } + + app.getRests().forEach(r -> { + List<RestDefinition> list = new ArrayList<>(); + list.add(r); + RestsDefinition def = new RestsDefinition(); + def.setRests(list); + setRestCollection(def); + }); + + app.getRouteConfigurations().forEach(rc -> { + List<RouteConfigurationDefinition> list = new ArrayList<>(); + list.add(rc); + RouteConfigurationsDefinition def = new RouteConfigurationsDefinition(); + def.setRouteConfigurations(list); + addConfigurations(def); + }); + + app.getRouteTemplates().forEach(rt -> { + List<RouteTemplateDefinition> list = new ArrayList<>(); + list.add(rt); + RouteTemplatesDefinition def = new RouteTemplatesDefinition(); + def.setRouteTemplates(list); + setRouteTemplateCollection(def); + }); + + app.getTemplatedRoutes().forEach(tr -> { + List<TemplatedRouteDefinition> list = new ArrayList<>(); + list.add(tr); + TemplatedRoutesDefinition def = new TemplatedRoutesDefinition(); + def.setTemplatedRoutes(list); + setTemplatedRouteCollection(def); + }); + + app.getRoutes().forEach(r -> { + List<RouteDefinition> list = new ArrayList<>(); + list.add(r); + RoutesDefinition def = new RoutesDefinition(); + def.setRoutes(list); + addRoutes(def); + }); } private void addRoutes(RoutesDefinition routes) { diff --git a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadAppTest.java b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadAppTest.java new file mode 100644 index 00000000000..89eb56bc862 --- /dev/null +++ b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadAppTest.java @@ -0,0 +1,67 @@ +/* + * 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.dsl.xml.io; + +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.spi.Resource; +import org.apache.camel.support.DIRegistry; +import org.apache.camel.support.DefaultRegistry; +import org.apache.camel.support.PluginHelper; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class XmlLoadAppTest { + + @Test + public void testLoadCamelAppFromXml() throws Exception { + try (DefaultCamelContext context = new DefaultCamelContext()) { + context.getCamelContextExtension().setRegistry(new DefaultRegistry(new DIRegistry())); + context.start(); + + // load route from XML and add them to the existing camel context + String[] contexts = new String[] { + "camel-app1.xml", + "camel-app2.xml" + }; + for (String r : contexts) { + Resource resource = PluginHelper.getResourceLoader(context).resolveResource( + "/org/apache/camel/dsl/xml/io/" + r); + + PluginHelper.getRoutesLoader(context).loadRoutes(resource); + } + + assertNotNull(context.getRoute("r1"), "Loaded r1 route should be there"); + assertNotNull(context.getRoute("r2"), "Loaded r2 route should be there"); + assertEquals(2, context.getRoutes().size()); + + // test that loaded route works + MockEndpoint y1 = context.getEndpoint("mock:y1", MockEndpoint.class); + y1.expectedBodiesReceived("Hello World"); + context.createProducerTemplate().sendBody("direct:x1", "I'm World"); + y1.assertIsSatisfied(); + + MockEndpoint y2 = context.getEndpoint("mock:y2", MockEndpoint.class); + y2.expectedBodiesReceived("Hello World"); + context.createProducerTemplate().sendBody("direct:x2", "I'm World"); + y2.assertIsSatisfied(); + } + } + +} diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainRegistry.java b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/Greeter.java similarity index 55% copy from core/camel-main/src/main/java/org/apache/camel/main/MainRegistry.java copy to dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/Greeter.java index 14928c99e7c..81f29e8d34b 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/MainRegistry.java +++ b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/Greeter.java @@ -14,24 +14,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.main; +package org.apache.camel.dsl.xml.io.beans; -import java.util.Set; +import jakarta.inject.Inject; +import jakarta.inject.Named; -import org.apache.camel.support.DefaultRegistry; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.util.StringHelper; -/** - * {@link org.apache.camel.spi.Registry} used by Camel Main. - */ -public final class MainRegistry extends DefaultRegistry { +@Named("bean-from-registry") +public class Greeter implements Processor { + + private final GreeterMessage message; - /** - * Finds beans in the registry by their type. - * - * @param type the type of the beans - * @return the types found. Returns an empty Set if none found. - */ - public <T> Set<T> findBindingsByType(Class<T> type) { - return fallbackRegistry.findByType(type); + @Inject + public Greeter(GreeterMessage message) { + this.message = message; } + + @Override + public void process(Exchange exchange) throws Exception { + String msg = exchange.getIn().getBody(String.class); + exchange.getIn().setBody(message.getMsg() + " " + StringHelper.after(msg, "I'm ")); + } + } diff --git a/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/support/package-info.java b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/GreeterMessage.java similarity index 79% rename from tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/support/package-info.java rename to dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/GreeterMessage.java index 9a670cd2628..f091c25c544 100644 --- a/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/support/package-info.java +++ b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/GreeterMessage.java @@ -14,8 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package org.apache.camel.dsl.xml.io.beans; -/** - * Package with classes that are used together with maven-resolver. - */ -package org.apache.camel.tooling.maven.support; +import jakarta.inject.Named; + +@Named +public class GreeterMessage { + + private final String msg = "Hello"; + + public String getMsg() { + return msg; + } + +} diff --git a/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app1.xml b/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app1.xml new file mode 100644 index 00000000000..c0075882276 --- /dev/null +++ b/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app1.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<camel-app xmlns="http://camel.apache.org/schema/spring"> + + <component-scan use-jsr-330="true" base-package="org.apache.camel.dsl.xml.io.beans" /> + + <route id="r1"> + <from uri="direct:x1"/> + <bean ref="bean-from-registry" /> + <to uri="mock:y1"/> + </route> + +</camel-app> diff --git a/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app2.xml b/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app2.xml new file mode 100644 index 00000000000..05d51ea6329 --- /dev/null +++ b/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app2.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<camel-app> + + <component-scan base-package="org.apache.camel.dsl.xml.io.beans" /> + + <route id="r2"> + <from uri="direct:x2"/> + <bean ref="bean-from-registry" /> + <to uri="mock:y2"/> + </route> + +</camel-app> diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java index ab61de5c701..35ca7a626cc 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java @@ -99,6 +99,9 @@ import org.apache.camel.model.ValueDefinition; import org.apache.camel.model.WhenDefinition; import org.apache.camel.model.WhenSkipSendToEndpointDefinition; import org.apache.camel.model.WireTapDefinition; +import org.apache.camel.model.app.ApplicationDefinition; +import org.apache.camel.model.app.BeansDefinition; +import org.apache.camel.model.app.ComponentScanDefinition; import org.apache.camel.model.cloud.BlacklistServiceCallServiceFilterConfiguration; import org.apache.camel.model.cloud.CachingServiceCallServiceDiscoveryConfiguration; import org.apache.camel.model.cloud.CombinedServiceCallServiceDiscoveryConfiguration; @@ -582,6 +585,71 @@ public final class ModelDeserializers extends YamlDeserializerSupport { } } + @YamlType( + nodes = "camel-app", + types = org.apache.camel.model.app.ApplicationDefinition.class, + order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1, + properties = { + @YamlProperty(name = "component-scan", type = "array:org.apache.camel.model.app.ComponentScanDefinition"), + @YamlProperty(name = "rest", type = "array:org.apache.camel.model.rest.RestDefinition"), + @YamlProperty(name = "route", type = "array:org.apache.camel.model.RouteDefinition"), + @YamlProperty(name = "route-configuration", type = "array:org.apache.camel.model.RouteConfigurationDefinition"), + @YamlProperty(name = "route-template", type = "array:org.apache.camel.model.RouteTemplateDefinition"), + @YamlProperty(name = "templated-route", type = "array:org.apache.camel.model.TemplatedRouteDefinition") + } + ) + public static class ApplicationDefinitionDeserializer extends YamlDeserializerBase<ApplicationDefinition> { + public ApplicationDefinitionDeserializer() { + super(ApplicationDefinition.class); + } + + @Override + protected ApplicationDefinition newInstance() { + return new ApplicationDefinition(); + } + + @Override + protected boolean setProperty(ApplicationDefinition target, String propertyKey, + String propertyName, Node node) { + switch(propertyKey) { + case "component-scan": { + java.util.List<org.apache.camel.model.app.ComponentScanDefinition> val = asFlatList(node, org.apache.camel.model.app.ComponentScanDefinition.class); + target.setComponentScanning(val); + break; + } + case "rest": { + java.util.List<org.apache.camel.model.rest.RestDefinition> val = asFlatList(node, org.apache.camel.model.rest.RestDefinition.class); + target.setRests(val); + break; + } + case "route-configuration": { + java.util.List<org.apache.camel.model.RouteConfigurationDefinition> val = asFlatList(node, org.apache.camel.model.RouteConfigurationDefinition.class); + target.setRouteConfigurations(val); + break; + } + case "route-template": { + java.util.List<org.apache.camel.model.RouteTemplateDefinition> val = asFlatList(node, org.apache.camel.model.RouteTemplateDefinition.class); + target.setRouteTemplates(val); + break; + } + case "route": { + java.util.List<org.apache.camel.model.RouteDefinition> val = asFlatList(node, org.apache.camel.model.RouteDefinition.class); + target.setRoutes(val); + break; + } + case "templated-route": { + java.util.List<org.apache.camel.model.TemplatedRouteDefinition> val = asFlatList(node, org.apache.camel.model.TemplatedRouteDefinition.class); + target.setTemplatedRoutes(val); + break; + } + default: { + return false; + } + } + return true; + } + } + @YamlType( nodes = "avro", inline = true, @@ -1040,6 +1108,71 @@ public final class ModelDeserializers extends YamlDeserializerSupport { } } + @YamlType( + nodes = "beans", + types = org.apache.camel.model.app.BeansDefinition.class, + order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1, + properties = { + @YamlProperty(name = "component-scan", type = "array:org.apache.camel.model.app.ComponentScanDefinition"), + @YamlProperty(name = "rest", type = "array:org.apache.camel.model.rest.RestDefinition"), + @YamlProperty(name = "route", type = "array:org.apache.camel.model.RouteDefinition"), + @YamlProperty(name = "route-configuration", type = "array:org.apache.camel.model.RouteConfigurationDefinition"), + @YamlProperty(name = "route-template", type = "array:org.apache.camel.model.RouteTemplateDefinition"), + @YamlProperty(name = "templated-route", type = "array:org.apache.camel.model.TemplatedRouteDefinition") + } + ) + public static class BeansDefinitionDeserializer extends YamlDeserializerBase<BeansDefinition> { + public BeansDefinitionDeserializer() { + super(BeansDefinition.class); + } + + @Override + protected BeansDefinition newInstance() { + return new BeansDefinition(); + } + + @Override + protected boolean setProperty(BeansDefinition target, String propertyKey, + String propertyName, Node node) { + switch(propertyKey) { + case "component-scan": { + java.util.List<org.apache.camel.model.app.ComponentScanDefinition> val = asFlatList(node, org.apache.camel.model.app.ComponentScanDefinition.class); + target.setComponentScanning(val); + break; + } + case "rest": { + java.util.List<org.apache.camel.model.rest.RestDefinition> val = asFlatList(node, org.apache.camel.model.rest.RestDefinition.class); + target.setRests(val); + break; + } + case "route-configuration": { + java.util.List<org.apache.camel.model.RouteConfigurationDefinition> val = asFlatList(node, org.apache.camel.model.RouteConfigurationDefinition.class); + target.setRouteConfigurations(val); + break; + } + case "route-template": { + java.util.List<org.apache.camel.model.RouteTemplateDefinition> val = asFlatList(node, org.apache.camel.model.RouteTemplateDefinition.class); + target.setRouteTemplates(val); + break; + } + case "route": { + java.util.List<org.apache.camel.model.RouteDefinition> val = asFlatList(node, org.apache.camel.model.RouteDefinition.class); + target.setRoutes(val); + break; + } + case "templated-route": { + java.util.List<org.apache.camel.model.TemplatedRouteDefinition> val = asFlatList(node, org.apache.camel.model.TemplatedRouteDefinition.class); + target.setTemplatedRoutes(val); + break; + } + default: { + return false; + } + } + return true; + } + } + @YamlType( nodes = { "bearer-token", @@ -1976,6 +2109,46 @@ public final class ModelDeserializers extends YamlDeserializerSupport { } } + @YamlType( + types = org.apache.camel.model.app.ComponentScanDefinition.class, + order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1, + properties = { + @YamlProperty(name = "base-package", type = "string"), + @YamlProperty(name = "use-jsr-330", type = "boolean") + } + ) + public static class ComponentScanDefinitionDeserializer extends YamlDeserializerBase<ComponentScanDefinition> { + public ComponentScanDefinitionDeserializer() { + super(ComponentScanDefinition.class); + } + + @Override + protected ComponentScanDefinition newInstance() { + return new ComponentScanDefinition(); + } + + @Override + protected boolean setProperty(ComponentScanDefinition target, String propertyKey, + String propertyName, Node node) { + switch(propertyKey) { + case "base-package": { + String val = asText(node); + target.setBasePackage(val); + break; + } + case "use-jsr-330": { + String val = asText(node); + target.setUseJsr330(val); + break; + } + default: { + return false; + } + } + return true; + } + } + @YamlType( nodes = "constant", inline = true, diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java index d3dbc50422c..1cd50129800 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java @@ -22,6 +22,8 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve case "api-key": return new ModelDeserializers.ApiKeyDefinitionDeserializer(); case "apiKey": return new ModelDeserializers.ApiKeyDefinitionDeserializer(); case "org.apache.camel.model.rest.ApiKeyDefinition": return new ModelDeserializers.ApiKeyDefinitionDeserializer(); + case "camel-app": return new ModelDeserializers.ApplicationDefinitionDeserializer(); + case "org.apache.camel.model.app.ApplicationDefinition": return new ModelDeserializers.ApplicationDefinitionDeserializer(); case "avro": return new ModelDeserializers.AvroDataFormatDeserializer(); case "org.apache.camel.model.dataformat.AvroDataFormat": return new ModelDeserializers.AvroDataFormatDeserializer(); case "barcode": return new ModelDeserializers.BarcodeDataFormatDeserializer(); @@ -35,6 +37,8 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve case "org.apache.camel.model.config.BatchResequencerConfig": return new ModelDeserializers.BatchResequencerConfigDeserializer(); case "bean": return new ModelDeserializers.BeanDefinitionDeserializer(); case "org.apache.camel.model.BeanDefinition": return new ModelDeserializers.BeanDefinitionDeserializer(); + case "beans": return new ModelDeserializers.BeansDefinitionDeserializer(); + case "org.apache.camel.model.app.BeansDefinition": return new ModelDeserializers.BeansDefinitionDeserializer(); case "bearer-token": return new ModelDeserializers.BearerTokenDefinitionDeserializer(); case "bearerToken": return new ModelDeserializers.BearerTokenDefinitionDeserializer(); case "org.apache.camel.model.rest.BearerTokenDefinition": return new ModelDeserializers.BearerTokenDefinitionDeserializer(); @@ -67,6 +71,7 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve case "combined-service-filter": return new ModelDeserializers.CombinedServiceCallServiceFilterConfigurationDeserializer(); case "combinedServiceFilter": return new ModelDeserializers.CombinedServiceCallServiceFilterConfigurationDeserializer(); case "org.apache.camel.model.cloud.CombinedServiceCallServiceFilterConfiguration": return new ModelDeserializers.CombinedServiceCallServiceFilterConfigurationDeserializer(); + case "org.apache.camel.model.app.ComponentScanDefinition": return new ModelDeserializers.ComponentScanDefinitionDeserializer(); case "constant": return new ModelDeserializers.ConstantExpressionDeserializer(); case "org.apache.camel.model.language.ConstantExpression": return new ModelDeserializers.ConstantExpressionDeserializer(); case "consul-service-discovery": return new ModelDeserializers.ConsulServiceCallServiceDiscoveryConfigurationDeserializer(); diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camel-yaml-dsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camel-yaml-dsl.json index 43b22904ea8..dc9ea6efc51 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camel-yaml-dsl.json +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camel-yaml-dsl.json @@ -3665,6 +3665,99 @@ }, "required" : [ "uri" ] }, + "org.apache.camel.model.app.ApplicationDefinition" : { + "type" : "object", + "properties" : { + "component-scan" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.app.ComponentScanDefinition" + } + }, + "rest" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.rest.RestDefinition" + } + }, + "route" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteDefinition" + } + }, + "route-configuration" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteConfigurationDefinition" + } + }, + "route-template" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteTemplateDefinition" + } + }, + "templated-route" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.TemplatedRouteDefinition" + } + } + } + }, + "org.apache.camel.model.app.BeansDefinition" : { + "type" : "object", + "properties" : { + "component-scan" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.app.ComponentScanDefinition" + } + }, + "rest" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.rest.RestDefinition" + } + }, + "route" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteDefinition" + } + }, + "route-configuration" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteConfigurationDefinition" + } + }, + "route-template" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteTemplateDefinition" + } + }, + "templated-route" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.TemplatedRouteDefinition" + } + } + } + }, + "org.apache.camel.model.app.ComponentScanDefinition" : { + "type" : "object", + "properties" : { + "base-package" : { + "type" : "string" + }, + "use-jsr-330" : { + "type" : "boolean" + } + } + }, "org.apache.camel.model.cloud.BlacklistServiceCallServiceFilterConfiguration" : { "type" : "object", "properties" : { diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json index 6ddf8e25943..6f904d77af0 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json @@ -3575,6 +3575,99 @@ }, "required" : [ "uri" ] }, + "org.apache.camel.model.app.ApplicationDefinition" : { + "type" : "object", + "properties" : { + "componentScan" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.app.ComponentScanDefinition" + } + }, + "rest" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.rest.RestDefinition" + } + }, + "route" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteDefinition" + } + }, + "routeConfiguration" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteConfigurationDefinition" + } + }, + "routeTemplate" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteTemplateDefinition" + } + }, + "templatedRoute" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.TemplatedRouteDefinition" + } + } + } + }, + "org.apache.camel.model.app.BeansDefinition" : { + "type" : "object", + "properties" : { + "componentScan" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.app.ComponentScanDefinition" + } + }, + "rest" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.rest.RestDefinition" + } + }, + "route" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteDefinition" + } + }, + "routeConfiguration" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteConfigurationDefinition" + } + }, + "routeTemplate" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.RouteTemplateDefinition" + } + }, + "templatedRoute" : { + "type" : "array", + "items" : { + "$ref" : "#/items/definitions/org.apache.camel.model.TemplatedRouteDefinition" + } + } + } + }, + "org.apache.camel.model.app.ComponentScanDefinition" : { + "type" : "object", + "properties" : { + "basePackage" : { + "type" : "string" + }, + "useJsr330" : { + "type" : "boolean" + } + } + }, "org.apache.camel.model.cloud.BlacklistServiceCallServiceFilterConfiguration" : { "type" : "object", "properties" : { diff --git a/tooling/camel-tooling-maven/pom.xml b/tooling/camel-tooling-maven/pom.xml index 378cb70cc71..adecc316e89 100644 --- a/tooling/camel-tooling-maven/pom.xml +++ b/tooling/camel-tooling-maven/pom.xml @@ -47,12 +47,6 @@ <artifactId>camel-support</artifactId> </dependency> - <dependency> - <groupId>jakarta.inject</groupId> - <artifactId>jakarta.inject-api</artifactId> - <version>${jakarta-inject-version}</version> - </dependency> - <!-- maven / maven resolver --> <dependency> <groupId>org.apache.maven</groupId> diff --git a/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/MavenDownloaderImpl.java b/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/MavenDownloaderImpl.java index 3340e24fbb5..ae59d11514e 100644 --- a/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/MavenDownloaderImpl.java +++ b/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/MavenDownloaderImpl.java @@ -37,8 +37,8 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; +import org.apache.camel.support.DIRegistry; import org.apache.camel.support.service.ServiceSupport; -import org.apache.camel.tooling.maven.support.DIRegistry; import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader; import org.apache.maven.model.building.DefaultModelBuilderFactory; import org.apache.maven.model.building.ModelBuilder; diff --git a/tooling/camel-tooling-maven/src/test/java/org/apache/camel/tooling/maven/MavenResolverTest.java b/tooling/camel-tooling-maven/src/test/java/org/apache/camel/tooling/maven/MavenResolverTest.java index 7ce93bdbdcc..d871db62043 100644 --- a/tooling/camel-tooling-maven/src/test/java/org/apache/camel/tooling/maven/MavenResolverTest.java +++ b/tooling/camel-tooling-maven/src/test/java/org/apache/camel/tooling/maven/MavenResolverTest.java @@ -26,7 +26,7 @@ import java.util.List; import java.util.Properties; import java.util.concurrent.TimeUnit; -import org.apache.camel.tooling.maven.support.DIRegistry; +import org.apache.camel.support.DIRegistry; import org.apache.camel.util.FileUtil; import org.apache.commons.codec.binary.Hex; import org.apache.http.Header; diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ModelXmlParserGeneratorMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ModelXmlParserGeneratorMojo.java index 393a90f88f3..407b6d2aae7 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ModelXmlParserGeneratorMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ModelXmlParserGeneratorMojo.java @@ -108,6 +108,8 @@ public class ModelXmlParserGeneratorMojo extends AbstractGeneratorMojo { private Class<?> restsDefinitionClass; private Class<?> processorDefinitionClass; private Class<?> dataFormatDefinitionClass; + private Class<?> beansDefinitionClass; + private Class<?> applicationDefinitionClass; @Override public void execute(MavenProject project, MavenProjectHelper projectHelper, BuildContext buildContext) @@ -144,6 +146,8 @@ public class ModelXmlParserGeneratorMojo extends AbstractGeneratorMojo { processorDefinitionClass = loadClass(classLoader, MODEL_PACKAGE + ".ProcessorDefinition"); restsDefinitionClass = loadClass(classLoader, MODEL_PACKAGE + ".rest.RestsDefinition"); expressionDefinitionClass = loadClass(classLoader, MODEL_PACKAGE + ".language.ExpressionDefinition"); + beansDefinitionClass = loadClass(classLoader, MODEL_PACKAGE + ".app.BeansDefinition"); + applicationDefinitionClass = loadClass(classLoader, MODEL_PACKAGE + ".app.ApplicationDefinition"); String resName = routesDefinitionClass.getName().replace('.', '/') + ".class"; String url = classLoader.getResource(resName).toExternalForm().replace(resName, JandexStore.DEFAULT_NAME); @@ -494,6 +498,22 @@ public class ModelXmlParserGeneratorMojo extends AbstractGeneratorMojo { } return " noValueHandler()"; }); + + if (clazz == beansDefinitionClass || clazz == applicationDefinitionClass) { + // for beans/camel-app we want public methods to be invoked by camel-xml-io-dsl + + parser.addMethod().setPublic() + .setReturnType(new GenericType(Optional.class, new GenericType(clazz))) + .setName("parse" + name) + .addThrows(IOException.class) + .addThrows(XML_PULL_PARSER_EXCEPTION) + .setBody(String.format("String tag = getNextTag(\"%s\", \"%s\");", "beans", "camel-app"), + "if (tag != null) {", + String.format(" return Optional.of(doParse%s());", name), + "}", + "return Optional.empty();"); + } + if (clazz == routesDefinitionClass || clazz == routeTemplatesDefinitionClass || clazz == templatedRoutesDefinitionClass || clazz == restsDefinitionClass || clazz == routeConfigurationsDefinitionClass) { // for routes/rests/routeTemplates we want to support single-mode as well, this means