Configuring OSGi package imports in CICS Java applications
The OSGi framework provides a comprehensive set of features for both application developers and JVM runtimes to control application modularity and declaration of dependencies.
Java™ applications that are deployed into CICS® JVM servers need to be packaged as OSGi bundles. In the OSGi JVM server environment Java class loading is controlled by the embedded OSGi framework. For this reason, Java classes are not loaded by the traditional CLASSPATH configuration, instead, each OSGi bundle has its own class loader and is used in combination with the OSGi framework to resolve any dependencies. Dependencies are typically provided by other OSGi bundles, or from the underlying JRE by virtue of the OSGi system bundle.
Code that requires access to a Java package that is
not included within its own OSGi bundle must explicitly import the package as part of
the OSGi bundle definition. Imported packages are specified as a comma-separated list on
the Import-Package
statement in the OSGi manifest. Conversely, a bundle
that is the provider of these required packages must explicitly export the package from
its own OSGi bundle definition. Exported packages are listed on the
Export-Package
statement in the provider OSGi bundle manifest. When
both OSGi bundles are deployed into the environment, the dependency can be resolved by
the OSGi framework at runtime.
Where are classes loaded from?
- The core JRE, or java.* packages
- The parent class loader from the JVM boot class path (boot delegated packages)
- Imported packages from other OSGi bundles, or from the OSGi framework system bundle
- Required bundles (though best practice dictates Required bundles should be avoided)
- The current OSGi bundle's class loader (including anything on the Bundle-classpath)
- Bundle fragments
- Dynamic Imports
The JVM boot class path
Any java.*
packages must be loaded by the JVM itself due to security
restrictions in Java. Therefore, an OSGi bundle must not
declare imports or exports for java.*
packages - doing so is an error and
installation of the bundle will fail. Class loading of java.*
packages is
implemented by delegation to the parent class loader of the JVM (referred to as boot
delegation). Conversely, all other required packages such as com.ibm.*
or Java SE components such as javax.*
or
org.xml.sax
must be explicitly imported in the OSGi bundle manifest by using the
relevant Import-Package
statements.
The OSGi framework
The system bundle is a special bundle that represents the OSGi framework and is used to export a
variety of system components. Export definitions from the system bundle are treated
like regular bundle exports - they can have version numbers and are used to resolve
import definitions as part of the normal bundle resolution process. The advantage of
this approach is that other bundles can provide alternative (newer) implementations
of the same packages should it be necessary. By default, all
javax.*
packages are exported by the system bundle and so must
be imported by using Import-Package
statements in the application's
bundle manifest. In addition, the CICS JVM
server extends the list of exported system bundles by ensuring that key packages
from the z/OS Java runtime are added to the default list exported by the system
bundle. Examples of classes in this category are
com.ibm.jzos.fields.ByteArrayField
which is part of IBMJZOS and
javax.resource.cci.Record
which is part of JCA (Java Connector
Architecture). Exports from the system bundle can be extended by adding additional
packages to the system property
org.osgi.framework.system.packages.extra
. Note, all additional
packages must already be available from the JRE classpath before they can be exposed
by the OSGi system bundle.
port
is a free TCP/IP port.OSGI_CONSOLE=true
-Dosgi.console=port
-Dfile.encoding=ISO-8859-1
bundle 0
command, which produces a detailed
listing:>bundle 0
....
Exported packages
org.eclipse.core.runtime.adaptor; version="0.0.0"[exported]
org.eclipse.core.runtime.internal.adaptor; version="0.0.0"[exported]
org.eclipse.equinox.log; version="1.0.0"[exported]
.....
Imports from other bundles
com.ibm.cics.server
bundle is installed by CICS and provides the JCICS classes which wrapper the CICS API. In addition, if a third-party component is available as an OSGi bundle, it can also
be installed as either:- A middleware bundle using the JVM server OSGI_BUNDLES option. This is the usual approach for shared middleware components that do not need to be versioned without restarting the JVM server.
- An OSGi bundle deployed within a CICS bundle. This option is useful for a modularized application with separately versioned components that do not need to be shared between applications. This is because the same version of an OSGi bundle cannot be installed more than once into the OSGi framework and it is usual for Java applications to be deployed in a single CICS bundle package to simplify deployment. If multiple CICS bundles contain duplicates of the same version of an OSGi bundle, then some of the CICS bundles will fail to install.
Imports from the current bundle
All packages in the same OSGI bundle as the application are available to the bundle class loader.
If your application requires access to classes from a JAR that is not OSGi enabled then this can be
added to the bundle classpath using the Bundle-ClassPath:
statement in the OSGI
bundle manifest. This limits class loading of a JAR to the deployed bundle, and prevents sharing the
JAR outside of the scope of the OSGi bundle.
java.*
can also be loaded from the JVM boot classpath once all other bundle class loaders have been
searched. This behavior is controlled via the osgi.compatibility.bootdelegation
system property and allows the OSGi runtime to be more tolerant if explicit dependencies were
overlooked at development time. For strict OSGi compliance set this option to false
and ensure all the packages used in your OSGi bundles are explicitly declared in the bundle
manifest. For further details refer to JVM system
properties.