com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links' is unknown.

ServerShutdownHandler

The ServerShutDownHandler interface allows to perform specific things that need to be done before the server is shut down. Therefore, any pre-shutdown work that needs to be done can be registered as an implementation of this interface. The interface contains a single method, invoke() that takes no parameters, which will be executed during server shutdown.

The org.wso2.carbon.core.internal.CarbonCoreServiceComponent implementation adds all the available ServerShutDownHandlers to a single list. If a server shutdown is requested (forceful shutdown or graceful shutdown), the CarbonCoreServiceComponent implementation calls the invoke() method of all the registered ServerShutDownHandlers.

Implementing ServerShutDownHandler

Following is the sample implementation (DeployeManager) that implements the ServerShutdownHandler interface to remove a deployer that was registered for web apps. Let's assume that the deploymentEngine already has a deployer registered for web apps.

import org.apache.axis2.deployment.DeploymentEngine;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.core.ServerShutdownHandler;
import org.wso2.carbon.shutdown.sample.ConfigHolder;
import org.wso2.carbon.utils.ConfigurationContextService;

/**
* This shutdown handler responsible for 
* removing webapp deployers from deployment engine 
* before shutting down the Carbon server.
*/
public class DeployeManager implements ServerShutdownHandler {
   private static Log log = LogFactory.getLog(DeployeManager.class);

   @Override
   public void invoke() {
       log.info("Logging message before shutting down server ....................... ");
       ConfigurationContextService configurationContextService = ConfigHolder.getInstance().getConfigurationContextService();
       AxisConfiguration axisConfiguration = configurationContextService.getServerConfigContext().getAxisConfiguration();
      
       removeDeployer(axisConfiguration);

   }

   //Remove deployer registered for webapps
   private void removeDeployer(AxisConfiguration axisConfiguration) {
       DeploymentEngine deploymentEngine = (DeploymentEngine) axisConfiguration.getConfigurator();
       deploymentEngine.removeDeployer("webapps", "war");
   }

Next, we are registering the sample ServerShutdownHandler implementation to the bundle context inside the activate() method of the service component below. We are also adding bind/unbind methods (setConfigurationContextService and unsetConfigurationContextService) for ConfigurationContextService in order to add them to a data holder (ConfigHolder).

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.*;
import org.wso2.carbon.core.ServerShutdownHandler;
import org.wso2.carbon.shutdown.sample.ConfigHolder;
import org.wso2.carbon.shutdown.sample.handler.DeployeManager;
import org.wso2.carbon.utils.ConfigurationContextService;


/**
* This service component register a DeployeManager as 
* a ServerShutdownHandler.
*/
@Component(name = "sample.shutdown.service", immediate = true)
public class ShutdownServiceComponent {
   private static Log log = LogFactory.getLog(ShutdownServiceComponent.class);
   private static BundleContext bundleContext;

   @Activate
   protected void activate(ComponentContext context) {
       bundleContext = context.getBundleContext();
       bundleContext.registerService(ServerShutdownHandler.class.getName(), new DeployeManager(), null);
   }

   @Reference (name = "sample.config.service",
               cardinality = ReferenceCardinality.MANDATORY,
               policy = ReferencePolicy.DYNAMIC,
               service = org.wso2.carbon.utils.ConfigurationContextService.class,
               unbind = "unsetConfigurationContextService")
   protected void setConfigurationContextService(ConfigurationContextService configurationContextService) {
       log.debug("******* ConfigurationContextService  is set ******* ");
       ConfigHolder.getInstance().setConfigurationContextService(configurationContextService);
   }

   protected void unsetConfigurationContextService(ConfigurationContextService configurationContextService) {
       log.debug("******* ConfigurationContextService is unset ******* ");
   }

   protected void deactivate(ComponentContext context) {
       ShutdownServiceComponent.bundleContext = null;
       log.debug("Carbon Shutdown Services bundle is deactivated ");
   }
}

Shown below is the data holder class that is used for the implementation. We have used a ConfigurationContextService where any service can be used to perform the required operations during server shutdown.

import org.wso2.carbon.utils.ConfigurationContextService;

/**
* A singleton ConfigurationContext holder class to keep references to ConfigurationContextService.
*/
public class ConfigHolder {

   private ConfigurationContextService configurationContextService;
   private static final ConfigHolder configHolder = new ConfigHolder();

   private ConfigHolder() {

   }

   public static ConfigHolder getInstance() {
       return configHolder;
   }
   public ConfigurationContextService getConfigurationContextService() {
       return configurationContextService;
   }

   public void setConfigurationContextService(ConfigurationContextService configurationContextService) {
       this.configurationContextService = configurationContextService;
   }
}

Shown below is the POM file of the sample OSGi bundle, which points out the required maven dependencies.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>org.wso2.carbon</groupId>
   <artifactId>org.wso2.carbon.shutdown</artifactId>
   <version>1.0.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
   <name>WSO2 Carbon - Samples</name>
   <url>http://wso2.org</url>

   <pluginRepositories>
       <pluginRepository>
           <id>wso2-nexus</id>
           <name>WSO2 internal Repository</name>
           <url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
           <releases>
               <enabled>true</enabled>
               <updatePolicy>daily</updatePolicy>
               <checksumPolicy>ignore</checksumPolicy>
           </releases>
       </pluginRepository>
   </pluginRepositories>

   <dependencies>
       <dependency>
           <groupId>org.apache.felix</groupId>
           <artifactId>org.osgi.core</artifactId>
           <version>1.4.0</version>
       </dependency>
       <dependency>
           <groupId>org.wso2.carbon</groupId>
           <artifactId>org.wso2.carbon.utils</artifactId>
           <version>${core.version}</version>
       </dependency>
       <dependency>
           <groupId>org.wso2.carbon</groupId>
           <artifactId>org.wso2.carbon.core</artifactId>
           <version>${core.version}</version>
       </dependency>
       ...
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.apache.felix</groupId>
               <artifactId>maven-scr-plugin</artifactId>
               <version>1.9.0</version>
               <executions>
                   <execution>
                       <id>generate-scr-scrdescriptor</id>
                       <goals>
                           <goal>scr</goal>
                       </goals>
                   </execution>
               </executions>
           </plugin>
           <plugin>
               <groupId>org.apache.felix</groupId>
               <artifactId>maven-bundle-plugin</artifactId>
               <extensions>true</extensions>
               <configuration>
                   <instructions>
                       <Bundle-Vendor>WSO2 Inc</Bundle-Vendor>
                       <Bundle-SymbolicName>org.wso2.carbon.shutdown.sample</Bundle-SymbolicName>
                       <Bundle-Name>org.wso2.carbon.shutdown.sample</Bundle-Name>
                       <Private-Package>org.wso2.carbon.shutdown.sample.internal</Private-Package>
                       <Bundle-Version>1.0.0</Bundle-Version>
                       <Bundle-Activator>org.wso2.carbon.shutdown.sample.activator.ShutdownActivator</Bundle-Activator>
                       <Import-Package>
                           org.osgi.framework, org.wso2.carbon.core, org.wso2.carbon.utils.*
                           *;resolution:=optional
                       </Import-Package>
                       <Export-Package>!org.wso2.carbon.shutdown.sample.internal,
                           org.wso2.carbon.shutdown.sample.*
                       </Export-Package>
                       <DynamicImport-Package>*</DynamicImport-Package>
                   </instructions>
               </configuration>
           </plugin>
       </plugins>
   </build>

</project>

After building the above sample, you can add your OSGi bundle to the <PRODUCT_HOME>/repository/components/dropins directory and start the Carbon server. Try shutting down the server, which will trigger the invoke() method of your custom handler implementations. You can write your own custom logic that need to be invoked when shutting down the server.

com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.