Thursday, February 6, 2014

OSGi Bundle Using Blueprint Dymisfied

Introduction

In my previous blog, I have described how to create OSGi bundle using org.apache.camel.archetypes. We can create OSGi project from scratch in that way and it works fine. In this blog I am going to describe the process to create OSGi using blueprint from scratch. In addition, I am going to demonstrate how to load property file dynamically. And how to use these properties in camel routes and spring beans.

Create OSGi Blueprint From Scratch

To create a maven OSGi maven project, I use the following script:


$ cat createCamelBlueprint.sh
mvn archetype:generate \
 -DarchetypeGroupId=org.apache.camel.archetypes \
 -DarchetypeArtifactId=camel-archetype-blueprint \
 -DarchetypeVersion=2.10.4 \
 -DgroupId=com.ggl.esb.osgi \
 -DartifactId=osgi.blueprint.demo \
 -Dversion=0.0.1-SNAPSHOT

The about script can be run on linux or mac os. If you want to use windows, you can replace the \ with ^ for line continuation and name it as createCamelBlueprint.bat. I run my script under /cygdrive/c/Camel-Dev-Demo. After executing the script, I see the following standard output:

$ ./createCamelBlueprint.sh
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] Archetype repository missing. Using the one from [org.apache.camel.archetypes:camel-archetype-blueprint:2.12.2] found in catalog remote
[INFO] Using property: groupId = com.ggl.esb.osgi
[INFO] Using property: artifactId = osgi.blueprint.demo
[INFO] Using property: version = 0.0.1-SNAPSHOT
[INFO] Using property: package = com.ggl.esb.osgi
[INFO] Using property: camel-version = 2.10.4
[INFO] Using property: log4j-version = 1.2.17
[INFO] Using property: maven-bundle-plugin-version = 2.3.7
[INFO] Using property: maven-compiler-plugin-version = 2.5.1
[INFO] Using property: maven-resources-plugin-version = 2.4.3
[INFO] Using property: slf4j-version = 1.6.6
Confirm properties configuration:
groupId: com.ggl.esb.osgi
artifactId: osgi.blueprint.demo
version: 0.0.1-SNAPSHOT
package: com.ggl.esb.osgi
camel-version: 2.10.4
log4j-version: 1.2.17
maven-bundle-plugin-version: 2.3.7
maven-compiler-plugin-version: 2.5.1
maven-resources-plugin-version: 2.4.3
slf4j-version: 1.6.6
 Y: :
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: camel-archetype-blueprint:2.10.4
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.ggl.esb.osgi
[INFO] Parameter: artifactId, Value: osgi.blueprint.demo
[INFO] Parameter: version, Value: 0.0.1-SNAPSHOT
[INFO] Parameter: package, Value: com.ggl.esb.osgi
[INFO] Parameter: packageInPathFormat, Value: com/ggl/esb/osgi
[INFO] Parameter: maven-bundle-plugin-version, Value: 2.3.7
[INFO] Parameter: maven-resources-plugin-version, Value: 2.4.3
[INFO] Parameter: groupId, Value: com.ggl.esb.osgi
[INFO] Parameter: maven-compiler-plugin-version, Value: 2.5.1
[INFO] Parameter: slf4j-version, Value: 1.6.6
[INFO] Parameter: version, Value: 0.0.1-SNAPSHOT
[INFO] Parameter: log4j-version, Value: 1.2.17
[INFO] Parameter: camel-version, Value: 2.10.4
[INFO] Parameter: package, Value: com.ggl.esb.osgi
[INFO] Parameter: artifactId, Value: osgi.blueprint.demo
[INFO] project created from Archetype in dir: C:\Camel-Dev-Demo\osgi.blueprint.demo
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1:30.173s
[INFO] Finished at: Thu Feb 06 11:05:17 CST 2014
[INFO] Final Memory: 14M/243M
[INFO] ------------------------------------------------------------------------


Note: it asks slf4j version. You can type Y or hit enter. From the command line output, you can see what version of different artifacts are used. If you list the contents under the current directory, you should see the following:

gliu@BGUNDAPA-1 /cygdrive/c/Camel-Dev-Demo
$ ls
createCamelBlueprint.sh  osgi.blueprint.demo

You can see that a new directory named: osgi.blueprint.demo has been created. At this point, a default OSGi blueprint project has been created with a default route. You can execute the following commands:

    cd osgi.blueprint.demo
    mvn clean install
    mvn camel:run

You should see the camel route print out messages every 5 second. Here is the standard output you should see:

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building A Camel Blueprint Route 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> camel-maven-plugin:2.10.4:run (default-cli) @ osgi.blueprint.demo >>>
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ osgi.blueprint.demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ osgi.blueprint.demo ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ osgi.blueprint.demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ osgi.blueprint.demo ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] <<< camel-maven-plugin:2.10.4:run (default-cli) @ osgi.blueprint.demo <<<
[INFO]
[INFO] --- camel-maven-plugin:2.10.4:run (default-cli) @ osgi.blueprint.demo ---
[INFO] Using org.apache.camel.test.blueprint.Main to initiate a CamelContext
[mel.test.blueprint.Main.main()] MainSupport                    INFO  Apache Camel 2.10.4 starting
[mel.test.blueprint.Main.main()] Activator                      INFO  Camel activator starting
[mel.test.blueprint.Main.main()] Activator                      INFO  Camel activator started
[mel.test.blueprint.Main.main()] BlueprintExtender              INFO  No quiesce support is available, so blueprint components will not participate in quiesce operations
[         Blueprint Extender: 1] BlueprintContainerImpl         INFO  Bundle osgi.blueprint.demo is waiting for namespace handlers
[         Blueprint Extender: 1] ManagementStrategyFactory      INFO  JMX enabled.
[         Blueprint Extender: 1] BlueprintCamelContext          INFO  Apache Camel 2.10.4 (CamelContext: blueprintContext) is starting
[         Blueprint Extender: 1] BlueprintCamelContext          INFO  Route: timerToLog started and consuming from: Endpoint[timer://foo?period=5000]
[         Blueprint Extender: 1] ultManagementLifecycleStrategy INFO  StatisticsLevel at All so enabling load performance statistics
[         Blueprint Extender: 1] BlueprintCamelContext          INFO  Total 1 routes, of which 1 is started.
[         Blueprint Extender: 1] BlueprintCamelContext          INFO  Apache Camel 2.10.4 (CamelContext: blueprintContext) started in 0.419 seconds
[ntext) thread #0 - timer://foo] timerToLog                     INFO  The message contains Hi from Camel at 2014-02-06 11:08:40
[ntext) thread #0 - timer://foo] timerToLog                     INFO  The message contains Hi from Camel at 2014-02-06 11:08:45

As you can see the last 2 lines are the output from the default camel route we just created. Therefore, all the ground work has been done by maven archetypes. This is really handy! At this point, if you deploy the bundle to karaf container it will work. At this point, all the ground for development OSGi bundle with blueprint is done. we can start to write our own routes, processors, components etc.

Before we do that, let's take a look what interesting source code has been generated. Let's import the newly generated project to eclipse IDE. I am using STS [Spring Tool Suite] 3.4.0. The other current version of Eclipse should work fine.

After the project is imported successfully, you should see the following directory structures:

We can inspect the blueprint.xml file. It has the following contents:




  
      
  

  
    
      
      
          
      
      
      
    
  



Load Property Files Dynamically

Now I am going to demonstrate how to update the blueprint.xml file to load a property file and how use the property in camel routes and spring beans. In real world applications, we want to have variables in our route and spring beans. And in different environments, such as, DEV, TEST, PROD, the configurations are different. The apache karaf container has a very unique feature to monitor the property files in etc directory. Thus, we want to put the property files under that directory. And when we change it, the new configurations should be loaded dynamically.

In order to demonstrate this feature, let's add a name member and change the timer uri to quartz. The new blueprint.xml are list in the following:




 
  
 

 

 
  
   
  
 


 
 
  
            
   
    
   
   
   
  

 



Before I explain the details about the new blueprint.xml. Let's deploy the bundle into karaf container. Currently, I am using Talend's ESB container which is apache karaf container. To deploy the bundle, build it first.

$ mvn clean install -Dmaven.test.skip=true

Note: we use -Dmaven.test.skip=true to skip the unit test.

Once the bundle is built successfully. We can deploy the bundle to the karaf container. Because we are using quartz component and an environment variable, we need to execute the following command on the karaf console.

    system-property -p runtime.environment DEV
    features:install camel-quartz
    osgi:install -s mvn:com.ggl.esb.osgi/osgi.blueprint.demo/0.0.1-SNAPSHOT

The first command above is to set an environment variable named: runtime.environment. The second is to install Apache camel quartz component. The last command is to deploy the bundle. Now if you tail the karaf output log, you will see error. This is because the value of cron.value used for quartz uri is not default. Consequently, the route cannot start. Now let add the file named BlueprintDemoDEV.cfg to etc dir. The content of the file is listed as below:

activemq.broker.url=failover:(tcp://uit-amq-1.corp.vha.com:61616,tcp://uit-amq-2.corp.vha.com:61616)
name.value=Gary Liu
cron.value=0/5+*+*+*+*+?

Once the file is created, the route will start and you will see message on the standard output look like:

16:03:40,001 | INFO  | Context_Worker-4 | rg.apache.camel.util.CamelLogger  176 | 174 - org.apache.camel.camel-core - 2.10.4 | The message contains Gary Liu at 2014-02-06 16:03:40 failover:(tcp://uit-amq-1.corp.vha.com:61616,tcp://uit-amq-2.corp.vha.com:61616)

Now if you change cron.value by replacing the 5 with 20. The print out from standard output will occur every 20 seconds. This means karaf container load the property file dynamically, like the hot deployment of other containers, like tomcat.

Hot Development of Properties Explained

We has demonstrated in the above session that:
  • Variables can be placed in side came routes definition and spring bean definition
  • Properties can be hot-deployed
  • Environment variable can be attached to a file name

No comments:

Post a Comment

Anypoint Studio Error: The project is missing Munit lIbrary to run tests

Anypoint Studio 7.9 has a bug. Even if we following the article: https://help.mulesoft.com/s/article/The-project-is-missing-MUnit-libraries-...