Author: davsclaus Date: Fri Jun 12 12:50:42 2009 New Revision: 784101 URL: http://svn.apache.org/viewvc?rev=784101&view=rev Log: CAMEL-1701: Added support for camel-spring detecting and adding InterceptorStrategy from the spring application context. Allows you to easily add interceptors that are container wide.
Added: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptor.java (with props) camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.java (with props) camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.xml - copied, changed from r784038, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/traceFormatterTest.xml Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DefaultChannel.java camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DefaultChannel.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DefaultChannel.java?rev=784101&r1=784100&r2=784101&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DefaultChannel.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DefaultChannel.java Fri Jun 12 12:50:42 2009 @@ -134,7 +134,8 @@ // wrap the output with the interceptors Processor target = nextProcessor; for (InterceptStrategy strategy : interceptors) { - target = strategy.wrapProcessorInInterceptors(outputDefinition, target, nextProcessor); + Processor next = target == nextProcessor ? null : nextProcessor; + target = strategy.wrapProcessorInInterceptors(outputDefinition, target, next); } // sets the delegate to our wrapped output Modified: camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java?rev=784101&r1=784100&r2=784101&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java (original) +++ camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java Fri Jun 12 12:50:42 2009 @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; @@ -55,6 +56,7 @@ import org.apache.camel.processor.interceptor.Tracer; import org.apache.camel.spi.ClassResolver; import org.apache.camel.spi.FactoryFinderResolver; +import org.apache.camel.spi.InterceptStrategy; import org.apache.camel.spi.LifecycleStrategy; import org.apache.camel.spi.PackageScanClassResolver; import org.apache.camel.spi.Registry; @@ -171,22 +173,41 @@ if (properties != null) { getContext().setProperties(properties.asMap()); } + // set the resolvers first PackageScanClassResolver packageResolver = getBeanForType(PackageScanClassResolver.class); if (packageResolver != null) { + LOG.info("Using custom PackageScanClassResolver: " + packageResolver); getContext().setPackageScanClassResolver(packageResolver); } ClassResolver classResolver = getBeanForType(ClassResolver.class); if (classResolver != null) { + LOG.info("Using custom ClassResolver: " + classResolver); getContext().setClassResolver(classResolver); } FactoryFinderResolver factoryFinderResolver = getBeanForType(FactoryFinderResolver.class); if (factoryFinderResolver != null) { + LOG.info("Using custom FactoryFinderResolver: " + factoryFinderResolver); getContext().setFactoryFinderResolver(factoryFinderResolver); } + // set the lifecycle strategy if defined + LifecycleStrategy lifecycleStrategy = getBeanForType(LifecycleStrategy.class); + if (lifecycleStrategy != null) { + LOG.info("Using custom LifecycleStrategy: " + lifecycleStrategy); + getContext().setLifecycleStrategy(lifecycleStrategy); + } + + // set the strategy if defined + Registry registry = getBeanForType(Registry.class); + if (registry != null) { + LOG.info("Using custom Registry: " + registry); + getContext().setRegistry(registry); + } + Debugger debugger = getBeanForType(Debugger.class); if (debugger != null) { + LOG.info("Using custom Debugger: " + debugger); getContext().addInterceptStrategy(debugger); } @@ -197,29 +218,30 @@ if (formatter != null) { tracer.setFormatter(formatter); } + LOG.info("Using custom Tracer: " + tracer); getContext().addInterceptStrategy(tracer); } HandleFault handleFault = getBeanForType(HandleFault.class); if (handleFault != null) { + LOG.info("Using custom HandleFault: " + handleFault); getContext().addInterceptStrategy(handleFault); } Delayer delayer = getBeanForType(Delayer.class); if (delayer != null) { + LOG.info("Using custom Delayer: " + delayer); getContext().addInterceptStrategy(delayer); } - // set the lifecycle strategy if defined - LifecycleStrategy lifecycleStrategy = getBeanForType(LifecycleStrategy.class); - if (lifecycleStrategy != null) { - getContext().setLifecycleStrategy(lifecycleStrategy); - } - - // set the strategy if defined - Registry registry = getBeanForType(Registry.class); - if (registry != null) { - getContext().setRegistry(registry); + // add global interceptors + Map<String, InterceptStrategy> strategies = getContext().getRegistry().lookupByType(InterceptStrategy.class); + if (strategies != null && !strategies.isEmpty()) { + for (String id : strategies.keySet()) { + InterceptStrategy strategy = strategies.get(id); + LOG.info("Using custom intercept strategy with id: " + id + " and implementation:" + strategy); + getContext().addInterceptStrategy(strategy); + } } // Set the application context and camelContext for the beanPostProcessor @@ -682,7 +704,7 @@ if (errorHandlerRef != null) { ErrorHandlerBuilder errorHandlerBuilder = (ErrorHandlerBuilder) getApplicationContext().getBean(errorHandlerRef, ErrorHandlerBuilder.class); if (errorHandlerBuilder == null) { - throw new IllegalArgumentException("Could not find bean: " + errorHandlerRef); + throw new IllegalArgumentException("Cannot find ErrorHandlerBuilder bean with id: " + errorHandlerRef); } ctx.setErrorHandlerBuilder(errorHandlerBuilder); } @@ -752,6 +774,9 @@ for (String name : getPackages()) { name = ObjectHelper.normalizeClassName(name); if (ObjectHelper.isNotEmpty(name)) { + if (LOG.isTraceEnabled()) { + LOG.trace("Using package: " + name + " to scan for RouteBuilder classes"); + } packages.add(name); } } Added: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptor.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptor.java?rev=784101&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptor.java (added) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptor.java Fri Jun 12 12:50:42 2009 @@ -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.spring.interceptor; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.model.ProcessorDefinition; +import org.apache.camel.spi.InterceptStrategy; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @version $Revision$ + */ +// START SNIPPET: e1 +public class ContainerWideInterceptor implements InterceptStrategy { + + private static final transient Log LOG = LogFactory.getLog(ContainerWideInterceptor.class); + private static int count; + + public Processor wrapProcessorInInterceptors(final ProcessorDefinition processorDefinition, + final Processor target, final Processor nextTarget) throws Exception { + + // as this is based on an unit test we are a bit lazy and just create an inlined processor + // where we implement our interception logic. + return new Processor() { + public void process(Exchange exchange) throws Exception { + // we just count number of interceptions + count++; + LOG.info("I am the container wide interceptor. Intercepted total count: " + count); + // its important that we delegate to the real target so we let target process the exchange + target.process(exchange); + } + + @Override + public String toString() { + return "ContainerWideInterceptor[" + target + "]"; + } + }; + } + + public int getCount() { + return count; + } +} +// END SNIPPET: e1 Propchange: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptor.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptor.java ------------------------------------------------------------------------------ svn:keywords = Rev Date Added: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.java?rev=784101&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.java (added) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.java Fri Jun 12 12:50:42 2009 @@ -0,0 +1,84 @@ +/** + * 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.spring.interceptor; + +import org.apache.camel.CamelContext; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.TestSupport; +import org.apache.camel.component.mock.MockEndpoint; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @version $Revision$ + */ +public class ContainerWideInterceptorTest extends TestSupport { + + private CamelContext camel1; + private CamelContext camel2; + private ApplicationContext ac; + private ContainerWideInterceptor myInterceptor; + + @Override + protected void setUp() throws Exception { + super.setUp(); + ac = new ClassPathXmlApplicationContext("/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.xml"); + camel1 = (CamelContext) ac.getBean("camel1"); + camel2 = (CamelContext) ac.getBean("camel2"); + myInterceptor = (ContainerWideInterceptor) ac.getBean("myInterceptor"); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + camel2.stop(); + camel1.stop(); + } + + public void testOne() throws Exception { + int start = myInterceptor.getCount(); + + MockEndpoint result = camel1.getEndpoint("mock:result", MockEndpoint.class); + result.expectedBodiesReceived("Hello World"); + + ProducerTemplate template = camel1.createProducerTemplate(); + template.sendBody("direct:one", "Hello World"); + + result.assertIsSatisfied(); + + // lets see if the counter is +1 since last (has 1 step in the route) + int delta = myInterceptor.getCount() - start; + assertEquals("Should have been counted +1", 1, delta); + } + + public void testTwo() throws Exception { + int start = myInterceptor.getCount(); + + MockEndpoint result = camel2.getEndpoint("mock:result", MockEndpoint.class); + result.expectedBodiesReceived("Bye World"); + + ProducerTemplate template = camel2.createProducerTemplate(); + template.sendBody("direct:two", "Bye World"); + + result.assertIsSatisfied(); + + // lets see if the counter is +2 since last (has 2 steps in the route) + int delta = myInterceptor.getCount() - start; + assertEquals("Should have been counted +2", 2, delta); + } + +} Propchange: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.java ------------------------------------------------------------------------------ svn:keywords = Rev Date Copied: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.xml (from r784038, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/traceFormatterTest.xml) URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.xml?p2=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.xml&p1=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/traceFormatterTest.xml&r1=784038&r2=784101&rev=784101&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/traceFormatterTest.xml (original) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/interceptor/ContainerWideInterceptorTest.xml Fri Jun 12 12:50:42 2009 @@ -21,21 +21,33 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd "> + <!-- START SNIPPET: e1 --> - <!-- SNIPPET START: e1 --> - <bean id="traceFormatter" class="org.apache.camel.processor.interceptor.DefaultTraceFormatter"> - <property name="showBody" value="true"/> - <property name="showBodyType" value="false"/> - <property name="showBreadCrumb" value="false"/> - <property name="maxChars" value="100"/> - </bean> + <!-- here we define a spring bean that is our container wide interceptor + its important to notice that the class ContainerWideInterceptor implements + org.apache.camel.spi.InterceptStrategy that allows us to plugin our interceptors + Camel will at startup automatic look for any beans in spring registry that is an + instance of org.apache.camel.spi.InterceptStrategy and add it as interceptor + to all its routes. Using this we are capable of defining container wide interceptors + that gets used in all camel contests we define with spring --> + <bean id="myInterceptor" class="org.apache.camel.spring.interceptor.ContainerWideInterceptor"/> - <camelContext id="camel" trace="true" xmlns="http://camel.apache.org/schema/spring"> + <!-- here we have the 1st CamelContext --> + <camelContext id="camel1" xmlns="http://camel.apache.org/schema/spring"> <route> - <from uri="direct:start"/> + <from uri="direct:one"/> <to uri="mock:result"/> </route> </camelContext> - <!-- SNIPPET END: e1 --> + + <!-- and there we have the 2nd CamelContext --> + <camelContext id="camel2" xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:two"/> + <to uri="log:two"/> + <to uri="mock:result"/> + </route> + </camelContext> + <!-- END SNIPPET: e1 --> </beans>