Author: davsclaus Date: Sun Jun 3 09:40:19 2012 New Revision: 1345637 URL: http://svn.apache.org/viewvc?rev=1345637&view=rev Log: CAMEL-3547: Added bridge property placeholder between Spring and Camel, to make it easier to use Spring placeholders in Camel apps, without double configuration.
Added: camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/BridgePropertyPlaceholderConfigurer.java camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurer2Test.java camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.java camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/HelloBean.java camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurer2Test.xml camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.xml Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/properties/PropertiesResolver.java camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/cheese.properties Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/properties/PropertiesResolver.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/properties/PropertiesResolver.java?rev=1345637&r1=1345636&r2=1345637&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/component/properties/PropertiesResolver.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/properties/PropertiesResolver.java Sun Jun 3 09:40:19 2012 @@ -32,10 +32,10 @@ public interface PropertiesResolver { /** * Resolve properties from the given uri * - * * @param context the camel context * @param ignoreMissingLocation ignore silently if the property file is missing - * @param uri uri(s) defining the source(s) @return the properties + * @param uri uri(s) defining the source(s) + * @return the properties * @throws Exception is thrown if resolving the properties failed */ Properties resolveProperties(CamelContext context, boolean ignoreMissingLocation, String... uri) throws Exception; 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=1345637&r1=1345636&r2=1345637&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 Sun Jun 3 09:40:19 2012 @@ -18,6 +18,7 @@ package org.apache.camel.spring; 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; @@ -31,6 +32,7 @@ import org.apache.camel.RoutesBuilder; import org.apache.camel.ShutdownRoute; import org.apache.camel.ShutdownRunningTask; import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.properties.PropertiesComponent; import org.apache.camel.core.xml.AbstractCamelContextFactoryBean; import org.apache.camel.core.xml.CamelJMXAgentDefinition; import org.apache.camel.core.xml.CamelPropertyPlaceholderDefinition; @@ -51,6 +53,7 @@ import org.apache.camel.model.config.Pro import org.apache.camel.model.dataformat.DataFormatsDefinition; import org.apache.camel.spi.PackageScanFilter; import org.apache.camel.spi.Registry; +import org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; @@ -232,6 +235,40 @@ public class CamelContextFactoryBean ext } } + @Override + protected void initPropertyPlaceholder() throws Exception { + super.initPropertyPlaceholder(); + + Map<String, BridgePropertyPlaceholderConfigurer> beans = applicationContext.getBeansOfType(BridgePropertyPlaceholderConfigurer.class); + if (beans.size() == 1) { + // setup properties component that uses this beans + BridgePropertyPlaceholderConfigurer configurer = beans.values().iterator().next(); + String id = beans.keySet().iterator().next(); + LOG.info("Bridging Camel and Spring property placeholder configurer with id: " + id); + + // get properties component + PropertiesComponent pc = getContext().getComponent("properties", PropertiesComponent.class); + // replace existing resolver with us + configurer.setResolver(pc.getPropertiesResolver()); + String ref = "ref:" + id; + pc.setPropertiesResolver(configurer); + // and update locations to have our as ref first + String[] locations = pc.getLocations(); + String[] updatedLocations; + if (locations != null && locations.length > 0) { + updatedLocations = new String[locations.length + 1]; + updatedLocations[0] = ref; + System.arraycopy(locations, 0, updatedLocations, 1, locations.length); + } else { + updatedLocations = new String[]{ref}; + } + pc.setLocations(updatedLocations); + } else if (beans.size() > 1) { + LOG.warn("Cannot bridge Camel and Spring property placeholders, as only exact 1 bean of type CamelSpringPropertyPlaceholderConfigurer" + + " must be defined, was {} beans", beans.size()); + } + } + public void onApplicationEvent(ApplicationEvent event) { // From Spring 3.0.1, The BeanFactory applicationEventListener // and Bean's applicationEventListener will be called, @@ -248,7 +285,7 @@ public class CamelContextFactoryBean ext // now lets start the CamelContext so that all its possible // dependencies are initialized try { - LOG.debug("Starting the context now!"); + LOG.trace("Starting the context now"); getContext().start(); } catch (Exception e) { throw wrapRuntimeCamelException(e); Added: camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/BridgePropertyPlaceholderConfigurer.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/BridgePropertyPlaceholderConfigurer.java?rev=1345637&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/BridgePropertyPlaceholderConfigurer.java (added) +++ camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/spi/BridgePropertyPlaceholderConfigurer.java Sun Jun 3 09:40:19 2012 @@ -0,0 +1,78 @@ +/** + * 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.spi; + +import java.util.Properties; + +import org.apache.camel.CamelContext; +import org.apache.camel.component.properties.PropertiesResolver; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; + +/** + * A {@link PropertyPlaceholderConfigurer} that bridges Camel's <a href="http://camel.apache.org/using-propertyplaceholder.html"> + * property placeholder</a> with the Spring property placeholder mechanism. + */ +public class BridgePropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer implements PropertiesResolver { + + // NOTE: this class must be in the spi package as if its in the root package, then Spring fails to parse the XML + // files due some weird spring issue. But that is okay as having this class in the spi package is fine anyway. + + private final Properties properties = new Properties(); + private PropertiesResolver resolver; + private String id; + + @Override + protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException { + // store all the spring properties so we can refer to them later + properties.putAll(props); + super.processProperties(beanFactoryToProcess, props); + } + + @Override + public void setBeanName(String beanName) { + this.id = beanName; + super.setBeanName(beanName); + } + + @Override + public Properties resolveProperties(CamelContext context, boolean ignoreMissingLocation, String... uri) throws Exception { + // return the spring properties, if it + Properties answer = new Properties(); + for (String u : uri) { + String ref = "ref:" + id; + if (ref.equals(u)) { + answer.putAll(properties); + } else if (resolver != null) { + Properties p = resolver.resolveProperties(context, ignoreMissingLocation, u); + if (p != null) { + answer.putAll(p); + } + } + } + if (answer.isEmpty()) { + return null; + } else { + return answer; + } + } + + public void setResolver(PropertiesResolver resolver) { + this.resolver = resolver; + } +} Added: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurer2Test.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurer2Test.java?rev=1345637&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurer2Test.java (added) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurer2Test.java Sun Jun 3 09:40:19 2012 @@ -0,0 +1,41 @@ +/** + * 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.component.properties; + +import org.apache.camel.spring.SpringTestSupport; +import org.springframework.context.support.AbstractXmlApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * + */ +public class CamelSpringPropertyPlaceholderConfigurer2Test extends SpringTestSupport { + + @Override + protected AbstractXmlApplicationContext createApplicationContext() { + return new ClassPathXmlApplicationContext("org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurer2Test.xml"); + } + + public void testCamelSpringPropertyPlaceholderConfigurerTest() throws Exception { + getMockEndpoint("mock:result").expectedBodiesReceived("Bonjour Camel"); + + template.sendBody("direct:bar", "Camel"); + + assertMockEndpointsSatisfied(); + } + +} Added: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.java?rev=1345637&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.java (added) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.java Sun Jun 3 09:40:19 2012 @@ -0,0 +1,41 @@ +/** + * 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.component.properties; + +import org.apache.camel.spring.SpringTestSupport; +import org.springframework.context.support.AbstractXmlApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * + */ +public class CamelSpringPropertyPlaceholderConfigurerTest extends SpringTestSupport { + + @Override + protected AbstractXmlApplicationContext createApplicationContext() { + return new ClassPathXmlApplicationContext("org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.xml"); + } + + public void testCamelSpringPropertyPlaceholderConfigurerTest() throws Exception { + getMockEndpoint("mock:result").expectedBodiesReceived("Bonjour Camel"); + + template.sendBody("direct:bar", "Camel"); + + assertMockEndpointsSatisfied(); + } + +} Added: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/HelloBean.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/HelloBean.java?rev=1345637&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/HelloBean.java (added) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/properties/HelloBean.java Sun Jun 3 09:40:19 2012 @@ -0,0 +1,37 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.properties; + +/** + * + */ +public class HelloBean { + + private String greeting; + + public String getGreeting() { + return greeting; + } + + public void setGreeting(String greeting) { + this.greeting = greeting; + } + + public String say(String hi) { + return greeting + " " + hi; + } +} Added: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurer2Test.xml URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurer2Test.xml?rev=1345637&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurer2Test.xml (added) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurer2Test.xml Sun Jun 3 09:40:19 2012 @@ -0,0 +1,48 @@ +<?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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:p="http://www.springframework.org/schema/beans" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> + + <!-- bridge spring property placeholder with Camel --> + <!-- you must NOT use the <context:property-placeholder at the same time, only this bridge bean --> + <bean id="bridgePropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer"> + <p:property name="location" value="classpath:org/apache/camel/component/properties/cheese.properties"/> + </bean> + + <!-- a bean that uses Spring property placeholder --> + <!-- the ${hi} is a spring property placeholder --> + <bean id="hello" class="org.apache.camel.component.properties.HelloBean"> + <p:property name="greeting" value="${hi}"/> + </bean> + + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <!-- also define Camel properties placeholder where we can configure it as well --> + <propertyPlaceholder id="properties" location="classpath:org/apache/camel/component/properties/myprop.properties"/> + <!-- in this route we use Camels property placeholder {{ }} style --> + <route> + <from uri="direct:{{cool.bar}}"/> + <bean ref="hello"/> + <!-- this property is from the Camel property placeholder, and not from spring --> + <to uri="{{result}}"/> + </route> + </camelContext> + +</beans> Added: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.xml URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.xml?rev=1345637&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.xml (added) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.xml Sun Jun 3 09:40:19 2012 @@ -0,0 +1,53 @@ +<?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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:p="http://www.springframework.org/schema/beans" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> + + <!-- START SNIPPET: e1 --> + + <!-- bridge spring property placeholder with Camel --> + <!-- you must NOT use the <context:property-placeholder at the same time, only this bridge bean --> + <bean id="bridgePropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer"> + <p:property name="location" value="classpath:org/apache/camel/component/properties/cheese.properties"/> + </bean> + + <!-- END SNIPPET: e1 --> + + <!-- START SNIPPET: e2 --> + + <!-- a bean that uses Spring property placeholder --> + <!-- the ${hi} is a spring property placeholder --> + <bean id="hello" class="org.apache.camel.component.properties.HelloBean"> + <p:property name="greeting" value="${hi}"/> + </bean> + + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <!-- in this route we use Camels property placeholder {{ }} style --> + <route> + <from uri="direct:{{cool.bar}}"/> + <bean ref="hello"/> + <to uri="{{cool.end}}"/> + </route> + </camelContext> + + <!-- END SNIPPET: e2 --> + +</beans> Modified: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/cheese.properties URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/cheese.properties?rev=1345637&r1=1345636&r2=1345637&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/cheese.properties (original) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/cheese.properties Sun Jun 3 09:40:19 2012 @@ -22,4 +22,6 @@ myCoolCharset=iso-8859-1 slipDelimiter=## delay=25 -max=3 \ No newline at end of file +max=3 + +hi=Bonjour \ No newline at end of file