This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
commit d4a22ecfa69c0f1810a5bd349da785813c46ce5d Author: Claus Ibsen <[email protected]> AuthorDate: Fri Jun 25 16:18:07 2021 +0200 CAMEL-16630: camel-core - EIP model that is configured with bean from registry, can now use #class: to specify creating a new bean from the given class instead of lookup. --- .../org/apache/camel/reifier/AbstractReifier.java | 63 +++++++++++++++++++- .../enricher/EnricherRefBeanClassTest.java | 67 ++++++++++++++++++++++ .../org/apache/camel/dsl/yaml/AggregateTest.groovy | 30 ++++++++++ 3 files changed, 157 insertions(+), 3 deletions(-) diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AbstractReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AbstractReifier.java index e6b67f1..efdd572 100644 --- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AbstractReifier.java +++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AbstractReifier.java @@ -26,12 +26,15 @@ import org.apache.camel.Expression; import org.apache.camel.NoSuchEndpointException; import org.apache.camel.Predicate; import org.apache.camel.Route; +import org.apache.camel.RuntimeCamelException; import org.apache.camel.model.ExpressionSubElementDefinition; import org.apache.camel.model.language.ExpressionDefinition; import org.apache.camel.reifier.language.ExpressionReifier; import org.apache.camel.spi.BeanRepository; import org.apache.camel.support.CamelContextHelper; +import org.apache.camel.support.PropertyBindingSupport; import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.StringHelper; public abstract class AbstractReifier implements BeanRepository { @@ -147,15 +150,69 @@ public abstract class AbstractReifier implements BeanRepository { @Override public Object lookupByName(String name) { - return getRegistry().lookupByName(name); + if (name != null && name.startsWith("#class:")) { + return createBean(name, Object.class); + } else { + return getRegistry().lookupByName(name); + } } public <T> T lookup(String name, Class<T> type) { - return lookupByNameAndType(name, type); + if (name != null && name.startsWith("#class:")) { + return createBean(name, type); + } else { + return lookupByNameAndType(name, type); + } } public <T> T lookupByNameAndType(String name, Class<T> type) { - return getRegistry().lookupByNameAndType(name, type); + if (name != null && name.startsWith("#class:")) { + return createBean(name, type); + } else { + return getRegistry().lookupByNameAndType(name, type); + } + } + + private <T> T createBean(String name, Class<T> type) { + try { + return doCreateBean(name, type); + } catch (Exception e) { + throw RuntimeCamelException.wrapRuntimeException(e); + } + } + + private <T> T doCreateBean(String name, Class<T> type) throws Exception { + Object answer; + + // if there is a factory method then the class/bean should be created in a different way + String className; + String factoryMethod = null; + String parameters = null; + className = name.substring(7); + if (className.endsWith(")") && className.indexOf('(') != -1) { + parameters = StringHelper.after(className, "("); + parameters = parameters.substring(0, parameters.length() - 1); // clip last ) + className = StringHelper.before(className, "("); + } + if (className != null && className.indexOf('#') != -1) { + factoryMethod = StringHelper.after(className, "#"); + className = StringHelper.before(className, "#"); + } + Class<?> clazz = camelContext.getClassResolver().resolveMandatoryClass(className); + + if (factoryMethod != null && parameters != null) { + answer = PropertyBindingSupport.newInstanceFactoryParameters(camelContext, clazz, factoryMethod, parameters); + } else if (factoryMethod != null) { + answer = camelContext.getInjector().newInstance(type, factoryMethod); + } else if (parameters != null) { + answer = PropertyBindingSupport.newInstanceConstructorParameters(camelContext, clazz, parameters); + } else { + answer = camelContext.getInjector().newInstance(clazz); + } + if (answer == null) { + throw new IllegalStateException("Cannot create bean: " + name); + } + return type.cast(answer); } @Override diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/enricher/EnricherRefBeanClassTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/enricher/EnricherRefBeanClassTest.java new file mode 100644 index 0000000..eabe781 --- /dev/null +++ b/core/camel-core/src/test/java/org/apache/camel/processor/enricher/EnricherRefBeanClassTest.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.processor.enricher; + +import org.apache.camel.ContextTestSupport; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockComponent; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.spi.Registry; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class EnricherRefBeanClassTest extends ContextTestSupport { + + private MockEndpoint cool = new MockEndpoint("mock:cool", new MockComponent(context)); + + @Override + protected Registry createRegistry() throws Exception { + Registry jndi = super.createRegistry(); + jndi.bind("cool", cool); + return jndi; + } + + @Test + public void testEnrichRef() throws Exception { + cool.whenAnyExchangeReceived(new Processor() { + public void process(Exchange exchange) throws Exception { + exchange.getMessage().setBody("Bye World"); + } + }); + cool.expectedBodiesReceived("Hello World"); + + String out = template.requestBody("direct:start", "Hello World", String.class); + assertEquals("Bye World", out); + + cool.assertIsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + cool.setCamelContext(context); + + from("direct:start").enrich().simple("ref:cool").aggregationStrategyRef("#class:org.apache.camel.processor.aggregate.UseLatestAggregationStrategy"); + } + }; + } +} diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/AggregateTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/AggregateTest.groovy index 8ed4ee4..5e96353 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/AggregateTest.groovy +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/AggregateTest.groovy @@ -114,4 +114,34 @@ class AggregateTest extends YamlTestSupport { def ex = thrown(FailedToCreateRouteException) ex.message.contains('Failed to create route') } + + def 'aggregate (strategy-ref class)'() { + setup: + loadRoutes ''' + - from: + uri: "direct:route" + steps: + - aggregate: + strategy-ref: "#class:org.apache.camel.processor.aggregate.UseLatestAggregationStrategy" + completion-size: 2 + correlation-expression: + simple: "${header.StockSymbol}" + steps: + - to: "mock:route" + ''' + + withMock('mock:route') { + expectedBodiesReceived '2', '4' + } + + when: + withTemplate { + to('direct:route').withBody('1').withHeader('StockSymbol', 1).send() + to('direct:route').withBody('2').withHeader('StockSymbol', 1).send() + to('direct:route').withBody('3').withHeader('StockSymbol', 2).send() + to('direct:route').withBody('4').withHeader('StockSymbol', 2).send() + } + then: + MockEndpoint.assertIsSatisfied(context) + } }
