Sunday, August 10, 2014

Using reexport with Require-Bundle in Manifest.mf.

Hi,

Today I am going to give a small description on use of  'reexport' with Require-Bundle in Manifest.mf.

Require-Bundle is used to add dependencies to other bundles.

Example:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: P2
Bundle-SymbolicName: p2
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: p2.Activator
Require-Bundle: org.eclipse.ui,
 org.eclipse.core.runtime
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy
Export-Package: p2

What is reexport feature in Require-Bundle.

OSGI has given a directive called 'visibility' which can be used with 'Require_bundle'.
If the value is private (Default), then all visible packages from
the required bundles are not re-exported. If the value is reexport then
bundles that require this bundle will transitively have access to these
required bundle’s exported packages.

Eg:

Require-Bundle: org.eclipse.ui,
 org.eclipse.core.runtime,
 p1;bundle-version="1.0.0";visibility:=reexport

Here P1 bundle is re-exported to other dependent plugins.
Let us understand this with a simple exmaple.

1. Create 3 plugin projects P1, P2, P3.
2. Situation is : P3 requires P2. P2 requies P1. Now add add theses dependencies.
-----------------------------------------------------------------------------------------------------
Eg:
Manifest of  P3: 
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: P3
Bundle-SymbolicName: p3
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: p3.Activator
Require-Bundle: org.eclipse.ui,
 org.eclipse.core.runtime,
 p2;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy

Manifest of P2:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: P2
Bundle-SymbolicName: p2
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: p2.Activator
Require-Bundle: org.eclipse.ui,
 org.eclipse.core.runtime,
 p1;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy
Export-Package: p2

Manifest of P1:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: P1
Bundle-SymbolicName: p1
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: p1.Activator
Require-Bundle: org.eclipse.ui,
 org.eclipse.core.runtime
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy
Export-Package: p1
------------------------------------------------------------------------------------------------------

3. Now if you try to access any class of p1 from p3 it will say that p1 is not resolvable.
4. How can i still access P1 exported package? They way left is adding P1 as require bundle in P3.

5. There is another way of doing it. As we see that P3 requires P2.
    And P2 as access to P1, So P2 can re-export the P1 bundle to its dependents for access.
    This can be done using visibillity:reexport.

eg:

Manifest of P2:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: P2
Bundle-SymbolicName: p2
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: p2.Activator
Require-Bundle: org.eclipse.ui,
 org.eclipse.core.runtime,
 p1;bundle-version="1.0.0";visibility:=reexport
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy

Export-Package: p2


So, Now I am able to access P1 from P3 as well.


----------------------------------------------------------------------------------------------------------
Another use of using visibility:reexport:

Situation: Let us suppose that we have a Plugin A and Plugin B requires Plugin A.
                 Now there is a business requirement to break Plugin A into smaller bundle due to some re factoring or so.
Now breaking break Plugin A as Plugin A, Plugin A1, Plugin A2.

So Plugin A----> requires  Plugin A1 and Plugin A2.

What changes needs to be done in Plugin B to work this application correctly?
Yes correct, No change in Plugin B would be required if we use visibility:reexport derivative.

Simply, re-export the bundles which Plugin A requires and Plugin B will be able to use it without any error.

eg:
Entry in Plugin A manifest.

Require-Bundle: A1;visibility:=reexport,
                          A2:visibility:=reexport

----------------------------------------------------------------------------------------------------------------------------------

Please do give your valuable suggestions to improve it and your queries.
Cheers. :)

3 comments:

  1. When to avoid re-export ? What about using split packages in this case ?

    ReplyDelete
    Replies
    1. Generally We should avoid using re-export because once you have added re-export you cannot remove it without considering the corresponding API change. So it increases the dependency.
      Also, Avoiding re-export generally gives more flexibility to remove or refactor dependencies in the future without breaking the API exposed by your plug-in.

      And using split packages have even more drawbacks.
      Refer OSGI Specification :3.13.3

      Avoiding re-export generally gives more flexibility to remove or refactor dependencies in the future without breaking the API exposed by your plug-in.

      Delete
  2. Nice post, it help lots.. Thanks

    ReplyDelete