Basic Extensions using Liberty Libraries
1.0

This feature enables the configuration of Basic Extensions using Liberty Libraries (BELL).

The BELL feature enables libraries to define the implementation of an Open Liberty SPI or API with Java ServiceLoader configuration files. These files are included in the /META-INF/services/ directory of the library JAR file.

With the BELL feature, a library declares a /META-INF/services/ resource with the name of the fully qualified API or SPI interface and provides a class that implements the interface. The feature processes the /META-INF/services/ resources and provides the library interface implementation to the Open Liberty runtime.

Enabling this feature

To enable the Basic Extensions using Liberty Libraries 1.0 feature, add the following element declaration into your server.xml file, inside the featureManager element:

<feature>bells-1.0</feature>

Examples

Configure a BELL

The minimum server.xml configuration for the BELL feature requires a library element and a bell element that references the library.

<library id="servicesLib">
  <file name="path to jar">
</library>

<bell libraryRef="servicesLib" />

The BELL feature discovers all services in the META-INF/services folder of the referenced library. Alternatively, you can configure the service attribute to specify the name of the service the feature looks up in the META-INF/service folder, as shown in the following example.

<bell libraryRef="servicesLib"
   service="name.of.fully.qualified.api.or.spi.interface" />

For every service that is discovered or specified, the BELL feature registers the service interface and implementation class as an OSGi service, which makes the service available to the Open Liberty runtime.

Be sure to enable the Open Liberty features that provide the API or SPI packages that are required by the library.

Enable SPI access for libraries

Shared libraries do not support access for SPI packages. When a library provides an implementation of an SPI interface, set the spiVisibility attribute to true in the BELL configuration. This attribute enables the library classloader to access SPI packages that are provided by Open Liberty.

<bell libraryRef="servicesLib" spiVisibility="true"/>

SPI visibility is disabled by default and applies only to the library that is referenced in the BELL configuration. SPI visibility is not supported for the Open Liberty global shared library.

For more information, see Expose a new REST endpoint.

Enable services to receive configuration properties

Services can receive properties that are declared in the BELL configuration. To configure properties, add a properties element to your BELL configuration and declare one or more name="value" attributes. Properties are String type and inject into all services that are enabled to receive them. The following example declares the hello and serverHome properties.

<bell libraryRef="servicesLib">
 <properties hello="WORLD" serverHome="${server.output.dir}" />
</bell>

To enable a service to receive configuration properties, define an updateBell public method or a public constructor in the service implementation class. The method signature must declare a single parameter of the java.util.Map<String,String> type. The following example defines both methods to receive properties in a BELL configuration.

public class YourServiceImpl implements api.or.spi.Interface {
 public YourServiceImpl(java.util.Map<String,String> bellProperties) {...}
 // OR
 public void updateBell(java.util.Map<String,String> bellProperties) {...}
}

At service creation, the BELL feature invokes the updateBell or constructor methods to inject an unmodifiable map that contains a key/value pair for each property. For the previous examples, the resulting map contains the pairs "hello"/"WORLD" and "serverHome"/"<resolved value of ${server.out.dir}>"

The BELL feature does not support nondestructive updates. When you update a BELL configuration while the server is running, the feature does not inject updated properties into existing service instances. However, it affords this future enhancement by allowing users to define the updateBell method within the service implementation class. If you define the updateBell method to receive properties, ensure that the class can tolerate multiple calls to the updateBell method on the same instance.

For more information, see Expose a new REST endpoint.

Configure a servlet filter for applications

In certain scenarios, a servlet filter implementation must be applied to all applications that are deployed to Open Liberty. For example, a servlet filter might be used to add new headers to each request. The jakarta.servlet.ServletContainerInitializer interface provides an onStartup method that you can use to add a servlet filter implementation class to all applications.

You can use the BELL feature to configure a library that provides a ServletContainerInitializer implementation as a service. The ServletContainerInitializer service onStartup method is called by Open Liberty for each application that starts. In the following example, a ServletContainerInitializer implementation is configured to add a servlet filter implementation with each ServletContext object that is in a Java file. The ServletContext.addFilter(String, Filter) method is used by the onStartup method to add the servlet filter implementation.

public class SCI implements ServletContainerInitializer {
  @Override
  public void onStartup(Set<Class<?>> arg0, ServletContext arg1)
    throws ServletException {
    arg1.addFilter("myFilter", MyFilter.class).addMappingForUrlPatterns(null, false, "/*");
  }
}

To register the ServletContainerInitializer interface that adds the servlet filter for an application, a class name is specified in the library JAR file. The library JAR file contains a META-INF/services/jakarta.servlet.ServletContainerInitializer file that specifies the fully qualified ServletContainerInitializer implementation class name that is contained in the library. The following example uses the file element to specify a path to the JAR file and add it to the library. It also specifies the service that the BELL feature looks up and registers.

<library id="servletExtLib">
  <file name="path to jar"/>
</library>

<bell libraryRef="servletExtLib"
    service="jakarta.servlet.ServletContainerInitializer" />

Expose a new REST endpoint

The REST Handler framework provides the com.ibm.wsspi.rest.handler.RESTHandler interface, which Open Liberty extension developers use to expose new REST endpoints. You can use the BELL feature to configure a library that provides a RESTHandler implementation as a service. This library enables the REST Handler framework to register the service as a listener for a new specified endpoint URL.

In the following service implementation example, the BellEndpoint class overrides the handleRequest method and defines a single-argument constructor to receive BELL configuration properties at service creation.

package your.org.rest.example;
import com.ibm.wsspi.rest.handler.*;

public class BellEndpoint implements RESTHandler {
  java.util.Map<String,String> props;
  public BellEndpoint(java.util.Map<String, String> bellProperties) {props=bellProperties;}
  @Override
  public void handleRequest(RESTRequest request, RESTResponse response) {...}
}

For this example, the following service resource and implementation class files are packaged in the RestEpLib.jar file.

META-INF/services/com.ibm.wsspi.rest.handler.RESTHandler
your/org/rest/example/BellEndpoint.class

To enable the endpoint, the /META-INF/services/com.ibm.wsspi.rest.handler.RESTHandler service resource must declare both the com.ibm.wsspi.rest.handler.root OSGi service property in addition to the fully qualified name of the service implementation class. This OSGI service property is required by the RESTHandler SPI to register the service as a listener for the specified subroot of the /ibm/api URL path. Set the property to equal the name of the endpoint that you want to expose on the /ibm/api/ URL path.

You can configure OSGi properties that are specific to a service implementation class by adding one or more properties, prefixed by the # character, to the service resource. Add the properties immediately before the name of the service implementation class to which they apply. The BELL feature registers the service interface with the implementation class and the specific OSGi properties.

The com.ibm.wsspi.rest.handler.root OSGi property in the following example enables an endpoint with the /ibm/api/bellEP URL path.

#com.ibm.wsspi.rest.handler.root=/bellEP
your.org.rest.example.BellEndpoint

The following example shows the BELL configuration in the server.xml file that references the RestEpLib library. The configuration specifies the spiVisibility="true" attribute to enable the RestEpLib library to access the REST Handler SPI packages. It also declares one BELL property. Notice that the RestEpLib.jar library JAR is copied to the ${server.config.dir}/sharedlib directory.

<library id=”RestEpLib">
  <fileset dir="${server.config.dir}/sharedLib" includes="RestEpLib.jar" />
</library>

<bell libraryRef=”RestEpLib” spiVisibility=”true">
  <properties hello=“WORLD” />
</bell>

The server.xml file requires more configuration than just the BELL to expose the endpoint. In addition to the BELL feature, you must enable the Admin REST Connector (restConnector-2.0) and Transport Security (transportSecurity-1.0) features. The Admin REST Connector feature provides the REST Handler framework SPI. Endpoint access requires secure transport and a user who is mapped to the administrator role. The Transport Security feature and the related keyStore, basicRegistry, and administrator-role configurations support secure access to the endpoint. The following server.xml file example shows a possible configuration, including the BELL configuration from the previous example.

<featureManager>
  <feature>bells-1.0</feature>
  <feature>restConnector-2.0</feature>
  <feature>transportSecurity-1.0</feature>
</featureManager>

<keyStore id="defaultKeyStore" password="keystorePassword" />
<basicRegistry>
  <user name="you" password="yourPassword" />
  <group name="yourGroup" />
</basicRegistry>
<administrator-role>
  <user>you</user>
  <group>yourGroup</group>
</administrator-role>

<library id=”RestEpLib">
  <fileset dir="${server.config.dir}/sharedLib" includes="RestEpLib.jar" />
</library>

<bell libraryRef=”RestEpLib” spiVisibility=”true">
  <properties hello=“WORLD” />
</bell>

When this server starts, the BELL feature registers the RESTHandler interface with the BellEndpoint class and the com.ibm.wsspi.rest.handler.root=/bellEP OSGi service property into the OSGi framework. The REST Handler framework then registers the service and makes the endpoint available at the https://<host>:8020/ibm/api/bellEP URL.

When you make calls to the endpoint, the REST Handler framework handles the initial request by getting an instance of the service. The BELL feature creates an instance of the BellEndpoint class that is injected with an unmodifiable map that contains the "hello"/"WORLD" key/value pair. The framework then services the initial and subsequent requests by calling the handleRequest method on the BellEnpoint instance.

Feature configuration elements

Supported Java versions

  • JavaSE-1.8

  • JavaSE-11.0

  • JavaSE-17.0

  • JavaSE-21.0

  • JavaSE-22.0

Developing a feature that depends on this feature

If you are developing a feature that depends on this feature, include the following item in the Subsystem-Content header in your feature manifest file.

com.ibm.websphere.appserver.bells-1.0; type="osgi.subsystem.feature"