Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Fix formatting and links.

...

Download the source bundle or grab the source files from Tomcat Git repository (at GitHub).

The docs are in the webapps/docs subdirectory. They are in XML format and get processed into the HTML documentation as part of the Tomcat release.

...

The best way is to use jsvc, available as part of the commons-daemon Apache Commons Daemon project.

...

One Other way is to put Apache httpd with mod_jk before your Tomcat servers, and use ports >=1024 in the Tomcat(s). However, if httpd is not needed for some other reason, this is the most inefficient approach.

...

Another An other method is to use SetUID scripts (assuming you have the capability) to do this. Here's how I do it.

...

There are some other methods available, like using ServletContext.getContextPath() to get the context name of your web application and locate some resources accordingly, or to define <context-param> elements in WEB-INF/web.xml file of your web application and then set the values for them in Tomcat context file (META-INF/context.xml). See https://tomcat.apache.org/tomcat-79.0-doc/config/context.html .

How do I configure Tomcat Connectors?

...

How do I enable Server Side Includes (SSI)?

See http https://tomcat.apache.org/tomcat-7.0-doc/ssi-howto.html

How do I install the Administration web app?

...

  1. Add a line to your c:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\tomcat-users.xml file so that you have a user who has admin role. For example, add this line just before the last line (containing </tomcat-users>) of the file:
    • <user username="admin" password="makesomethingup" roles="admin,manager"/>
  2. Restart Tomcat.
  3. Now when you visit _http://localhost:8080/admin_ you should see a page that asks for a user name and password. If you still see the "no longer loaded" error message in your browser, you must either force a full reload of the web page (in Firefox, hold down Shift key while clicking on the Reload button) or just restart your browser completely.

...

If you start Tomcat by using the standard script files (such as CATALINA_HOME/bin/catalina.bat or catalina.sh), this can be done by setting CATALINA_OPTS environment variable. The recommended way to do so is to create a setenv.bat or setenv.sh file, — read RUNNING.txt for details.

Let say you want to increase it to 256 MB (as you required but make sure you have enough amount of physical memory/RAM and for 32bit system, use no more than 1.0-1.1 GB heap space size ). Set the CATALINA_OPTS to the value of -Xms256m -Xmx256m. In some cases it is better to set slightly lower size for -Xms.

...

For other parameters, look at the following pages:

If you are running Tomcat as a Windows service, then environment variables and setenv.bat script have no effect. The relevant settings for the service wrapper application are stored in the Windows registry. They can be edited via Configuration application (tomcat<N>w.exe). See "Java" tab in the configuration dialog. The{{-Xms}} and -Xmx options are configured in fields named "Initial memory pool" and "Maximum memory pool". Other options can be added to "Java Options" field as if they were specified on the command line of java executable.

...

Congratulations. You have created and tested a first web application (traditionally called "mywebapp"), users can access it via the URL "http://myhost.company.com/mywebapp". You are very proud and satisfied. But now, how do you change the setup, so that "mywebapp" gets called when the user enters the URL "http://myhost.company.com" ?

...

The

...

pages

...

and

...

code

...

of

...

your

...

"mywebapp"

...

application

...

currently

...

reside

...

in

...

(CATALINA_BASE)/webapps/mywebapp/.

...

In

...

a

...

standard

...

Tomcat

...

installation,

...

you

...

will

...

notice

...

that

...

under

...

the

...

same

...

directory

...

(CATALINA_BASE)/webapps/,

...

there

...

is

...

a

...

directory

...

called

...

ROOT

...

(the

...

capitals

...

are

...

important,

...

even

...

under

...

Windows).

...

That

...

is

...

the

...

residence

...

of

...

the

...

current

...

Tomcat

...

default

...

application,

...

the

...

one

...

that

...

is

...

called

...

right

...

now

...

when

...

a

...

user

...

calls

...

up

...

"http://myhost.company.com

...

[:port

...

]".

...

The

...

trick

...

is

...

to

...

put

...

your

...

application

...

in

...

its

...

place.

First stop Tomcat.
Then before you replace the current default application, it may be a good idea to make a copy of it somewhere else.
Then delete everything under the ROOT directory, and move everything that was previously under the (CATALINA_BASE)/webapps/mywebapp/ directory, toward this (CATALINA_BASE)/webapps/ROOT directory. In other words, what was previously .../mywebapp/WEB-INF should now be .../ROOT/WEB-INF (and not .../ROOT/mywebapp/WEB-INF).

...

For more information about this topic in general, consult this page : "Configuration Reference / Context"

Addendum 2: If for some reason you want another method..

If, for some reason, you do not want to deploy your application under the CATALINA_BASE/webapps/ROOT subdirectory, or you do not want to name your war-file "ROOT.war", then read on. But you should first read this : "Configuration Reference / Context" and make sure you understand the implications.

...

Here are the three most popular ways::

  • Use a classloader's getResource() method to get an url to the properties file and load it into the Properties. The properties file must be located within the webapp classpath (i.e. either WEB-INF/classes/... or in a jar in WEB-INF/lib/).

A challenge is to get the classloader when you are in a static initializer:

No Format

  public class Config {
     private static java.util.Properties prop = new java.util.Properties();
     private static loadProperties() {
          // get class loader
          ClassLoader loader = Config.class.getClassLoader();
          if(loader==null)
            loader = ClassLoader.getSystemClassLoader();

          // assuming you want to load application.properties located in WEB-INF/classes/conf/
          String propFile = "conf/application.properties";
          java.net.URL url = loader.getResource(propFile);
          try{prop.load(url.openStream());}catch(Exception e){System.err.println("Could not load configuration file: " + propFile);}
     }

     //....
     // add your methods here. prop is filled with the content of conf/application.properties

     // load the properties when class is accessed
     static {
        loadProperties();
     }
  }

This method even works in a standalone java application. So it is my preferred way.

...

  • Use a ResourceBundle. See the Java docs for the specifics of how the ResourceBundle class works. Using this method, the properties file must go into the WEB-INF/classes directory or in a jar file contained in the WEB-INF/lib directory.
  • Another way is to use the method getResourceAsStream() from the ServletContext class. This allows you update the file without having to reload the webapp as required by the first method. Here is an example code snippet, without any error trapping:
No Format

// Assuming you are in a Servlet extending HttpServlet
// This will look for a file called "/more/cowbell.properties" relative
// to your servlet Root Context
InputStream is = getServletContext().getResourceAsStream("/more/cowbell.properties");
Properties  p  = new Properties();
p.load(is);
is.close();

...

You cannot share sessions directly across web apps, as that would be a violation of the Servlet Specification. There are workarounds, including using a singleton class loaded from the common classloader repository to hold shared information, or putting some of this shared information in a database or another data store. Some of these approaches have been discussed on the tomcat-user mailing list, whose archives you should search for more information.

...

Here's what you would like to do, but it throws ClassCastException:

No Format

MyPrincipal p = request.getUserPrincipal();
String emailAddress = p.getEmailAddress();

Here are 4 ways you might get around the classloader boundary:

1) Reflection

No Format

Principal p = request.getUserPrincipal();
String emailAddress = p.getClass().getMethod("getEmailAddress", null).invoke(p, null);

...

Rather than move the implementing custom classes up, you could define interfaces for your customs classes, and put the interfaces in the common directory. You're code would look like this:

No Format

public interface MyPrincipalInterface extends java.security.Principal {
  public String getEmailAddress();
}

public class MyPrincipal implements MyPrincipalInterface {
...
  public String getEmailAddress() {
    return emailAddress;
  }
}

public class MyServlet implements Servlet {
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    MyPrincipalInterface p = (MyPrincipalInterface)request.getUserPrincipal();
    String emailAddress = p.getEmailAddress();
...
}

...

4) Serializing / Deserializing

...

You

...

might

...

want

...

to

...

try

...

serializing

...

the

...

response

...

of

...

request.getUserPrincipal()

...

and

...

deserialize

...

it

...

to

...

an

...

instance

...

of

...

webapp's MyPrincipal.

How do I get direct access to a Tomcat Realm?

Credit: This code is from a post by Yoav Shapira http https://www.yoavshapira.com/ in the user list

Sometimes access directly into the Tomcat realm object is needed; to do, this the following code can be used. Be aware, however, that by using this, your application is relying on a Tomcat extension and is therefore non-standard.

Note that in order for this to work the Context of the web application in question needs to have its privileged attribute set to "true", otherwise web apps do not have access to the Tomcat classes.

No Format

Server server = ServerFactory.getServer();
//Note, this assumes the Container is "Catalina"
Service service = server.findService("Catalina");
Engine engine = (Engine) service.getContainer();
Host host = (Host) engine.findChild(engine.getDefaultHost());
//Note, this assumes your context is "myContext"
Context context = (Context) host.findChild("myContext");
Realm realm = context.getRealm();

Warning: The above recipe on how to obtain a Context for a web application is a bit obsolete and does not work in Tomcat 7 and later (as Server is no longer a singleton). There are other ways to achieve that. An easy one is to add a Valve or Listener to a context, as those classes have access to Tomcat internals. There may be other ways mentioned in the archives of the users mailing list.

How do I redirect System.out and System.err to my web page?

I have met a situation where I needed to redirect a portion of standard ouput (System.out, STDOUT) and standard error (System.err, STDERR) to my web page instead of a log file. An example of such an application is a compiler research platform that our resarch team is putting online for anybody to be able to quickly compile-test their programs on line. Naturally, the compilers dump some of their stuff to STDERR or STDOUT and they are not web application .jar. Thus, I needed badly these streams related to the compiler output to be redirected to my web editor interface. Having found no easy instructions on how to do that lead me writing up this quick HOWTO. The HOWTO is based on Servlets, but similar arrangements can be done for JSPs. The below example shows the essentials, with most non-essentials removed.

No Format

public class WebEditor
 extends HttpServlet
{
 ...
        public void doGet
        (
                HttpServletRequest poHTTPRequest,
                HttpServletResponse poHTTPResponse
        )
        throws IOException, ServletException
        {
                poHTTPResponse.setContentType("text/html");

                ServletOutputStream out = poHTTPResponse.getOutputStream();

                out.println("<html>");
                out.println("<body>");
                out.println("<head>");
                out.println("<title>WebEditor Test $Revision: 1.6 $</title>");
                out.println("</head>");
                out.println("<body>");
                out.println("<h3>WebEditor Test $Revision: 1.6 $</h3>");
                out.println("<hr />");

                // Backup the streams
                PrintStream oStdOutBackup = System.out;
                PrintStream oStdErrBackup = System.err;

                try {

                  // Redired STDOUT and STDERR to the ServletOutputStream
                  System.setOut(new PrintStream(out));
                  System.setErr(new PrintStream(out));

                  try {
                        // ... call compiler here that produces
                        // tons of STDOUT/STDERR messages ...
                  } catch(Exception e) {
                        out.println(e);
                  }

                } finally {

                  // Restore original STDOUT and STDERR
                  System.setOut(oStdOutBackup);
                  System.setErr(oStdErrBackup);

                }

                out.println("<hr />");
                out.println("</body>");
                out.println("</html>");
        }
}

...

Basically, this works just as described in httphttps://tomcat.apache.org/tomcat-79.0-doc/jndi-resources-howto.html: Within your application, you are using the standard JNDI and JMS API calls. In web.xml (the container independent application descriptor), you specify resource references (stub resources). And in context.xml (the container specific application descriptor), you are actually configuring the JMS connection.

More to the point. Here's some example code, which might be added to a Servlet. The example is sending a message to an MQ server:

No Format

    import javax.jms.Queue;
    import javax.jms.QueueConnection;
    import javax.jms.QueueConnectionFactory;
    import javax.jms.QueueSender;
    import javax.jms.QueueSession;
    import javax.jms.Session;
    import javax.jms.TextMessage;
    import javax.naming.Context;
    import javax.naming.InitialContext;

    Context ctx = (Context) new InitialContext().lookup("java:comp/env");
    QueueConnectionFactory qcf = (QueueConnectionFactory) ctx.lookup("jms/MyQCF");
    QueueConnection qc = qcf.createQueueConnection();
    Queue q = (Queue) ctx.lookup("jms/MyQ");
    QueueSession qs = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    TextMessage tm = qs.createTextMessage();
    tm.setText("Hi, there!");
    QueueSender sender = qc.createSender();
    sender.send(tm);
    sender.close();
    qs.close();
    qc.close();

...

  1. I have intentionally omitted proper resource handling. For example, one ought to ensure that qc.close() is always called by using a try { .. } finally { ..} block.

...

  1. The code contains absolutely no references to com.ibm.mq*.jar.

...

  1. There are only two items, which need configuration: "jms/MyQCF", and "jms/MyQ". We'll find them again in web.xml, and context.xml.

We have now written the code. Additionally, our web application needs the following files, and directories:

No Format

    +--META-INF
    |  +--- context.xml
    +--WEB-INF
       +--- web.xml
       +--- lib
            +--- com.ibm.mq.jar
            +--- com.ibm.mqjms.jar
            +--- connector.jar
            +--- dhbcore.jar
            +--- geronimo-j2ee-management_1.0_spec-1.0.jar
            +--- geronimo-jms_1.1_spec-1.0.jar

The application descriptor web.xml looks just the same as usual, with the exception of the following lines:

No Format

  <resource-env-ref>
    <resource-env-ref-name>jms/MyQCF</resource-env-ref-name>
    <resource-env-ref-type>javax.jms.QueueConnectionFactory</resource-env-ref-type>
  </resource-env-ref>

  <resource-env-ref>
    <resource-env-ref-name>jms/MyQ</resource-env-ref-name>
    <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
  </resource-env-ref>

This is simply telling, that the items "jms/MyQCF", and "jms/MyQ" exist, and are instances of QueueConnectionFactory, and Queue, respectively. The actual configuration is in context.xml:

No Format

   <Resource
      name="jms/MyQCF"
      auth="Container"
      type="com.ibm.mq.jms.MQQueueConnectionFactory"
      factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
      description="JMS Queue Connection Factory for sending messages"
      HOST="<mymqserver>"
      PORT="1414"
      CHAN="<mychannel>"
      TRAN="1"
      QMGR="<myqueuemanager>"/>
   <Resource
      name="jms/MyQ"
      auth="Container"
      type="com.ibm.mq.jms.MQQueue"
      factory="com.ibm.mq.jms.MQQueueFactory"
      description="JMS Queue for receiving messages from Dialog"
      QU="<myqueue>"/>

Basically, you just have to enter your values for <myqserver> (the WebSphere MQ servers host name), <mychannel> (the channel name), <myqueuemanager> (the queue manager name), and <myqueue> (the queue name). Both these values, the associated names (HOST, PORT, CHAN, ...), and their collection is truly MQ specific. For example, with ActiveMQ, you typically have a broker URL, and a broker name, rather than HOST, PORT, CHAN, ...

The main thing to know (and the reason why I am writing this, because it took me some hours to find out): How do I know the property names, their meaning, and possible values? Well, there is an excellent manual, called "WebSphere MQ Using Java". It should be easy to find by entering the title into Google. The manual contains a section, called "Administering JMS objects", which describes the objects being configured in JNDI. But the most important part is the subsection on "Properties", which contains all the required details.

How do I use DataSources with Tomcat?

See UsingDataSources

...

See TomcatHibernate

How do I use DataSourceRealms for authentication and authorization?

...

Thus, if you have JNI code that follows the convention of including a static initilaizer like this:

No Format

class FooWrapper {
    static {
        System.loadLibrary("foo");
    }

    native void doFoo();
  }

then both this class and the shared library should be placed in the $CATALINA_HOME/shared/lib directory.

...

The symptom of this problem that I encountered looked something like this -

No Format

java.lang.UnsatisfiedLinkError: Native Library WEB-INF/lib/libfoo.so already loaded in another classloader
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1525)

...

  • If you have not already done so begin by creating a new Tomcat context for your application. Navigate to TOMCAT_HOME\conf\Catalina\localhost and create a new file, say, myapp.xml. This will become part of your url, so to access your app you'll have to type *http://localhost:8080/myapp*.
  • Enter the following in myapp.xml:
No Format

<Context docBase="c:/workspace/myapp/WebRoot" />
  • This assumes you have a web application containing WEB-INF in c:/workspace/myapp/WebRoot
  • Create two environment variables:
No Format

C:\>set JPDA_ADDRESS=1044
C:\>set JPDA_TRANSPORT=dt_socket
  • Now, you can launch Tomcat with these debug options:
No Format

TOMCAT_HOME\bin\>catalina jpda start
  • Use your IDE to connect to Tomcat through port 1044

See also: FAQ/Developing

How do I debug a Tomcat application when Tomcat is run as a Windows service ?

...

  • Launch a command prompt
  • Set the proper CATALINA_HOME environment variable: pointing to tomcat home
  • Run the following command:
No Format

%CATALINA_HOME%\bin\tomcat6w.exe //ES//tomcat6
  • Select the Java tab in the properties dialog box,
  • Add the following two lines to the Java Options text box:
No Format

-Xdebug
-Xrunjdwp:transport=dt_socket,address=127.0.0.1:1044,server=y,suspend=n

...

For IntelliJ IDEA you choose a remote debug target and set transport to "socket" and mode to "attach" , then you specify the host (127.0.0.1) and port (1044)

See also: FAQ/Developing

How do I check whether Tomcat is UP or DOWN? There is no status command

...

Here is my code to do this. Consider it public domain and use it as you see fit. Tomcat makes a note of this connection with something like this on the console.

No Format

May 1, 2007 5:10:35 PM org.apache.catalina.core.StandardServer await
WARNING: StandardServer.await: Invalid command '' received

Ideally this should be incorporated into org.apache.catalina.util.ServerInfo by some committer. In addition to the shutdown command they should add commands like status (UP or DOWN) and uptime in the await method of org.apache.catalina.core.StandardServer

No Format

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

/**
 * Check to see if Tomcat is UP/DOWN.
 *
 * This parses the server.xml file for the Tomcat admin port and see if
 * we can connect to it. If we can, then the Tomcat is UP otherwise it
 * is DOWN
 *
 * It is invoked as follows:
 *    java -Dcatalina.base=c:/tomcat-6.0.10 CatalinaStatus
 *
 * It can also (optionally) shutdown the Tomcat by adding the shutdown
 * command line parameter as follows:
 *
 *    java -Dcatalina.base=c:/tomcat-6.0.10 CatalinaStatus shutdown
 *
 * @author Shiraz Kanga <skanga at yahoo.com>
 */
public class CatalinaStatus
{
  /**
   * Pathname to the server configuration file.
   */
  protected static String configFile = "conf/server.xml";
  protected static String serverShutdown;
  protected static int serverPort;

  /**
   * The application main program.
   *
   * @param args Command line arguments
   */
  public static void main (String args[])
  {
    Document configDom = getXmlDom (configFile ());
    parseDocument (configDom);
    // System.out.println ("Catalina.serverPort: " + serverPort);
    // System.out.println ("Catalina.serverShutdown: " + serverShutdown);

    // Stop the existing server
    try
    {
      Socket localSocket = new Socket ("127.0.0.1", serverPort);
      System.err.println ("Server status:  UP");
      if ((args.length > 0) && (args[0].equalsIgnoreCase ("shutdown")))
      {
        System.out.println ("Tomcat shutdown initiated" );
        doShutdown (localSocket);
      }

      localSocket.close ();
    }
    catch (IOException e)
    {
      System.err.println ("Server status:  DOWN");
      System.exit(1);
    }
  }

  /**
   * Return a File object representing our configuration file.
   */
  protected static File configFile ()
  {
    File confFile = new File (configFile);
    if (!confFile.isAbsolute())
      confFile = new File (System.getProperty ("catalina.base"), configFile);
    return (confFile);
  }

  /**
   * Parses an XML file and returns a DOM document.
   */
  public static Document getXmlDom (File fileName)
  {
    try
    {
      // Create a builder factory
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance ();

      // Create the builder and parse the file
      Document doc = factory.newDocumentBuilder ().parse (fileName);
      return doc;
    }
    catch (SAXException e)
    {
      // A parsing error occurred; the xml input is not valid
      e.printStackTrace ();
    }
    catch (ParserConfigurationException e)
    {
      e.printStackTrace ();
    }
    catch (IOException e)
    {
      e.printStackTrace ();
    }
    return null;
  }

  /**
   * Extract the server port & shutdown command from the DOM
   */
  private static void parseDocument (Document configDom)
  {
    //get the root element which is Server Eg: <Server port="8005" shutdown="SHUTDOWN">

    Element docEle = configDom.getDocumentElement ();
    serverPort = Integer.parseInt (docEle.getAttribute ("port"));
    serverShutdown = docEle.getAttribute ("shutdown");
  }

  /**
   * Send the shutdown command to the server
   */
  private static void doShutdown (Socket localSocket)
  {
    try
    {
      OutputStream outStream = localSocket.getOutputStream ();

      for (int i = 0; i < serverShutdown.length (); i++)
        outStream.write (serverShutdown.charAt (i));
      outStream.flush ();
      outStream.close ();
    }
    catch (IOException e)
    {
      System.out.println ("ERROR: I/O Exception during server shutdown.");
      e.printStackTrace ();
    }
  }
}

...

Oracle JDK (not the JRE) (formerly Sun JDK) since version 1.6 (and since 1.4 on *nix systems) ships with a program called jstack (or jstack.exe on Microsoft Windows) which will give you a thread dump on standard output. Redirect the output into a file and you have your thread dump. You will need the process id ("pid") of the process to dump. Use of the program jps (jps.exe on Microsoft Windows) can help you determine the pid of a specific Java process.

See Tools page in JDK documentation for usage reference.

...

If you are running on Microsoft Windows

You can try to use SendSignal, developed specifically for this purpose. Make sure you read the comments for certain sitautions (e.g. running as a service, RDP connections, etc.). http://www.latenighthacking.com/projects/2003/sendSignal/

...

If the monitoring application is not running, you can start it manually. The command is

Tomcat8wTomcat9w.exe //MS//

or

Tomcat8wTomcat9w.exe //MS//servicename

If you installed Tomcat with an "exe" installer, "Apache Tomcat version servicename" group in the Windows menu has shortcut "Monitor Tomcat" that starts the monitoring application.

For details, see Windows service page in Tomcat documentation.

If you have Tomcat running in a console

...

Tomcat Manager web application starting with Tomcat 7.0.58 / 8.0.0 supports a command that outputs a thread dump. (Tomcat 8 9 documentation, BZ 57261)

StuckThreadDetectionValve valve logs stacktraces of request processing threads that are busy for longer than configured time limit. It is available starting with Tomcat 6.0.36 / 7.0.14. (Tomcat 8 9 documentation)

...

How do I read a Java thread dump ?

...

One such tool is the Thread Dump Viewer (TDV), which you can find here: httphttps://tdv.sourceforge.net/projects/tdv/. It is a bit old (last release: 2007) but it can be somewhat helpful.

How do I obtain a heap dump?

See Getting a Heap Dump on the help pages of Eclipse Memory Analysis Tool.

How do I add my own custom MBean to monitor my application within Tomcat 6?

First of all, you can read this great tutorial from Christopher Blunck ( chris@wxnet.org ). I will just add my comments and improvements.

...

1. Start your Tomcat and check that you have access to http://localhost:8080/manager/jmxproxy/.

It means that JMX is enabled on your Tomcat configuration (if not, check if the following line is in your /conf/server.xml file:
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />

...


Otherwise, check the Tomcat documentation to activate it). Let this page opened to check further if your custom

...

MBean is detected by Tomcat.

2. Build your custom MBean by following the Christopher Blunck's example:

...

In this implementation, firstly notice the ObjectName representing the MBean (in the constructor):
name = new ObjectName("Application:Name=Server,Type=Server");
Do not hesitate to change the domain name (the first parameter) by your own to easily find your MBean reference in the http://localhost:8080/manager/jmxproxy page.

Secondly, take a look at your MBean constructor:

  1. First step is to get a reference to the Tomcat's MBeanServer with MBeanServer server = getServer();.

...

  1. The getServer() method returns the first MBean server in the list of MBean servers registered in JVM, which is the one used by Tomcat.

In my application architecture, I placed the 2 MBeans files (the interface and its implementation) in a particular package (I don't think its compulsary but definitely more aesthetic). Compile those one in a jar archive and place it in the Tomcat's library folder (/lib).

3. Build your ContextListener: According to the Tomcat's documentation, a Listener is a a component that performs actions when specific events occur, usually Tomcat starting or Tomcat stopping.. We need to instantiate and load our MBean at Tomcat's start. So we build a ContextListener.java file which is placed wherever you want in your project architecture:

No Format

package '''org.bonitasoft.context''';

/**
 * @author Christophe Havard
 *
 */

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.bonitasoft.mbeans.Server;

public final class ContextListener  implements ServletContextListener {

  public void contextInitialized(ServletContextEvent event) {
    Server mbean = new Server();
  }

  public void contextDestroyed(ServletContextEvent event) { }

}

...

Then, you have to modify your WEB-INF/web.xml file to make Tomcat execute your ContextListener.

No Format

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  <display-name>My Web Application</display-name>
 '''''bla bla bla...'''''
  <listener>
    <listener-class>org.bonitasoft.context.ContextListener</listener-class>
  </listener>
</web-app>

...

5. The configuration should be over. You should have done those the following operations:

  1. Build your MBean,

...

  1. Compile it and place the .jar archive in the Tomcat's /lib folder,

...

  1. Build your ContextListener.java,

...

  1. Add a reference to your ContextListener inside your WEB-INF/web.xml file

You can try to run your project. Open the http://localhost:8080/manager/jmxproxy page and find your custom MBean (with a simple ctrl+f). You can see its domain, name, type and its attributes and methods.

You can now use this MBean in your application by getting a reference to the Tomcat's MBean server:

No Format

MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
//call operations with invoke(...) and attributes with getAttributes(...)

Do not hesitate to check the ManagementFactory class javadoc.CategoryFAQ