tag:blogger.com,1999:blog-666582706624906172024-03-20T01:15:23.819-07:00Aniketos OSGiATC Bloggerhttp://www.blogger.com/profile/12339569691943810552noreply@blogger.comBlogger6125tag:blogger.com,1999:blog-66658270662490617.post-15116461866208210292012-12-18T05:25:00.001-08:002012-12-18T05:55:54.803-08:00Karaf and CXF DOSGi updated<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: Verdana, sans-serif;">The Aniketos Runtime platform is based on Apache Karaf OSGi container. Another key technology for the platform is Apache CXF DOSGi. This is an implementation of OSGi Remote Services that allows services in different containers to be discovered and exchange information. In a simple scenario, CXF DOSGi can also be used to provide a SOAP WSDL service from inside an OSGi bundle. This service can be consumed from either an OSGi client in another container or a common WSDL client.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">As 2012 approaches to the end good news appeared for both these technologies. Apache Karaf has been updated to <a href="http://karaf.apache.org/" rel="nofollow" target="_blank">2.3.0</a> version. Although Apache Karaf received regular updates throughout the year, this is a milestone for the project, as it marks the swift from OSGi 4.2 to OSGi 4.3 specification. This new version of Karaf supports Felix Framework 4.0 and Eclipse Equinox 3.8. This was a long awaited feature as Karaf has fallen behind from the latest advances in core OSGi containers. In practical matters this change will make both development and deployment easier. Since most developers use recent versions of OSGi containers in their development environment, they were previously often caught by surprise when trying to deploy a bundle. Especially in situations when more than 100 bundles need to be installed, the differences in OSGi implementations could have a significant impact. It is always good to develop in the same environment that you are going to deploy. I have also found that recent versions of the OSGi containers produce more meaningful messages in the case a bundle fails to install.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Apache CXF DOSGi is also going to be updated to version <a href="http://cxf.apache.org/dosgi-releases.html" rel="nofollow" target="_blank">1.4.0</a> soon. This is the first update from the 1.3.1 release in April 2012. The highlights for this release are very interesting:</span><br />
<ul style="text-align: left;">
<li><span style="font-family: Verdana, sans-serif;">30 issues resolved (see jira)</span></li>
<li><span style="font-family: Verdana, sans-serif;">Karaf feature for easy installation in Apache Karaf</span></li>
<li><span style="font-family: Verdana, sans-serif;">Zookeeper discovery now supports automatic reconnects and Cluster configuration</span></li>
<li><span style="font-family: Verdana, sans-serif;">DOSGi is now independent of spring dm</span></li>
<li><span style="font-family: Verdana, sans-serif;">Custom intents are now created by publishing e.g. CXF Features as services</span></li>
<li><span style="font-family: Verdana, sans-serif;">Big refactorings make the code much easier to understand</span></li>
</ul>
<div>
<span style="font-family: Verdana, sans-serif;">We have experienced problems running CXF DOSGi together with some other bundles and we hope that the new version will solve most of them. The provision of Karaf feature is of course happily welcomed. We still haven't set up a Zookeeper server, but we definitely plan to do in the future. The new version will make this task easier. Anyway it is very good to see that this project is evolving, as before version 1.3 it was stalled for over a year.</span></div>
<br />
<br />
<br />
<br /></div>
ATC Bloggerhttp://www.blogger.com/profile/12339569691943810552noreply@blogger.com0tag:blogger.com,1999:blog-66658270662490617.post-50957588192401195152012-11-07T05:25:00.002-08:002012-11-07T05:25:49.576-08:00Declarative Services in Apache Karaf<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: Verdana, sans-serif;">In this post I would like to demonstrate how easy it is to use Declarative Services in Karaf. The source code will be based on the Converter service and client that were used in a previous example about <a href="http://aniketos-osgi.blogspot.gr/2012/10/osgi-remote-services.html" target="_blank">remote services</a>. This time however both the service and the client will reside in the same OSGi container and instead of Activators Declarative Services will be used. The source code of this example is available in <a href="https://github.com/research-atc/aniketos-osgi/tree/master/karaf-ds" rel="nofollow" target="_blank">GitHub</a>. The following projects are implemented:</span><br />
<ul>
<li><span style="font-family: Verdana, sans-serif;">converter (interface of a conversion service - same as in previous example)</span></li>
<li><span style="font-family: Verdana, sans-serif;">converter-impl (implementation of conversion service using DS)</span></li>
<li><span style="font-family: Verdana, sans-serif;">converter-client (client of conversion service using DS)</span></li>
<li><span style="font-family: Verdana, sans-serif;">converter-ds-feature (maven host project for converter ds feature)</span></li>
</ul>
<h4 style="text-align: left;">
<span style="font-family: Verdana, sans-serif;"><br /></span></h4>
<h4 style="text-align: left;">
<span style="font-family: Verdana, sans-serif;">Converter Service</span></h4>
<div>
<span style="font-family: Verdana, sans-serif;">The converter interface is exact same as in the previous example not using Declarative Services. It simply provides the interface of the service. The service implementation however is modified. We no longer need the Activator. The ServiceImpl class is the only thing needed. In addition to the Interface implementations methods, two more methods are added:</span></div>
<pre class="brush: java">protected void activate(ComponentContext context) {
System.out.println("*** Activating Service");
}
protected void deactivate(ComponentContext context) {
System.out.println("*** Deactivating Service");
}
</pre>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">These methods are called for the Declarative Services runtime, when the service is activated and de-activated. In this simple scenario they do nothig but printing a message. In order for the DS runtime to work, we need to add a service component file. This file is declared in the MANIFEST.MF. In our case we modify the pom.xml to make the appropriate line appear in the manifest file:</span><br />
<pre class="brush: xml"><configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-Description>Implementation of a service that converts Celcius temperatures to Fahrenheit and vice-versa</Bundle-Description>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>${bundle.export.package}</Export-Package>
<Import-Package>${bundle.import.package}</Import-Package>
<Service-Component>OSGI-INF/component.xml</Service-Component>
</instructions>
</configuration>
</pre>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Notice that a Service-Component entry was added and that the Bundle-Activator was removed.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">The last thing we need to do is to actually create the service component file in resources/OSGI-INF/component.xml:</span><br />
<pre class="brush: xml"><?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
name="gr.atc.aniketos.demos.converter.impl">
<implementation class="gr.atc.aniketos.demos.converter.impl.ConverterImpl"/>
<service>
<provide interface="gr.atc.aniketos.demos.converter.Converter"/>
</service>
</scr:component>
</pre>
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">How this file works should be self-explanatory. We define which service we provide and which is the implementation class.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<h4 style="text-align: left;">
<span style="font-family: Verdana, sans-serif;">Converter Client</span></h4>
<div>
<span style="font-family: Verdana, sans-serif;">The service client follows a similar approach as the service. The Activator is removed and the pom.xml file is modified to add the service component entry. The compoment.xml looks like this:</span></div>
<pre class="brush: java"><?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
name="gr.atc.aniketos.demos.converter.client">
<implementation class="gr.atc.aniketos.demos.converter.client.ConverterClient"/>
<reference name="Converter" policy="static" cardinality="1..1"
interface="gr.atc.aniketos.demos.converter.Converter"
bind="setService" unbind="unsetService"/>
</scr:component>
</pre>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<span style="font-family: Verdana, sans-serif;">In this file we define which service we want to look up. We search for services based on interfaces and not concrete implementations. We also define which methods to call, when the service is set and unset by the DS runtime. This methods are implemented by our class:</span><br />
<pre class="brush: java">public class ConverterClient {
private ConverterDialog converterDialog;
private Converter service;
protected void activate(ComponentContext context) {
System.out.println("*** Activating Client");
}
protected void deactivate(ComponentContext context) {
System.out.println("*** Deactivating Client");
service = null;
if (converterDialog != null) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
converterDialog.setVisible(false);
converterDialog.dispose();
converterDialog = null;
}
});
}
}
public synchronized void setService(Converter _service) {
System.out.println("Converter Service was set. !");
this.service = _service;
converterDialog = new ConverterDialog(new ConverterDialog.ConverterDialogListener() {
@Override
public double onCelciusToFahrenheit(double celcius) {
double fahrenheit = service.toFahrenheit(celcius);
System.out.println("Celcius " + celcius + " => Fahrenheit " + fahrenheit);
return fahrenheit;
}
@Override
public double onFahrenheitToCelcius(double fahrenheit) {
double celcius = service.toCelcius(fahrenheit);
System.out.println("Fahrenheit " + fahrenheit + " => Celcius " + celcius);
return celcius;
}
});
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
converterDialog.setVisible(true);
}
});
}
public synchronized void unsetService(Converter service) {
System.out.println("Converter Service was unset.");
if (this.service == service) {
this.service = null;
}
}
}
</pre>
<br />
<h4 style="text-align: left;">
<span style="font-family: Verdana, sans-serif;">Deploying in Karaf</span></h4>
<span style="font-family: Verdana, sans-serif;">We are now ready to deploy in Karaf. Although a feature is provided, I would like to install the bundles one by one to demonstrate a subtle point:</span>
<br />
<pre class="brush: vb">karaf&root> install -s mvn:org.apache.felix/org.apache.felix.scr/1.6.0
Bundle ID: 50
karaf&root> install -s mvn:gr.atc.aniketos.demos.converterservice/converter/1.0.0
Bundle ID: 51
karaf&root> install mvn:gr.atc.aniketos.demos.converterservice/converter/1.0.0
Bundle ID: 52
karaf&root> install mvn:gr.atc.aniketos.demos.converterservice/client/1.0.0
Bundle ID: 53
</pre>
<br />
<span style="font-family: Verdana, sans-serif;">The org.apache.felix.scr dependency is the Felix implementation of the Service Component Runtime. If you are testing this in Equinox, you need the following dependencies:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><a href="http://ebr.springsource.com/repository/app/bundle/version/download?name=org.eclipse.equinox.util&version=1.0.200.v20100503&type=binary" rel="nofollow" target="_blank">org.eclipse.osgi.services</a></span><br />
<span style="font-family: Verdana, sans-serif;"><a href="http://ebr.springsource.com/repository/app/bundle/version/download?name=org.eclipse.osgi.services&version=3.3.0.v20101018&type=binary" rel="nofollow" target="_blank">org.eclipse.equinox.util</a></span><br />
<span style="font-family: Verdana, sans-serif;"><a href="http://ebr.springsource.com/repository/app/bundle/version/download?name=org.eclipse.equinox.ds&version=1.3.0.v20110124-0830&type=binary" rel="nofollow" target="_blank">org.eclipse.equinox.ds</a></span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">I provide links to these bundles from the Spring Enterprise Bundle Repository. There is also a commented out section with them at the features.xml file.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Now let's start the service and the client:</span>
<br />
<pre class="brush: vb">karaf&root> start 52
karaf&root> start 53
*** Activating Service
Converter Service was set. !
*** Activating Client
karaf&root> stop 53
*** Deactivating Client
Converter Service was unset.
*** Deactivating Service
</pre>
<br />
<span style="font-family: Verdana, sans-serif;">Notice that when we start the service nothing happens. The activate method isn't called. This method isn't a replacement of the Activator's start method. It isn't called, when the bundle is started. It is called by the DS runtime, when it is needed to. This only happens, when a client with a reference to this service is started. So, everything happens when the client is started. Notice the sequence of the print-out messages. First the service activate method is called. Then the set and the activate method of the client follow. When we stop the client, both the client and the service are de-activated. Of course the service wouldn't be de-activated, if there was a reference to it from another bundle.</span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
ATC Bloggerhttp://www.blogger.com/profile/12339569691943810552noreply@blogger.com0tag:blogger.com,1999:blog-66658270662490617.post-73075075198689922962012-10-26T07:14:00.000-07:002012-10-26T07:14:16.219-07:00OSGi Remote Services<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: Verdana, sans-serif;">Remote Services is a feature introduced in the 4.2 version of the OSGi specification. It provides a way for accessing OSGi services from remote OSGi containers. <a href="http://cxf.apache.org/distributed-osgi.html" rel="nofollow" target="_blank">CXF DOSGi</a> is an open source implementation of Remote Services.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">An <a href="http://cxf.apache.org/distributed-osgi-greeter-demo-walkthrough.html" rel="nofollow" target="_blank">example</a> for running an OSGi service in one container and accessing it from another is included in the DOSGi samples. I would like to present here another example, based on Apache Karaf features. The source code of this example is available in <a href="https://github.com/research-atc/aniketos-osgi/tree/master/remote-services" rel="nofollow" target="_blank">GitHub</a>.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">The source code consists of the following projects:</span><br />
<ul style="text-align: left;">
<li><span style="font-family: Verdana, sans-serif;">converter (interface of a conversion service)</span></li>
<li><span style="font-family: Verdana, sans-serif;">converter-impl (implementation of conversion service)</span></li>
<li><span style="font-family: Verdana, sans-serif;">converter-client (client of conversion service)</span></li>
<li><span style="font-family: Verdana, sans-serif;">converter-server-feature (maven host project for converter server feature)</span></li>
<li><span style="font-family: Verdana, sans-serif;">converter-client-feature (maven host project for converter client feature)</span></li>
</ul>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<h4 style="text-align: left;">
<span style="font-family: Verdana, sans-serif;">Temperature Convertion Service</span></h4>
<div>
<span style="font-family: Verdana, sans-serif;">The example implements a temperature conversion feature. The interface of the service is as follows:</span></div>
<pre class="brush: java">public interface Converter {
double toCelcius(double fahrenheit);
double toFahrenheit(double celcius);
}
</pre>
</div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">And the implemetation:</span><br />
<pre class="brush: java">public class ConverterImpl implements Converter {
@Override
public double toCelcius(double fahrenheit) {
double celcius = ((fahrenheit - 32) * 5) / 9;
System.out.println("Fahrenheit " + fahrenheit +
" => Celcius " + celcius);
return celcius;
}
@Override
public double toFahrenheit(double celcius) {
double fahrenheit = 32 + ((celcius*9)/5);
System.out.println("Celcius " + celcius +
" => Fahrenheit " + fahrenheit);
return fahrenheit;
}
}
</pre>
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">The implementation bundle requires an Activator that will register the service.</span><br />
<pre class="brush: java">public class Activator implements BundleActivator {
private ServiceRegistration registration;
public void start(BundleContext bc) throws Exception {
Dictionary props = new Hashtable();
props.put("service.exported.interfaces", "*");
props.put("service.exported.configs", "org.apache.cxf.ws");
props.put("org.apache.cxf.ws.address",
"http://localhost:9090/converter");
registration = bc.registerService(Converter.class.getName(),
new ConverterImpl(), props);
}
public void stop(BundleContext bc) throws Exception {
registration.unregister();
}
}
</pre>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">This is how a simple OSGi service will be registered. The only extra thing is the CXF DOSGi parameters. If the CXF DOSGi bundle (or bundles - both a single and a multi bundle version are available for <a href="http://cxf.apache.org/dosgi-releases.html" rel="nofollow" target="_blank">download</a>) is not present, then these properties are ignored and the service can still be discovered by bundles in the same container. If however the CXF Distributed OSGi component is installed, then the above properties will have the effect of exporting a SOAP Web Service at the <a href="http://localhost:9090/converter">http://localhost:9090/converter</a> endpoint. The generated WSDL file is available at <a href="http://localhost:9090/converter?wsdl">http://localhost:9090/converter?wsdl</a>.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><b><i>Note: </i></b>It is very easy to export the OSGi service as a RESTful JAX-RS service as well. The only thing needed is to replace 'ws' with 'rs' in the above property values!</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">If you have downloaded the source code from GitHub, it will be very easy now to test the service implementation. Build the code with maven, start Karaf and type the following in Karaf's command prompt:</span><br />
<pre class="brush: vb">features:addURl mvn:gr.atc.aniketos.demos.converterservice/converter-server-feature/1.0.0/xml
features:install converter-server-feature
</pre>
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">The above commands will install the interface and the implementation bundles, as well as the single-bundle distribution of CXF DOSGi (The features.xml points to a file system location of the CXF DOSGi bundle. You need to download the file and modify features.xml to point to the downloaded jar file in your file system. You need to do this before building the projects and running the above commands in Karaf).</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">After running the commands allow for a minute or so for the bundles to install and then point your browser to </span><a href="http://localhost:9090/converter?wsdl" style="font-family: Verdana, sans-serif;">http://localhost:9090/converter?wsdl</a><span style="font-family: Verdana, sans-serif;">. The WSDL file of the conversion service should appear. You can treat this service as a regular SOAP Web Service and consume it through any SOAP Service client. What is more interesting however, is to access it as a remote OSGi service from a bundle running in a different container.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<h4 style="text-align: left;">
<span style="font-family: Verdana, sans-serif;">Service Client</span></h4>
<div>
<span style="font-family: Verdana, sans-serif;">The Service Client project utilizes an Activator that tries to discover a Consumer Service implementation using ServiceTracker.</span></div>
<pre class="brush: java">public void start(final BundleContext bundleContext) throws Exception {
tracker = new ServiceTracker(bundleContext, Converter.class.getName(), null) {
@Override
public Object addingService(ServiceReference reference) {
Object result = super.addingService(reference);
// Do something with the service
useService(bundleContext, reference);
return result;
}
};
tracker.open();
}</pre>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">Insice the </span><span style="font-family: Courier New, Courier, monospace;">useServive </span><span style="font-family: Verdana, sans-serif;">method a simpe JFrame dialog is started, which provides a basic interface for entering values for conversion.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIWXiTBAXoCQTMCGBKLhCp2wIJj1AJqaNJXgaw1oMF1Vj3Lm4tqYGn0mdlVQNf6ByfqGJFVCVf0jKNqCsCihqD-c4TepyuvqzcuIdvbPKlBRCHgCPh2jBV-69Q3-KZ_LSRBtatG_ccfg/s1600/Temperature+Conversions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="167" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIWXiTBAXoCQTMCGBKLhCp2wIJj1AJqaNJXgaw1oMF1Vj3Lm4tqYGn0mdlVQNf6ByfqGJFVCVf0jKNqCsCihqD-c4TepyuvqzcuIdvbPKlBRCHgCPh2jBV-69Q3-KZ_LSRBtatG_ccfg/s320/Temperature+Conversions.png" width="320" /></a></div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">There isn't a single line of Java code in the client bundle that relates with DOSGi. You can treat the client bundle as a regular OSGi bundle. You will need of course to install it in a container, where a conversion service implementation is also installed. As soon as a service is discovered, the JFrame dialog will appear and you can start doing conversions. Type a temperature in one of the two text fields and then click "Invoke". The result will appear in the command prompt.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><b><i>Note: </i></b>This is a very basic example. Things like the service going away aren't treated.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">In order to enable the discovery of a remote service, what is needed is a </span><span style="font-family: Courier New, Courier, monospace;">remote-services.xml</span><span style="font-family: Verdana, sans-serif;"> file. This file must be present in</span><span style="font-family: Courier New, Courier, monospace;"> OSGI-INF/remote-service/remote-services.xml</span><span style="font-family: Verdana, sans-serif;"> location inside the client bundle. The contents of the file are as follows:</span><br />
<pre class="brush: xml"><?xml version="1.0" encoding="UTF-8"?>
<service-descriptions xmlns="http://www.osgi.org/xmlns/sd/v1.0.0">
<service-description>
<provide interface="gr.atc.aniketos.demos.converter.Converter"></provide>
<property name="service.exported.interfaces">*</property>
<property name="service.exported.configs">org.apache.cxf.ws</property>
<property name="org.apache.cxf.ws.address">http://localhost:9090/converter</property>
</service-description>
</service-descriptions>
</pre>
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">What we define here is the interface of the service we want to discover and the endpoint to look it up. (We also define if it is about a SOAP or a RESTful service.)</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">We are now ready to test the client bundle in a different container. Build the projects (change the location of the CXF DOSGi single bundle distribution jar file in </span><span style="font-family: Courier New, Courier, monospace;">converter-client-feature\src\main\resources\features.xml</span><span style="font-family: Verdana, sans-serif;">), start a second instance of Karaf and type the following:</span>
<br />
<pre class="brush: vb">features:addURl mvn:gr.atc.aniketos.demos.converterservice/converter-client-feature/1.0.0/xml
features:install converter-client-feature
</pre>
<span style="font-family: Verdana, sans-serif;"><br /><b><i>Note:</i></b> In order to run two instances of Karaf in the same machine, you need to make some changes in the </span><span style="font-family: Courier New, Courier, monospace;">etc/org.apache.karaf.management.cfg</span><span style="font-family: Verdana, sans-serif;"> file. In this file two port numbers for RMI connections are defined. Make sure that the two Karaf instances use different port numbers.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">After running the above commands, wait for some seconds for the bundles to install and the remote service to be discovered. Then the conversion dialog will appear. Type a temperature and click "Invoke". The result of the conversion should appear in the command prompt of both instances of Karaf.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">You can of course use a different container than Karaf for either the service or the client. In that case however the convenient features mechanism can be used and you will need to find another way for installing the bundles. If you install the service in a different machine than the client, then you need to replace localhost in the </span><span style="font-family: Courier New, Courier, monospace;">org.apache.cxf.ws.address</span><span style="font-family: Verdana, sans-serif;"> property of the </span><span style="font-family: Courier New, Courier, monospace;">remote-services.xml</span><span style="font-family: Verdana, sans-serif;"> with the correct address.</span></div>
</div>
ATC Bloggerhttp://www.blogger.com/profile/12339569691943810552noreply@blogger.com0tag:blogger.com,1999:blog-66658270662490617.post-82801735108949549662012-10-12T04:23:00.000-07:002012-10-12T04:24:19.046-07:00Using WRAP protocol to install bundles in Apache Karaf<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<span style="font-family: Verdana, sans-serif;">The WRAP protocol provides a convenient way to install bundles in Apache Karaf in many situations. I will try to describe it here with some real examples.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">First let us try to install <a href="http://repo1.maven.org/maven2/org/eclipse/jdt/core/compiler/ecj/3.5.1/ecj-3.5.1.jar" rel="nofollow" target="_blank">ecj-3.5.1.jar</a>. This is the Eclipse Compiler for Java bundle and can be downloaded from a Maven repository.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Start Karaf and type:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: vb">karaf@root> install http://repo1.maven.org/maven2/org/eclipse/jdt/core/compiler/ecj/3.5.1/ecj-3.5.1.jar
Bundle ID: 162
karaf@root> start 162
karaf@root> list
START LEVEL 100 , List Threshold: 50
ID State Blueprint Level Name
[ 162] [Active ] [ ] [ 80] Eclipse Compiler for Java (3.3.0)
</pre>
<br />
<span style="font-family: Verdana, sans-serif;">The bundle started OK. Now let us uninstall it and try installing it again by copying it in the deploy folder. After we have done so, we try to find out if the new jar is properly installed:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: vb">karaf@root> list
START LEVEL 100 , List Threshold: 50
ID State Blueprint Level Name
</pre>
<br />
<span style="font-family: Verdana, sans-serif;">It seems that the bundle didn't install! No messages appeared either. To see what happened we need to have a look at the Karaf log located at data/log/karaf.log:</span><br />
<br />
<pre class="brush: vb">2012-10-10 13:10:04,423 | ERROR | af-server/deploy | fileinstall | 6 - org.apache.felix.fileinstall - 3.2.4 | Failed to install artifact: C:\Tools\Aniketos\apache-karaf-server\deploy\ecj-3.5.1.jar
org.osgi.framework.BundleException: The bundle file:/C:/Tools/Aniketos/apache-karaf-server/deploy/ecj-3.5.1.jar does not have a META-INF/MANIFEST.MF! Make sure, META-INF and MANIFEST.MF are the first 2 entries in your JAR!
</pre>
<br />
<span style="font-family: Verdana, sans-serif;">Now we can understand what happened. The jar file is malformed. A jar file isn't a simple zip file renamed with a jar extension. It is also specified that both a META-INF and a META-INF/MANIFEST.MF entry must be present and in fact be the first 2 entries in the JAR. This requirement is seldomly mentioned, because it is (almost) nowhere used. However Apache Karaf does respect it and doesn't allow the installation of jar files that don't follow this rule. Well, it actually respects the rule if either a features.xml or deploy folder is used and ignores it in the case of installation in the command prompt. In the case of a features.xml an error message in red, similar to the error message in the log, appears when you try to install such a file. In case of installation through the deploy folder the failure is silent. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><b><i>Note:</i> </b><i>The Apache Karaf log file (available at </i></span><span style="font-family: Verdana, sans-serif;"><i>data/log/karaf.log) should be checked for exceptions. Not all errors make it to the command prompt.</i></span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">One can verify that there is indeed a problem with the specific jar, by using the jar tool that is available in the JDK:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">jar -tf ecj-3.5.1.jar > entries.txt</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">The first lines in the entries.txt file are the following:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">META-INF/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/core/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/core/compiler/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/core/compiler/batch/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/antadapter/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/apt/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/apt/dispatch/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/apt/model/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/apt/util/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/ast/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/batch/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/classfmt/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/codegen/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/env/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/flow/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/impl/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/lookup/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/parser/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/parser/diagnose/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/problem/</span><br />
<span style="font-family: Courier New, Courier, monospace;">org/eclipse/jdt/internal/compiler/util/</span><br />
<span style="font-family: Courier New, Courier, monospace;">META-INF/MANIFEST.MF</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Indeed the META-INF/MANIFEST.MF isn't among the first two. I don't know how this happened in a jar file uploaded in an official Maven repositoty. Perhaps the Jar file was "hand-edited", i.e. someone used a zip utility to alter its contents in some way. This is another reason, why this practice should be avoided.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><b><i>Note:</i> </b><i>If you use a zip utility, like 7zip, to modify the contents of a JAR file, then this won't install in Karaf.</i></span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">What we can do in such cases? One solution is to re-jar the file so that is properly formed. This can be achieved with the jar tool. But let's see what karaf has to offer us. Create the following features.xml file:</span><br />
<br />
<pre class="brush: xml"><features><features>
<feature name="wrap_test" version="1.0">
<bundle>http://repo1.maven.org/maven2/org/eclipse/jdt/core/compiler/ecj/3.5.1/ecj-3.5.1.jar</bundle>
</feature>
</features>
</features></pre>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Try to install the feature. An error appears. Now let's use the wrap protocol:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: xml"><features><features>
<feature name="wrap_test" version="1.0">
<bundle>wrap:http://repo1.maven.org/maven2/org/eclipse/jdt/core/compiler/ecj/3.5.1/ecj-3.5.1.jar</bundle>
</feature>
</features>
</features></pre>
<br />
<span style="font-family: Verdana, sans-serif;">We need to refresh the URL and install again. This situation is depicted in the figure below:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXvp687uOEh5uFmHeg9_4OsrZHkEVJTgmSqDf6fnmI_mu55NGll_AcgerQ_ucBOmxc3nG3zeNoHiUC7dWBPNUPrbrUCb9ldKwg92jS4Y8aEnJibbK_AF0D4jI7lPAR0HOhesga3DLCIA/s1600/Karaf+Installation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXvp687uOEh5uFmHeg9_4OsrZHkEVJTgmSqDf6fnmI_mu55NGll_AcgerQ_ucBOmxc3nG3zeNoHiUC7dWBPNUPrbrUCb9ldKwg92jS4Y8aEnJibbK_AF0D4jI7lPAR0HOhesga3DLCIA/s1600/Karaf+Installation.png" /></a></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">The wrapping did the job for us. Karaf downloaded the file and wrapped it so that is a proper OSGi jar file. This means that is a proper jar of course and that an appropriate OSGi manifest is added.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">To demonstrate the addition of OSGi MANIFEST let us try to install <a href="http://repo1.maven.org/maven2/org/apache/activemq/protobuf/activemq-protobuf/1.1/activemq-protobuf-1.1.jar" rel="nofollow" target="_blank">activemq-protobuf-1.1.jar</a>. This is ActiveMQ Protocol Buffers Implementation and Compiler jar file and is also available at a standard Maven repository. We add it at the features.xml and refresh the URL. After refreshing a URL, it is always good to issue a features:info command in order to verify that the changes have taken effect. Now the installation of the feature, fails with the following message:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: vb">Error executing command: Jar is not a bundle, no Bundle-SymbolicName http://repo1.maven.org/maven2/org/apache/activemq/protobuf/activemq-protobuf/1.1/activemq-p
rotobuf-1.1.jar
</pre>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Again, if we use the wrap protocol, refresh the URL and install, the jar is successfully deployed.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9_zd5uicKI7oZC9qpeWyYerlINOf5k1jipbvdYZQOmAY2nc8zXuYHmcaZFADOgS7VFKR9zug7ek5ivnHoN9VOKwwcErrFxmwqtzGNYaID9RUWOrLCxiQSnbJ8uOavJzVMwWhvNI-Tug/s1600/Karaf+Installation+2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9_zd5uicKI7oZC9qpeWyYerlINOf5k1jipbvdYZQOmAY2nc8zXuYHmcaZFADOgS7VFKR9zug7ek5ivnHoN9VOKwwcErrFxmwqtzGNYaID9RUWOrLCxiQSnbJ8uOavJzVMwWhvNI-Tug/s1600/Karaf+Installation+2.png" /></a></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><b>Note: </b><i>Apache Karaf 2.2.9 was used for the above examples. Both of the above cases were discovered in a real-life situation (working for <a href="http://www.aniketos.eu/project" rel="nofollow" target="_blank">Aniketos</a> project), while trying to migrate an application from Equinox in Karaf. Equinox didn't complain for the above two jar files. Karaf on the other side, required these to be specially handled.</i></span></div>
ATC Bloggerhttp://www.blogger.com/profile/12339569691943810552noreply@blogger.com0tag:blogger.com,1999:blog-66658270662490617.post-52174945575529794462012-10-10T02:57:00.001-07:002012-10-12T04:23:56.770-07:00Easy installation of bundles in Apache Karaf<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: Verdana, sans-serif;">Apache Karaf provides many convenient ways for bundles installation:</span><br />
<ul style="text-align: left;">
<li><span style="font-family: Verdana, sans-serif;">Use of the install command in Karaf's command prompt</span></li>
<li><span style="font-family: Verdana, sans-serif;">Copying of bundles to the deploy directory</span></li>
<li><span style="font-family: Verdana, sans-serif;">Use of Apache Karaf features</span></li>
</ul>
<div>
<span style="font-family: Verdana, sans-serif;">From these three alternatives Karaf features seems to be the most advantageus. It allows the installation and uninstallation of many bundles in one go. No bundles will be installed, if there is a problem even with a single one. This helps you keep a clean container and spot errors easier. It supports mvn, http and file protocols making the installation of bundles from different locations easier. Last, but not least, it can also install non-OSGi jars (jars without an OGSi manifest), with the aid of the wrap protocol.</span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">In a previous post about <a href="http://aniketos-osgi.blogspot.gr/2012/10/spring-jdbc-in-osgi.html">Spring-JDBC</a> in an OSGi environment the usage of Karaf features with the Maven protocol was presented. A features.xml file pointing to bundles in Maven repositories was created. The features.xml file was hosted by a Maven project, making it possible to add a features Maven URL in Karaf.</span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">However bundles are not always available in Maven repositories. Sometimes all you have is a zip file with all necessary jars or some HTTP URLs. This is especially true in <a href="http://www.aniketos.eu/project">Aniketos </a>project, where there are contributions from many partners, using both Maven and Eclipse RCP for development and there is also some legacy code involved. In these cases Apache Karaf are still useful. </span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">This is an example of a features.xml file that points to jar files in the local file system:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<pre class="brush: xml"><features>
<feature name='greeter_server' version='1.0'>
<bundle>file:///c:/Tools/Aniketos/bundles/common/org.osgi.compendium-4.2.0.jar</bundle>
<bundle>file:///c:/Tools/Aniketos/bundles/greeter_sample/cxf-dosgi-ri-singlebundle-distribution-1.3.1.jar</bundle>
<bundle>file:///c:/Tools/Aniketos/bundles/greeter_sample/cxf-dosgi-ri-samples-greeter-interface-1.3.1.jar</bundle>
<bundle>file:///c:/Tools/Aniketos/bundles/greeter_sample/cxf-dosgi-ri-samples-greeter-client-1.3.1.jar</bundle>
</feature>
</features></pre>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">These can easily be installed in one go:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: vb">karaf@root> features:addURl file:///path/to/features.xml
karaf@root> features:install greeter_server
</pre>
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">If you modify one of the jar files and you want to re-install, then you can use:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: vb">karaf@root> features:uninstall greeter_server
karaf@root> features:install greeter_server</pre>
<span style="font-family: Verdana, sans-serif;"> </span>
<span style="font-family: Verdana, sans-serif;"> </span><br />
<span style="font-family: Verdana, sans-serif;">If you want to remove or add a jar file in the features.xml file, then you can refresh the URL:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: vb">karaf@root> features:refreshURl file:///path/to/features.xml
karaf@root> features:install greeter_server</pre>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br />
<span style="font-family: Verdana, sans-serif;">In another post I am going to explain how the wrap protocol supported by Karaf can help in certain situations.</span></span><br />
<span style="font-family: Verdana, sans-serif;">
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"> </span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span></span></div>
<div>
</div>
</div>
ATC Bloggerhttp://www.blogger.com/profile/12339569691943810552noreply@blogger.com0tag:blogger.com,1999:blog-66658270662490617.post-61408949922651431532012-10-09T06:15:00.001-07:002012-10-09T06:48:36.790-07:00Spring JDBC in OSGi<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: Verdana, sans-serif;"><a href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jdbc.html" rel="nofollow" target="_blank">Spring JDBC</a> provides an excellent alternative to the dreadful Java JDBC API for accessing a database. However, using it in an OSGi container isn't so easy, as there are some pitfalls to avoid. I will try to describe here a solution to this problem.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<h3 style="text-align: left;">
<span style="font-family: Verdana, sans-serif;">Test Database</span></h3>
<div>
<span style="font-family: Verdana, sans-serif;">First let's create a test database. We are going to use MySQL. Open a MySQL command prompt and type the following:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<pre class="brush: sql">CREATE DATABASE `repository`;
USE `repository`;
CREATE TABLE `items` (
`ItemId` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(255) NOT NULL,
PRIMARY KEY (`ItemId`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
insert into `items`(`ItemId`,`Name`) values (1,'Name 1'),(2,'Name 2'),(3,'Name 3');
</pre>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<h3 style="text-align: left;">
<span style="font-family: Verdana, sans-serif;">Spring-JDBC bundle</span></h3>
<span style="font-family: Verdana, sans-serif;">Now we are going to create a test bundle to access the data stored in the above table. The following pom.xml contains the appropriate configuration and the required dependencies. Notice that we need spring-core, spring-jdbc and spring-tx (transaction) bundles. These are the necessary compile time dependencies. There are more runtime dependencies that we need to install in the OSGi container. The exact list of dependencies will be presented later.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: 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">
<modelVersion>4.0.0</modelVersion>
<groupId>aniketos</groupId>
<artifactId>springjdbc-test-impl</artifactId>
<packaging>bundle</packaging>
<version>1.0.0</version>
<name>springjdbc-test</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>3.1.1.RELEASE</spring.version>
<bundle.require.bundle>org.springframework.jdbc</bundle.require.bundle>
<bundle.import.package>
javax.sql,
org.springframework.core;version="[2.5.6,3.1.2)",
org.springframework.jdbc;version="[2.5.6,3.1.2)",
org.springframework.transaction;version="[2.5.6,3.1.2)"
</bundle.import.package>
<bundle.export.package></bundle.export.package>
<bundle.dynamicimport.package>*</bundle.dynamicimport.package>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.1.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Activator>gr.atc.aniketos.springjdbc.MainActivator</Bundle-Activator>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-Description>A bundle that demonstrates the use of SPRING JDBC in an OSGi environment</Bundle-Description>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Require-Bundle>${bundle.require.bundle}</Require-Bundle>
<Import-Package>${bundle.import.package}</Import-Package>
<Export-Package>${bundle.export.package}</Export-Package>
<DynamicImport-Package>${bundle.dynamicimport.package}</DynamicImport-Package>
</instructions>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project></pre>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">The Java code is simple as we only want to demonstrate that the access to the database is succesfull.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: java">public class MainActivator implements BundleActivator {
public void start(BundleContext context) throws Exception {
System.out.println("Started...");
String databaseUrl = "jdbc:mysql://localhost:3306/repository";
String databaseUser = "root";
String databasePassword = "";
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
} catch (Exception ex) {
System.out.println(ex.getMessage());
throw new IllegalStateException(
"Could not load JDBC driver class", ex);
}
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(databaseUrl);
dataSource.setUsername(databaseUser);
dataSource.setPassword(databasePassword);
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
Collection<String> names = jdbcTemplate.query(
"SELECT `items`.`Name` FROM `items`",
new Object [0], new ServiceNameMapper());
for(String name: names) {
System.out.println(name);
}
}
private final class ServiceNameMapper implements RowMapper<String> {
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString("Name");
}
}
public void stop(BundleContext context) throws Exception {
}
}</pre>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<h3 style="text-align: left;">
<span style="font-family: Verdana, sans-serif;">mysql-springjdbc-fragment bundle</span></h3>
<span style="font-family: Verdana, sans-serif;">In order to test the above bundle you of course need to install a MySQL driver to your OSGi container. However this isn't enough. The same class loader needs to be used from both Spring-JDBC and the driver. This isn't the case though, as these two are in different bundles and have separate class loaders. The solution is to use a fragment bundle. This can be an empty bundle that all it does is to attach the MySQL driver to Spring-JDBC, so that these two can share the same classloaders. This pom.xml creates the fragment bundle:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: xml"><build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.1.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Fragment-Host>org.springframework.jdbc</Fragment-Host>
<Import-Package>com.mysql.jdbc</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build></pre>
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;"><u>Warning:</u> Maven (bnd tool internally) doesn't let you build a completely empty jar. Just place a text file in the META-INF folder to overcome this.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<h3 style="text-align: left;">
<span style="font-family: Verdana, sans-serif;">Running everything in Apache Karaf</span></h3>
<span style="font-family: Verdana, sans-serif;">Now let's see how can we easily install everything in Apache Karaf. We are going to make use of Apache Karaf features. In order for this to work Maven needs to be installed and the M2_HOME variable properly set.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Karaf features allows you to group a bundle and its dependencies and install everything in one go. All bundles are defined in a features.xml file. Since Karaf supports the mvn protocol, we can use mvn URLs. We can use both remote and local repositories.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: xml"><features>
<feature name="springjdbc_test" version="1.0">
<bundle>mvn:org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1</bundle>
<bundle>mvn:org.springframework/spring-core/3.1.1.RELEASE</bundle>
<bundle>mvn:org.springframework/spring-asm/3.1.1.RELEASE</bundle>
<bundle>mvn:org.springframework/spring-beans/3.1.1.RELEASE</bundle>
<bundle>mvn:org.springframework/spring-context/3.1.1.RELEASE</bundle>
<bundle>mvn:org.springframework/spring-tx/3.1.1.RELEASE</bundle>
<bundle>mvn:org.springframework/spring-jdbc/3.1.1.RELEASE</bundle>
<bundle>mvn:aniketos/mysql-springjdbc-fragment/1.0.0</bundle>
<bundle>mvn:com.mysql.jdbc/com.springsource.com.mysql.jdbc/5.1.6</bundle>
<bundle>mvn:aniketos/springjdbc-test-impl/1.0.0</bundle>
</feature>
</features></pre>
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">You can easily install the springjdbc_test feature by copying the above features.xml file in your file system and then typing in Apache Karaf:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: vb">karaf@root> features:addURl file:///path/to/features.xml
karaf@root> features:install springjdbc_test
</pre>
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">However we can also create a Maven project to hold the features.xml file. The features.xml needs to go under src/main/resources. The pom.xml for building the project is the following:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: xml"><?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>aniketos</groupId>
<artifactId>springjdbc-feature</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>springjdbc-feature</name>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>filter</id>
<phase>generate-resources</phase>
<goals>
<goal>resources</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>attach-artifacts</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>target/classes/features.xml</file>
<type>xml</type>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project></pre>
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">Now the feature can be install by adding a URL with the mvn protocol:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<pre class="brush: vb">karaf@root> features:addURl mvn:aniketos/springjdbc-feature/1.0.0/xml
karaf@root> features:install springjdbc_test
</pre>
<br />
<h3 style="text-align: left;">
<span style="font-family: Verdana, sans-serif;">Summary</span></h3>
<div>
<span style="font-family: Verdana, sans-serif;">In this post we presented how Spring-JDBC can be used in an OSGi environment. A fragment bundle that will attach the SQL driver to the Spring-JDBC bundle is needed. The client bundle only needs to import spring-jdbc and javax.sql packages. However, a dynamic import is also necessary.</span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">We also showed how the Apache Karaf features can be used to easily install a bundle and its dependencies.</span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">The code of this example is available in <a href="https://github.com/research-atc/osgi-spring-jdbc" rel="nofollow" target="_blank">GitHub</a>.</span></div>
<br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div>
<br /></div>
</div>
</div>
ATC Bloggerhttp://www.blogger.com/profile/12339569691943810552noreply@blogger.com0