Deploying GWT Applications in SpringSource dm Server - Part 2

Engineering | Ben Corrie | November 24, 2008 | ...

Introduction

This is the second in a series of three blogs describing a step-by-step approach to building and deploying GWT applications in the SpringSource dm Server™. The first blog looked at the process of creating a simple WAR file from a sample GWT application. This next blog will look at turning the WAR file we created in Part 1 into a "Shared Libraries" WAR. This means that we are going to externalize the GWT dependencies of our application into an OSGi bundle so that it can be shared by any number of GWT applications. You can think of it as extending our dm Server with GWT remoting capabilities.

As mentioned in Part 1, I am not using the Spring Framework in this second blog posting, rather I am focusing on the SpringSource dm Server™ and SpringSource Tool Suite to deploy "pure" GWT.

Please also see Part 1 for the background to the GWT StockWatcher sample and the software I'm using.

Quick Catch Up

In Part 1, we built the GWT StockWatcher sample application from scratch as an Eclipse project and then generated the code into a Dynamic Web project which we then deployed into dm Server. Finally, we exported the Dynamic Web project into a WAR file and deployed it outside of STS.

The step by step approach described here will build on what we did in Part 1, rather than start over. The only thing we did in Part 1 that we're now going to change is to remove the explicit dependency on the gwt-servlet.jar library.

Step 1: Turn our GWT dependency into a OSGi bundle

Firstly, a little more background. The whole concept of the "Shared Libraries" approach is to create a map of dependencies within the dm Server using explicit imports and exports between OSGi bundles. With a small WAR such as our StockWatcher sample, this is mostly just an interesting academic exercise. However, given that many commercial web projects ship in large WAR files which are packaged with tens or even hundreds of dependent jar files, breaking out these dependencies into shareable resources not only makes sense from a footprint perspective, but also makes the packaging, versioning and maintenance of the applications significantly less painful.

The good news is that much of work to create these dependencies has already been done for you. The SpringSource Enterprise Bundle Repository contains "bundlized" versions of most common libraries. However, at the time of writing, our GWT dependency is an example of a library that you have to turn into a bundle…

Diagnosing OSGi uses conflicts

Engineering | Rob Harrop | November 22, 2008 | ...

In his recent blog entry, Glyn provided an introduction to the OSGi “uses” directive. In this blog, I want to dig a little deeper into the causes of uses constraint violations and present some tips for diagnosing uses problems in your applications.

For most of the examples I’m going to be using raw Equinox and not dm Server. The reason for this is that uses constraints are not specific to dm Server but are relevant to all OSGi users. At the end of this blog, I’ll demonstrate some of the smart constraint failure diagnostics built into dm Server.

Dependent Constraint Mismatch

The most common cause of uses violations is a mismatch between one or more of the dependent constraints. As an example of this consider the three manifests below:

Manifest-Version: 1.0
Bundle-Name: Spring Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: spring
Bundle-Version: 2.5.5
Export-Package: spring.orm.hibernate;version="2.5.5";uses:="eclipselink"
Import-Package: eclipselink;version="[1.0, 2.0)"

Manifest-Version: 1.0
Bundle-Name: EclipseLink 1 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: eclipselink
Bundle-Version: 1
Export-Package: eclipselink;version="1.0.0"

Manifest-Version: 1.0
Bundle-Name: EclipseLink 2 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: eclipselink
Bundle-Version: 2
Export-Package: eclipselink;version="2.0.0"

Here you can see a spring bundle and two eclipselink bundles. Obviously, these are not the real bundles. The spring bundle has an import for package eclipselink in the range [1.0, 2.0). Clearly, only the eclipselink_1 bundle can satisfy this constraint. Now, consider these manifests from two different applications:

Manifest-Version: 1.0
Bundle-Name: App1 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: app1
Bundle-Version: 1.0.0
Import-Package: spring.orm.hibernate,eclipselink;version="[1.0, 1.0]"

Manifest-Version: 1.0
Bundle-Name: App2 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: app2
Bundle-Version: 1.0.0
Import-Package: spring.orm.hibernate,eclipselink;version="[2.0, 2.0]"

Here we can see that app1 imports eclipselink in range [1.0, 1.0] and app2 imports eclipselink in range [2.0, 2.0]. If I install these bundles into Equinox and then attempt to start the app bundles, the console shows something like this:

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
2       RESOLVED    spring_2.5.5
3       RESOLVED    eclipselink_1.0.0
4       RESOLVED    eclipselink_2.0.0
5       ACTIVE      app1_1.0.0
6       INSTALLED   app2_1.0.0

Here we can see that the spring and eclipselink bundles are all resolved. The app1 bundle has started, but the app2 bundle won’t start. To find out why we can use the diag command:

osgi> diag app2
file:/Users/robharrop/dev/resdiag/uses/app2/bin [6]
  Package uses conflict: Import-Package: spring.orm.hibernate; version="0.0.0"

Here we can see that the app2 bundle can’t resolve because there is a package uses conflict for its import of spring.orm.hibernate. This means that the import in app2 for spring.orm.hibernate cannot be satisfied because one of its other imports conflicts with a uses constraint on the bundle that could supply spring.orm.hibernate - in this case the spring bundle.

The first step in diagnosing this is to find out the possible suppliers of the spring.orm.hibernate bundle. We know from our use case that the only possible supplier is the spring bundle, but if you don’t know the suppliers you can find them using the packages command:

osgi> packages spring.orm.hibernate
spring.orm.hibernate; version="2.5.5"<file:/Users/robharrop/dev/resdiag/uses/spring/bin [2]>
  file:/Users/robharrop/dev/resdiag/uses/app1/bin [5] imports

This shows us that the spring.orm.hibernate package is exported by bundle 2. With this knowledge we can find out which packages are listed in the uses directive for the spring.orm.hibernate package in bundle 2:

osgi> headers 2
Bundle headers:
 Bundle-ManifestVersion = 2
 Bundle-Name = Spring Bundle
 Bundle-SymbolicName = spring
 Bundle-Version = 2.5.5
 Export-Package = spring.orm.hibernate;version="2.5.5";uses:="eclipselink"
 Import-Package = eclipselink;version="[1.0, 2.0)"
 Manifest-Version = 1.0

Here we can see that the only package in the uses is the eclipselink package so that must be the culprit. Indeed, we can see the Spring bundle requires eclipselink in the range [1.0, 2.0) whereas app2 requires eclipselink in range [2.0, 2.0] - these thwo ranges are disjoint, meaning that app2 cannot wire to the same version of eclipselink as the spring bundle.

In the case where the uses list is long, you can narrow down the possible violations by finding out which of the listed packages have more than one supplier. There must always be more than one supplier for you to see a uses constraint violation.

Version mismatch is not the only cause of dependent constraint mismatch. The constraints might not match because of attributes as well as version.

Install Order Problems

If we revisit the previous example and change the manifest of the spring bundle so that it can accept version 2.0 of the eclipselink package and relax the range on app1 so it can accept anything over 1.0 we should be able to fix the problem:

Manifest-Version: 1.0
Bundle-Name: Spring Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: spring
Bundle-Version: 2.5.5
Export-Package: spring.orm.hibernate;version="2.5.5";uses:="eclipselink"
Import-Package: eclipselink;version="[1.0, 2.0]"

Manifest-Version: 1.0
Bundle-Name: App1 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: app1
Bundle-Version: 1.0.0
Import-Package: spring.orm.hibernate,eclipselink;version="1.0"

Installing the bundles and starting the app bundles show that this change makes a big difference:

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
1       RESOLVED    spring_2.5.5
2       RESOLVED    eclipselink_1.0.0
3       RESOLVED    eclipselink_2.0.0
4       ACTIVE      app1_1.0.0
5       ACTIVE      app2_1.0.0

Now both app bundles can start. Unfortunately, there is a more subtle issue awaiting us. Depending on the installation order, this set of bundles might still fail to run together. To illustrate this, let’s install spring, eclipselink_1 and app1 as one transaction and start app1:

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
1       RESOLVED    spring_2.5.5
2       RESOLVED    eclipselink_1.0.0
3       ACTIVE      app1_1.0.0

Now, let’s install eclipselink_2 and app2:

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
1       RESOLVED    spring_2.5.5
2       RESOLVED    eclipselink_1.0.0
3       ACTIVE      app1_1.0.0
4       RESOLVED    eclipselink_2.0.0
5       INSTALLED   app2_1.0.0

The app2 bundle won’t start. The output from diag tells us why:

osgi> diag app2
file:/Users/robharrop/dev/resdiag/uses/app2/bin [5]
  Package uses conflict: Import-Package: spring.orm.hibernate; version="0.0.0"

The uses constraint is back. Running through the diagnosis steps identified in the previous section won’t help here because there are no dependent constraint mismatches - we know that because the first time around these bundles resolved just fine.

The issue here is one of resolution order. The bundles were installed and resolved in two distinct chunks. The first chunk included spring, eclipselink_1 and app1, the second eclipselink_2 and app2. When the first chunk is resolved (as a result of starting the app1 bundle), the spring bundle gets wired to the eclipselink_1 bundle for its import of the eclipselink package. This can be confirmed using the console:

osgi> bundle app1
file:/Users/robharrop/dev/resdiag/uses/app1/bin [3]
  Id=3, Status=ACTIVE      Data Root=/opt/springsource-dm-server-1.0.0.RELEASE/lib/configuration/org.eclipse.osgi/bundles/3/data
  No registered services.
  No services in use.
  No exported packages
  Imported packages
    spring.orm.hibernate; version="2.5.5"<file:/Users/robharrop/dev/resdiag/uses/spring/bin [1]>
    eclipselink; version="1.0.0"<file:/Users/robharrop/dev/resdiag/uses/eclipselink1/bin [2]>
  No fragment bundles
  Named class space
    app1; bundle-version="1.0.0"[provided]
  No required bundles

Notice that the imported package section shows that eclipselink version 1.0.0 is imported from the eclipselink_1 bundle. When the second chunk is installed, the app2 bundle cannot resolve because it requires eclipselink at version 2.0.0 but spring is already wired to eclipselink at version 1.0.0. When all the bundles are installed and resolved as one chunk, the OSGi resolver will attempt to satisfy all constraints, including making sure that the uses constraint on spring.orm.hibernate can be satisfied.

To fix this problem we don’t need to change our bundles. Instead, we can either reinstall the bundles in one chunk or we can trigger a refresh against the spring bundle - effectively asking OSGi to rerun the resolution process. Now that the eclipselink_2 bundle is installed we can expect this to have a different outcome:

osgi> refresh spring

osgi> ss

Framework is launched.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
1       RESOLVED    spring_2.5.5
2       RESOLVED    eclipselink_1.0.0
3       ACTIVE      app1_1.0.0
4       RESOLVED    eclipselink_2.0.0
5       ACTIVE      app2_1.0.0

osgi> bundle spring
file:/Users/robharrop/dev/resdiag/uses/spring/bin [1]
  Id=1, Status=RESOLVED    Data Root=/opt/springsource-dm-server-1.0.0.RELEASE/lib/configuration/org.eclipse.osgi/bundles/1/data
  No registered services.
  No services in use.
  Exported packages
    spring.orm.hibernate; version="2.5.5"[exported]
  Imported packages
    eclipselink; version="2.0.0"<file:/Users/robharrop/dev/resdiag/uses/eclipselink2/bin [4]>
  No fragment bundles
  Named class space
    spring; bundle-version="2.5.5"[provided]
  No required bundles

Notice that refreshing spring caused the app2 bundle to resolve. The wiring for the eclipselink package in the spring has changed to be satisfied by the export at version 2.0.0 from the eclipselink_2 bundle.

Uses constraints in dm Server

When you encounter a uses constraint violation in dm Server, we already attempt to perform some of the analysis steps for you, in particular identifying the possible dependent constraints that might be mismatched:

Could not satisfy constraints for bundle 'app2' at version '1.0.0'.
 Cannot resolve: app2
  Resolver report:
    Bundle: app2_1.0.0 - Uses Conflict: Import-Package: spring.orm.hibernate; version="0.0.0"
      Possible Supplier: spring_2.5.5 - Export-Package: spring.orm.hibernate; version="2.5.5"
        Possible Conflicts: eclipselink

Uses constraints are common in enterprise libraries, and manually diagnosing a failure can be a real nightmare. In particular, determining the possible conflicts can be extremely time-consuming when you have an exported package with 10 or more packages listed in its uses clause. For this reason, automated diagnosis is a must, and I hope to improve the diagnosis code in dm Server all the time so that dealing with common errors becomes trivial.

In the next release, we are planning to build diagnosis tools right into our dm Server Eclipse tools so that most of these problems will be automatically diagnosed by dm Server.

First Grails Release Under the SpringSource Banner

Engineering | Graeme Rocher | November 14, 2008 | ...

I'm pleased to announce the first release of Grails since the acquisition of G2One by SpringSource. Grails 1.0.4 includes a number of improvements as well as upgrades to key libraries that underpin Grails and can be downloaded from the Grails download page. More specifically Grails 1.0.4 ships with the latest Spring 2.5.6 release that came out a week or so ago.

Beyond the improvements there are a couple of interesting new features in this release. The first is the addition of a feature that better supports mapping of Hibernate user type definitions in GORM. You can now map custom user types…

More Weapons for the War on Complexity: SpringSource Acquires Groovy/Grails Leader

Engineering | Rod Johnson | November 11, 2008 | ...

I am delighted to announce that SpringSource has acquired G2One, the company behind Grails and Groovy.

Why?

I’m excited about this deal for many reasons.

Grails is a great fit with Spring and SpringSource technologies. Grails is built on Spring. It offers another route to adopt Spring, the de facto standard component model for enterprise Java. All the power of Spring (and Java) lies beneath the surface of every Grails based application—a key reason that Grails can scale to enterprise use, as well as a validation of Spring’s power and flexibility.

Like Spring, Grails is a technology that simplifies the lives of developers and makes them more productive. As our new tagline, Weapons for the war on Java complexity, reflects, simplification has always been core to what we’ve done as a company and as technologists…

Deploying GWT Applications in SpringSource dm Server - Part 1

Engineering | Ben Corrie | November 07, 2008 | ...

Introduction

This will be a series of 3 blogs describing a step-by-step approach to building and deploying GWT applications in the SpringSource dm Server™. The focus of the blogs will be as follows:
  1. Building and deploying the GWT StockWatcher sample app as a WAR file in dm Server, using the SpringSource Tool Suite to build it from scratch.
  2. Deploying with a "Shared Libraries" approach: How to remove the GWT dependencies from the WAR and deploy them as an OSGi bundle in dm Server.
  3. Deploying with a "Shared Services" approach: We convert the single WAR file into OSGi services which can be shared by other applications and hot-swapped out.
It is worth noting that I am not using the Spring Framework anywhere in these first two blogs. Integration between Spring and GWT is a subject in itself and I want to try to keep each blog as focused as possible. In the third blog, I will show how to use Spring to publish and consume OSGi services and how this can be integrated with GWT.

Background

The blog will take a practical step-by-step approach to building the GWT StockWatcher sample described here. The Google tutorial takes you through the steps required to build a GWT sample from scratch using RPC. I will be referring to pages in the tutorial as we go through and discussing the advantages/disadvantages to various approaches.

The blog assumes that you have an install of SpringSource Tool Suite 1.1.1 (I'm using the Eclipse 3.4 version),  dm Server 1.0.0 and GWT 1.5. It also assumes that you have a good understanding of Java programming and a basic understanding of Javascript and Ajax.

For the purposes of the paths used in the demo, I created a new Eclipse workspace at /Users/bcorrie/gwt/workspace. I have included zipped up projects you can download below, which contain a GWT_ROOT_INSTALL variable I have defined. To use my projects, when you import them navigate to "Preferences" -> "Java" -> "Build Path" -> "Classpath Variables" and define your own GWT_ROOT_INSTALL

A Word About the Election

Engineering | Rod Johnson | October 28, 2008 | ...

No, not the Obama/McCain smackdown on Nov 4. As you may have read in SD Times, SpringSource has been elected to the JCP Executive Committee for Java SE/EE, along with SAP, Ericsson, Nokia, Philips, and IBM. I will be the SpringSource representative.

Not that the JCP matches the scale of the presidential race. But this is an important moment for SpringSource, and one that reflects the years of hard work and leadership the entire team at SpringSource has provided in enterprise Java. More importantly, I believe that our election will help us to make Java stronger.

From the first book through the…

Getting started with SpringSource dm Server

Engineering | Rob Harrop | October 22, 2008 | ...

Updated 28-Oct-2008: Added up-to-date sample links and link to third sample

Last night I presented 'Introduction to SpringSource dm Server' at the Philadelphia Spring User's Group. During this presentation I created a small application called GreenPages, demonstrating all the major aspects of dm Server. I promised the attendees that I would post the application and the slides here.

In the last few weeks since the GA release of dm Server many people have been asking about the best way to get started with dm Server, so I'm using this entry to collect all the relevant information together…

Spring Batch 2.0 New Feature Rundown

Engineering | Dave Syer | October 21, 2008 | ...

In this article we outline the main themes of Spring Batch 2.0, and highlight the changes from 1.x. Development work on the new release is well underway, with an M2 release last week, and we are getting a lot of interest, so now seems like a good time to give a few pointers.

Spring Batch 2.0 Themes

The four main themes of the new release are

  • Java 5 and Spring 3.0
  • Non-sequential execution
  • Scalability
  • Configuration: annotations and XML namespace
so we'll cover each of those areas separately and describe what they mean and the impact of the changes on Spring Batch existing users. There is more detail below for features that are already implemented, which is mostly in the first category with some enabling features in other areas.

There are no changes to the physical layout of the project in Spring Batch 2.0.0.M2 (same old downloads, same basic layout of Java packages). We have not removed any features, but we have taken the opportunity to revise a couple of APIs, and there are some minor changes for…

Understanding the OSGi uses Directive

Engineering | Glyn Normington | October 20, 2008 | ...

If you build an application for the SpringSource dm Server, or any other OSGi platform, you'll probably encounter the uses directive before long. Unless you have a clear understanding of the purpose of the directive, you won't know when to code it and you'll be left guessing when a bundle fails to resolve because of a uses conflict. This article should give you a thorough understanding of the uses directive, when to use it, and how to debug uses conflicts.

Bundle Resolution

OSGi is designed so that once bundles are 'resolved', you shouldn't typically hit class cast exceptions and similar problems due to type…

Optimising and Tuning Apache Tomcat - Part 2

Engineering | Mark Thomas | October 14, 2008 | ...

A few weeks ago Filip Hanik and I gave the second in a series of webinars on Optimising and Tuning Apache Tomcat. A recording of the webinar and a copy of the slides can be obtained from the webinars section of the SpringSource website. The same page has links for all the previous SpringSource webinars, as well as the Covalent webinar archive.

We weren't able to get to all of the questions during the Q&A session so, as promised, here are the remaining questions and our answers.

  • How do you identify memory leaks in a Tomcat application?

    You will almost certainly need to use a profiler to identify the root cause of a memory leak. The latest Sun JDKs include tools like jhat and jmap. There are also many other profilers available, both free and commercial. Filip and I use YourKit when investigating Tomcat memory leaks as YourKit provide free licences to open source developers.

  • How can redeployment cause a memory leak?

    This usually occurs when a class loaded by Tomcat retains a reference to a class loaded by the web application. When the web application is stopped, the Tomcat class loader continues to retain the reference to the class loaded by the web application. This class retains a reference to the web application's class loader which in turn, retains references to all the classes it loaded. Therefore, the web application class loader and all the classes it loaded are not eligible for garbage collection. This causes a memory leak. The typical root causes of this are JDBC drivers and logging frameworks.

  • What is the best way to change the JVM Tomcat uses?

    The JVM to use is set using the JAVA_HOME (full JDK) or JRE_HOME (JRE only) environment variable. The correct place to set this will depend on your environment, particularly if Tomcat is configured to start automatically at system start. If you have a free choice on where to set this then use setenv.bat or setenv.sh as appropriate for your operating system.

  • Do you recommend a particular JVM?

    No, we do not. The JVM vendor you choose depends on your OS.

  • Which connector should I use to connect Apache httpd to Tomcat?

    We recommend mod_proxy_http with mod_jk a close second. Generally, mod_proxy_ajp is less stable than either mod_proxy_http or mod_jk. Note that mod_jk2 has been deprecated and should no longer be used.

  • What is the correct setting for maxKeepAliveRequests when using SSL?

    When using SSL HTTP keep alive should be enabled as the SSL handshake is a relatively expensive operation to perform for every request.

  • If we run Tomcat on Solaris, do you recommend against using the native APR connector?

    Yes, we do. The feedback we have received from clients is that the APR connector is not stable on Solaris.

  • We previously tried moving to mod_proxy_http on Solaris but we encountered several bugs. Have these bugs been resolved?

    Without knowing the exact bugs or version you were using, it is difficult to comment. All known Apache httpd issues and the current status can be found in the ASF Bugzilla Database. Tomcat issues can also be found in Bugzilla.

  • What value should I use for maxKeepAliveRequests with the default blocking IO HTTP connector?

    For high concurrency environments, set it to 1. Otherwise, set it to the average number of objects you have on a page, anywhere between 10 and 100.

  • How do I configure JkOptions +DisableReuse?

    JkOptions +DisableReuse should be placed in your httpd.conf file with your other mod_jk settings.

  • When is it best to use the bon-blocking IO HTTP connector?

    When you need to support high concurrency with keep alive and APR is not an option, e.g. because it is unstable on your platform.

  • Will I see better performance if I use Apache httpd in front of Apache Tomcat?

    It depends. If you proxy all of the requests to Tomcat then performance will decrease slightly. If httpd handles some requests (eg all the static content) then you will probably see some benefit. There are a number of benchmarks that attempt to demonstrate that one connector is better than another. However, it is very unlikely that any of these benchmarks will be representative of your application. The only way to know for sure is to test it in your environment with realistic load and usage patterns.

  • Can Tomcat be used in production without a web server in front of it?

    Yes. Whether this offers the best performance for your environment will depend on that environment and your application. As with the previous question, the only way to know for sure is to test it in your environment with realistic load and usage patterns.

  • Will using Apache httpd in front of Tomcat increase security?

    The security of your installation will depend on many factors. The use, or not, of Apache httpd is unlikely to significantly change the security of your installation. Other factors such as keep up to date with patches and using a firewall usually have a much greater impact on your overall level of security.

  • Which Apache httpd MPM provides the best performance?

    As always, it will depend on your environment but the httpd performance tuning documentation offers some useful general guidance.

  • What is the performance difference between SpringSource ERS and Apache Tomcat?

    SpringSource ERS is much more than just Apache Tomcat. From a pure Tomcat perspective, performance isn't the differentiating factor. The benefits of ERS are the simple installation, the easy to manage upgrades and patching, support for multiple instances and the integration of all of the components.

  • My company uses Tomcat and XYZ application server. How does Tomcat compare to XYZ application server and are there benefits in consolidating?

    There will be lots of differences and the differences that matter will vary from organisation to organisation. Start by working out what you want from an application server and then compare that list to the market. There are benefits in consolidating. Greater consistency means simpler maintenance, less training and so on. However, there are also costs. You would need to look at your organisation and how it planned to consolidate (new projects only, all projects for next major release, everything now, etc) to compare the costs with the associated benefit.

  • Do you have performance comparisons available for Tomcat and XYZ application server?

    Various reports have been published in this area. How useful the results are depends on how well matches the test is to your load. As always, the only way to know for sure is to test in your environment with realistic load and usage patterns.

  • What is a good method for load testing a Tomcat server?

    There are several options available with tools that drive load, both free and commercial. The free tools include ab and JMeter.

  • For high availability and performance, can Tomcat be configured to launch multiple JVMs for the same web application?

    Tomcat does not provide this as a configuration option. You can, of course, create multiple Tomcat instances, install your application on each instance and then load-balance across the instances.

  • Is there a generic health-check script for Tomcat?

    The Manager status page is probably a good place to start. You can use the code for that Servlet as the basis for your own, more specific/extensive checks if required. If you do enhance it, consider contributing your enhancements back to the Apache Tomcat community.

  • Where is the logging.properties file located?

    The default location is in $CATALINA_BASE/conf.

Get the Spring newsletter

Stay connected with the Spring newsletter

Subscribe

Get ahead

VMware offers training and certification to turbo-charge your progress.

Learn more

Get support

Tanzu Spring offers support and binaries for OpenJDK™, Spring, and Apache Tomcat® in one simple subscription.

Learn more

Upcoming events

Check out all the upcoming events in the Spring community.

View all