Hot Deployment of KMC Components

SAP Developer Network

Applies To:

Knowledge Management 6.0

Summary

This article describes the technical background of hot-deployment and discusses the related pitfalls for customers when writing their own KMC components.

By Dieter Guendisch

11 Jan 2006

 

Technical Background

In general, hot-deployment describes the ability to exchange code without the need to restart the surrounding container.

In a KMC scenario, hot-deployment means the ability to redeploy a KMC component without having to restart the container that loaded this component. As KMC components are wrapped inside a portal application archive (.par file), they use the portal’s deployment and class loading mechanisms, thus making the portal runtime (PRT) the loading container for KMC components.

KMC also provides a runtime container called the component runtime (CRT), which is a logical container for KMC components enforcing the programming and service life-cycle model of KMC. The CRT does not actually load the classes of the KMC components but merely delegates this task to the PRT.

KMC Implementation

As already mentioned above, KMC components are wrapped inside a .par file. This is done by placing the .jar files that make up the KMC component and a special service stub (usually named RFServiceWrapper) inside the .par file. This service stub implements the service interface of the PRT (IService) and calls a special registration method of the CRT in its init() method to register the class loader with the CRT.

When a KMC component is hot-deployed (typically by uploading the corresponding .par file using the portal archive uploader or using NetWeaver Developer Studio), the following steps take place internally:

  1. The portal runtime’s deployment mechanism is triggered by uploading the .par file.

  2. The PRT releases its reference to the class loader that was previously used to load the respective .par file.

  3. A new class loader is created to load the classes of the newly deployed .par file.

  4. The PRT calls the init() method on the aforementioned service stub.

  5. The implementation (as generated by the KMC plug-ins) of the init() method simply calls CrtClassLoaderRegistry.addClassLoader(“myID”, getClass().getClassLoader()) with a string constant as a key and its new class loader as the second parameter.

  6. The CRT recognizes that a class loader was already registered for that key and that the new class loader is different to the old one, thus a hot-deployment must have taken place.

  7. The CRT initializes the KMC system again.

  8. During reinitialization, all components and services are released and new ones are created. The CRT and all other KMC components do not change their class loaders, in contrast to the hot-deployed component, which is loaded using a new class loader.

Memory Leaks

Generally speaking, memory leaks occur when a hot-deployment has taken place, but some of the released KMC objects are still referenced by another object, thus preventing them from being garbage collected. In the next sections, you can see some of the typical scenarios that can lead to such memory leaks.

Static References

In the following example, component X references a KMC object using a static variable:

public class MyRepositoryManager extends AbstractManager {
private static ResourceFactory resourceFactory = ResourceFactory.getInstance();
    ...
}
				

Scenario One: Hot-Deploying Component X

When the developer hot-deploys component X itself, everything might work as expected. See the graphic below for a schematic memory snapshot before and after hot-deployment of component X:

Graphic 1: A component with static references to a KMC object

Upon deployment, component X is loaded using a new class loader, which results in its static fields being initialized. Thus – from a functional point of view – MyRepositoryManager works as expected because it references the new ResourceFactory object.

Problems may arise as soon as one object inside component X’s class loader scope cannot be garbage collected,for example, because it is registered as a listener outside of KM (for example, in the configuration framework or user management). This object hinders its effective class loader from being garbage collected, which in turn hinders all classes (not objects) loaded using this class loader (including their static references) from being garbage collected too.

By doing so, you effectively introduce not only a memory leak for your own component (parts of component X cannot be garbage collected) but also a memory leak for many KMC objects, which cannot be garbage collected either because they are referenced by parts of component X.

Scenario Two: Hot-Deploying a Component Other than Component X

Let us stay with the example of component X, which has a static reference to some KMC objects. In this section, I analyze the case if another component is hot-deployed instead of component X. See the graphic below for a schematic memory snapshot before and after hot-deployment:

Graphic 2: Component X after hot-deployment of another component

Since component X was not directly hot-deployed, its class loader was not renewed. Thus, references to the MyRepositoryManager object were removed during hot-deployment and a new instance of MyRepositoryManager was created by the CRT after hot-deployment. Because creating a new instance of an object leaves its static references untouched if the object was already used before, the reference from the new MyRepositoryManager object still points to the old instance of object ResourceFactory.

At runtime, MyRepositoryManager uses an old instance of ResourceFactory, which results in undefined behavior. In addition, this reference also introduces a memory leak because the old instance of ResourceFactory and all objects that it directly or indirectly references cannot be garbage collected any more.

Improvement Attempt

Note that you could try to move the assignment of the static variable into the startupImpl method of your repository manager:

public class MyRepositoryManager extends AbstractManager {
private static ResourceFactory resourceFactory;
    protected void startUpImpl() {
      resourceFactory = ResourceFactory.getInstance();
      ...
    }
    ...
}
				

By doing this, the static variable would be updated each time the repository manager is started. Thus, scenario two in our hot-deployment example would work without memory leaks. On the other hand, the problems described in scenario one still hold true, because the old class (including its static references) still might reside in the memory and thus reference the old instance of ResourceFactory. Again, ResourceFactory and all objects that it references could not be garbage collected.

As a consequence of the behavior described above, the following general rule applies when writing components that are aware of hot-deployment:

(1) Do not use static variables to reference KMC objects.

Non-Static References

When referencing KMC objects using member variables of your components, these references are recreated during a KMC restart, since the CRT releases old instances of your component and creates new ones when hot-deployment takes place. When your component shuts down, you only have to make sure that your objects are not referenced from outside of KMC (for example, if they are registered for user management events, you have to deregister your objects now). This can be accomplished by overwriting the shutDownImpl() method.

public class MyRepositoryManager extends AbstractManager implements UserListener {
    protected void startUpImpl() {
  UMFactory.getUserFactory().registerListener(this, 
  UserListener.INFORM_ON_USER_REMOVED);
  ...
    }
				
protected void shutDownImpl() {
  UMFactory.getUserFactory().unregisterListener(this);
  //additional clean-up calls
  ...
    }
    
}
				

To sum it up, the following rule applies:

(2) Ensure that when your component shuts down, no references from outside of KMC are pointing to your objects. For example, you have to deregister listener objects that were previously registered.

Using Caches

When using the KMC Cache API, you have to clear your caches when your component shuts down. Otherwise, there is a risk that some cache entries contain references to old KMC objects, which prevents them from being garbage collected. Thus, the following rule applies:

(3) Clear any existing caches when your component shuts down.

What About Client Applications?

Until now, I have only talked about the behavior of KMC components developed by the customer. In the following section, I want to examine whether the previous findings also hold true when writing client applications that only use KMC without extending it.

Applications that only use KMC APIs are not components in terms of the component runtime. This means that they do not participate in the CRT lifecycle, which involves starting and stopping components. However, client applications can also contain references to KMC objects. If the client application should continue to work after hot-deployment, then keeping references to KMC objects is generally a bad idea because a client application does not know whether the referenced object is still valid, or if it is already outdated because a developer hot-deployed a KMC component developed by the customer in the meantime.

Conclusion

This article presents an insight into what happens “under the hood” when KMC components are hot-deployed. As you can see, special care has to be taken when writing components that are aware of hot-deployment.

Finally, I want to add that hot-deployment is solely for use in development systems. Because KMC currently lacks the means to find out which component contains incorrect references to KMC objects and because KMC has no control over essential container features (for example, class loading is not done by KMC itself), hot-deployment of KMC components developed by the customer is currently not officially supported by SAP (for more information, see SAP Note 894884).

Author's Bio

Dieter Guendisch is a developer at SAP and currently working on various aspects of the repository framework.

Table of Contents



Content Options

Copyright © 2005 SAP AG, Inc. All Rights Reserved. SAP, mySAP, mySAP.com, xApps, xApp, and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP AG in Germany and in several other countries all over the world. All other product, service names, trademarks and registered trademarks mentioned are the trademarks of their respective owners.

SAP Developer Network