Isolating open source software packages

You can use several methods to isolate Java™ Platform, Enterprise Edition (Java EE) applications and other Java EE deployable artifacts from Open Source Software (OSS) packages. Apply these methods to resolve class loading errors and unexpected runtime behaviors that might occur when OSS packages included with WebSphere® Application Server are used.

The Open source software APIs topic lists the OSS packages provided by WebSphere Application Server that are intended for directed application use, and provides references to documentation regarding their use.

If a Java EE application encounters a problem with an OSS package intended for direct application use, refer to the corresponding usage documentation to verify that the application and server are correctly configured. For example, if an application encounters a class loading problem that involves Apache Commons Logging, refer to the Jakarta Commons Logging topic.

When an application encounters a problem with an OSS package not intended for direct application use, refer to the Best practices for isolating Java EE applications from OSS packages section included in this topic to learn how to protect OSS packages provided for the application when linking to the same packages provided by WebSphere Application Server.

There are fewer ways to isolate other Java EE artifacts. Stand-alone resource adapters and resource providers have a configuration option to enable isolation. For stand-alone resources that encounter a problem with an OSS package included with WebSphere Application Server, refer to the Considerations for isolated resource providers topic to determine whether isolating the resource is feasible. If so, set the option. When the server is restarted the runtime loads the resource using a separate class loader configured with parent_last delegation and the resource classpath.

When resource isolation is not feasible, or the failing Java EE artifact is not a resource, use the method that is described in the Configuring always-protected (isolated) packages section of this document to isolate the artifact from the problematic OSS package.

Best practices for isolating Java EE applications from OSS packages

Use shared libraries, parent_last class loader delegation, or if necessary, always-protected packages to protect applications from OSS packages included with WebSphere Application Server.

Isolated shared libraries

An ideal method to isolate an application from an OSS package included with WebSphere Application Server is to deploy the package as an isolated shared library and associate it to all dependent applications and web application archive (WAR) modules. This method enables only the applications and WAR modules that are associated with the library to use the OSS package. At runtime, classes of an isolated shared library load from their own class loader instance, ensuring that the OSS classes are loaded immediately by the library loader, and that the library classes define once over all applications that share the library.

For each isolated shared library associated to an application or WAR module, the server runtime creates and configures a class loader with the library's class path and then wires it as an internal delegate to the corresponding application and WAR class loaders. When loading classes, the class loader (delegation) mode of the application and WAR module class loaders determines the order in which these loaders search for application classes in the WebSphere Application Server class loader hierarchy. When one or more isolated shared libraries are associated to an application or WAR module and the delegation mode of the corresponding class order (for example, myAppCL) is set to Classes loaded with the parent class loader first (Parent_first), then method myAppCL.loadClass(clsName) finds clsName in this order:
  1. Searches the JVM class cache for defined class <myAppCL, clsName>
  2. Searches the classpath of each associated isolated library class loader for clsName
  3. Delegates loadClass(clsName) to the parent class loader of myAppCL
  4. Searches the classpath of myAppCL for clsName
When the delegation mode is set to Classes loaded with the parent class loader last (Parent_last), then method myAppCL.loadClass(clsName) finds clsName in this order:
  1. Searches the JVM class cache for defined class <myAppCL, clsName>
  2. Searches the classpath of myAppCL for clsName
  3. Searches the classpath of each associated isolated library class loader for clsName
  4. Delegates loadClass(clsName) to the parent class loader of myAppCL

Because the associated shared libraries are always searched before the module class loaders delegate to the parent, the method works whether myAppCL is configured to be Parent_first or Parent_last.

Server shared libraries

Another method to isolate OSS packages from an application is to associate a shared library to a class loader defined in the server configuration. The delegation mode of the server-defined class loader must be set to Parent_last. This method is less preferable than using an isolated shared library, because all application and WAR module class loaders must delegate loadClass() to at least one parent to load a class in the library.

Read the Managing shared libraries topic for information about how to create and configure the shared libraries.

Class loader delegation

When shared libraries are not feasible, assemble the OSS package as a dependency jar within the application. After the application is installed, set the class loading (delegation) mode to Parent_last for each application and WAR module class loader that load the OSS package. This method is less preferable than using an isolated shared library, because when an isolated shared library class loader defines a class and the JVM loads dependent classes that use the same class loader, dependent classes are not found on any other application, WAR module, or server-defined class loader.

The Class loading topic describes how to set the delegation mode of application and WAR module class loaders.

When none of the previously mentioned methods are feasible, try Configuring always-protected (isolated) packages as described in the next section.

Configuring always-protected (isolated) packages

WebSphere Application Server maintains lists of always-protected (or isolated) package names it hides from all class loaders beneath the OSGi gateway in the WebSphere Application Server class loader hierarchy. Configure always-protected packages to isolate all Java EE deployed artifacts from OSS packages that are included with WebSphere Application Server.

Always-protected packages control whether the WebSphere Extensions Classloader (ExtClassLoader), the logical parent of application and shared library class loaders, delegates load operations to the OSGi gateway. Because the OSS packages are made visible by the OSGi gateway, preventing delegation to the gateway effectively prevents Java EE applications and shared libraries from unexpectedly linking to OSS packages declared as always-protected. This feature also supports deployed artifacts that load directly from the ExtClassLoader classpath, including stand-alone resource adapters and providers that are configured as non-isolated, custom services, and custom authentication modules.

Using always-protected packages, you cannot specify packages that interfere with WebSphere Application Server function. Prohibited packages include {"java.", "com.", "com.ibm."}. Although less likely, you might also configure always-protected resource paths. Prohibited resource names include {"java/", "com/", "com/ibm/", "META-INF/services/"}. The server ignores these inputs and any input that is syntactically or semantically invalid.

The following procedure might not work when both applications and other artifacts provide the same OSS package. If an application and a stand-alone resource adapter (configured as non-isolated) both provide an OSS package, it is possible that both link to the package provided by the resource adapter, and are visible on the ExtClassLoader classpath. In such a deployment, you must either re-configure the stand-alone resource adapter as isolated or apply the previously mentioned suggestions to the application deployment (such as setting the application class loader delegation mode to Parent_last or associating an isolated shared library to the application). Always-protected packages are enabled by default and cannot be disabled. You can always add to the list of always-protected packages.

  1. Determine the root package name of the problematic OSS framework. For example, the root package name for Apache HTTP Components is org.apache.http.. All classes in Apache HTTP components have this root package name as a prefix. Refer to the Open source software APIs topic for more information.
  2. Under Server Infrastructure on the server settings page in the administrative console, click Java and process management > Process definition.
  3. Select Java virtual machine.
  4. Define the following system properties in the JVM generic arguments section as follows:
    1. Define system property -Dws.ext.debug=true.
    2. Define system property -Dcom.ibm.ws.classloader.server.alwaysProtectedPackages=<pkg1>,...,<pkgN> in the JVM generic arguments to hide OSS packages <pkg1>...<pkgN> from deployed Java EE artifacts. This setting alone should hide problematic OSS packages.
      Always-Protected Packages: com.ibm.ws.classloader.server.alwaysProtectedPackages

      A comma (',') separated string of package names that the WebSphere Application Server isolates (protects) from all deployed artifacts. Always-Protected package names must end with '.' and must not be a subpackage of any prohibited package name. WebSphere Application Server ignores invalid always-protected package names.

      When this property is set, the ExtClassLoader resource API, getResource(rscName), does not delegate to the OSGi Gateway whenever clsName contains an always-protected package name as a prefix. The method returns a class only when clsName is visible on the local class path of the ExtClassLoader. Similarly, the ExtClassLoader resource API does not delegate to the OSGi Gateway whenever a resource name ends with .class and is in a path. After conversion to a package name, it contains an always-protected package name as a prefix.

      For example, if package name org.oss.pkg. is always-protected, ExtClassLoader.loadClass(org.oss.pkg.Unexpected) does not delegate to the OSGi Gateway and effectively prevents any JEE application, shared library, custom authentication module, stand-alone resource, or custom service from unexpectedly linking to classes in package org.oss.pkg..

      Similarly, method ExtClassLoader.getResource(org/oss/pkg/Unexpected.class) does not delegate to the OSGi gateway, further ensuring that deployed artifacts cannot discover class files in the org.oss.pkg. package that is provided by WebSphere Application Server.

      The default value is unset.

    3. If a deployed artifact unexpectedly loads a resource that is provided by an OSS package included with WebSphere Application Server, define system property -Dcom.ibm.ws.classloader.server.alwaysProtectedResources=<rsc>,...,<rscN> to hide OSS resource paths <rsc>...<rscN> from deployed artifacts.
      Always-Protected Resources: com.ibm.ws.classloader.server.alwaysProtectedResources

      A ','-separated string of resource names that WebSphere Application Server isolates (protects) from all deployed artifacts. Always-Protected resource names must not start with '/' (must be relative), can end with '/', and must not be a substring of any prohibited resource name. WebSphere Application Server ignores invalid always-protected resource names.

      When this property is set, the ExtClassLoader resource API, (getResource(rscName), does not delegate to the OSGi Gateway whenever rscName contains an always-protected resource name as a prefix.

      For example, if resource name org/oss/pkg/ is always-protected, ExtClassLoader.getResource(org/oss/pkgs/unexpected) does not delegate the operation to the OSGi Gateway and effectively prevents any deployed artifact from discovering resources in the org/oss/pkg/ path that is provided by WebSphere Application Server.

      It is unnecessary to specify always-protected resource names for .class files in always-protected packages because they are protected.

      The default value is unset.

    4. If a deployed artifact depends on a subpackage or class in an always-protected package, define the system property -Dcom.ibm.ws.classloader.server.alwaysAllowedPackages=<pkgOrClass1>,... ,<pkgOrClassN> in the JVM generic arguments to make OSS packages <pkgOrClass1>...<pkgOrClassN> accessible to deployed Java EE artifacts. This setting is most likely used when a deployed artifact only requires an interface within an always-protected OSS package.
      Always-Allowed Packages: com.ibm.ws.classloader.server.alwaysAllowedPackages

      A ','-separated string of subpackages or fully qualified class names of Always-Protected packages that WebSphere Application Server makes visible to all deployed artifacts. WebSphere Application Server ignores invalid, always-protected resource names, including absolute names (names that start with '/'.) WebSphere Application Server ignores invalid always-allowed package names.

      For example, if package name org.oss.pkg. is always-protected, and org.oss.pkg.api. is always-allowed, then ExtClassLoader. loadClass (org.oss.pkg.api.PkgFactory) delegates to the OSGi Gateway and allows a deployed class to link with the org.oss.pkg.api.PkgFactory provided by WebSphere Application Server; but prevents it from linking to classes in packages org.oss.pkgor or org.oss.pkg.impl, also provided by WebSphere Application Server.

      The default value is unset.

    5. If a deployed artifact must load a resource in a subpath of an always-protected resource path, define the system property -Dcom.ibm.ws.classloader.server.alwaysAllowedResources=<rsc1>...<rscN> in the JVM generic arguments to make OSS resources <rsc1>...<rscN> accessible to deployed Java EE artifacts.
      Always-Allowed Resources: com.ibm.ws.classloader.server.alwaysAllowedResources

      A ','-separated string of subpaths or exact path names of Always-Protected resources (paths) that WebSphere Application Server makes visible to all deployed artifacts. WebSphere Application Server ignores invalid always-allowed resource names.

      For example, if resource name org/oss/pkg/is always-protected, and "org/oss/pkg/api/ is always-allowed, the method ExtClassLoader.getResource(org/oss/pkg/api/PkgFactory.class) delegates to the OSGi Gateway and allows a deployed class to discover "org/oss/pkg/api/PkgFactory.class"s provided by WebSphere Application Server; but prevents it from discovering resources in paths org/oss/pkg or org/oss/pkg/impl/, also provided by WebSphere Application Server.

      The default value is unset.

  5. Click Apply.
  6. Click OK.
  7. Save the changes. Make sure that a file synchronization is done before you restart the servers.
  8. Restart WebSphere Application Server for the changes to take effect.
  9. Examine the native_stdout.log and find the system properties that are previously defined.
    For example, when you specify always-protected package org.apache.http., statements such as the following might appear:
    ProtectionMetaData.clinit: system property: com.ibm.ws.classloader.server.alwaysProtectedPackages=org.apache.http.
    	...
    	...
    	ProtectionMetaData.clinit: always-protected packages:
    		org.slf4j.
    		org.slf4j.spi.
    		org.slf4j.impl.
    		org.slf4j.helpers.
    		org.apache.http.

    If you see your packages included in the list of always-protected packages, such as in org.apache.http. in the previous example, you correctly configured the server to hide the OSS package that is provided by WebSphere Application Server. There are other packages the server always protects, like org.slf4j. Your applications are protected from these packages as well. If you do not see your always-protected packages included in the list, a message appears in the same working area of native_stdout.log that indicates why the package (or packages) was ignored. Revise the property values and restart the server.

  10. Remove system property -Dws.ext.debug=true before you place the new server configuration into production.