Monitoring and Managing Tomcat

Table of Contents

Introduction

Monitoring is a key aspect of system administration. Looking inside a running server, obtaining some statistics or reconfiguring some aspects of an application are all daily administration tasks.

Enabling JMX Remote

Note: This configuration is needed only if you are going to monitor Tomcat remotely. It is not needed if you are going to monitor it locally, using the same user that Tomcat runs with.

The Oracle website includes the list of options and how to configure JMX Remote on Java 6: http://docs.oracle.com/javase/6/docs/technotes/guides/management/agent.html.

The following is a quick configuration guide for Java 6:

Add the following parameters to setenv.bat script of your Tomcat (see RUNNING.txt for details).
Note: This syntax is for Microsoft Windows. The command has to be on the same line. It is wrapped to be more readable. If Tomcat is running as a Windows service, use its configuration dialog to set java options for the service. For un*xes remove "set " from beginning of the line.

set CATALINA_OPTS=-Dcom.sun.management.jmxremote
  -Dcom.sun.management.jmxremote.port=%my.jmx.port%
  -Dcom.sun.management.jmxremote.ssl=false
  -Dcom.sun.management.jmxremote.authenticate=false
  1. If you require authorization, add and change this:
      -Dcom.sun.management.jmxremote.authenticate=true
      -Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password
      -Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access
  2. edit the access authorization file $CATALINA_BASE/conf/jmxremote.access:
    monitorRole readonly
    controlRole readwrite
  3. edit the password file $CATALINA_BASE/conf/jmxremote.password:
    monitorRole tomcat
    controlRole tomcat
    Tip: The password file should be read-only and only accessible by the operating system user Tomcat is running as.

Note: The JSR 160 JMX-Adaptor opens a second data channel on a random port. That is a problem when you have a local firewall installed. To fix it, configure a JmxRemoteLifecycleListener, as described in listeners documentation.

Manage Tomcat with JMX remote Ant Tasks

To simplify JMX usage with Ant 1.6.x, a set of tasks is provided that may be used with antlib.

antlib: Copy your catalina-ant.jar from $CATALINA_HOME/lib to $ANT_HOME/lib.

The following example shows the JMX Accessor usage:
Note: The name attribute value was wrapped here to be more readable. It has to be all on the same line, without spaces.

<project name="Catalina Ant JMX"
      xmlns:jmx="antlib:org.apache.catalina.ant.jmx"
      default="state"
      basedir=".">
  <property name="jmx.server.name" value="localhost" />
  <property name="jmx.server.port" value="9012" />
  <property name="cluster.server.address" value="192.168.1.75" />
  <property name="cluster.server.port" value="9025" />

  <target name="state" description="Show JMX Cluster state">
    <jmx:open
      host="${jmx.server.name}"
      port="${jmx.server.port}"
      username="controlRole"
      password="tomcat"/>
    <jmx:get
      name=
"Catalina:type=IDataSender,host=localhost,
senderAddress=${cluster.server.address},senderPort=${cluster.server.port}"
      attribute="connected"
      resultproperty="IDataSender.backup.connected"
      echo="false"
    />
    <jmx:get
      name="Catalina:type=ClusterSender,host=localhost"
      attribute="senderObjectNames"
      resultproperty="senderObjectNames"
      echo="false"
    />
    <!-- get current maxActiveSession from ClusterTest application
       echo it to Ant output and store at
       property <em>clustertest.maxActiveSessions.orginal</em>
    -->
    <jmx:get
      name="Catalina:type=Manager,context=/ClusterTest,host=localhost"
      attribute="maxActiveSessions"
      resultproperty="clustertest.maxActiveSessions.orginal"
      echo="true"
    />
    <!-- set maxActiveSession to 100
    -->
    <jmx:set
      name="Catalina:type=Manager,context=/ClusterTest,host=localhost"
      attribute="maxActiveSessions"
      value="100"
      type="int"
    />
    <!-- get all sessions and split result as delimiter <em>SPACE</em> for easy
       access all session ids directly with Ant property sessions.[0..n].
    -->
    <jmx:invoke
      name="Catalina:type=Manager,context=/ClusterTest,host=localhost"
      operation="listSessionIds"
      resultproperty="sessions"
      echo="false"
      delimiter=" "
    />
    <!-- Access session attribute <em>Hello</em> from first session.
    -->
    <jmx:invoke
      name="Catalina:type=Manager,context=/ClusterTest,host=localhost"
      operation="getSessionAttribute"
      resultproperty="Hello"
      echo="false"
    >
      <arg value="${sessions.0}"/>
      <arg value="Hello"/>
    </jmx:invoke>
    <!-- Query for all application manager.of the server from all hosts
       and bind all attributes from all found manager MBeans.
    -->
    <jmx:query
      name="Catalina:type=Manager,*"
      resultproperty="manager"
      echo="true"
      attributebinding="true"
    />
    <!-- echo the create properties -->
<echo>
senderObjectNames: ${senderObjectNames.0}
IDataSender.backup.connected: ${IDataSender.backup.connected}
session: ${sessions.0}
manager.length: ${manager.length}
manager.0.name: ${manager.0.name}
manager.1.name: ${manager.1.name}
hello: ${Hello}
manager.ClusterTest.0.name: ${manager.ClusterTest.0.name}
manager.ClusterTest.0.activeSessions: ${manager.ClusterTest.0.activeSessions}
manager.ClusterTest.0.counterSend_EVT_SESSION_EXPIRED:
 ${manager.ClusterTest.0.counterSend_EVT_SESSION_EXPIRED}
manager.ClusterTest.0.counterSend_EVT_GET_ALL_SESSIONS:
 ${manager.ClusterTest.0.counterSend_EVT_GET_ALL_SESSIONS}
</echo>

  </target>

</project>

import: Import the JMX Accessor Project with <import file="${CATALINA.HOME}/bin/catalina-tasks.xml" /> and reference the tasks with jmxOpen, jmxSet, jmxGet, jmxQuery, jmxInvoke, jmxEquals and jmxCondition.

JMXAccessorOpenTask - JMX open connection task

List of Attributes

Attribute Description Default value
url Set JMX connection URL - service:jmx:rmi:///jndi/rmi://localhost:8050/jmxrmi
host Set the host, shortcut the very long URL syntax. localhost
port Set the remote connection port 8050
username remote JMX connection user name.
password remote JMX connection password.
ref Name of the internal connection reference. With this attribute you can configure more the one connection inside the same Ant project. jmx.server
echo Echo the command usage (for access analysis or debugging) false
if Only execute if a property of the given name exists in the current project.
unless Only execute if a property of the given name not exists in the current project.

Example to open a new JMX connection

  <jmx:open
    host="${jmx.server.name}"
    port="${jmx.server.port}"
  />

Example to open a JMX connection from URL, with authorization and store at other reference

  <jmx:open
    url="service:jmx:rmi:///jndi/rmi://localhost:9024/jmxrmi"
    ref="jmx.server.9024"
    username="controlRole"
    password="tomcat"
  />

Example to open a JMX connection from URL, with authorization and store at other reference, but only when property jmx.