JBoss Community Archive (Read Only)

JBoss AS 7.1

Tomcat Storeconfig Usages

From JBoss EWS 2.1.0, the Tomcat6 and 7 will include a component called StoreConfig. It is a component that can let users to persist the server runtime configuration changes into configuration files. JBoss JON uses it to manage Tomcat servers. In this article, I'd like to give a brief introduction to StoreConfig.

The StoreConfig component is jar that will be placed into Tomcat's 'lib' directory:

master:lib weinanli$ pwd
/Users/weinanli/projs/apache-tomcat-7.0.54/lib
master:lib weinanli$ ls tomcat7-store*
tomcat7-storeconfig-0.0.1.Alpha3-redhat-5.jar

Please note Tomcat 6 and Tomcat 7 are using different versions of storeconfig. Because their configurations to be dealt with have differences. As the bash command show above, in Tomcat 7 it's using tomcat7-storeconfig-0.0.1.Alpha3-redhat-5.jar.

To enable StoreConfig, we need to add a line in server.xml:

<Server port="8005" shutdown="SHUTDOWN">
  ...
  <Listener className="org.apache.catalina.storeconfig.StoreConfigLifecycleListener" />
  ...

The StoreConfig is exposed as MBeans at runtime, so to use it, we need to enable JMX during Tomcat startup. To achieve this, we need to set 'CATALINA_OPTS' properly:

export CATALINA_OPTS='-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=6667 -Dcom.sun.management.jmxremote.authenticate=false'

Then we can start Tomcat server:

master:bin weinanli$ pwd
/Users/weinanli/projs/apache-tomcat-7.0.54/bin

master:bin weinanli$ ./startup.sh
Using CATALINA_BASE:   /Users/weinanli/projs/apache-tomcat-7.0.54
Using CATALINA_HOME:   /Users/weinanli/projs/apache-tomcat-7.0.54
Using CATALINA_TMPDIR: /Users/weinanli/projs/apache-tomcat-7.0.54/temp
Using JRE_HOME:        /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home
Using CLASSPATH:       /Users/weinanli/projs/apache-tomcat-7.0.54/bin/bootstrap.jar:/Users/weinanli/projs/apache-tomcat-7.0.54/bin/tomcat-juli.jar
Tomcat started.

To access StoreConfig, we can use 'jconsole' to connect to Tomcat JMX port:

images/author/download/attachments/81855213/ScreenSnapz113.png

From JConsole, we can see the StoreConfig is in 'Catalina:StoreConfig' category, and it contains multiple operations:

images/author/download/attachments/81855213/ScreenSnapz114.png

We can try to click 'storeConfig' operation and it's like this:

images/author/download/attachments/81855213/ScreenSnapz115.png

And from the tomcat log file 'catalina.out' we can see the StoreConfig actions:

Jul 09, 2014 4:55:31 PM org.apache.catalina.storeconfig.StandardContextSF storeWithBackup
INFO: Store Context /manager separate with backup (at file /Users/weinanli/projs/apache-tomcat-7.0.54/webapps/manager/META-INF/context.xml.2014-07-09.16-55-31 )
Jul 09, 2014 4:55:31 PM org.apache.catalina.storeconfig.StandardContextSF storeWithBackup
INFO: Store Context  separate with backup (at file /Users/weinanli/projs/apache-tomcat-7.0.54/conf/Catalina/localhost/ROOT.xml.2014-07-09.16-55-31 )
Jul 09, 2014 4:55:31 PM org.apache.catalina.storeconfig.StandardContextSF storeWithBackup
INFO: Store Context /docs separate with backup (at file /Users/weinanli/projs/apache-tomcat-7.0.54/conf/Catalina/localhost/docs.xml.2014-07-09.16-55-31 )
Jul 09, 2014 4:55:31 PM org.apache.catalina.storeconfig.StandardContextSF storeWithBackup
INFO: Store Context /examples separate with backup (at file /Users/weinanli/projs/apache-tomcat-7.0.54/conf/Catalina/localhost/examples.xml.2014-07-09.16-55-31 )
Jul 09, 2014 4:55:31 PM org.apache.catalina.storeconfig.StandardContextSF storeWithBackup
INFO: Store Context /host-manager separate with backup (at file /Users/weinanli/projs/apache-tomcat-7.0.54/webapps/host-manager/META-INF/context.xml.2014-07-09.16-55-31 )
Jul 09, 2014 4:55:37 PM org.apache.catalina.startup.HostConfig undeploy
INFO: Undeploying context [/host-manager]
Jul 09, 2014 4:55:38 PM org.apache.catalina.startup.HostConfig undeploy
INFO: Undeploying context [/docs]
Jul 09, 2014 4:55:38 PM org.apache.catalina.startup.HostConfig undeploy
INFO: Undeploying context []
Jul 09, 2014 4:55:38 PM org.apache.catalina.startup.HostConfig undeploy
INFO: Undeploying context [/examples]
Jul 09, 2014 4:55:39 PM org.apache.catalina.startup.HostConfig undeploy
INFO: Undeploying context [/manager]
Jul 09, 2014 4:55:39 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor /Users/weinanli/projs/apache-tomcat-7.0.54/conf/Catalina/localhost/docs.xml
Jul 09, 2014 4:55:39 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deployment of configuration descriptor /Users/weinanli/projs/apache-tomcat-7.0.54/conf/Catalina/localhost/docs.xml has finished in 154 ms
Jul 09, 2014 4:55:39 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor /Users/weinanli/projs/apache-tomcat-7.0.54/conf/Catalina/localhost/examples.xml
Jul 09, 2014 4:55:40 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deployment of configuration descriptor /Users/weinanli/projs/apache-tomcat-7.0.54/conf/Catalina/localhost/examples.xml has finished in 331 ms
Jul 09, 2014 4:55:40 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor /Users/weinanli/projs/apache-tomcat-7.0.54/conf/Catalina/localhost/ROOT.xml
Jul 09, 2014 4:55:40 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deployment of configuration descriptor /Users/weinanli/projs/apache-tomcat-7.0.54/conf/Catalina/localhost/ROOT.xml has finished in 147 ms
Jul 09, 2014 4:55:40 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /Users/weinanli/projs/apache-tomcat-7.0.54/webapps/host-manager
Jul 09, 2014 4:55:40 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory /Users/weinanli/projs/apache-tomcat-7.0.54/webapps/host-manager has finished in 167 ms
Jul 09, 2014 4:55:40 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /Users/weinanli/projs/apache-tomcat-7.0.54/webapps/manager
Jul 09, 2014 4:55:40 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory /Users/weinanli/projs/apache-tomcat-7.0.54/webapps/manager has finished in 210 ms

From the log we can see the server configuration files are saved.

Now we can have a look at the design of Storeconfig. The Storeconfig is written as MBeans and registered into Tomcat as a Listener in Tomcat's configuration file 'server.xml':

  <Listener className="org.apache.catalina.storeconfig.StoreConfigLifecycleListener" />

We can have a look at the source code of StoreConfigLifecycleListener to see how it's implemented:

public class StoreConfigLifecycleListener implements LifecycleListener {
    private static Log log = LogFactory
            .getLog(StoreConfigLifecycleListener.class);

    IStoreConfig storeConfig;

    private String storeConfigClass = "org.apache.catalina.storeconfig.StoreConfig";

    private String storeRegistry = null;

    /*
     * register StoreRegistry after Start the complete Server
     * 
     * @see org.apache.catalina.LifecycleListener#lifecycleEvent(org.apache.catalina.LifecycleEvent)
     */
    public void lifecycleEvent(LifecycleEvent event) {
        if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
            if (event.getSource() instanceof StandardServer) {
                createMBean((StandardServer) event.getSource());
            }
        }
    }

    /**
     * create StoreConfig MBean and load StoreRgistry MBeans name is
     * <i>Catalina:type=StoreConfig </i>
     */
    protected void createMBean(StandardServer server) {
        StoreLoader loader = new StoreLoader();
        try {
            Class clazz = Class.forName(getStoreConfigClass(), true, this
                    .getClass().getClassLoader());
            storeConfig = (IStoreConfig) clazz.newInstance();
            if (null == getStoreRegistry())
                // default Loading
                loader.load();
            else
                // load a spezial file registry (url)
                loader.load(getStoreRegistry());
            // use the loader Registry
            storeConfig.setRegistry(loader.getRegistry());
            storeConfig.setServer(server);
        } catch (Exception e) {
            log.error("createMBean load", e);
            return;
        }
        MBeanServer mserver = MBeanUtils.createServer();
        InputStream descriptor = null;
        try {
            ObjectName objectName = new ObjectName("Catalina:type=StoreConfig" );
            if (!mserver.isRegistered(objectName)) {
                descriptor = this.getClass().getResourceAsStream(
                        "mbeans-descriptors.xml");
                Registry registry = MBeanUtils.createRegistry();
                registry.loadMetadata(descriptor);
                mserver.registerMBean(getManagedBean(storeConfig), objectName);
            }
        } catch (Exception ex) {
            log.error("createMBean register MBean", ex);

        } finally {
            if (descriptor != null) {
                try {
                    descriptor.close();
                    descriptor = null;
                } catch (Exception ex) {
                    log.error("createMBean register MBean", ex);
                }
            }
        }
    }

}

I've trimmed the code a little bit, the import method is 'createMBean' which will register Storeconfig mbeans into Tomcat. We can see this part of code:

ObjectName objectName = new ObjectName("Catalina:type=StoreConfig" );
if (!mserver.isRegistered(objectName)) {
    descriptor = this.getClass().getResourceAsStream(
            "mbeans-descriptors.xml");
    Registry registry = MBeanUtils.createRegistry();
    registry.loadMetadata(descriptor);
    mserver.registerMBean(getManagedBean(storeConfig), objectName);

This is the process how the mbeans are registered into 'Catalina:type=StoreConfig" category. The descriptions of mbeans for StoreConfig are in the mbeans-descriptor.xml file:

<?xml version="1.0"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<mbeans-descriptors>

  <mbean         name="StoreConfig"
          description="Implementation of a store server.xml config"
               domain="Catalina"
                group="StoreConfig"
                 type="org.apache.catalina.storeconfig.StoreConfig">
    <operation name="storeConfig" 
               description="Store Server" 
               impact="ACTION" returnType="void" />
    <operation name="storeServer" 
               description="Store Server from ObjectName" 
               impact="ACTION" returnType="void" >
         <parameter name="objectname"
                 description="Objectname from Server"
                 type="java.lang.String"
                 default="Catalina:type=Server"/>
         <parameter name="backup"
                 description="store Context with backup"
                 type="boolean"/>
         <parameter name="externalAllowed"
                 description="store all Context external that have a configFile"
                 type="boolean"/>
    </operation>

<!--
   Catalina:j2eeType=WebModule,name=//localhost/manager,J2EEApplication=none,J2EEServer=none
-->
   <operation name="storeContext" 
               description="Store Context from ObjectName" 
               impact="ACTION" returnType="void" >
         <parameter name="objectname"
                 description="ObjectName from Context"
                 type="java.lang.String"/>
         <parameter name="backup"
                 description="store with Backup"
                 type="boolean"/>
         <parameter name="externalAllowed"
                 description="store all or store only internal server.xml context (configFile == null)"
                 type="boolean"/>
    </operation>           
    <operation name="store" 
               description="Store Server" 
               impact="ACTION" returnType="void" >
          <parameter name="server"
                 description="Server"
                 type="org.apache.catalina.Server"
                 />
    </operation>           
    <operation name="store" 
               description="Store Context" 
               impact="ACTION" returnType="void" >
          <parameter name="context"
                 description="Context"
                 type="org.apache.catalina.context"/>
    </operation>           
    <operation name="store" 
               description="Store Host" 
               impact="ACTION" returnType="void" >
          <parameter name="host"
                 description="Host"
                 type="org.apache.catalina.Host"/>
    </operation>           
    <operation name="store" 
               description="Store Service" 
               impact="ACTION" returnType="void" >
          <parameter name="service"
                 description="service"
                 type="org.apache.catalina.Service"/>
    </operation>           
 
  </mbean>

</mbeans-descriptors>

This is the scheme used by Tomcat. There is a reference document to introduce 'mbeans-descriptor.xml' on Tomcat website: MBean Descriptor How To

This is how StoreConfig registered into Tomcat. If you are interested in how to write MBeans for Tomcat, here is an excellent introduction article: MBeans and Tomcat: A HOWTO Guide for Managing YOUR Application

Now let's dig a little bit in Tomcat source code to see how it support Storeconfig:

public synchronized void storeConfig() throws Exception {
    ObjectName sname = new ObjectName("Catalina:type=StoreConfig");
    mserver.invoke(sname, "storeConfig", null, null);            
}


public synchronized void storeContext(Context context) throws Exception {
    
    ObjectName sname = null;    
    try {
       sname = new ObjectName("Catalina:type=StoreConfig");
       if(mserver.isRegistered(sname)) {
           mserver.invoke(sname, "store",
               new Object[] {context}, 
               new String [] { "java.lang.String"});
       } else
           log.error("StoreConfig mbean not registered" + sname);
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        log.error(t);
    }

}

Above are codes in org.apache.catalina.core.StandardServer if Tomcat 7.0.54. We can see the Tomcat server will use Storeconfig to store its configurations if StoreConfig is present.

JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-13 13:25:08 UTC, last content change 2014-07-09 12:38:20 UTC.