Learn all about OSGi Bundles, Right Here!

Assuming, You have already gone through the blog – AEM OSGi: All you need to know!, time to learn more about the OSGi Bundles. In the previous blog, I had just touched the topic, here, I will explain it in detail.

Bundles are the basic units of modularity in OSGi. Each bundle is essentially a JAR file containing Java classes, resources, and a manifest file. The manifest file contains metadata about the bundle, such as its version, dependencies, and the packages it exports or imports.

aem osgi bundles

In a nutshell, OSGi achieves the said modularity with the help of Bundles.

What are the Key Components of a Bundle?

  • Manifest File: This XML file describes the bundle’s metadata, including its name, version, dependencies, exported packages, and imported packages.
  • Java Classes: The actual code that implements the bundle’s functionality.
  • Resources: Additional files like configurations, templates, and images.

How do Bundles Interact?

  • Dependency Management: Bundles can declare dependencies on other bundles. OSGi ensures that these dependencies are resolved correctly before the bundle starts.
  • Service Registry: Bundles can register services they provide and consume services offered by other bundles. This promotes loose coupling and dynamic interactions.
  • Lifecycle Management: Bundles have a lifecycle that includes installation, starting, stopping, and updating. OSGi manages these transitions.

What lifecycle does a bundle typically have?

In OSGi, a bundle goes through a well-defined lifecycle, managed by the OSGi framework. The lifecycle of a bundle typically includes the following states:

Installed -> Resolved -> Starting -> Active -> Stopping -> Uninstalled

1. Installed

  • Description: The bundle has been installed into the OSGi environment, but its dependencies have not yet been resolved. At this stage, the OSGi framework is aware of the bundle, but it cannot be used because it has not been started yet.
  • Implications: The bundle’s code is not yet executing, and it has not been linked with any of its required dependencies.

2. Resolved

  • Description: The OSGi framework has resolved the bundle’s dependencies, meaning all required classes and packages that the bundle needs are available and linked. The bundle is ready to be started.
  • Implications: The bundle is now in a state where it can be started, but it is not active yet. If the bundle’s dependencies cannot be resolved, it will remain in the “Installed” state.

3. Starting

  • Description: The bundle is in the process of starting. The OSGi framework calls the start() method of the bundle’s BundleActivator class if it has one.
  • Implications: During this phase, the bundle can execute code to initialize resources, register services, or perform other startup tasks. The bundle is not yet fully active until the start() method completes successfully.

4. Active

  • Description: The bundle is fully active and running. It can now provide services to other bundles, and its classes and resources are available for use by other parts of the application.
  • Implications: This is the main operational state for a bundle, where it performs its intended functions. The bundle remains in this state until it is stopped.

5. Stopping

  • Description: The bundle is in the process of stopping. The OSGi framework calls the stop() method of the bundle’s BundleActivator class.
  • Implications: During this phase, the bundle should release any resources it holds, unregister any services it has registered, and perform cleanup tasks. The bundle is transitioning out of the active state.

6. Uninstalled

  • Description: The bundle has been removed from the OSGi environment. It is no longer available for use, and its resources have been released.
  • Implications: Once in this state, the bundle cannot be reactivated unless it is re-installed into the OSGi framework.

Bundle State Transitions

  • Installed → Resolved: When all dependencies of the bundle are satisfied.
  • Resolved → Starting: When the start() method is called on the bundle.
  • Starting → Active: When the start() method completes successfully.
  • Active → Stopping: When the stop() method is called on the bundle.
  • Stopping → Resolved: When the stop() method completes successfully.
  • Resolved → Installed: When the bundle’s dependencies are no longer satisfied.
  • Installed/Resolved/Active → Uninstalled: When the bundle is removed from the OSGi environment.

Bundle Lifecycle Summary

In a nutshell, the bundle lifecycle can be summarized as –

  1. Installed: The bundle is installed in the OSGi environment but is not yet usable.
  2. Resolved: All dependencies are resolved, and the bundle is ready to be started.
  3. Starting: The bundle is in the process of starting, and running its initialization code.
  4. Active: The bundle is fully running and providing its services.
  5. Stopping: The bundle is in the process of stopping and cleaning up resources.
  6. Uninstalled: The bundle is removed from the OSGi environment and is no longer available.

These questions are usually asked in AEM developer-level interviews. It’s good to have a grasp of this information to impress the interviewer. 🙂

What is the difference between a normal jar file and a Bundle jar file

FeatureNormal JAROSGi Bundle
MetadataNo special fileMETA-INF/MANIFEST.MF with OSGi headers
ModularityNot modularModular with package and service boundaries
Lifecycle ManagementNo built-in managementDynamic management by OSGi framework
Dependency ManagementClasspath basedOSGi service registry and package imports/exports
Service RegistryNo service registryCan register and use services
VersioningNo explicit supportSupports versioning of bundles and packages

How do you create dependencies between bundle A and bundle B?

To create dependencies between Bundle A and Bundle B in OSGi, follow these steps:

  1. Export Packages in Bundle B:
    • Bundle B needs to specify which packages it provides. This is done in the MANIFEST.MF file using the Export-Package header.
    plaintextCopy codeExport-Package: com.example.service
  2. Import Packages in Bundle A:
    • Bundle A needs to declare its dependency on the packages provided by Bundle B. This is done in the MANIFEST.MF file using the Import-Package header.
    plaintextCopy codeImport-Package: com.example.service
  3. Ensure Proper Versioning:
    • Both bundles should include version information in the Export-Package and Import-Package headers to manage compatibility.
    plaintextCopy codeExport-Package: com.example.service; version="1.0.0" Import-Package: com.example.service; version="[1.0.0,2.0.0)"
  4. Deploy and Start Bundles:
    • Deploy both bundles to the OSGi container. Bundle A can only start successfully if Bundle B is also installed and resolved, as it depends on the packages provided by Bundle B.
  5. Service Dependencies (if applicable):
    • If Bundle A relies on services provided by Bundle B, Bundle A should use OSGi service registry mechanisms (e.g., ServiceReference) to bind to the services exposed by Bundle B.
aem tarmk mongomk which one is good

Sample OSGi Bundle Manifest File

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.example.mybundle
Bundle-Version: 1.0.0
Bundle-Activator: com.example.mybundle.Activator
Import-Package: org.osgi.framework
Export-Package: com.example.mybundle.api

What are the specific entries that need to be done in the pom.xml file to use bundles in AEM?

Uber-jar Dependency

<dependencies>
    <!-- Example: AEM API dependencies -->
    <dependency>
        <groupId>com.adobe.aem</groupId>
        <artifactId>uber-jar</artifactId>
        <version>6.5.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- Add other dependencies as needed -->
</dependencies>

Plugin changes

<build>
    <plugins>
        <!-- Apache Felix Maven Bundle Plugin -->
        <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <version>5.1.2</version>
            <extensions>true</extensions>
            <configuration>
                <instructions>
                    <!-- OSGi metadata like Export/Import-Package -->
                    <Export-Package>com.example.mybundle.*</Export-Package>
                    <Import-Package>*</Import-Package>
                </instructions>
            </configuration>
        </plugin>

        <!-- Apache Sling Maven Plugin -->
        <plugin>
            <groupId>org.apache.sling</groupId>
            <artifactId>maven-sling-plugin</artifactId>
            <version>2.2.0</version>
        </plugin>
    </plugins>
</build>

Repository changes

<repositories>
    <repository>
        <id>adobe-public-releases</id>
        <url>https://repo.adobe.com/nexus/content/groups/public/</url>
    </repository>
</repositories>

I have tried to add almost all the /details in this blog related to bundles. Hope this is helpful.

Further Reference

Feel free to share your thoughts on this topic in the comments section below 👇 We would be happy to hear and discuss the same 🙂

Spread the word!
0Shares

Leave a comment

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