Plugins often must use Java classes from packages outside of themselves. Another OSGi bundle (a module or an OSGi Web Application Bundle) in the OSGi framework must export a package for your plugin to import it.
When an OSGi bundle (bundle) is set up to import packages, the OSGi framework finds other registered bundles that export the needed packages and wires them to the importing bundle. At run time, the importing bundle gets the class from the wired bundle that exports the class’s package.
For this to happen, a bundle’s META-INF/MANIFEST.MF
file must specify the
Import-Package
OSGi manifest header with a comma-separated list of the Java
packages it needs. For example, if a bundle needs classes from the
javax.portlet
and com.liferay.portal.kernel.util
packages, it must specify
them like so:
Import-Package: javax.portlet,com.liferay.portal.kernel.util,*
The *
character represents all packages that the module refers to explicitly. Bnd detects the referenced packages.
Import packages must sometimes be specified manually, but not always. Conveniently, Liferay DXP project templates and tools automatically detect the packages a bundle uses and add them to the package imports in the bundle’s manifest. Here are the different package import scenarios:
Let’s explore how package imports are specified in these scenarios.
Automatic Package Import Generation
Gradle and Maven module projects
created using
Blade CLI,
Liferay’s Maven archetypes,
or
Liferay Dev Studio DXP
use
bnd.
On building such a project’s module JAR, bnd detects the packages the module
uses and generates a META-INF/MANIFEST.MF
file whose Import-Package
header
specifies the packages.
For example, suppose you’re developing a Liferay module using Maven or Gradle.
In most cases, you specify your module’s dependencies in your pom.xml
or
build.gradle
file. At build time, the Maven or Gradle module plugin reads your
pom.xml
or build.gradle
file and bnd adds the required Import-Package
headers to your module JAR’s META-INF/MANIFEST.MF
.
Here’s an example dependencies section from a module’s build.gradle
file:
dependencies {
compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "2.0.0"
compileOnly group: "javax.portlet", name: "portlet-api", version: "2.0"
compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"
}
And here’s the Import-Package
header that’s generated in the module JAR’s
META-INF/MANIFEST.MF
file:
Import-Package: com.liferay.portal.kernel.portlet.bridges.mvc;version=
"[1.0,2)",com.liferay.portal.kernel.util;version="[7.0,8)",javax.nami
ng,javax.portlet;version="[2.0,3)",javax.servlet,javax.servlet.http,j
avax.sql
Note that your build file need only specify artifact dependencies. bnd examines your module’s class path to determine which packages from those artifacts contain classes your application uses and imports the packages. The examination includes all classes found in the class path–even those from embedded third party library JARs.
Regarding classes used by a plugin WAR,
Liferay’s WAB Generator
detects their use in the WAR’s JSPs, descriptor files, and classes (in
WEB-INF/classes
and embedded JARs). The WAB Generator searches the web.xml
,
liferay-web.xml
, portlet.xml
, liferay-portlet.xml
, and liferay-hook.xml
descriptor files. It adds package imports for classes that are neither found in
the plugin’s WEB-INF/classes
folder nor in its embedded JARs.
Manually Adding Package Imports
The WAB Generator and bnd don’t add package imports for classes referenced in these places:
- Unrecognized descriptor file
- Custom or unrecognized descriptor element or attribute
- Reflection code
- Class loader code
In such cases, you must manually determine these packages and specify an Import-Package
OSGi header that includes these packages and the packages that Bnd detects automatically. The Import-Package
header belongs in the location appropriate to your project type:
Project type | Import-Package header location |
---|---|
Module (uses bnd) | [project]/bnd.bnd |
Module (doesn’t use bnd) | [module JAR]/META-INF/MANIFEST.MF |
Traditional Liferay plugin WAR | WEB-INF/liferay-plugin-package.properties |
Here’s an example of adding a package called com.liferay.docs.foo
to the list of referenced packages that Bnd detects automatically:
Import-Package:\
com.liferay.docs.foo,\
*
Please see the Import-Package
header documentation for more information.
Congratulations! Now you can import all kinds of packages for your modules and plugins to use.