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