17 Developing OSGi Bundles for WebLogic Server Applications

This chapter describes the OSGi environment in WebLogic Server and how to deploy OSGi bundles to WebLogic Server. Developers who want to use OSGi in their applications can easily share OSGi facilities, such as the OSGi service registry, class loaders, and other OSGi services.

For general information about OSGi, see http://www.osgi.org.

This chapter includes the following sections:

Understanding OSGi

OSGi is a Java modularity system developed and maintained by the OSGi Alliance, of which Oracle is a member.

The OSGi specifications and related Javadoc together describe a comprehensive operating environment for Java applications:

As described on the OSGi Alliance Technology Web page (http://www.osgi.org/About/Technology), "OSGi technology is the dynamic module system for Java. The OSGi Service Platform provides functionality to Java that makes Java the premier environment for software integration and thus for development. Java provides the portability that is required to support products on many different platforms. The OSGi technology provides the standardized primitives that allow applications to be constructed from small, reusable and collaborative components. These components can be composed into an application and deployed."

The OSGi Architecture Web page http://www.osgi.org/About/WhatIsOSGi further describes the OSGi technology as "...a set of specifications that define a dynamic component system for Java. These specifications enable a development model where applications are (dynamically) composed of many different (reusable) components. The OSGi specifications enable components to hide their implementations from other components while communicating through services, which are objects that are specifically shared between components. This surprisingly simple model has far reaching effects for almost any aspect of the software development process."

OSGi offers you the following benefits, as described in Benefits of Using OSGi http://www.osgi.org/About/WhyOSGi:

  • Versioning of package wiring, for both implementors and users of interfaces.

  • The "uses" directive allows for intelligent wiring of class loaders and helps ensure a consistent class space.

  • Flexible and dynamic security.

  • Dynamic service wiring through an active registry.

  • Various standard OSGi specifications provided by multiple vendors.

Features Provided in WebLogic Server OSGi Implementation

WebLogic Server allows you to add a list of OSGi frameworks (maintained via OsgiFrameWorkMBean MBeans) to the server configuration. After the OSGi framework has been booted, a bundle object for the framework is placed into the local server JNDI tree. Applications can then get this bundle from JNDI and thereafter use that as their entry point into the OSGi system.

Applications can also deploy their own OSGi bundles. One specific OSGi bundle from the chosen framework instance can be used in the application classloader hierarchy.

WebLogic Server allows you to:

  • Configure and manage one or more instances of an OSGi framework from the Weblogic Server Administration Console and WLST.

    WebLogic Server includes the Apache Felix implementation of the OSGi framework. See http://felix.apache.org for information on Felix.

  • Create and deploy your own OSGi bundles.

    WebLogic Server includes an OSGi bundle containing the OSGi API. You can use this API to create your own OSGi bundles.

  • One specific OSGi bundle from the chosen framework instance can be used in the application classloader hierarchy.

  • Access OSGi bundles directly from JNDI.

  • Deploy and undeploy OSGi bundles.

  • Log OSGi status via the WebLogic Server logging mechanism.

  • Incorporate the OSGi services of your choice.

  • Enable OSGi persistence.

  • Manage OSGi bundle start levels for deployed bundles.

These topics are described in the sections that follow.

Configuring the OSGi Framework

As described in the OSGi Service Platform Core Specification, "The Framework forms the core of the OSGi Service Platform Specifications. It provides a general-purpose, secure, and managed Java framework that supports the deployment of extensible and downloadable applications known as bundles. "

WebLogic Server includes the Felix implementation of OSGi framework. You can configure and manage one or more instances of the Felix OSGi framework.

Note:

WebLogic Server supports only the Felix framework. Other OSGi Frameworks are not supported and have not been tested.

This section includes the following subsections:

Configuring OSGi Framework Instances

WebLogic Server includes an OSGi framework by default, but it does not automatically start it.

You must configure WebLogic Server to boot an OSGi framework when WebLogic Server boots. You can do this in four ways, according to your preference:

  • Use the WebLogic Server Administration Console to configure an OSGi framework instance.

  • Edit the DOMAIN_HOME\config\config.xml deployment descriptor file to add an entry for the OSGi server and set the attribute values. You specify the OSGi framework you want the WebLogic Server instance to use.

  • Use WLST to create the OSGi framework and set the attribute values. WLST then stores the values in the DOMAIN_HOME\config\config.xml deployment descriptor file.

  • Write a Java program to create the OSGi framework and set the attribute values.

In all four cases, configuration of an OSGi framework instance is controlled by the OsgiFrameWorkMBean. For each framework associated with an OsgiFrameWorkMBean, WebLogic Server boots an OSGi framework with a unique name.

You configure the OSGi framework attributes shown in Table 17-1.

Table 17-1 OSGi Framework Attributes

Attribute Usage

Target

This attribute is required. You must select a target (servers or clusters) on which an MBean will be deployed from the list of servers or clusters in the current domain on which this item can be deployed.

Name

The name of the framework instance. The name of a given framework instance must be unique within a WebLogic Server server instance.

Implementation Class

The name of the framework implementation class for the org.osgi.framework.launch.FrameworkFactory class. The default value is org.apache.felix.framework.FrameworkFactory.

Deploy Installation Bundles

Determines whether OSGi bundles are installed in the framework. This attribute is "populate" by default. See Parameter Required for Installing Bundles in the Framework for more information.

Dynamically Created

Determines whether the MBean is created dynamically or is persisted to config.xml. The configuration is always persisted if you use the WebLogic Server Administration Console and this attribute is not displayed.

Init Properties

The standard Felix properties to be used when initializing the framework. All standard properties and all properties specific to the framework can be set.

See Example 17-3 for an example of setting the Init Properties from a Java program.

The Apache Felix Framework Configuration Properties are described in http://felix.apache.org/documentation/subprojects/apache-felix-framework/apache-felix-framework-configuration-properties.html.

Framework Boot delegation

The name of the org.osgi.framework.bootdelegation property. Note that this value, if set, will take precedence over anything specified in the init-properties.

Framework System Packages Extra

The name of the org.osgi.framework.system.packages.extra property. Note that this value, if set, will take precedence over anything specified in the init-properties.

Register Global Data Sources

Boolean. Returns true if global data sources should be added to the OSGi service registry.

Register Global Work Managers

Boolean. Returns true if global work managers should be added to the OSGi service registry.


Configuring OSGi Framework Instance From Administration Console

You can configure an OSGi framework from the WebLogic Server Administration Console. Perform the following steps:

  1. In the WebLogic Server Administration Console, expand Services in the left panel.

  2. Click OSGi Frameworks in the left panel.

  3. On the Summary of OSGi Frameworks page, click New.

    If you have already created an OSGi framework, you can instead click Clone to use an existing framework as the basis for a new one.

  4. On the Creating a New OSGi Framework page, name this framework instance. The name must be unique.

  5. Click Next.

  6. On the OSGI Framework Targets page, select the servers or clusters to which you would like to deploy this OSGi framework.

  7. Click Finish.

  8. On the Summary of OSGi Frameworks page, select the framework you just created.

  9. On the Settings for Framework page, examine the defaults to make sure that they are correct for your environment. See Table 17-1 for a description of the attributes.

See "Configure OSGi Frameworks" in the Oracle WebLogic Server Administration Console Online Help.

Configuring OSGi Framework Instance From config.xml

Example 17-1 shows an example of updating config.xml to add the OSGi framework to be used by WebLogic Server. Add the <osgi-framework> element just before the </domain> element.

If you need to add multiple OSGi framework instances, add multiple <osgi-framework> elements. Remember that each <name> element must be unique within the server.

After you add this element, you must reboot the WebLogic Server instance.

Example 17-1 Configuring OSGi Framework Instance From config.xml

<osgi-framework>
       <name>test-osgi-frame</name>
       <target>AdminServer</target>
   </osgi-framework>

Configuring OSGi Framework Instance From WLST

Example 17-2 shows an example of using WLST to add the OSGi framework to be used by the WebLogic Server instance.

Example 17-2 Configuring OSGi Framework Instance From WLST

java weblogic.WLST
 
connect('weblogic', 'password')
edit()
startEdit()
wls:/mydomain/edit !> cmo.createOsgiFramework('test-osgi-frame')
[MBeanServerInvocationHandler]com.bea:Name=test-osgi-frame,Type=OsgiFramework
targetServer=cmo.lookupServer('AdminServer')
cd('OsgiFrameworks')
cd('test-osgi-frame')
cmo.addTarget(targetServer)
wls:/mydomain/edit !> save()
wls:/mydomain/edit !> activate()
wls:/mydomain/edit/OsgiFrameworks> ls('a')
drw-   test-osgi-frame
wls:/mydomain/edit/OsgiFrameworks> cd('test-osgi-frame')
wls:/mydomain/edit/OsgiFrameworks/test-osgi-frame> ls('a')
-rw-   DeployInstallationBundles                    populate
-rw-   DeploymentOrder                              1000
-r--   DynamicallyCreated                           false
-rw-   FactoryImplementationClass                   org.apache.felix.framework.F
rameworkFactory
-r--   Id                                           0
-rw-   InitProperties                               null
-rw-   Name                                         test-osgi-frame
-rw-   Notes                                        null
-rw-   OrgOsgiFrameworkBootdelegation               null
-rw-   OrgOsgiFrameworkSystemPackagesExtra          null
-rw-   RegisterGlobalDataSources                    true
-rw-   RegisterGlobalWorkManagers                   true
-r--   Type                                         OsgiFramework

Configuring OSGi Framework Instance from a Java Program

Example 17-3 shows an example of using a Java program to add the OSGi framework to be used by the WebLogic Server instance. Comments in the code describe each operation.

Example 17-3 Configuring OSGi Framework from Java Program

/**...imports omitted
*/
  /**
   * Create an OSGi framework instance with the designated name
   * 
   * @param frameworkName
   */
  protected void createOSGiFrameworkInstance(String frameworkName) {
    createOSGiFrameworkInstance(frameworkName, null, null, null, null, null);
  }
 
  protected void createOSGiFrameworkInstance(String frameworkName,
                                             String isRegisterGlobalWorkManagers,
                                             String isRegisterGlobalDataSources,
                                             String deployInstallationBundles,
                                             String orgOsgiFrameworkBootdelegation,
                                             String orgOsgiFrameworkSystemPackagesExtra) {
    createOSGiFrameworkInstance(frameworkName,
                                null,
                                isRegisterGlobalWorkManagers,
                                isRegisterGlobalDataSources,
                                deployInstallationBundles,
                                orgOsgiFrameworkBootdelegation,
                                orgOsgiFrameworkSystemPackagesExtra);
  }
 
  /**
   * Create a fresh framework
   * 
   * @param isRegisterGlobalWorkManagers
   * @param isRegisterGlobalDataSources
   * @param deployInstallationBundles
   * @param orgOsgiFrameworkBootdelegation
   * @param orgOsgiFrameworkSystemPackagesExtra
   */
  protected void createOSGiFrameworkInstance(String frameworkName,
                                             Properties initProp,
                                             String isRegisterGlobalWorkManagers,
                                             String isRegisterGlobalDataSources,
                                             String deployInstallationBundles,
                                             String orgOsgiFrameworkBootdelegation,
                                             String orgOsgiFrameworkSystemPackagesExtra) {
 
    frameworkInstances.add(frameworkName);
 
    if (initProp == null) {
      initProp = new Properties();
    }
    initProp.setProperty("wlstest.framework.instance.name", frameworkName);
    //initProp.setProperty("felix.cache.locking", "false");
    //initProp.setProperty("org.osgi.framework.storage.clean", "onFirstInit");
 
    MBeanServerConnection connection = null;
 
    try {
 
      // Initiate the necessary MBean facilities.
      connection = initConnection();
      // Switch the edit session on.
      ObjectName domainMBean = startEditSession(connection);
 
      // Get the current WebLogic server MBean:
      ObjectName serverMBean = null;
      ObjectName[] serverMBeans = (ObjectName[]) connection.getAttribute(domainMBean, "Servers");
      for (ObjectName objectName : serverMBeans) {
        log("found server: " + objectName);
        serverMBean = objectName;
      }
 
      // Get or create an OsgiFrameworkMBean:
      ObjectName osgiFrameworkMBean = null;
      ObjectName[] osgiFrameworkMBeans = (ObjectName[]) connection.getAttribute(domainMBean, "OsgiFrameworks");
      log("osgiFrameworkMBeans.length=" + osgiFrameworkMBeans.length);
      for (ObjectName objectName : osgiFrameworkMBeans) {
        String osgiFrameworkName = (String) connection.getAttribute(objectName, "Name");
        log("--------------> " + osgiFrameworkName);
        if (osgiFrameworkName.equals(frameworkName)) {
          osgiFrameworkMBean = objectName;
          log("Found OSGi framework instance: " + frameworkName);
          break;
        }
      }
 
      if (osgiFrameworkMBean != null) {
        log("Will destroy the framework instance: " + osgiFrameworkMBean);
        connection.invoke(osgiFrameworkMBean,
                          "removeTarget",
                          new Object[] { serverMBean },
                          new String[] { "javax.management.ObjectName" });
        connection.invoke(domainMBean,
                          "destroyOsgiFramework",
                          new Object[] { osgiFrameworkMBean },
                          new String[] { "javax.management.ObjectName" });
      }
 
      log("Will create a new framework instance from scratch");
      osgiFrameworkMBean = (ObjectName) connection.invoke(domainMBean,
                                                          "createOsgiFramework",
                                                          new Object[] { frameworkName },
                                                          new String[] { "java.lang.String" });
 
      // Set common properties:
      if (initProp != null) {
        Attribute initPropAttr = new Attribute("InitProperties", initProp);
        connection.setAttribute(osgiFrameworkMBean, initPropAttr);
      }
      Attribute systemPackagesExtraAttr = new Attribute("OrgOsgiFrameworkSystemPackagesExtra",
                                                        "javax.naming,weblogic.work,javax.sql");
      connection.setAttribute(osgiFrameworkMBean, systemPackagesExtraAttr);
      connection.invoke(osgiFrameworkMBean,
                        "addTarget",
                        new Object[] { serverMBean },
                        new String[] { "javax.management.ObjectName" });
 
      // Set individual property to the OSGi framework instance:
      if (isRegisterGlobalWorkManagers != null) {
        Attribute attr = new Attribute("RegisterGlobalWorkManagers", Boolean.parseBoolean(isRegisterGlobalWorkManagers));
        connection.setAttribute(osgiFrameworkMBean, attr);
      }
 
      if (isRegisterGlobalDataSources != null) {
        Attribute attr = new Attribute("RegisterGlobalDataSources", Boolean.parseBoolean(isRegisterGlobalDataSources));
        connection.setAttribute(osgiFrameworkMBean, attr);
      }
 
      if (deployInstallationBundles != null) {
        Attribute attr = new Attribute("DeployInstallationBundles", deployInstallationBundles);
        connection.setAttribute(osgiFrameworkMBean, attr);
      }
 
      if (orgOsgiFrameworkBootdelegation != null) {
        Attribute attr = new Attribute("OrgOsgiFrameworkBootdelegation", orgOsgiFrameworkBootdelegation);
        connection.setAttribute(osgiFrameworkMBean, attr);
      }
 
      if (orgOsgiFrameworkSystemPackagesExtra != null) {
        Attribute attr = new Attribute("OrgOsgiFrameworkSystemPackagesExtra", orgOsgiFrameworkSystemPackagesExtra);
        connection.setAttribute(osgiFrameworkMBean, attr);
      }
 
      MBeanInfo mi = connection.getMBeanInfo(osgiFrameworkMBean);
      log("Attributes are as below:");
      for (MBeanAttributeInfo mai : mi.getAttributes()) {
        Object value = connection.getAttribute(osgiFrameworkMBean, mai.getName());
        System.out.printf("    %-40s = %s\n", mai.getName(), value);
      }
 
      // Save your changes
      ObjectName cfgMgr = (ObjectName) connection.getAttribute(service, "ConfigurationManager");
      connection.invoke(cfgMgr, "save", null, null);

Parameter Required for Installing Bundles in the Framework

The OsgiFrameWorkMBean MBean Deploy Installation Bundles attribute controls whether or not bundles present in the osgi-lib directory (described later in this chapter in Deploying OSGi Bundles in the osgi-lib Directory) are actually installed into the framework.

The Deploy Installation Bundles parameter accepts the following values:

  • ignore — None of the bundles in this directory are installed and started.

  • populate — The bundles are installed and started if possible. This is the default. Furthermore, a few extra packages are added to the boot delegation classpath parameters in order to enable the bundles in the osgi-lib directory if they are not already there.

    It is not be considered a failure that causes the system to not boot if these bundles do not properly resolve and therefore cannot be started.

Configuring OSGi Framework Persistence

OSGi has a persistence mechanism, described in http://www.osgi.org/javadoc/r4v43/org/osgi/framework/launch/Framework.html, in which all installed bundles must be started in accordance with each bundle's persistent autostart setting.

This persistence mechanism is disabled by default. However, you can use the standard Felix Init property shown in Table 17-1 to enable the OSGi persistence mechanism.

Note: WebLogic Server is not directly involved in the OSGi persistence mechanism. In particular, WebLogic Server does not fail the data over to other servers.

Using OSGi Services

You can make standard OSGi services available to your OSGi bundle. To do this, import the correct packages for the Felix framework and make sure that the application bundle has the required authorization.

These services are described in the OSGi Service Platform Core Specification (http://www.osgi.org/Download/File?url=/download/r4v43/r4.core.pdf) and include but are not limited to standard Framework supplied services such as the Package Admin Service, Conditional Permission Admin Service, or the StartLevel Service.

See the "Apache Felix Tutorial Example 1, Service Event Listener Bundle" for an example of creating a simple bundle that listens for OSGi service events.

Creating OSGi Bundles

You use the OSGi API bundle (provided with WebLogic Server) to create your own OSGI bundle.

See the "Apache Felix Tutorial Example 1, Service Event Listener Bundle" for an example of creating a simple bundle. As described in this example, the Import-Package attribute of the manifest file informs the framework of the bundle's dependencies on external packages. All bundles with an activator must import org.osgi.framework because it contains the core OSGi class definitions.

Deploying OSGi Bundles

This section includes the following subsections:

Preparing to Deploy an OSGi Bundle on a Target System

You can deploy OSGi bundles from inside a JAR, EAR, or WAR file, as appropriate for your application.

Before you do this, you must first specify which OSGi framework you want your bundle to use, and identity the bundle to WebLogic Server.

Note:

If the OSGi framework instance you specify does not exist on the target server, the OSGi bundle fails to deploy.

How you do this depends on whether your bundle is inside a WAR file or an EAR file:

  • WAR — The framework instance and bundle name must be in an element in the Web application's weblogic.xml deployment descriptor file.

  • EAR — The framework instance and bundle name must be in an element in the application's weblogic-application.xml deployment descriptor file.

    If the EAR file contains WAR files, then the bundles inside the WAR files are deployed using the weblogic.xml deployment descriptor file from the embedded WAR files.

The sections that follow describe the required steps in detail.

For more information about WebLogic Server deployment descriptors, see Deploying Applications to Oracle WebLogic Server.

Preparing to Deploy Bundles as Enterprise Applications

Before you deploy your OSGi bundle, you must first:

  1. Use either the DOMAIN_HOME\config\config.xml deployment descriptor file or WLST to add an entry for the OSGi framework, as described in Configuring OSGi Framework Instances.

  2. In the EAR file that contains the OSGi bundle, add both the name of the OSGi framework and the name of the bundle itself to the weblogic-application.xml deployment descriptor file.

Example 17-1 shows an example of updating config.xml to add the OSGi framework used by the WebLogic Server.

Example 17-4 shows an example of updating weblogic-application.xml to add both the name of the OSGi framework and the name and location of the bundle.

Example 17-4 Adding the Framework and Bundle to weblogic-application.xml

<osgi-framework-reference>
    <name>test-osgi-frame</name>
    <application-bundle-symbolic-name>com.oracle.weblogic.test.client
</application-bundle-symbolic-name>
  <bundles-directory>rashi/osgi-lib</bundles-directory>
</osgi-framework-reference>

The stanza in Example 17-4 tells the WebLogic Server to attach to the OSGi framework named "test-osgi-frame" and to find the bundle in that server with the symbolic name com.oracle.weblogic.test.client in order to find classes from that OSGi framework.

Preparing to Deploy Bundles as Web Applications

Before you install your bundle as a WAR file, you must first:

  1. Use either the DOMAIN_HOME\config\config.xml deployment descriptor file or WLST to add an entry for the OSGi framework, as described in Configuring OSGi Framework Instances.

  2. Add both the name of the OSGi framework and the name of the bundle itself to the web application's weblogic.xml deployment descriptor file.

Example 17-1 shows an example of updating config.xml to add the OSGi framework used by the WebLogic Server.

Example 17-5 shows an example of updating weblogic.xml to add both the name of the OSGi framework and the name and location of the bundle.

Example 17-5 Adding the Framework and Bundle to weblogic.xml

<osgi-framework-reference>
    <name>test-osgi-frame</name>
    <application-bundle-symbolic-name>com.oracle.weblogic.test.client
</application-bundle-symbolic-name>
  <bundles-directory>rashi/osgi-lib</bundles-directory>
</osgi-framework-reference>

The stanza in Example 17-4 tells the WebLogic Server to attach to the OSGi framework named "test-osgi-frame" and to find the bundle in that server with the symbolic name com.oracle.weblogic.test.client in order to find classes from that OSGi framework.

Global Work Managers

Work Managers prioritize work based on rules you define and by monitoring actual run time performance statistics. This information is then used to optimize the performance of your application. See "Using Work Managers to Optimize Scheduled Work" in Administering Server Environments for Oracle WebLogic Server.

The OSGi implementation can take advantage of global work managers if the Register Global Work Managers MBean attribute is set to true, as described in Table 17-1.

You can determine which global work manager is in use from a Java application, as shown in Example 17-7.

Example 17-6 Determining Global Work Managers

    // Get the global scoped work manager service:
    ServiceReference[] refWmSvcs = bc.getServiceReferences(WorkManager.class.getCanonicalName(),
                                                           "(name=GlobalScopedWorkManager)");
    if (refWmSvcs != null) {
      logger.setAttribute(frameworkInstanceName, bundleIdentifier + "_WorkManager_Count", refWmSvcs.length);
      for (int i = 0; i < refWmSvcs.length; i++) {
        ServiceReference refWmSvc = refWmSvcs[i];
        WorkManager wm = (WorkManager) bc.getService(refWmSvc);
        logger.setAttribute(frameworkInstanceName, bundleIdentifier + "_WorkManager" + (i + 1), wm.getName());
        bc.ungetService(refWmSvc);
      }
    }
 

Global Data Sources

In WebLogic Server, you can configure database connectivity by configuring JDBC data sources and multi data sources and then targeting or deploying the JDBC resources to servers or clusters in your WebLogic domain, as described in WebLogic Server Data Sources in Understanding Oracle WebLogic Server.

The OSGi implementation can take advantage of global data sources if the Register Global Data Sources MBean attribute is set to true, as described in Table 17-1.

You can determine which global data source is in use from a Java application, as shown in Example 17-7.

Example 17-7 Determining Global Data Sources

    // Get the global data source services:
    ServiceReference[] refDsSvcs = bc.getServiceReferences(DataSource.class.getCanonicalName(), "(name=OsgiDS)");
    if (refDsSvcs != null) {
      logger.setAttribute(frameworkInstanceName, bundleIdentifier + "_DataSource_Count", refDsSvcs.length);
      for (int i = 0; i < refDsSvcs.length; i++) {
        String data = null;
        ServiceReference refDsSvc = refDsSvcs[i];
        DataSource ds = (DataSource) bc.getService(refDsSvc);
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
          conn = ds.getConnection();
          stmt = conn.createStatement();
          rs = stmt.executeQuery("select * from dual");
          rs.next();
          data = rs.getString(0);
        } catch (SQLException e) {
 

Deploying OSGi Bundles in the osgi-lib Directory

Note:

The OsgiFrameWorkMBean MBean Deploy Installation Bundles attribute controls whether or not bundles present in the osgi-lib directory are actually installed, as described in Parameter Required for Installing Bundles in the Framework. This attribute is true by default, and the bundles are installed.

To deploy a bundle with the start-level of 1, create the WL_HOME/server/osgi-lib directory if it does not already exist, and then copy the archive file (EAR, WAR) file to it.

Any files in this directory that end with .jar, .ear, or .war are considered an OSGi bundle to be installed into a framework when it starts.

WL_HOME/server/osgi-lib is consulted only when the server first boots, and is not monitored for changes thereafter. If you add a new OSGi bundle to the WL_HOME/server/osgi-lib directory and want to deploy it, you must reboot WebLogic Server.

Setting the Start Level and Run Level for a Bundle

To deploy a bundle with the start-level of 1, copy the archive file (EAR, WAR) file to the WL_HOME/server/osgi-lib directory.

In addition, the WL_HOME/server/osgi-lib directory supports a start- and run-level scheme based on subdirectories.

If you create subdirectories with names that begin with a number between 1 and 32K (for example 2, 3, 4), then the archive files under those directories are installed and started with the given run-level.

Accessing Deployed Bundle Objects From JNDI

After the OSGi server has been booted, a bundle object is placed into the local server JNDI tree. Applications can therefore get this bundle from JNDI and thereafter use that as the entry point into the OSGi system.

The org.osgi.framework.Bundle is placed into the java:app/osgi/Bundle JNDI environment of the application.

One specific OSGi bundle from the chosen framework instance can be used in the application classloader hierarchy.

Example 17-8 shows how to access a bundle that you create from JNDI.

Example 17-8 Accessing Your OSGi Bundle From JNDI

    public static final String BUNDLE_JNDI_NAME = "java:app/osgi/Bundle";
...
    String bundleSymbolicName = null;
 
    Bundle bundle = null;
    OsgiInfo info = new OsgiInfo();
    List<String> errorMessages = new ArrayList<String>();
 
    try {
      Context initCtx = new InitialContext();
      bundle = (Bundle) initCtx.lookup(Constants.BUNDLE_JNDI_NAME);
    } catch (NamingException e) {
      errorMessages.add(e.toString());
      System.out.println("Failed to lookup bundle from JNDI due to " + e);
    }
 
    if (bundle != null) {
 
      bundleSymbolicName = bundle.getSymbolicName() + "_" + bundle.getVersion();
      info.setCurrentBundle(bundleSymbolicName);
 
      BundleContext bc = bundle.getBundleContext();
 
      if (bc != null) {
 
        // Get the start level service:
        StartLevel startLevelSvc = null;
        ServiceReference startLevelSr = bc.getServiceReference("org.osgi.service.startlevel.StartLevel");
        if (startLevelSr != null) {
          startLevelSvc = (StartLevel) bc.getService(startLevelSr);
        }
 
        List<String> allInstalledBundles = new ArrayList<String>();
        List<String> allActivatedBundles = new ArrayList<String>();
        Map<String, List<String>> services = new HashMap<String, List<String>>();
        Map<String, String> startLevels = new HashMap<String, String>();
 
        for (Bundle b : bc.getBundles()) {
 
          // Collect all the installed and activated bundles:
          String bundleId = b.getSymbolicName() + "_" + b.getVersion();
          allInstalledBundles.add(bundleId);
          if (b.getState() == Bundle.ACTIVE) {
            allActivatedBundles.add(bundleId);
          }
 
          // Collect the registered services:
          ServiceReference[] srs = b.getRegisteredServices();
          if (srs != null) {
            List<String> list = new ArrayList<String>();
            for (ServiceReference sr : srs) {
              list.add(sr + "-->" + bc.getService(sr));
            }
            services.put(bundleId, list);
          }
 
          // Collect the start levels:
          if (startLevelSvc != null) {
            startLevels.put(bundleId, startLevelSvc.getBundleStartLevel(b) + "");
          }
        }
 
        info.setAllInstalledBundles(allInstalledBundles);
        info.setAllActivatedBundles(allActivatedBundles);
        info.setRegisteredServices(services);
        info.setStartLevels(startLevels);
 
        // Query the work manager services:
        List<String> workManagers = new ArrayList<String>();
        try {
          ServiceReference[] wmSrs = bc.getServiceReferences(WorkManager.class.getCanonicalName(), null);
          if (wmSrs != null) {
            for (ServiceReference sr : wmSrs) {
              WorkManager wm = (WorkManager) bc.getService(sr);
              workManagers.add(wm.getName());
            }
          }
        } catch (InvalidSyntaxException e) {
          e.printStackTrace(System.out);
        }
        info.setWorkManagers(workManagers);
 
        // Query the data source services:
        List<String> dataSources = new ArrayList<String>();
        try {
          ServiceReference[] dsSrs = bc.getServiceReferences(DataSource.class.getCanonicalName(), null);
          if (dsSrs != null) {
            for (ServiceReference sr : dsSrs) {
              dataSources.add(sr.getProperty("name").toString());
            }
          }
        } catch (InvalidSyntaxException e) {
          e.printStackTrace(System.out);
        }
        info.setDataSources(dataSources);
 
      }
    }
 
    String bundleFileName = null;
    try {
      BundleIntrospect introspection = new BundleIntrospect();
      bundleFileName = introspection.whichBundleFile();
      info.setCurrentBundleFileName(bundleFileName);
    } catch (Throwable e) {
      errorMessages.add(e.toString());
      //e.printStackTrace(System.out);
    }
    info.setErrorMessages(errorMessages);
 
    return info;
 
  }
 
}

Using OSGi Logging Via WebLogic Server

The Apache Felix implementation of the OSGi Log service, version 1.0.0, is installed by default in the installation directory WL_HOME/server/osgi-lib.

An OSGi bundle com.oracle.weblogic.osgi.logger_1.0.0.jar is also installed in WL_HOME/server/osgi-lib. This bundle registers itself with the OSGi logging service and sends logs from the OSGi logger to the WebLogic Server logger.

The logger system name is OSGiForApps. The messages severity levels are mapped between OSGi and WebLogic Server as shown in Table 17-2.

Table 17-2 OSGi and WebLogic Server Logging Severity Mapping

OSGi Severity Levels WebLogic Server Severity Level

LogLevel.LOG_ERROR

Severities.ERROR

LogLevel.LOG_WARNING

Severities.WARNING

LogLevel.LOG_INFO

Severities.INFO

LogLevel.LOG_DEBUG

Severities.DEBUG


Configuring a Filtering ClassLoader for OSGi Bundles

You can use a filtering classloader to specify the use of alternate library versions that are deployed as OSGi bundles.

To configure the FilteringClassLoader to specify that a certain package is loaded from an application, add a prefer-application-packages descriptor element to weblogic-application.xml, which details the list of packages to be loaded from the application. The following example specifies that org.apache.log4j.* and antlr.* packages are loaded from the application, not the system classloader:

<prefer-application-packages>
  <package-name>org.apache.log4j.*</package-name>
  <package-name>antlr.*</package-name>
</prefer-application-packages>

Place packages in WEB-INF/lib or in WEB-INF/osgi-lib if the package is an OSGi bundle. You can either add OSGi bundle dependencies directly to WEB-INF/osgi-lib or configure the org.osgi.framework.system.packages.extra property (see Table 17-1) in your OSGi framework instance to export the necessary javax packages that the application needs.

For more information on filtering classloaders, see "Using a Filtering ClassLoader".

OSGI Example

WebLogic Server includes an example that demonstrates how to deploy OSGi bundles to WebLogic Server. If you installed the WebLogic Server examples, the OSGi example source code is available in ORACLE_HOME/\wlserver\samples\server\examples\src\examples\osgi\osgiApp, where ORACLE_HOME represents the directory in which you installed WebLogic Server. For more information about the WebLogic Server code examples, see "Sample Applications and Code Examples" in Understanding Oracle WebLogic Server.

There are two simple bundles: client and server. The server bundle (ServerBundle) exports a packet that the client bundle (ClientBundle) imports.

The example produces an HTML page that displays the deployed OSGi bundles.