Embedding Jetty means shipping your Java application and its web container together as a single runnable unit. For DevOps teams operating critical services, this model can reduce environment drift, simplify rollback, and keep test and production behavior closer together.
This guide explains the production pattern described in the original post, where it helps most, and what you must explicitly design for monitoring, security, load balancing, and operational consistency.
Originally published on 2010-03-09; fully revised and updated.

What embedded Jetty changes in production
In a traditional Java setup, multiple applications are deployed into a shared application server. In an embedded model, each application carries its own server runtime (Jetty libraries) and starts from its own main method. Practically, this shifts control from platform-level deployment to application-level deployment.
The original seminar example used this model to avoid server-level dependency constraints and to make deployment as simple as replacing one JAR with another.
Deployment model: one artifact, minimal host prerequisites
The original post demonstrates packaging and shipping a standalone artifact (example project: embedded-container sample application) and requiring only a JVM on the target host.
mvn clean install
scp server/target/app-1.0.onejar.jar appuser@appserver:/home/appuser/test-env1/
ssh appuser@appserver "cd /home/appuser/test-env1/ && java -jar app-1.0.onejar.jar &"Code language: JavaScript (javascript)
This enables straightforward rollback (replace artifact with a previous one) and easy horizontal scaling (run multiple instances with separate ports and process supervision).
Why teams adopt this pattern
- Runtime independence: each service can evolve JVM and library choices without coordinating every change across a shared server platform.
- Dependency control: application dependencies are bundled and versioned with the service, reducing classpath surprises from server-provided libraries.
- Simpler release mechanics: deployment and rollback are artifact operations rather than app-server console operations.
- CI/CD friendliness: immutable artifacts map cleanly to pull- or push-based deployment workflows.
- Test and production parity: you can start Jetty inside tests (example from the original post: JUnit-based Jetty startup), reducing server-behavior differences between environments.
- Operational clarity: operations teams can work with standard process controls (start, stop, status, logs) per service.
Operational capabilities you must explicitly own
When you stop relying on a full external app server, you gain control but also inherit explicit responsibilities.
Monitoring and health checks
At minimum, write logs to a known location and expose a health endpoint that checks application-critical dependencies (database, downstream services, file shares, queues).
curl -fsS http://127.0.0.1:8080/healthCode language: JavaScript (javascript)
Load balancing and session behavior
Embedded Jetty does not automatically provide cluster routing behavior. Handle load balancing at reverse proxy, ingress, or network tiers, and decide whether you need sticky sessions. The original post points to Jetty-related proxy/session guidance here: Configuring mod_proxy.
Security boundaries
The source notes JAAS support and SSO patterns where identity is forwarded via HTTP headers. In production, this only works safely when those headers are injected by a trusted upstream component and spoofed headers are stripped at the edge.
Consistency across services
Standardize service layout and operations: startup commands, log paths, config conventions, health URLs, and runbooks. This keeps multi-service operations manageable even when each app owns its runtime.
Deployment and runtime workflow
flowchart TD
A[Build with Maven] --> B[Create runnable artifact]
B --> C[Publish artifact]
C --> D[Copy or pull to target host]
D --> E[Start java jar process]
E --> F[Serve traffic behind proxy]
E --> G[Expose health endpoint]
G --> H[Monitoring checks]
E --> I[Write logs]
I --> J[Central log collection]
H --> K{Healthy}
K -- no --> L[Restart or rollback]
K -- yes --> M[Continue serving]
Minimal embedded Jetty bootstrap example
A small bootstrap class illustrates the model: the application constructs and starts Jetty directly.
public class App {
public static void main(String[] args) throws Exception {
int port = Integer.parseInt(System.getProperty("server.port", "8080"));
Server server = new Server(port);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.addServlet(HealthServlet.class, "/health");
context.addServlet(AppServlet.class, "/*");
server.setHandler(context);
server.start();
server.join();
}
}Code language: JavaScript (javascript)
Externalize runtime settings rather than hardcoding them:
server.port=8080
app.environment=production
log.dir=/var/log/myapp
health.check.dependencies=trueCode language: JavaScript (javascript)
Embedded Jetty vs shared application server
| Option | Strengths | Trade-offs | Best for |
|---|---|---|---|
| Embedded Jetty per application | Strong app isolation, consistent packaging, easy rollback, simpler per-service CI/CD | You must implement operational standards yourself (health, supervision, conventions) | Service-oriented teams that want independent release velocity |
| Shared external application server | Centralized platform controls and shared operational model | Cross-app dependency coupling, slower coordinated upgrades, potential classpath conflicts | Environments with strict centralized middleware governance |
Best practices for mission-critical use
- Treat the deployable artifact as immutable and versioned.
- Use process supervision (systemd, container orchestrator, or equivalent) rather than ad-hoc background processes.
- Make health checks dependency-aware, not just process-aware.
- Keep config external and environment-specific.
- Define a standard service contract: ports, logs, metrics, startup, shutdown, and alerting behavior.
- Validate authentication header trust boundaries at the reverse proxy layer.
Historical reference from the original post: http://www.javaworld.com/community/?q=node/4133
I’m Rajesh Kumar, a DevOps, SRE, DevSecOps, Cloud, and Platform Engineering expert passionate about sharing practical knowledge, real-world experiences, and industry best practices. I have worked at Cotocus and regularly write about technology, travel, investing, health, product reviews, and digital marketing through my various platforms.
I publish technical articles at DevOps School, travel stories at Holiday Landmark, stock market insights at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow, and SEO and digital marketing strategies at Wizbrand.
Find Trusted Cardiac Hospitals
Compare heart hospitals by city and services — all in one place.
Explore Hospitals