Configuration notifiers provide a mechanism to perform application specific configuration auditing and to associate application behavior with configuration state changes.
Configuration notifiers are defined by extending
com.kabira.platform.switchconfig.ConfigurationListener
.
Creating an instance of a user defined configuration notifier implicitly
registers the notifier to be called by the configuration framework.
Configuration notifiers can be created as part of application
initialization and deleted as part of application termination. Another
mechanism to install and remove configuration notifiers is to use
ActiveSpaces® Transactions
component notifiers. See the section called “Notifiers” for details.
There are two different kinds of methods in a configuration notifier:
Audit
State change
Audit methods are always called before its associated state change
method (except for load where they are called after the load method). If a
method throws the
com.kabira.platform.switchconfig.ConfigurationException
it is an audit method. An audit method reports an audit failure by
throwing a
com.kabira.platform.switchconfig.ConfigurationException
exception. An audit failure prevents the requested configuration state
change from occurring. Audit methods should not change the application
state in any way.
A state change method cannot fail. It is only called if its associated audit method did not report an error. Any application state changes triggered by the configuration state change should be implemented in state methods.
The loaded
state change method provides a
mechanism to manually add additional configuration objects to the ones
loaded from an external file. To add additional configuration objects, the
implementation of the loaded
method should create
configuration instances and return them to the framework in the
additions
parameter.
Here is an example of a configuration notifier.
Example 9.9. Configuration notifier
// $Revision: 1.1.2.1 $ package com.kabira.snippets.configuring; import com.kabira.platform.switchconfig.Config; import com.kabira.platform.switchconfig.ConfigurationException; import com.kabira.platform.switchconfig.ConfigurationListener; import com.kabira.platform.switchconfig.Version; /** * Configuration notifier */ public class UserNotifier extends ConfigurationListener { public UserNotifier() { super( User.class.getPackage().getName()); } @Override public void loaded( Version version, java.util.List<Config> additions) { System.out.println("Loading type: " + version.groupKindId + " name: " + version.groupId + " version: " + version.versionId); } @Override public void auditLoad(Version version) throws ConfigurationException { System.out.println("Auditing load for type: " + version.groupKindId + " name: " + version.groupId + " version: " + version.versionId); } @Override public void auditActivate(Version version) throws ConfigurationException { System.out.println("Auditing activation for type: " + version.groupKindId + " name: " + version.groupId + " version: " + version.versionId); } @Override public void activated(Version version) { System.out.println("Activating type: " + version.groupKindId + " name: " + version.groupId + " version: " + version.versionId); } @Override public void auditReplace( Version deactivating, Version activating) throws ConfigurationException { System.out.println("Auditing replace (deactivation) of type: " + deactivating.groupKindId + " name: " + deactivating.groupId + " version: " + deactivating.versionId); System.out.println("Auditing replace (activation) of type: " + activating.groupKindId + " name: " + activating.groupId + " version: " + activating.versionId); } @Override public void replaced(Version deactivating, Version activating) { System.out.println("Replacing (deactivation) type: " + deactivating.groupKindId + " name: " + deactivating.groupId + " version: " + deactivating.versionId); System.out.println("Replacing (activation) type: " + activating.groupKindId + " name: " + activating.groupId + " version: " + activating.versionId); } @Override public void auditDeactivate(Version version) throws ConfigurationException { System.out.println("Auditing deactivation of type: " + version.groupKindId + " name: " + version.groupId + " version: " + version.versionId); } @Override public void deactivated(Version version) { System.out.println("Deactivating type: " + version.groupKindId + " name: " + version.groupId + " version: " + version.versionId); } @Override public void auditRemove(Version version) throws ConfigurationException { System.out.println("Auditing removal of type: " + version.groupKindId + " name: " + version.groupId + " version: " + version.versionId); } @Override public void removed(Version version) { System.out.println("Removing type: " + version.groupKindId + " name: " + version.groupId + " version: " + version.versionId); } }
Configuration notifiers are installed by creating an instance. They are removed by deleting the instance.
Example 9.10, “Notifier initialization and termination” contains a complete example of initializing and terminating a configuration notifier. See Example 9.9, “Configuration notifier” for the notifier that is being installed.
Example 9.10. Notifier initialization and termination
// $Revision: 1.1.2.1 $ package com.kabira.snippets.configuring; import com.kabira.platform.ManagedObject; import com.kabira.platform.Transaction; import com.kabira.test.management.Client; import com.kabira.test.management.CommandFailed; import java.net.URL; /** * Snippet to install and terminate configuration notifiers * * NOTE: This snippet requires the classpath to include the * directory where the configuration files are located. This * allows the get resource call to locate the configuration files * * <p> * <h2> Target Nodes</h2> * <ul> * <li> <b>domainnode</b> = A * </ul> */ public class NotifierLifeCycle { /** * Initialize the configuration notifier */ public void initialize() { new Transaction("Initialize Configuration Notifier") { @Override protected void run() throws Rollback { m_userNotifier = new UserNotifier(); } }.execute(); } /** * Terminate the configuration notifier */ public void terminate() { new Transaction("Terminate Configuration Notifier") { @Override protected void run() throws Rollback { // // Delete the configuration notifier // ManagedObject.delete(m_userNotifier); m_userNotifier = null; } }.execute(); } /** * Execute snippet * * @param args Not used * @throws CommandFailed Configuration command failed * @throws ClassNotFoundException Configuration class not found */ public static void main(String[] args) throws CommandFailed, ClassNotFoundException { Client client = new Client("guest", "guest"); URL url1 = client.getClass().getClassLoader().getResource("user1.kcs"); URL url2 = client.getClass().getClassLoader().getResource("user2.kcs"); if ((url1 == null) || (url2 == null)) { throw new Error( "Configuration files not located - are they installed into " + "current class path?"); } Client.Configuration version1 = client.new Configuration(url1); Client.Configuration version2 = client.new Configuration(url2); // // Install configuration notifiers // NotifierLifeCycle notifierLifeCycle = new NotifierLifeCycle(); notifierLifeCycle.initialize(); // // Resolve configuration classes // Class.forName("com.kabira.snippets.configuring.User"); // // Load configuration files // version1.load(); version2.load(); // // Activate version 1 // version1.activate(); // // Activate version 2 - causes replace notifier to be called // version2.activate(); // // Deactive version 2 // version2.deactivate(); // // Remove configurations // version1.remove(); version2.remove(); // // Remove configuration notifiers // notifierLifeCycle.terminate(); } private UserNotifier m_userNotifier; }
When Example 9.10, “Notifier initialization and termination” is run it outputs the following (annotation added):
# # Load and audit version 1.0 # [A] Loading type: com.kabira.snippets.configuring name: user version: 1.0 [A] Auditing load for type: com.kabira.snippets.configuring name: user version: 1.0 # # Load and audit version 2.0 # [A] Loading type: com.kabira.snippets.configuring name: user version: 2.0 [A] Auditing load for type: com.kabira.snippets.configuring name: user version: 2.0 # # Audit activation, and activate version 1.0 # [A] Auditing activation for type: com.kabira.snippets.configuring name: user version: 1.0 [A] Activating type: com.kabira.snippets.configuring name: user version: 1.0 # # Audit replace, and then replace version 1.0 with version 2.0 # [A] Auditing replace (deactivation) of type: com.kabira.snippets.configuring name: user version: 1.0 [A] Auditing replace (activation) of type: com.kabira.snippets.configuring name: user version: 2.0 [A] Replacing (deactivation) type: com.kabira.snippets.configuring name: user version: 1.0 [A] Replacing (activation) type: com.kabira.snippets.configuring name: user version: 2.0 # # Audit deactivation, and then deactivate version 2.0 # [A] Auditing deactivation of type: com.kabira.snippets.configuring name: user version: 2.0 [A] Deactivating type: com.kabira.snippets.configuring name: user version: 2.0 # # Audit removal, and then remove, version 1.0 # [A] Auditing removal of type: com.kabira.snippets.configuring name: user version: 1.0 [A] Removing type: com.kabira.snippets.configuring name: user version: 1.0 # # Audit removal, and then remove, version 2.0 # [A] Auditing removal of type: com.kabira.snippets.configuring name: user version: 2.0 [A] Removing type: com.kabira.snippets.configuring name: user version: 2.0