DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Software Design and Architecture
  3. Cloud Architecture
  4. Understanding How OSGI Bundles Get Resolved: Part II

Understanding How OSGI Bundles Get Resolved: Part II

Christian Posta user avatar by
Christian Posta
·
May. 30, 12 · Interview
Like (0)
Save
Tweet
Share
10.26K Views

Join the DZone community and get the full member experience.

Join For Free

In my previous post, I introduced the rules for how bundles get resolved in an OSGI container. In this post, I’d like to demonstrate each rule step using the Apache Karaf OSGI container. Karaf is based on the Apache Felix core, although the Equinox core can be substituted if desired. Karaf is a full-featured OSGI container and is the cornerstone of the Apache ServiceMix integration container. ServiceMix is basically Karaf but specifically tuned for Apache Camel, Apache ActiveMQ and Apache CXF.

This tutorial will require Maven and Karaf. Download maven from the maven website. Download and install karaf as described in the getting started guide on the Karaf website. You will also need the code that goes along with this example. You can get it at my github repo. After getting it, make sure to run ‘mvn install’ from the top-level project. This will build and install all of the bundles into your local maven repository. Although you can install bundles a couple different ways, using maven is easiest. Note that this sample code is mostly made up of package names without any real Java classes (except where the tutorial specifies).

First thing to do is start up karaf. In a plain distribution there should be no bundles installed. Verify this by doing “osgi:list” at the karaf commandline. Going in order, we will test out the rules from part one of this two-part series:

For every Import-Package package declaration, there must be a corresponding Export-Package with the same package

To test this rule, let’s install Bundle A from our sample bundles. Bundle A specifies an Import-Package of “org.apache.foo” package. According to the first rule, this bundle cannot move to the “Resolved” state since there is no corresponding bundle with an “Export-Package” of org.apache.foo.

From the karaf commandline, type “osgi:install mvn:explore-bundle-resolution/bundleA/1.0″. This will install the bundleA bundle. Now do a “osgi:list” again. You should see the bundle installed, and under the “State” column, it should say “Installed”. Now try “osgi:resolve bundle id” where bundle id is the ID listed from the “osgi:list” command. This will try to resolve all bundle dependencies and put it into the “Resolved” state. It won’t resolve, however. Type “osgi:list” again to see the state of the bundle. It’s still in “Installed” state even though we asked OSGI to resolve it. Let’s find out why. Execute the “osgi:headers bundle id“. Under the Import-Package, you should see the package name org.apache.foo listed in a red color. This dependency is missing, so let’s add it. Type “osgi:install -s mvn:explore-bundle-resolution/bundleB/1.0″. Note the ‘-s’ switch in the command. This tells OSGI to start the bundle once it’s installed. Now type the osgi:resolve command again (with the appropriate bundle ID). This will now resolve the bundle.

Import-Package dictates exactly what version (or attribute) it needs, and a corresponding Export-Package with the same attribute must exist

Let’s install bundle C: “osgi:install -s mvn:explore-bundle-resolution/bundleC/1.0″ List the bundles again, and you’ll see that although bundle C depends on org.apache.foo, it specifies an Import-Package with a specific version=1.5. There is no version 1.5 that is resolved, so bundle C will also not resolve. Bundle D happens to export a package org.apache.foo with a version equal to 1.5. Install bundle D the same way we’ve installed the others, using the -s to start it. Now try to resolve bundle C and it should work (“osgi:resolve bundle id“).

Bundles installed first are used to satisfy a dependency when multiple packages with the same version are found

This rule says that if there are multiple packages exported with the same version, OSGI will choose the first-installed bundle to use when trying to resolve bundles that import the package. Continuing on with the previous example where we installed bundle C and D… consider that bundle D exports org.apache.foo;version=1.5. So if we install bundle F that exports the exact same package and version, we should see that bundle C is resolved with the package from bundle D and not bundle F. Let’s see.. install bundle F: “osgi:install -s mvn:explore-bundle-resolution/bundleF/1.0″. Do an osgi:list and see that both bundle D and F are correctly installed and “Active”. This is a cool feature of OSGI: we can have multiple versions of the same package deployed at the same time, (including in this example the exact same version). Now we should uninstall bundle C and re-install it to see which bundle it uses to resolve for its import of org.apache.foo. Try running “osgi:uninstall bundle id” to uninstall bundle C. Now re-install it using the command from above. It should resolve to use bundle D. Use “package:import bundle id” to verify. You can try switching things around to get F to resolve. You may need to use “osgi:refresh” to refresh the OSGI bundles.

Bundles that have already been resolved have a higher precedence that those not resolved

In a way, we have already seen this with the previous rule, but this rule comes into play when hot deploying. This is left as an exercise to the reader as this post is already getting pretty long and I would like to cover the “uses” directive next.

Bundle “uses” directive

The “uses” directive adds one of the last rules and constraints to avoid runtime class-cast exceptions. Please review my previous blog post for details about the “uses” directive. To simulate how the “uses” directive works, we will install bundles G, H, I, and J and notice how the container enforces the “uses” directive.

Bundle G represents a sort of “service” module that client modules can call to “execute” some form of processing and return a result. The result it returns is an object of type BarClass that comes from Bundle H. But if a client makes a call to bundle G, it too must use the BarClass from bundle H or it will result in a class cast exception. In our samples, Bundle I is the client code and Bundle J represents a different version of the BarClass. Install the bundles in any order you like, but my demonstration followed this order: J, H, G, I. Note that the version of org.apache.bar is indeed the 2.0.0 version which comes from bundle H even though bundle H was installed second (contrary to the rule above). This is because bundle G specified the “uses” directive to depend on a specific version of org.apache.bar.

Directive (programming) Container Apache Maven POST (HTTP) Command (computing) Apache Felix Apache ActiveMQ Apache ServiceMix Dependency

Published at DZone with permission of Christian Posta, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Master Spring Boot 3 With GraalVM Native Image
  • Multi-Cloud Integration
  • Real-Time Analytics for IoT
  • How To Build a Spring Boot GraalVM Image

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: