; last updated - 11 minutes read

Recently it crossed my mind there's something wrong with Java application servers. You know, our team is still using them the way they're meant. The way they were originally meant. We've got many applications running on a common application server that's managed centrally.

I'm told we're one of the last companies to do so. These days, most companies dedicate an entire application server to a single application and put them in a virtual machine.

In other words, application servers have become part of the application. Originally, it was meant to be the other way round, and that's why Eberhard Wolff claims application servers are dead. His JAX talk was a real eye-opener, by the way. He expressed the thoughts that ware already lingering in the subconscious part of my mind. As usual, I'll mention a few key points of his talk in this post, plus a few thoughts of my own. If you're interested in the entire talk, have a glance at his slides. He also published an article in the Java-Magazin 7.2014 (in German language, and as far as I know, only available in print).

So what's wrong with the original idea of applications servers? Let me put the question differently: Have you ever seen an application server that runs out of the box, without being modified?

I guess you haven't. Almost every application server is modified in one way or another. One of the most common customizations is to add libraries into the shared folder of the application server.

Former versions Tomcat used to have a dedicated folder for that purpose (./lib/ext). The folder has vanished a couple of versions ago, and that's a subtle hint you shouldn't share libraries among applications.

In fact, that's a very bad idea. We used to do the same in the Windows world, and called it DLL hell. It's pretty astonishing the Java world hasn't learned from this misery.[1] Quite the contrary, application servers do even worse than Windows (there's no counter indicating how many applications use a particular library, let alone which ones). Mind you, what happens when you want to update one of the shared libraries? You have to test every application on the server simultaneously. If a single application isn't compatible, you can't update any application (without moving it to another server, that is). Testing applications tends to take a lot of time, so this approach is unreasonable expensive. It's better to move the jar files from the common folder to the individual application's folders. Dedicating entire application servers to individual applications is a particular radical approach to that.

As it turns out, this approach has many advantages. Possibly the most important advantage: the responsibility for the application isn't scattered across departments. Developers deliver both the application and it's application server. This means they are responsible for choosing compatible libraries. That's bad in that developers need more time to inform themselves whether one of their libraries has to be updated to fix a security issue. On the other hand they save a lot of time because they don't have to trace down bugs caused by different libraries on the developer machines and the central server. In the past that has always been a big point of pain, so I daresay the small extra amount of research time is easily outweighed by the time saved. Can you imagine how much time my team and I have spend to find bugs that only happen on the test systems, or even on the production systems? In most cases these bugs are caused by different configuration files, different folder structures or different versions of the same library. Concurrency problems and errors caused by heave load come second, and they're much more difficult to hunt down and to fix. So the good news that there's a simple solution for the most common type of "production-only" errors: Let the development department ships prepackaged virtual machines, and this type of errors is a thing of the past.[2]

You may have noticed by now the title of this article is sort of misleading. I don't propose to get rid of Tomcat, Jetty, Glassfish, JBoss or which other application server you may be using. Granted, I don't think it's a good idea to use a full-blown JavaEE application server. I prefer to use a simple servlet container such as Tomcat or Jetty and to add the jar I want to use. Full-blown application servers contain everything and the kitchen sink, making them feel like supertankers. But that's another story, and it seems to be a question of personal taste. Today's story is about the changing role of application servers. They've died recently, but only sort of: they live on as part of the application.

There are many other reasons why it's a good idea not to put many applications on a application server. For instance, your operations department doesn't have to deal with Java files. I'm told running an application server isn't exactly their primary field of expertise (at least if your operations department is specialized in managing UNIX systems). Another interesting point is Java applications stop to "steal" each other's resources and much more. Application servers go to great lengths to make you believe the applications are independent of each other, but that remains a fiction. The applications are separated (for example, they have their own class loaders), but only to a certain extend. An application running havok quickly brings the entire server into trouble. Virtual machines are better prepared to deal with these problems.

At this point I'd like you to point you to Eberhard Wolffs slides or his Java-Magazin article instead of exploring the details further.

It's time to get our feet wet and start writing code.

How to package an application and it's application server?

Eberhard Wolff - being big into Spring - suggests to use Spring Boot, which is an interesting product indeed. Another - fairly radical - way is to ship virtual machines. That's what a friend of mine does, and he's reporting he's made very good experiences with this approach. I'd recommend shipping virtual machines if you have little to none control over (or knowledge of) the target system.

Alternatively you can run Jetty embedded. Basically, that's simply adding a couple of jars and writing a main method like so:

package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; public class OneContext { public static void main(String[] args) throws Exception { Server server = new Server(8080); ContextHandler context = new ContextHandler(); context.setContextPath("/"); context.setResourceBase("."); context.setClassLoader(Thread.currentThread().getContextClassLoader()); context.setHandler(new HelloHandler()); server.setHandler(context); server.start(); server.join(); } }

Read the full story in the Jetty documentation.

Embedding Tomcat is just as simple, as you can read here.

Without having investigated I suspect it's a lot more difficult to embed a full-blown JavaEE application server (such as Glassfish or JBoss) into your application. That's one of the reasons why I prefer to use Jetty or Tomcat. The idea is to keep simple things simple.

No need to deploy!

Once your application runs an embedded Jetty or Tomcat, you'll notice you're working much more interactively than before. Every class you've changed is immediately reloaded, every modification of a JSF or JSP file immediately shows up in your program and so on. Only a few changes (Spring config files and web.xml) require a restart of your server, which boils down to a simple restart of your main class.

Granted, most modern IDEs do a good job at providing features like hot code replacement. In many cases they provide an interactive developing experience, so there's little to complain. However, I daresay things feel a little smoother running an embedded server. It's quite a challenge to provide hot code replacement with a non-embedded server. Mind you, the complete cycle includes packing a war file just to have it unpacked by the server. That's sort of ridiculous if you've just corrected a single typo. Eclipse implements quite a few shortcuts of the deployment cycle, but nothing beats an embedded server: there's no need to deploy the application. It's ready for use, out of the box.

Embedding Tomcat or Jetty frees you from having to package and deploy your application. That's a major advantage because you don't have to think about things like hot code replacement. It just works. As to my experience, development becomes a lot more fun, more interactive and of course faster.

Embed the browser

You can even go a step further and embed the browser, too. That's a nice feature for developers. Even if hardly anybody want to embed the browser in production, it's an interesting thought: instead of shipping pre-packaged application servers to the operations departement, you can ship the application, its application server and its embedded browser to the client. You end up with a traditional desktop application: it's started by a double click, opens a window and closing the windows also shuts down the entire application server. The only drawback is a slightly higher demand of server resources that are tradionally shared among clients (database connections, in particular).

In any case, it's a nice tool for developers. All you have to do is to add SWT to your libraries. You can use one of SWT's examples as a starting point: your default browser (i.e. Internet Explorer on Windows systems), Mozilla (aka Firefox) or WebKit (Safari, older versions of Google Chrome).

Basically, the code needed is very simple:

public static void main(String [] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setLayout(new FillLayout()); shell.setText("WebKit"); final Browser browser; try { browser = new Browser(shell, SWT.WEBKIT); } catch (SWTError e) { System.out.println("Could not instantiate Browser: " + e.getMessage()); display.dispose(); return; } shell.open(); browser.setUrl("http://webkit.org"); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); }

Start the application server in another thread and you're done. On the long run you'll probably add more code (for instance, to support the Javascript methode Window.open) - but even so, the source code of the browser we're using at company fits nicely on two or three pages in print. (We invented this mechanism to get rid of compatibility issues with the pre-installed browsers - but that's another day's story).

Conclusion

Application server's aren't really dead - I just couldn't resist to use the title. But nowadays they're frequently used differently than they were designed to be used. Instead of embedding an application into a server, things are done the other way round, and as it turns out, this simplifies the developers' lifes considerably. As a bonus, you can even embed the browser and ship the application as an almost traditional desktop application. Loosening the restrictions imposed by the browsers security system even allows you to escape the sandbox and to access the desktop machine's resources (e.g. local files). Granted, this isn't really something I'd suggest (you're better off using dedicated APIs such as JavaFX or even chosing another language ecosystem with better GUI support, such as VisualBasic or C#). Nonetheless this is an interesting idea closing the circle opened one or two decades ago by propagating thin client applications.

Reader feedback

This article has been bookmarked on Reddit. A surprisingly big number of readers agrees: even if the single-app-per-server model I describe above is not adopted by everyone, the general trend is to reduce the number of applications per server. However, doing the last step and using distributable jar files containing the server seems to be a fairly new idea: it wasn't discussed at all yet. Come on, give it a try!


Application Servers are dead! (Eberhard Wolff's slides)

Java-Magazin 7.2014

The discussion on Reddit about this article

Spring Boot and JSF in practice

simple PrimeFaces project on Spring Boot

PrimeFaces, Spring Boot, JSF custom scopes and Spring custom scopes.


  1. Truth to tell, the Java world has learned the lesson. But it seems to have forgotten what it once learned.↩
  2. But please don't underestimate the amount of time it takes to track security issues. Developers tend to neglect security issue because it distracts them from developing new, fancy features, so this is an important point to keep in mind).↩

Comments