Stop saying “heavyweight”saturday, april 09, 2016
When developing enterprise applications in Java one has the options to choose Java EE or any other “lightweight” framework. But what makes an enterprise framework lightweight?
As developers we should mainly care about the development process. Our time is precious (and expensive) and the less time we spend on overhead the better.
This mainly includes the time it takes to build the applications, deploy and test it — either locally or on a dedicated environment. To keep the turnaround time as small as possible the build may not take longer than a few seconds. Yes, seconds.
With Java EE there is the big advantage that the developer can rely on a standard which enables you to develop against an API — mostly just interfaces and annotations — with the real implementation of your framework not being included in your application. The Java EE dependency itself is “provided” by the application server which means you only need it during compile time but not in your deployment artifact. This has the effect that your war-file is almost empty — containing only the class files of your application. Everything else has to be provided by the Java EE implementation.
As long as you stay lean and minimalistic, which means using the Java EE (7) API only and no other third party dependency — unless really needed for your business use cases — you can achieve build times within few seconds. The main reasons for slow builds are either slow (integration) tests or big deployment artifacts with a lot of stuff to copy, respectively.
Deployment artifact size
Typical plain Java EE war files are about a few hunded kilobyte in size compared to 50 megabytes and more if you ship even a small (“lightweight”, you know) framework implementation with it.
If you count the whole application server plus your application then the result is bigger when using Java EE. But: The whole development process is faster, as you’re only creating kilobytes every time you build. The application server is usually already installed on your development machine — or any other environment — and the moving parts are small. This results in short build and deployment times, both on a development machine and on a Continuous Integration server. And: When deploying your artifacts to a central repository (Nexus or Maven central, etc.) you’re saving a lot of time and bandwith as well.
All of the recent Java EE 7 application servers (like Wildfly, TomEE, Glassfish / Payara, WLP) have a very short deployment time. With their module systems (like OSGi) they can load only the needed components and startup your application within a few seconds.
Compared to another framework (like Spring) running on a Tomcat the shortest deployment time I’ve ever measured was at least about 15 seconds — for a simple “Hello World” application — measured on the same machine.
Fat jars / Integration with containers
In the new microservices world it is common to ship the application as a standalone jar containing both the developed application and the framework implementation. Using Java EE this can be accomplished using technologies like Wildfly Swarm or TomEE Embedded.
However: As stated above I don’t recommend to make your deployment artifacts that big. The biggest problem with that approach is the build time as you need to copy a lot of things from A to B every time. And: When using container-based deployment approaches like Docker it doesn’t matter whether your application shippes the server as well or the server is already part of the container.
In fact if the container already includes the application server installation you can save a lot of (container) build time. Your base image isn’t changed then and you only add your (few hundred kB) application only — which is achieved in no time.
Since the old J2EE days there is the myth of the “heavyweight” application servers consuming a lot of memory as soon as they get started. Adam Bien has posted an interesting video showing the actual overhead of recent Java EE application servers.
From my point of view one of the most “lightweight” solution for enterprise applications is the following:
Java EE 7 & Java 8 only with the API being provided
Tiny war file only containing the business logic plus minimal plumbing (like JAX-RS resources or JPA)
Fast unit test without embedded container test frameworks (plain JUnit only)
Container-based deployments from base images containing already everything except the application
Continuous Delivery driven build processes which deploy the application using containers on every commit
Automated system tests against the deployed container (to ensure high quality of the whole application without the need for integration tests; the developers still get fast feedback)