With the rise of cloud-oriented software stacks and development methodologies in recent years, use of Java Application Servers such as Tomcat and Weblogic has decreased. But it’s way premature to consign Java Application Servers to the list of outmoded technologies: Along with the many existing Java Application Server solutions that are still doing the jobs they were created to do, quite a few businesses are opting for Java for new, self-contained on-premises and cloud-based applications that can be set up quickly and easily.
While maintaining and even creating new Java Application Servers systems makes business sense, deploying and especially debugging the systems is a whole other matter. As developers who’ve been around the block a few times, we know just how rough it can be to deploy and debug large, complex Java Application Server systems, especially when they include multiple applications.
To make available the most comprehensive assistance for our clients’ debugging needs, we decided right from the start that Rookout would offer support for the traditional deployments that many of our clients maintain, such as Java Application Servers, in addition to supporting cloud-oriented environments.
The debugging challenges our Java-using customers face include:
These issues make debugging slow and inefficient at best, and negatively impact overall developer productivity. And while a number of debugging tools are available, each has distinct plusses and minuses when it comes to accelerating the process.
The main approaches to debugging Java Application Servers include:
Let’s dig in a bit and look at the strengths and weaknesses of each, based on ease of use, ability to skip builds and restarts, application performance, and application stability.
The trusty debugger, that we all use and love, is embedded in every IDE worth its salt. However, it often fails to deliver when it comes to Java Application Servers.
Ease of use is often poor, since debugging a process on a remote server can be hard. Other issues that impact debugger usability include the complex configuration of Java Application Servers, their multiple-class loaders, and the many applications running inside the process that is being debugged.
Skip Build/Skip Restart Debuggers allow you to skip builds and restarts by setting breakpoints anywhere in the code.
Application Performance. Debuggers often have a significant performance overhead, since they are designed for dev -- not production -- environments. For expensive applications, the cost impact can be substantial.
Application Stability. A good debugger will not impact process stability from the JVM perspective. Unfortunately, breaking into an application causes all threads to be suspended. In a highly multithreaded environment, timeouts and other business logic failures will be the likely result.
In summary, while most developers are comfortable with classic debuggers, they are not optimal tools for debugging complex or multithreaded Java Applications Server applications, due to high-performance overhead and their potentially negative impact on overall application stability.
The tried-and-true System. Out (or log4j/logback/JUL) allows data to be extracted from a running process, without attaching a debugger or breaking in. Simply adding a log line to the code and deploying a new version provides the dev with additional data he or she needs.
Ease of use. Logging is simple and familiar to most devs from their earliest exposure to computer science.
Skip Build. Unfortunately, not an option: Changing the application code requires rebuilding, which can take quite a long time.
Skip Restart. Adding a log line generally requires rebuilding and restarting, which is costly and time-consuming. In limited cases, hot-swapping can be used to avoid restarting.
Application Performance. Application performance is generally fine unless an expensive log line is added to a hot code path.
Application Stability. Logging should not impact application stability unless an added log line throws an exception or causes an unanticipated side effect. In that case, the problematic log line must be removed, and the application rebuilt and restarted to restore stability.
In sum, while logging is a familiar, easy-to-use tool for most developers, in many instances it leads to time-consuming rebuilding and restarting.
What if you could add a log line without restarting the application you’re debugging? That’s where hot swapping, which allows you to change any code on the fly, comes in. However, it can also be a double-edged sword.
Ease of Use. Hot swapping entails a steep learning curve, and operating hot swappers on a remote server, within a complex Java Application Server, is tricky at best.
Skip Build. Not relevant for hot swappers, which require projects to be rebuilt, a time-consuming process.
Skip Restart. Good news here! Hot swappers allow restarts to be skipped! :)
Application Performance. Because hot swappers reload a new, functional piece of code that replaces an old one, they have almost no impact on performance.
Application Stability. Unfortunately, hot swapping often negatively impacts stability. While hot swapping is not intrinsically unstable, it tends to be an error-prone process. Various hot swapping technologies place differing limits to what can or can’t be changed. In addition, some changes might inadvertently corrupt the application’s logic. Overall, for us, humans, repeatedly reloading application code is likely to hurt stability.
Summing it up: While hot swapping is attractive in theory, it often backfires by making it very easy to crash your own system or creating “fake” bugs.
Production debuggers -- and Rapid Production Debuggers (RPD), their new-on-the-block cousins -- are innovative tools designed to provide agile visibility into production environments. Because a Java Application Server running on a remote dev machine more closely resembles a production environment than a classic development environment, production debuggers and RPDs are suitable tools for debugging Java Application Servers.
Ease of Use. Java production debuggers are quite easy to use. Just add a Java Agent to your code and configure it with your token.
Skip Build. Production debuggers allow you to skip rebuilding your code, much like a classic debugger.
Skip Restart. Production debuggers do not require to restart your server, similar to classic debuggers.
Application Performance. Production debuggers perform better than classic logging solutions. Some include built-in performance protections (for production use) and “misbehaving” rules can be removed with a click.
Application Stability. Production debuggers do the heavy lifting, enabling devs to insert breakpoints and get the data they need while ensuring that applications remain stable.
Additional Functionality. Some production debuggers, such as Rookout, go beyond showing requested data and offer valuable functionality, based on integrating ETL (Extract, Transform, Load) capabilities directly into an app. Using these functions, for instance, you can log a high-volume operation and upload it to a data platform such as DataDog or Elasticsearch, where the log can be stored and used to compare between executions/versions, searched, aggregated, and so on.
In sum, for Java Application Server debugging, production debuggers offer an attractive combination of efficiency, ease of use, and protection against performance and stability issues, as well as additional valuable functionality that is unique among debugging tools.
In this post, we reviewed the various options for debugging Java Application Servers, including a novel approach to debug Java Application Servers in the development environment using production debuggers such as Rookout. Stay tuned for our next article in this series, a step-by-step guide for getting started with Rookout on Java Application Servers such as Tomcat or JBoss.
Care to get your Java feet wet? Register for a free Rookout account today.