RF Components and Their Runtime


All extensions (regardless of type) and the built-in services are referred to as RF components.


Table of Contents

Configuration Framework

Component Runtime

Components, the Component Hierarchy, and Component Information

Lifestyle and Singletons

Lifecycle, State, and Configuration

Component Events

Usage of CRT Interfaces for RF Extensions

Logging and Tracing

Clustered Installation

Utility Packages

Current API: com.sapportals.wcm.util

New API: com.sap.netweaver.bc.rf.util

References




Configuration Framework

The configuration framework (CF) stores the configuration data for all RF components. It offers a GUI that allows administrators to change the configuration for the RF's components (see [Admin Guide] for information on how to use Knowledge Management's configuration UI).

Usually, developers only have to concern themselves with the configuration classes that define the set of parameters that an extension needs. For example, a CmRepositoryManager.cc.xml specifies the configuration class of the RF's default repository manager implementation. Configuration classes are built using the PDK Eclipse Plugin "Configuration Wizard".

The configurables are instances of configuration classes. For example, the configuration data for the /documents repository (stored in documents.co.xml) is an instance of CmRepositoryMananager.cc.xml. New configurables are created with the help of the configuration UI.

For further details on how to create configuration classes and use onfigurables, see [CF].

The retrieval of a component's configuration data is handled by the component runtime, which is described in the following section.





Component Runtime

The component runtime (CRT) manages the start-up and shutdown of RF components. It also provides the RF components with their configuration data from the configuration framework. The components' states can be inspected using the CRT component monitor, so an administrator can find out which components were started, which could not be started, and why.

Usually, the RF extensions do not need to concern themselves with the CRT because extensions are derived from the relevant RF classes (AbstractManager, AbstractFilterManager, AbstractRepositoryService and AbstractService; see RF Extensions), which already implement the required CRT interfaces for starting, stopping, and configuring a component with its configuration data.

However,, it might be helpful to know the CRT's interfaces in case you implement additional features:

Most of these interfaces are tagging interfaces, such as java.lang.Cloneable, for indicating a specific feature of the component.



Components, the Component Hierarchy, and Component Information

All components within the CRT implement the IComponent interface. The following things are true for each component:

Components that manage child components implement the IContainer interface. For example, the AbstractManager, which is the base class for a repository manager, contains its event broker as a child component (see RF Extensions).

The IComponentInfo and ILifecycleInfo interfaces support the retrieval of status information that is used by the CRT component monitor to show the current status of a component.




Lifestyle and Singletons

Components can have different lifestyles. The lifestyle defines how a component is instantiated:

If a component does not implement one of these three interfaces, a new instance is created each time the component is looked up or retrieved, for example, when a global service is retrieved using IServiceFactory.getService().




Lifecycle, State, and Configuration

The IStartable interface indicates that the component performs an initialization on start-up and carries out a certain amount of cleaning up at shutdown.

The initialization during start() should be used by all components (instead of doing this in the components constructor). In particular, lookup of other components must not be carried out in the components constructor, since this can lead to indissoluble lookup sequences during start-up, causing a CyclicDependencyException to be thrown.

IAutoStartable indicates components that are instantiated automatically during the start-up of the CRT (whereas components that are not started automatically are not be instantiated until the first lookup). Because automatic start-up only makes sense for a singleton, IAutoStartable is also derived from IThreadSafe.

IConfigurable indicates a component that requires configuration data. The CRT retrieves the components configuration and calls configure().

A component implements the IReconfigurable interface in order to enable hot reload. Hot reload is a component's ability to handle changes to its configuration without requiring a system restart. When a component implements IReconfigurable, the CRT calls reconfigure() with the changed configuration. The component must then change its internal state in line with the new configuration.

IReconfigurable can be used in conjunction with ISuspendable, which indicates that a component should be stopped during reconfiguration and resumed afterwards. This is especially useful if a component is not able to process any other requests during reconfiguration. The CRT calls suspend() before and resume() after the reconfiguration for an ISuspendable, and the component is marked as stopped during reconfiguration, which inhibits any further lookups for that component during the suspension.

A component that implements all available lifecycle interfaces (state and configuration) has the following methods called by the CRT:

  1. Constructor: The component is instantiated.
  2. IContextualizable.contextualize(): The component receives a CRT context object that might contain parameters from the component's container (its parent component).
  3. IConfigurable.configure(): The component receives its configuration data.
  4. IStartable.start(): The component initializes and acquires the resources necessary to provide its functionality.
  5. ISuspendable.suspend(): The component is suspended for reconfiguration.
  6. IReconfigurable.reconfigure(): The component receives new configuration data.
  7. ISuspendable.resume(): The component is accessible again after reconfiguration.
  8. IStartable.stop(): The component releases the acquired resources.

Each time a component changes its state (when a lifecycle interface method is called by the CRT), the component should call the appropriate pre()- and post()-methods of the ComponentStateHandler when entering or leaving the method in order to have its state automatically updated in its ILifecycleInfo.

For example, a component's reconfigure() method might look like this:

  public void reconfigure(IConfiguration config)
                   throws ConfigurationException {
    this.stateHandler.preReconfigure();
    try {
      … // do something for reconfiguration here
    }
    catch( Exception e ) {
      // handle exception and throw ConfigurationException
    }
    finally {
      this.stateHandler.postReconfigure();
    }
  }




Component Events

If the component depends on other components (for example, a repository service usually depends on the repository manager it is assigned to), it can implement the IComponentEventListener interface in order to be notified whenever a component is added, removed, or changed within the CRT. The CRT calls notify() with a ComponentEvent that holds the ID of the added, changed, or removed component.




Usage of CRT Interfaces for RF Extensions

The following table shows the CRT interfaces that are implemented by the different RF base classes (semantic object factories do not currently use the CRT):

Abstract Manager

Abstract Repository Service

Abstract Service

Abstract Filter Manager

IComponent

x

x

x

x

IComponentManager

x

 

 

 

IComponentInfo

x

x

x

x

ILifecycleInfo

x

x

x

x

IConfigurable

x

x

x

x

IStartable

x

x

x

x

IAutoStartable

 

x

 

 

IThreadSafe

x

x

 

x

IComponentEventListener

 

x

 

 

For further information on the CRT, see Component Runtime.





Logging and Tracing

Logs are used for reporting problems. Logging includes security auditing or database logging. The class com.sap.tc.logging.Category can be used for logging to such a (distinct) log.

While several processes or objects might write to the same log, a com.sap.tc.logging.Location represents the "source" location of the information logged.

Traces are used for tracing code execution - they are special logs used for support and development. A trace is the default category, and the class should be used as the tracing location within the RF.

For example:

import com.sap.tc.logging.Location;
…
private static Location trace = Location.getLocation(myClass.class);
…
  trace.errorT("myMethod", "myMessage");

The example creates a location instance trace. If trace.errorT() is called, an error trace is written to the RF's trace file.

The different methods for the several severities are:

For performance reasons, tracing should only be performed for warning, info, or debug traces if the appropriate severity is set. Moreover, since the line number is not included in the trace output automatically, it might be a good idea to include it in the first parameter.

For example (using 123 as line number):

  if( trace.beInfo() ) {
    trace.infoT("myMethod(123)", "my info message");
  }

To trace the backlog of an Exception or Throwable, the utility class LoggingFormatter is provided:

import com.sap.wcm.util.logging.LoggingFormatter;
…
  try {
    …
  }
  catch( Exception e ) {
    trace.errorT(
                "myMethod",
                "caught exception " + e.getMessage()
                + ":" + LoggingFormatter.extractCallstack(e)
                );
  }

SAP logging and tracing offers a lot of additional functions. For further details, see [Logging].





Clustered Installation

Since the RF has to support a large number of users working concurrently, performance is one of the major issues in the RF.

In order to support more users than one server might be able to handle, the RF can be distributed across several servers - this is called a clustered installation. Within a cluster, several instances of the RF run on different machines (in different VMs), but these instances use the same database (configuration, backend connections, and so on).

Each RF extension must be aware of supporting a clustered installation by implementing the relevant synchronization mechanisms.

An extension can check for the clustered installation using the following code fragment:

  boolean isClustered = true;
  try {
    ILandscapeService landscapeService =
    (ILandscapeService)ResourceFactory
                       .getInstance()
                       .getServiceFactory()
                       .getService(IServiceTypesConst.LANDSCAPE_SERVICE);
    if( landscapeService != null ) {
      isClustered = landscapeService.isClusterInstallation();
    }
  }
  catch( ResourceException e ) {
    // trace exception
  }





Utility Packages


Current API: com.sapportals.wcm.util

The following three lists provide a brief overview of the packages beneath com.sapportals.wcm.util and the interfaces and classes they provide:

The first group consists of packages that are related to the RF:

The next group of packages are those that are not related to the RF. These packages will not be incorporated into the new API. Most of these packages deal with content and string handling:

The third group of packages are implementations of features that should only be used internally. They should not be used by application developers for the following reasons: Either they provide basic functions, making it likely that either the portal runtime or the J2EE Engine will provide the same functionality in the future, the functionality is relevant for RF extensions only, or the package is already deprecated.




New API: com.sap.netweaver.bc.rf.util

The following list is just a brief summary of the packages beneath com.sap.netweaver.bc.rf.util.







References