Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

...

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 and will show you how a more real application (which is web based) can be re-scoped into a OSGI application.

...

Prerequisites

This tutorial uses:

Note: The sample project can be downloaded, see the resources section.

...

First, we create two eclipse projects using the maven archetype 'pax:create-bundle'. 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
Tip
titlePAX Project

More info about the PAX maven plugin can be found here. PAX project does not include only maven but also tools to run, debug and deploy web application. We will address them in the second part of the tutorial and particularly the web integration

...

Code Block
mvn org.ops4j:maven-pax-plugin:create-bundle -Dpackage=demo.service -DbundleGroupId=demo.service -DbundleName=demo.service-bundle -Dversion=0.1

Remark:

  • According to your project, you can change the artifactId to point to com.mycompany.application.service, and groupId com.mycompany.application

To allow your project to be imported in Eclipse, execute the following command in the directory demo.service-bundle.

...

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 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

Luckily, this is not the case because the specification has tried to avoid such pitfalls and interesting projects exist today to simplify our life:

The goals of these frameworks are to:

  • Design the business logic as POJO,
  • Inject dependency(ies) though IoC,
  • Handle lifecycle of the bundle and its relation with BundleContext

Although this tutorial is based on Spring Dynamic Modules.

...

So now, it is time to create the interface that we will use in this project. Open Eclipse environment if not already done and create a new folder "service" in src/main/java/demo tree. Add the interface TransformService.java and copy paste the code below:

Code Block
javajava
titleTransformService.java
java
package demo.service;

public interface TransformService {

    public Object transform(Object obj);

}

...

Next, we will create the class TransformServiceImpl implementing the interface TransformService in the folder "impl" in src/main/java/demo/service/impl.

Code Block
javajava
titleTransformServiceImpl.java
java
package demo.service.impl;

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;
    }
}

...

Create the file demo-service-bundle-contxt.xml in the folder src/main/resources/META-INF/spring

xml
Code Block
xml
titledemo-service-bundle-contxt.xml
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="transformService" class="demo.service.impl.TransformServiceImpl">
    </bean>
</beans>

...

Create the file demo-service-bundle-contxt-osgi.xml in the folder src/main/resources/META-INF/spring

xml
Code Block
xml
titledemo-service-bundle-contxt-osgi.xml
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"
	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:service ref="transformService">
		<osgi:interfaces>
			<value>demo.service.TransformService</value>
		</osgi:interfaces>
	</osgi:service>

</beans>

...

  • For the routing, create the following file in the folder src/main/resources/META-INF/spring of the project demo.camel-bundle:
xml
Code Block
xml
titleCamelContext.xml
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-2.5.xsd
       http://camel.apache.org/schema/spring
       http://camel.apache.org/schema/spring/camel-spring-2.0.0.xsd">

  <camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
      <from uri="timer://myTimer?fixedRate=true&amp;period=10000"/>
      <bean ref="myTransform" method="transform"/>
      <to uri="log:ExampleRouter"/>
    </route>
  </camelContext>
</beans>

...

  • To inject the dependency, we will create a second file named bundle-context-osgi.xml in the same folder:
xml
Code Block
xml
titlebundle-context-osgi.xml
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"
  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 7 : Generate the manifest and jar file

Prior to run/launch the command generating the MANIFEST file, you must modify the pom.xml file in order to allow the OSGI bundle to import/use the services classes : demo.service

Code Block
xmlxml
titlepom demo.camel-bundle
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://maven.apache.org/POM/4.0.0"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <properties>
    <bundle.symbolicName>demo.camel-bundle</bundle.symbolicName>
    <bundle.namespace>demo.camel</bundle.namespace>
  </properties>

  <modelVersion>4.0.0</modelVersion>
  <groupId>demo.camel</groupId>
  <artifactId>demo.camel-bundle</artifactId>
  <version>0.1</version>

  <name>${bundle.symbolicName} [${bundle.namespace}]</name>

  <packaging>bundle</packaging>

  <build>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
      </resource>
      <!--
       | example additional resource entries, useful when building Eclipse RCP applications
      -->
      <resource>
        <directory>.</directory>
        <includes>
          <include>plugin.xml</include>
          <include>plugin.properties</include>
          <include>icons/**</include>
          <include>META-INF/*</include>
        </includes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <groupId>org.ops4j</groupId>
        <artifactId>maven-pax-plugin</artifactId>
        <version>1.4</version>
        <!--
           | enable improved OSGi compilation support for the bundle life-cycle.
           | to switch back to the standard bundle life-cycle, move this setting
           | down to the maven-bundle-plugin section
          -->
        <extensions>true</extensions>
      </plugin>
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <version>1.4.3</version>
        <!--
         | the following instructions build a simple set of public/private classes into an OSGi bundle
        -->
        <configuration>
          <instructions>
            <Bundle-SymbolicName>${bundle.symbolicName}</Bundle-SymbolicName>
            <Bundle-Version>${pom.version}</Bundle-Version>
            <Import-Package>demo.service;version="${pom.version}"</Import-Package>
            <Include-Resource>src/main/resources</Include-Resource>
          </instructions>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>org.osgi</groupId>
      <artifactId>osgi_R4_core</artifactId>
      <version>1.0</version>
      <scope>provided</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.osgi</groupId>
      <artifactId>osgi_R4_compendium</artifactId>
      <version>1.0</version>
      <scope>provided</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>demo.service</groupId>
      <artifactId>demo.service-bundle</artifactId>
      <version>${pom.version}</version>
    </dependency>
  </dependencies>

</project>

...

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 Karaf, use the command: log:display

Spring DM server

Spring DM server compare to ServiceMix Kernel, Eclipse Equinox or Apache Felix is much more than a OSGI server. This is a completely module-based Java application server that is designed to run enterprise Java applications and Spring-powered applications with a new degree of flexibility and reliability. It offers a simple yet comprehensive platform to develop, deploy, and service enterprise Java applications.

...

When the server is started, open your favorite browser and point to the following url http://localhost:8080/admin using 'admin' as login and 'springsource' as password. In the administration page, click on the button "browse" to upload the different jars to be deployed. Select the folder where you have copied the following jars and upload them one by one (by respecting the order)

When the bundles are uploaded, the screen is refreshed and shows a list of the deployed applications like this :

...

Well, we have finished the first part of the tutorial. Even if the example is simple, we have introduced very important concepts and show you how to design a small SOA solution, package it and deploy it under two different OSGI servers. I'm really sure that in a near future a maven plugin will be created to facilitate this task and will automate the deployment within your favorite OSGI servers.

#Resources

  • Attachments
    patterns.*part1.zip