Creating OSGi Bundles

Problem: I have a third party Java library that I need to use in my CQ component.  It’s available as a standard jar file. I want to drop this in a lib folder somewhere and have access to the classes. But AEM doesn’t support libraries this way. How do I import and use this code?

Solution: AEM manages libraries as OSGi bundles.  OSGi bundles are essentially the same thing as standard jar files, but they contain extra metadata. This metadata relates to versioning and dependencies, and is stored in a jar’s \META-INF\MANIFEST.MF file.  AEM requires this metadata, so in order to use a third-party jar library in AEM, you must add that to the library’s jar file, turning it into what’s called an OSGi bundle.

How: Our case study will be a Java API for a third-party mailing list manager:  Ecwid’s MailChimp API.

Note that if all you want is a quick step-by-step solution, without images or explanations, see here.

Step 0: Since the source code for our third party library happens to be stored in git, and happens to be compiled with maven, we’ll need to install clients for each.  I’ll be using the windows command line clients with cygwin.

Step 1:  Build and compile the library

mailchimp-step-1

> git clone https://github.com/Ecwid/ecwid-mailchimp.git

Note that the URL was simply copied from “clone URL” field on the repository page linked above

> cd ecwid-mailchimp
> mvn clean package dependency:copy-dependencies -DskipTests=true

Note that I skipped the tests because they break without some API key configuration (which we can do later) and copy the dependencies for a reason I’ll explain in the next step.

Step 2: Figure out how to create a OSGi bundle jar file

There are many ways to build a jar as an OSGi bundle.  Here’s what we will not be doing

a) Manually writing up the MANIFEST.MF file.  This is untenable for even slightly complicated OSGi bundles because the file format is so fickle.  And mistakes don’t yield friendly errors.

b) Use a Maven OSGi plugin and modify the project poms.  Configuring this the first time can be nearly as complicated as manually building the manifest file.

c) Use bndtools to create one.  This is a good tool but is kind of indiscriminate into what it includes as dependencies.  This brings us to our next problem.

Problem: OSGi bundles won’t load unless their dependencies are loaded as OSGi bundles.

“Ideal” Solution: Track down each of the dependencies and recompile those as OSGi bundles.  Do the same for each of their dependencies, all the way down the chain.  In an ideal world, all jars would be OSGi capable.  But few libraries are currently packaged this way, and we’re not going to spend this kind of time on code that’s not ours.

Quick and Dirty Solution: Package the main jar and all its dependency jars as a single, combined OSGi bundle.  (Note how we explicitly copied those dependency jars in the maven command above).  There are downsides, and this defeats some of the points to OSGi dependency management, but it’s the most practical solution for moderately complex libraries.

Tool: Eclipse for ECP/Plug-in Developers

Why are we downloading a specialized version of Eclipse for something seemingly unrelated to what we’re doing?  Because it has a fantastic OSGi builder and interface!  Download and install the latest version somewhere.  Then open it.

Note that you can also just add “Eclipse Plug-in Devlopment Environment” to your existing Eclipse environment.

Step 3: Create OSGi project in Eclipse
New -> Other -> Plugin Development -> Plug-in from Existing JAR Archives
Add External
Select all the jars in the target folder (target\ecwid-mailchimp-2.0.0.1-SNAPSHOT.jar and target\dependencies\*.jar)
Set a project name
Check "Analyze library contents and add dependencies"
Select "an OSGi framework"
Select "standard"
Uncheck "Unzip the JAR..."
Finish

Step 4: Export the project as an OSGi bundle
Right click on project -> Export
Plug-in Development -> Deployable plug-ins and fragments
Select a directory
Click Finish
Open that directory -> Plugin folder
Copy the jar file

Step 5: Install the OSGi bundle into CQ
Open CRXDE
Navigate to apps\(project)\install
Paste jar file

Step 6: Verify OSGi bundle deployed in CQ
Open CQ OSGi Console
OSGi -> Bundles
Type "mailchimp" (or whatever project name was) into search bar and click "Apply Filter"
Use arrow to expand description of bundle
Scroll through imported packages
Note anything that is highlighted in red because it's unresolvable
Go back into eclipse and the OSGi project
Click "dependencies"
Remove the project dependencies under Imported Packages

Step 7: Redeploy OSGi bundle
Export OSGi bundle again from Eclipse as in previous step
Open CRXDE and delete the old OSGi bundle
Copy-paste the new one in
Verify no issues and an Active status within CQ's OSGi console

Step 8: Use it in a component.

Here’s some sample code from a component jsp that consumes this library, along with its position relative to the OSGi jar.

structure

Conclusion:

Adding third party code to CQ the “right way” isn’t necessarily trivial, but using some standard tools can be done without too much overhead. Suggestions and questions are welcome; based on feedback I may be appending or following up on this topic with more details and explanations.

Resources:

4 thoughts on “Creating OSGi Bundles

  1. v k

    This code will work with elder versions of the ecwid-mailchimp library (v1.3.x.x):

    However, the package name should be changed to com.ecwid.mailchimp.method.v1_3.list.* if the newest version (v2.0.x.x) is used.

    Reply
  2. Nick Matelli Post author

    Thanks for the tip, v k. This post was written for v2.0. It looks like the ecwid libarary made some updates three weeks ago to support versioning. I’ll incorporate your suggestion into this article if I get a chance to test it with the latest version.

    Note that the compiled bundle I’ve provided will still work with the example source code.

    Reply

Leave a Reply to Nick Matelli Cancel reply

Your email address will not be published. Required fields are marked *