...
Such a solution can be envisaged for big companies because the skills/time to market are important or when different development standards exist
inside the company like (Java, .NET).
In In the years 90's, such developments have been made using CORBA or COM+/DCOM Microsoft technology. But , both of the CORBA and COM approaches had (and still have) significant problems and limitations. Complexity is a big issue. Any of the data that is passed requires very specific formatting, and many of the rules for programming are simply too difficult to follow without encountering errors. Even at the height of their popularity, CORBA was used primarily in large system development staffed by legions of programmers, while COM was used, often reluctantly, by teams of Microsoft developers.
...
Coupling the OSGI framework with a lightweight Enterprise Service Bus will allow you easily to design easily the routing between your different modules. A module can be a Plain Old Java Object (POJO), a Web Service designed with Apache CxF CXF framework, a component like an ordering system. In fact, the module or bundle which is the term used by OSGI represent the level of granularity that you identify for your application.
In In this first part of the OSGI tutorial, we will show you how to:-
- Create a simple service (derived from the camel-osgi example) module (interface + implementation) and package it as a bundle,
...
- Create a Camel context with a small routing and package it as a separate bundle,
...
- The Camel routing will use an OSGI reference to call the simple service
The second part of this tutorial will be derived from the "Reporting Incident Tutorial" incident tutorial and will show you a more real application (which is web based) can be re-scoped into a OSGI application.
...
First, we create two eclipse projects using the maven archetype 'spring-osgi-bundle-archetype'. This archetype is helpful because it generates a pom.xml file that we will use with maven goal(s) to create the:-
- MANIFEST.MF file (file required and specifying the information about the bundle to deploy on the OSGI server, dependency with another bundle, version, ... )
...
- jar of the bundle to deploy on the server
To create the simple service project, execute the following command in your Unix/Dos console.
Code Block |
---|
mvn archetype:create -DarchetypeGroupId=org.springframework.osgi -DarchetypeArtifactId=spring-osgi-bundle-archetype -DarchetypeVersion=1.2.0-m2 -DgroupId=demo -DartifactId=demo.service-bundle -Dversion=0.1 |
Remarks:-
- The archetype version depends on the version of Spring Dynamic Module used and must be adapted in consequence,
...
- According to your project, you can change the artifactId to point to com.mycompany.application.service, and groupId com.mycompany.application
To create the Camel project, execute the following command
...
Two folders are created with the following name:-
- demo.service-bundle
...
- demo.camel-bundle
Next, you import these projects into your favorite workspace of Eclipse.
...
Developing an OSGI project could be 'potentially' time consuming regarding to: -
- The learning curve of the new technology to acquire,
...
- Packaging of the components, registering of the components,
...
- How to call the OSGI server? How Can I have access to the bundle context?
You could figure out that developing OSGI is similar to developp develop EJB components using EJB 1.0 specification. Remember that time when the only way to design an enterprise solution was to use EJB with its proxy, stub-skeleton classes, the protocol RMI/IIOP (blocked by most of the firewall) for the communication between the client and the server, ... and so on and so on
...
So now, it is time to create the interface that we will use through in this project. Open Eclipse environment if not already done and create a new folder "service" under in{{src/main/java/demo}} tree. Add the interface 'TransformService.java
' and copy paste the code hereunder below:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package demo.service; public interface TransformService {| public Object transform(Object obj); } |
...
Next, we will create the class 'TransformServiceImpl
' implmenting the interface 'TransformService
'.
Create the class 'TransformServiceImpl.java
' under in the folder src/main/java/demo/service
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package demo.service; import java.util.Date; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class TransformServiceImpl implements TransformService { private static final transient Log LOG = LogFactory.getLog(TransformServiceImpl.class); private boolean verbose = true; private String prefix = "MyTransform"; public Object transform(Object body) { String answer = prefix + " set body: " + new Date(); if (verbose) { System.out.println(">> call >> " + answer); } LOG.info(">> call >>" + answer); return answer; } public boolean isVerbose() { return verbose; } public void setVerbose(boolean verbose) { this.verbose = verbose; } public String getPrefix() { return prefix; } public void setPrefix(String prefix) { this.prefix = prefix; } } |
...
a) Dependency Injection
Create the file 'demo-service-bundle-contxt.xml
' under in the folder 'src/main/resources/META-INF/spring
'
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?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="transformService" class="demo.service.TransformServiceImpl"> </bean> </beans> |
b) OSGI 'Injection'
Create the file 'demo-service-bundle-contxt-osgi.xml
' under in the folder 'src/main/resources/META-INF/spring
'
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?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" 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"> <!-- definitions using elements of the osgi namespace can be included in this file. There is no requirement to keep these definitions in a separate file if you do not want to. The rationale for keeping these definitions separate is to facilitate integration testing of the bundle outside of an OSGi container --> <osgi:service ref="transformService"> <osgi:interfaces> <value>demo.service.TransformService</value> </osgi:interfaces> </osgi:service> </beans> |
Remark: for more information about Spring Dynamic Modules and configuration, I recommend to read their its documentation
Step 5 : Generate the MANIFEST.MF file and jar of the bundle
Now, that the code and the configuration files are ready, we will use maven to generate the MANIFEST.MF
file describing the information about our bundle, its version n°number, the package to export or import, etc.
This command can be launched from Eclipse (if you have integrated maven within Eclipse ( more info : eclipse maven plugin)) or a Unix/Dos prompt in the folder where your pom.xml file is located.:
Code Block |
---|
mvn package |
If this command does not report any error, then
...
a 'MANIFEST.MF' file containing the following information is created in the folder 'META-INF' and a demo.service-bundle-0.1.0.jar
jar is created in the target
folder:
Code Block |
---|
Manifest-Version: 1.0 Export-Package: demo.service;uses:="org.apache.commons.logging" Built-By: Charlesm Build-Jdk: 1.6.0_07 Bundle-Version: 0.1.0 Tool: Bnd-0.0.238 Bundle-Name: Demo Service Bundle Bnd-LastModified: 1228122578185 Created-By: Apache Maven Bundle Plugin Bundle-ManifestVersion: 2 Bundle-SymbolicName: demo.demo.service-bundle Import-Package: demo.service,org.apache.commons.logging |
...
Tip | ||
---|---|---|
| ||
The pom of spring dm uses the maven bundle plugin and the tool bnd to generate this manifest file. |
- a 'demo.service-bundle-0.1.0.jar' jar is created in the folder 'target'
Step 6 : Create the Camel context file and OSGI dependency
The next step is quite simple for Camel users because we will create two configurations files, one containing the routing and the other with a reference to our TransformationService deployed in a OSGI bundle.
- For the routing, create the following file under in the folder '
src/main/resources/META-INF/spring
" of the project 'demo.camel-bundle
':
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?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-2.5.xsd http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd"> <camelContext xmlns="http://activemq.apache.org/camel/schema/spring"> <route> <from uri="timer://myTimer?fixedRate=true&period=10000"/> <bean ref="myTransform" method="transform"/> <to uri="log:ExampleRouter"/> </route> </camelContext> </beans> |
The routing defined here is a timer who which will trigger every 10s 10th second and call the POJO 'MyTransform' and send the result to the 'camel:log' component. As, you can see, this is a pure Camel config configuration file without any reference to a an OSGI bundle
- To inject the dependency, we will create a second file named '
bundle-context-osgi.xml
' in the same folder:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?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" 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"> <osgi:reference id="myTransform" interface="demo.service.TransformService"/> </beans> |
Remarks: -
- The id of the bean referenced
...
myTransform
...
- used by the
...
- Camel context has a reference to the OSGI interface
...
demo.service.TransformService
...
...
- How could we imagine something more simplest? We don't have to call a JNDI server with a reference or something like that. Only a reference to the service interface.
Step 6 : Generate the manifest and jar file
Run the command 'mvn package
' (= Repeat the step 5#5).
Unfortunately, the MANIFEST.MF file of the Camel bundle does not contain a link to the package 'demo.Service
' that the bean 'myTransform' required in order the to instantiate the class. This link is not added by the bnd tool during the generation step. So we have to edit the file contained in the jar file 'demo.camel-bundle-0.1.jar
' in order to add adding the following line at the end of the MANIFEST.MF file.
...
If this is not yet done, download ServiceMix Kernel 1.0.0 server and install it. Launch the server by executing the command in the bin
folder 'bin' :
Code Block |
---|
c:\apache-servicemix-kernel-1.0.0\bin>servicemix |
If this is the first time that servicemix Servicemix is started, then you will see that a new data folder is created 'data'.
In order to allow our bundles to work with Camel, execute the following commands to download and install the 'Camel and Spring bundles':
...
Next, copy the two jar into the deploy
folder 'deploy', first the service and next the camel Camel bundle. After a few seconds, you should see on the servicemix Servicemix log console the following text:
Code Block |
---|
>> call >> MyTransform set body: Mon Dec 01 11:02:28 CET 2008 |
Remarks : -
- In case of trouble, use the command:
osgi list
to see if all the deployed bundles are installed correctly and have their status equals to
...
- active
...
- To see the log of ServiceMix, use the command:
log d
Spring DM server
TODO
#Resources
...