What are the modern alternatives to package and deploy server side java software1) in heterogeneous environments2) ?
I could not find a lot of coherent or up to date information on the topic but I have a few ideas. I'll start
- The traditional application server approach (Jetty, Tomcat, etc.)
- Assemble software into
war
files and craft your own provisioning and deployment script, e.g., using izpack, ant scripts, cargo or something similar.
- Rely on integration platforms, e.g., fabric8, servicemix, fuse, etc.
- Seems like a nice opinionated approach. If not already using one of these, apart from a lock-in, re-rolling an application into this format requires a bit of work. Isn't the trend to move away from large frameworks?
- Bundle application
war
files into ear
(Enterprise archives) files
- Requires a full-fledged java EE server, e.g., wildfly, glassfish etc. Unless the capabilities of such server is needed it adds a lot of overhead to what a zip-archive could do already.
- Virtual machines: Vagrant, Docker, etc.
- Docker is nice but on a windows host needs to be run in a VM anyway. VMs (vagrant or not) incurs a performance overhead and tends to rely on complex provisioning tools such as puppet or salt.
- Runnable jars, e.g., Capsule, maven shade plugin, One-JAR.
- Capsule seems great, it's like an executable, self-extracting zip file, which also runs the application. With an embedded jetty multiple traditional
war
files can be served from one executable.
The first option has been my reference approach for long but requires a lot of provisioning, install scripts, both which varies on different environments (e.g., Linux, Windows).
What modern alternatives are out there that makes packaging and deployment easier?
1) Picture a SOA like setup with microservices, RESTful communication etc.
2) With that in mind let's rule out PaaS
providers such as cloudbees, cloudfoundy etc. They deserve a topic of their own.
I recommend reading The Twelve-Factor App document, inspired by Patterns of Enterprise Application Architecture and Refactoring books by Martin Fowler. It suggests the following:
- There should be one codebase (version control system) per app, and many deploys of the app in different environments (development, staging, production).
- Dependencies should be explicitly declared and isolated (never relying on the implicit existence of system-wide packages or system tools).
- Config (everything that is likely to vary between deploys) should be stored in the environment, never in the code.
- Backing services (including other apps) should be treated as attached resources, accessed via locators/credentials stored in the config.
- Build, release and run stages should be strictly separated from each other.
- The app should be executed as one or more stateless and share-nothing processes (state should never be stored in "sticky sessions", but in a datastore that offers time-expiration).
- The app should be completely self-contained (typically adding a webserver library to the app), exporting HTTP as a service by port binding.
- Due to the partitionable nature of the twelve-factor app processes, adding more concurrency should be simply and reliably achieved via the process model.
- The app should treat disposability by achieving fast startup and graceful shutdown.
- Development, staging, and production environments should be as similar as possible (Dev/prod parity).
- The app should treat logs as event streams, never concerning with its routing or storage.
- Admin processes should run as one-off processes.
There's also the article on Microservices by James Lewis and Martin Fowler, that states some of the ideas enumerated above.
Regarding packaging and deploying, the latter article recommendations are:
Componentization via Services
Apps (and their microservices) should be implemented as out-of-process components (rather than in-process libraries) that can be independently replaced, upgraded, and deployed. Components provide a more explicit component interface by using explicit remote call mechanisms.
Organized around Business Capabilities
Each component should be organized around business capability, for a specific business area, taking a road-stack implementation of software including user-interface, persistent storage, and any external collaborations. This approach also allows a cross-team project to work together on the same component (and own the product over its full lifetime).
Smart endpoints and dumb pipes
Apps built from microservices should be choreographed using simple RESTish protocols. The two most commonly used protocols are HTTP request-response with resource API's, and lightweight messaging over a dumb bus (such as RabbitMQ or ZeroMQ).
Infrastructure Automation
The operational complexity of building, deploying and operating microservices can be reduced by automation with Continuous Delivery or it's precursor, Continuous Integration.