Lightweight way of packaging applications

The approach of zero-dependency applications simplifies many project build concerns. There is no need to manage third-party dependencies with regard to versions or collisions since there aren't any included.

What other aspects does this approach simplify? Project builds, no matter whether Gradle or Maven are being used, always show the best performance when nothing needs to be added to the artifact. The resulting size of the packages directly impacts the build time. In the case of zero-dependency applications, only the compiled classes are included, that is, only the actual business logic. Therefore, the resulting build times are as minimal as they will get. All build time is spent on compiling the project's classes, running the test cases, and packaging the classes into a thin deployment artifact. Building this approach should happen in seconds. Yes, seconds. As a general rule, every project build that takes more than 10 seconds should be reconsidered.

This rule, of course, puts certain pressure on project builds. It naturally requires to avoid including any larger dependency or implementation; these should be provided by the application server. Test run times are usually another aspect that prevents fast builds. Chapter 7, Testing, will shed light on how to develop tests in an effective way.

Fast builds are one benefit of crafting zero-dependency applications. Another implication is fast artifact transmission. Built artifacts, such as WAR or JAR files, are usually kept in an artifact repository for later use, for example, Sonatype Nexus or JFrog Artifactory. Transmitting these artifacts over the wire greatly speeds up if only a few kilobytes of data are involved. This applies to all sorts of artifact deployment. No matter where the built archives are shipped to, smaller footprints always pay off especially when workflows are executed often, as it is the case for Continuous Delivery.

The goal of reconsidering practices and stripping everything which does not provide value also targets the way of packaging applications. Traditionally, enterprise applications have been shipped as EAR files. The structure of these included a web archive, a WAR file, and one or more enterprise JARs. Enterprise JAR archives contained the business logic, usually implemented in EJBs. The web archive contained the web services and frontend technology communicating with the business logic using local or remote EJBs. However, this separation is not necessary, as all components are shipped on a single server instance.

Packaging several technical concerns in several sub-archives is not required anymore. All business logic as well as web services and cross-cutting concerns are packaged into a single WAR file. This greatly simplifies the project setup as well as the build process. Applications don't have to be zipped in multiple hierarchies just to be unzipped on a single server instance again. WAR files containing the required business code deployed in a container is the best implementation of thin artifacts. Because of this reason, deploying thin WAR files is faster than the corresponding EAR files.

The following demonstrates the contents of a thin web application artifact with typical components:

The deployment artifact only contains classes that are required to implement the business use case, no technology-specific implementation, and only minimal configuration. Especially, there are no library JAR files included.

The architecture of the Java EE platform encourages lightweight artifacts. This is due to the platform separating the API from the implementations. Developers only program against the API; the application server implements the API. This makes it possible to ship only the business logic, which includes certain aspects in lightweight artifacts. Besides the obvious benefits of avoiding dependency collisions and building vendor-independent solutions, this approach also enables fast deployments. The less content the artifacts include, the less unpacking needs to be done on the container side. Therefore, it's highly advisable to package enterprise applications into a single WAR file.

In the last year, we have seen more and more interest in shipping enterprise applications as fat JARs, that is, shipping the application together with the implementation. The approaches of fat deployment artifacts have usually been used in enterprise frameworks such as the Spring Framework. The motivation behind these approaches is that the versions of the required dependencies and frameworks are explicitly specified and shipped together with the business logic. Fat deployment artifacts can be created as fat WARs, which are deployed on a servlet container, or fat JARs started as standalone, executable JARs. A Java EE application packaged as fat JAR therefore ships the enterprise container together with the application in an executable JAR. However, as stated before, the build, shipping, and deployment times increase greatly if third-party dependencies are added to the artifact.

Experience shows that explicitly shipping the enterprise implementation together with the application is in most cases not technically but business-politically motivated. Operational environments within companies that are inflexible regarding application server and Java installations, especially regarding version upgrades, in some cases force developers to find workarounds. Enterprise applications that are built using newer technology cannot be deployed on older, existing server installations. Sometimes, the business-politically easier solution is to ignore the existing installations altogether and to directly execute the standalone JAR, which only requires a certain Java version. However, whereas these solutions are certainly justified, the technically more reasonable solutions would be to package applications into thin deployment artifacts. Interestingly, as we will see in the next chapter, shipping software in Linux containers holds the advantages of both approaches.

There is another interesting approach that enables to ship the whole application as an executable package and to keep fast workflows of thin deployments. Several application server vendors provide the solution to ship a custom application container as executable JAR that deploys the thin application as additional argument at startup time. By doing so, the whole package of both artifacts includes the business logic as well as the implementation and is started as a standalone application. The application is still separated from its runtime and packaged as thin artifact, as a so-called hollow JAR or WAR file. This approach especially makes sense if the addressed flexibility is required without the use of Linux containers.

As a conclusion, it is highly advisable to build thin deployment artifacts, ideally thin WAR files. If this approach does not work for business-political reasons, hollow JARs can provide a reasonable workaround. However, as we will see in the next chapter, container technologies such as Docker don't require to make use of executable JAR approaches and provide the same benefits.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.212.212