Java has more ways to run a web application than any other language, and the marketplace reflects that with five clustered packages that all look similar on a card. They are not interchangeable: each matches a kind of application, and putting a Spring Boot JAR on a Jakarta EE domain or a full EE application on a servlet container wastes either resources or features. This post follows a Java architect sorting a company's applications into them on MassiveGRID PaaS, which is built on Virtuozzo Application Platform, formerly Jelastic.

The company is an insurance software vendor we will call Ashworth Systems, with eight Java systems accumulated over fifteen years. The packages are the Tomcat/TomEE Cluster, the WildFly Managed Domain Cluster, the Auto-Scalable GlassFish Cluster, the Spring Boot Cluster and Open Liberty in Kubernetes.

What they share, so it can be set aside

Every package here gives you an NGINX load balancer (or a Kubernetes ingress) in front of two or more Java nodes on separate physical hosts, auto-scaling triggers, a current LTS JDK switchable from the dashboard, deployment from the dashboard or Git, built-in SSL with Let's Encrypt for custom domains, and per-cloudlet-hour billing on what the JVMs actually use. The JVM heap follows the container's cloudlet allocation, so no package needs hand-set memory flags. The differences are the runtime inside the node and the deployment model around it.

The five, in one table

PackageRuntimeArtefactProgramming modelState handlingBest for
Tomcat/TomEE ClusterServlet container (Tomcat) or Web Profile (TomEE)WARServlets, JSP, Spring MVC; TomEE adds CDI, JPA, JAX-RS, EJB LiteBuilt-in HTTP session replication, sticky sessionsClassic web apps with sessions, Spring WARs
WildFly Managed DomainFull Jakarta EEWAR, EARComplete EE: JMS, full EJB, JTA, clustering profilesHA profile clustering per server groupLarge EE applications, many servers, central management
GlassFish ClusterFull Jakarta EE (Eclipse GlassFish)WAR, EARComplete EE, the reference implementation lineageSession replication across instances via DAS-managed clusterEE applications built on GlassFish or Payara conventions
Spring Boot ClusterJava Engine (no server; embedded)Executable JARSpring BootStateless by convention; Spring Session with Redis, or stickySpring Boot services and APIs
Open Liberty in KubernetesOpen Liberty in containers on KubernetesContainer imageMicroProfile and Jakarta EE, container-firstStateless pods; external storesCloud-native microservices, teams already on Kubernetes

Sorting Ashworth's eight systems

The architect works through them by asking two questions of each: what does it need from the runtime, and how is it deployed today.

The two decisions people get wrong

Putting Spring Boot on Tomcat. It works, as a WAR, and teams do it out of habit. But Spring Boot embeds its own server, and the Java Engine nodes in the Spring Boot cluster run the JAR directly with less memory and nothing to configure. Use Tomcat for Spring only when the application is genuinely a WAR with servlet-container dependencies.

Choosing WildFly or GlassFish for a servlet application. A full EE server carries JMS, EJB containers and transaction managers that a servlet application never calls, and each server instance costs more heap for it. Tomcat, or TomEE when CDI and JPA are wanted without the rest, is lighter and the package's session replication covers the availability requirement. Reach for the full EE servers when the application uses the full EE.

Managing the estate

Eight systems on five packages sounds like sprawl, and on eight separately administered servers it was. On the platform it is eight environments in a few environment groups, each scaling and billing on its own, all deploying from Git through the Deployment Manager or a Maven build node, all with the same backup, TLS and alerting add-ons, and all clonable for testing. The Java version is a per-environment dropdown, so the 2009 portal stays on the JDK it was tested with while the fraud service runs the newest LTS, and the architect's upgrade plan is one clone at a time.

Cost shape

The Java Engine nodes for the Spring Boot services idle at 6 to 8 cloudlets (a cloudlet is 128 MiB of RAM plus 400 MHz of CPU) and the full EE servers at 20 to 30, because a full EE heap is larger; the domain and DAS controllers add a few each. Across the estate Ashworth averages about 220 cloudlets an hour, roughly $535 a month before discounts at MassiveGRID's published $0.003372 per cloudlet-hour, against eight always-on servers, two of which had carried commercial application-server licences that the open-source runtimes here do not need.

Frequently Asked Questions

Is Payara available, since GlassFish is often replaced by it?

The marketplace package is Eclipse GlassFish. Payara is a GlassFish derivative and Payara-targeted applications usually run on GlassFish unchanged; if you need Payara specifically, it can be deployed as a custom container or through the platform's Java stack list where available.

Can I run the Spring Boot cluster and a Tomcat cluster behind one domain?

Yes. Put a Traffic Distributor or an NGINX load balancer environment in front and route by path to the two environments over the internal network, or expose them on separate subdomains, which is simpler and the usual choice for APIs.

Which package gives the fastest deploy?

The Spring Boot cluster and Open Liberty on Kubernetes, because a JAR or a container image is a single artefact rolled sequentially. Tomcat WARs deploy quickly too. WildFly and GlassFish deployments to a server group or cluster target are fast once configured, but EE applications tend to be larger.

The right runtime for each Java application

Tomcat/TomEE, WildFly, GlassFish, Spring Boot and Open Liberty on Kubernetes all deploy as clusters in one click on MassiveGRID PaaS, on separate hosts with auto-scaling and per-cloudlet-hour billing. Free 14-day trial, no credit card.

GlassFish Cluster on MassiveGRID PaaS

Further Reading