Invoking a method on an OSGi (Spring DM) Service via Camel
mhuisking_michael.c.huisking Jul 22, 2011 8:46 AM(I'm posting this into the ESB forum, let me know if I should put it into MediationRouter/Camel instead.)
ServiceMix Version 4.3.1-fuse-01-15, Dev/Test on Windows7, Deployment/Production to Solaris JDK 1.6
Hi,
I don't think this is that much of a fringe case, but there really isn't that much information out there on invoking a method on a SpringDM Service. (Since 2009 or so)
From what I've read, this seems like it should be a real simple exercise: Register the service with ServiceMix, and then just use a bean ref in a Camel route to invoke a method on the service. When doing
the binding Camel first looks in the OSGi service registry and then falls back to the regular registry (e.g. Spring ApplicationContextRegistry) SO, I think I must be missing something...
Let me set up an example using a service from a FuseSource training session.
For the service, a very simple HelloWorld service, with 1 method
-
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <parent> <artifactId>osgi-exercises</artifactId> <groupId>com.fusesource</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.fusesource</groupId> <artifactId>osgi-exercises-hello-world-bundle</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>bundle</packaging> <name>osgi-exercises-hello-world-bundle</name> <build> <resources> <resource> <directory>src/main/resources</directory> </resource> </resources> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> <version>1.4.0</version> <configuration> <instructions> <Export-Package> !com.fusesource.training.osgi.helloworld.internal, com.fusesource.training.osgi.helloworld* </Export-Package> <Private-Package> com.fusesource.training.osgi.helloworld.internal </Private-Package> <Import-Package>*</Import-Package> <Include-Resource>src/main/resources</Include-Resource> </instructions> </configuration> </plugin> </plugins> </build> </project>
-
A HelloWorld Interface
package com.fusesource.training.osgi.helloworld; public interface HelloWorld { String sayHello(String message); }
-
HelloWorld Implementation
package com.fusesource.training.osgi.helloworld.internal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import com.fusesource.training.osgi.helloworld.HelloWorld; public class HelloWorldImpl implements HelloWorld, InitializingBean, DisposableBean { public static final Logger logger = LoggerFactory.getLogger(HelloWorldImpl.class); private String response; public String sayHello(String message) { logger.info("Just got message '" + message + "'"); logger.info("Returning... '" + response + "'"); return response; } public void setResponse(String response) { logger.info("Setting the response to '" + response + "'"); this.response = response; } public void afterPropertiesSet() throws Exception { logger.info("HelloWorldImpl initialized."); logger.info("Will return response '" + response + "'"); } public void destroy() throws Exception { logger.info("Shutting down HelloWorldImpl"); } }
-
Spring Bundle Context (bundle-context.xml)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- regular spring configuration file defining the beans for this bundle. The configuration of OSGi definitions is kept in a separate configuration file so that this file can easily be used for integration testing outside of an OSGi environment --> <bean id="helloWorld" class="com.fusesource.training.osgi.helloworld.internal.HelloWorldImpl"> <property name="response" value="${response}"></property> </bean> </beans>
-
OSGi Bundle Context (bundle-context-osgi.xml)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi" xmlns:osgix="http://www.springframework.org/schema/osgi-compendium" xmlns:ctx="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd http://www.springframework.org/schema/osgi-compendium http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd" > <osgix:cm-properties id="helloworld.cfg.with.defaults" persistent-id="helloworld"> <prop key="response">Right back at ya</prop> </osgix:cm-properties> <!-- placeholder configurer --> <ctx:property-placeholder properties-ref="helloworld.cfg.with.defaults"></ctx:property-placeholder> <osgi:service id="helloService" ref="helloWorld" interface="com.fusesource.training.osgi.helloworld.HelloWorld"></osgi:service> </beans>
-
So, I install and start this bundle.
karaf@root> osgi:ls 203
osgi-exercises-hello-world-bundle (203) provides:
org.springframework.osgi.bean.name = helloWorld
Bundle-SymbolicName = com.fusesource.osgi-exercises-hello-world-bundle
Bundle-Version = 0.0.1.SNAPSHOT
objectClass = com.fusesource.training.osgi.helloworld.HelloWorld
service.id = 277
org.springframework.context.service.name = com.fusesource.osgi-exercises-hello-world-bundle
Bundle-SymbolicName = com.fusesource.osgi-exercises-hello-world-bundle
Bundle-Version = 0.0.1.SNAPSHOT
objectClass = org.springframework.osgi.context.DelegatedExecutionOsgiBundleApplicationContext,
org.springframework.osgi.context.ConfigurableOsgiBundleApplicationContext,
org.springframework.context.ConfigurableApplicationContext, org.springframework.context.ApplicationContext,
org.springframework.context.Lifecycle, org.springframework.beans.factory.ListableBeanFactory,
org.springframework.beans.factory.HierarchicalBeanFactory, org.springframework.context.MessageSource,
org.springframework.context.ApplicationEventPublisher, org.springframework.core.io.support.ResourcePatternResolver,
org.springframework.beans.factory.BeanFactory, org.springframework.core.io.ResourceLoader,
org.springframework.beans.factory.DisposableBean
service.id = 279
-
At this point, I just want to make another bundle with a really simple Camel route that calls "sayHello()"
This project might be a bit off -- I just tweaked a pom real quick for this example.
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- ~ Copyright 2011 FuseSource ~ ~ Licensed 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. --> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.fusesource</groupId> <artifactId>sample_camel_route</artifactId> <packaging>bundle</packaging> <name>osgi-exercises :: Camel Route</name> <description>Camel Route Consumer for Simple OSGi Service</description> <version>0.0.1-SNAPSHOT</version> <properties> <camel.version>2.6.0-fuse-01-09</camel.version> </properties> <build> <defaultGoal>install</defaultGoal> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> <configuration> <instructions> <Import-Package> *, org.apache.servicemix.nmr.api </Import-Package> </instructions> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-spring</artifactId> <version>${camel.version}</version> </dependency> </dependencies> </project>
-
Camel Context
<?xml version="1.0" encoding="UTF-8"?> <!-- ~ Copyright 2011 FuseSource ~ ~ Licensed 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:camel="http://camel.apache.org/schema/spring" xmlns:osgi="http://www.springframework.org/schema/osgi" xmlns:typ="http://examples.fusesource.com/payment-service/types" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd "> <camel:camelContext> <camel:route> <camel:from uri="direct:start"></camel:from> <camel:bean ref="helloWorld" method="sayHello"></camel:bean> </camel:route> </camel:camelContext> </beans>
-
"helloWorld" can't be resolved. Am I missing a piece to link helloWorld to helloWorld Service? (In the sample_camel_route bundle) Are my namespaces screwed up? Or, should I just be using nmr for any kind of inter-bundle communication in ServiceMix?
Perhaps from what I learn I can tweak the out of date OSGi example on the Apache Camel website.
Thanks in advance,
Mick
Edited by: mhuisking on Jul 22, 2011 12:29 PM Fixed Formatting