Παρασκευή 12 Οκτωβρίου 2012

Using WRAP protocol to install bundles in Apache Karaf


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.

First let us try to install ecj-3.5.1.jar. This is the Eclipse Compiler for Java bundle and can be downloaded from a Maven repository.

Start Karaf and type:


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)

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:


karaf@root> list
START LEVEL 100 , List Threshold: 50
   ID   State         Blueprint      Level  Name

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:

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!

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. 

Note: The Apache Karaf log file (available at data/log/karaf.log) should be checked for exceptions. Not all errors make it to the command prompt.

One can verify that there is indeed a problem with the specific jar, by using the jar tool that is available in the JDK:

jar -tf ecj-3.5.1.jar > entries.txt

The first lines in the entries.txt file are the following:

META-INF/
org/
org/eclipse/
org/eclipse/jdt/
org/eclipse/jdt/core/
org/eclipse/jdt/core/compiler/
org/eclipse/jdt/core/compiler/batch/
org/eclipse/jdt/internal/
org/eclipse/jdt/internal/antadapter/
org/eclipse/jdt/internal/compiler/
org/eclipse/jdt/internal/compiler/apt/
org/eclipse/jdt/internal/compiler/apt/dispatch/
org/eclipse/jdt/internal/compiler/apt/model/
org/eclipse/jdt/internal/compiler/apt/util/
org/eclipse/jdt/internal/compiler/ast/
org/eclipse/jdt/internal/compiler/batch/
org/eclipse/jdt/internal/compiler/classfmt/
org/eclipse/jdt/internal/compiler/codegen/
org/eclipse/jdt/internal/compiler/env/
org/eclipse/jdt/internal/compiler/flow/
org/eclipse/jdt/internal/compiler/impl/
org/eclipse/jdt/internal/compiler/lookup/
org/eclipse/jdt/internal/compiler/parser/
org/eclipse/jdt/internal/compiler/parser/diagnose/
org/eclipse/jdt/internal/compiler/problem/
org/eclipse/jdt/internal/compiler/util/
META-INF/MANIFEST.MF

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.

Note: If you use a zip utility, like 7zip, to modify the contents of a JAR file, then this won't install in Karaf.

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:

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

Try to install the feature. An error appears. Now let's use the wrap protocol:


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

We need to refresh the URL and install again. This situation is depicted in the figure below:



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.

To demonstrate the addition of OSGi MANIFEST let us try to install activemq-protobuf-1.1.jar. 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:


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

Again, if we use the wrap protocol, refresh the URL and install, the jar is successfully deployed.



Note: 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 Aniketos 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.

Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου