Java application servers are dead!
Eberhard Wolff continues his examination of why we need to revise the role of Java application server in deployment, devops and microservices.
For years Enterprise Java has been a synonym for Application Servers. Deployment and operations of the Application Servers has changed little over the years – while the APIs have adapted to new paradigms and competitive programming models were introduced. Time to rethink this part of the traditional enterprise stack, too.
Application Servers support the deployment of applications. File formats include WARs for web applications, EAR for enterprise application with multiple different modules and JARs e.g. for EJBs or libraries. These file formats do not support dependencies outside the Java world. For example it is not possible to define that a Java application depends on a database server or a specific version of a database server.
Also it is not possible to define that a JAR, WAR or EAR depends on a specific application server or version of an application server – even though applications are often not portable across Application Servers. Other deployment tools e.g. Linux package managers support these kinds of dependencies.
They are also more generic and support any kind of application – not just Java. These tools are used by operations quite successfully. These tools can automatically configure and deploy server farms and clusters. It does not take an Application Server with cluster support to do this. Rather any well-run operations department should be able to install large clusters.
So some features of the operating system might be the better choice to deploy applications. Also the operating system can start applications – for example as Unix services. That way the application makes the best use of the operating systems and how applications should work on such a platform.
Java has a standard for monitoring: JMX (Java Management Extension). It provides an API to change the attributes in the running application and also emit events e.g. when a problem occurs. JMX is an established and powerful tool. It can be integrated in SNMP based systems that are quite common in operations. Also newer monitoring tools like graphite can be integrated with JMX. JMX is part of the JDK. So it can be used without an Application Server. Using Jolokia JMX data can also be accessed via REST as JSON data. That way it can easily be evaluated e.g. using simple shell scripts.
Often operations also use another source of information: Log files. These can be evaluated using tools such as the Graylog2 or the ELK stack. The ELK stack consists of Elasticsearch to store logs, Logstash to parse and interpret the log data and Kibana to analyze data stored in Elasticsearch.
So to sum up: Operations usually has a stack of standard tools for monitoring and log analysis that applications should integrate into. If monitoring features of an Application Server are used they make the tool stack more complex. So it is often easier to use this tool stack instead of creating a different one just for Java applications.
Clearly Application Servers are not a prerequisite for monitoring, deployment or professional operations of Java applications. Rather Application Server come with their own tool set for operations – which might not really be a benefit if a powerful generic tool stack is already implemented.
The Price We Pay
For developers the Application Server mean an additional step in the build-test cycle (see figure 1 below). The result of the build is compressed into a JAR or WAR file. Then this is uncompressed by the Application Server and can be tested by the developer. So the code is compressed – just to be uncompressed again. This cycle can be shortened with tools like JRebel that make the Application Server reload changed classes on the fly.
For production systems and test system the Application Server also adds a considerable burden:
- The Application Server must be deployed in addition to the application. The configuration of the Application Server is usually quite complex – sometimes even more complex than the configuration of the application itself. Automation scripts for Application Servers are therefore difficult to write. The available scripts for tools like Chef or Puppet prove that point.
- The configuration of the Application Server must fit the version and configuration of the application itself. And this must be ensured for each developer’s local installation and each testing stage. Of course also old configurations must be available – e.g. to test a bug fix in production. This is hard to get right.
- This problem become even more severe because nowadays applications are often developed using Continuous Delivery. Figure 2 (below) shows a Continuous Delivery Pipeline – the core of Continuous Delivery. It contains several testing phases – automated acceptance tests, automated capacity test, and explorative tests. In each of these stages the software must be deployed on a test system and tested – and the pipeline is executed several times per day. Additional complexity in the deployment process has a huge impact because there are so many deployments done every day. In such an environment the deployments must be as easy as possible. An Application Server should therefore be avoided.
So not just the benefits of using an Application Server are questionable – actually the Application Server adds a considerable burden to the deployment of applications and therefore to operations as well as development
New trends in IT also do not really fit to the idea of an Application Server. The DevOps proclaims a fusion of development (Dev) and operations (Ops) to DevOps. This leads to a different mindset: developers usually use tooling specialized for Java. Operations has a set of tools that support a broader landscape – for example deployment automation that might be based on package managers and monitoring tools for system and application metrics.
The DevOps mindset makes developers more aware of these tools so they use them for the setup of their own machines, too. This makes alternatives to the Application Server tooling more readily available also to developers.
Another influence on Application Servers are Micro Services. With this paradigm a system is composed of Micro Services instead of e.g. JARs. Services should have a business meaning and can be deployed independently. So instead of a deployment monolith the system is broken apart into several deployable components. Each of the communicates with the others via a protocol like REST. Each Micro Services is effectively a separate web application.
Deploying an Application Server for each of these Micro Services adds a considerable overhead to the system. A lot more instances are needed than in a traditional setup. Also Micro Services focus on specialized infrastructure: An Application Server might be perfectly fine for a front end Micro Service. But for data analysis a special infrastructure for Big Data like Hadoop might be a better fit. And if invoices should be processed in a batch some kind a batch infrastructure like Spring Batch might be the better choice.
So to sum up (See figure 3 above):
- Application Servers make the infrastructure more complex. It is not just another piece of software – it is a complicated piece of software that must be properly installed and configured. Also the configuration must fit the application.
- Application Server slow down the turn around for tests. The code must be packaged and deployed – i.e. compressed and uncompressed – before it is executed.
- Standard operations tools for monitoring and deployment are a great alternative for the solution that Application Servers provide. These standard tools become more popular due to the rise of DevOps.
- Finally Continuous Delivery means that software is deployed much more frequently. More complex infrastructure like Application Server should therefore usually avoided.
- Micro Services increase the number of components that are independently deployed. Again this means that complex infrastructure should be avoided.
If Application Servers just cause more complexity there is no good reasons to use them. An alternative are simple Java applications. They can be packaged as JAR files that contain a main class and thus can be started from the command-line. The JAR file contains all necessary infrastructure i.e. the libraries but also an embedded HTTP server for a web application. For monitoring and deployment standard tools like Graphite or systems based on JMX can be used. Deployment can be done with one of the many automation tools like Puppet, Chef or Ansible. Note that the automation is rather easy to setup.
The application needs an installed Java, the JAR file must be copied to the machine and probably a configuration file for the application must be created. The application can be started like any other application – via the command line. This is a lot less complex than the setup of a typical application server. So the automated installation is easy to set up – even if a cluster of servers has to be installed. This setup also makes isolating applications easy: Each application is a separate process and can be managed accordingly by the operating system.
For developers live is also easier: Applications can be debugged and run inside the IDE. Also acceptance tests are much simpler. Instead of deploying the application to an application server it can be run as a simple Java application – probably even inside the test itself. So for example a Selenium GUI tests can be run inside the same JVM as the application itself – also on an integration server like Jenkins.
Deploying Java applications as a simple JAR file has recently been implemented by some technologies:
- Spring Boot applies container less deployment to the full Spring eco system and several other technologies. This includes not just web applications but also Batches or Spring Integration applications. Spring Boot applications can also be deployed as WAR files to support Application Servers.
- Dropwizard supports only JSON REST Web Services with a pre defined technology stack. It is therefore simple to use – but also not very flexible.
- Vert.x is a framework that focuses on asynchronous applications and can be used with many different languages on the JVM. It offers an option to package the application plus the environment in one JAR.
- Play is written in Scala and can be used to write web application. To deploy Play applications a JAR can be built that includes the application and its environment and libraries.
It’s hard to come up with convincing technical reasons why Application Servers should still be used. The support for deployment and monitoring might as well be done with generic tools that operations is already used to. Libraries can provide the features developers need. Without an Application Server building applications is easier – and also deployment, testing and debugging becomes much simples.
However, if you already have application servers installed and you are used to run them in production things are different. Switching to container less deployment will change quite a few processes. The effort to do these changes must be balanced against the benefits.