Apache Geronimo is an open-source Java EE application server that implements the full Java Enterprise Edition specification — including EJB, JPA, JMS, and Servlet containers — in a modular OSGi-based runtime. Like most Java EE servers, Geronimo can enter a state where the JVM process is alive and the admin console is reachable while deployed applications are broken: connection pool exhaustion, JNDI binding failures after a hot redeploy, or an out-of-memory condition in one module that doesn't kill the container but renders it non-functional.
Vigilmon gives you external visibility into Geronimo availability through HTTP probe monitoring and heartbeat monitoring for scheduled background jobs. This tutorial walks through both.
Why Apache Geronimo Monitoring Matters
Geronimo's modular OSGi architecture is a strength — modules start and stop independently — but it introduces failure modes invisible to process monitors:
- A deployed web application can fail its startup sequence (missing JNDI resource, broken data source) while the Geronimo container process itself stays healthy, returning HTTP 404 or 500 for every request to the app
- JDBC connection pool exhaustion leaves the server running but unable to serve any database-backed request — and pools can exhaust slowly over hours without triggering any process-level alarm
- JVM OutOfMemoryError in one classloader can prevent a single WAR from functioning without crashing the JVM or other deployed modules
- The Geronimo admin console on port 8443 can be reachable while the application on port 8080 is not — admin console availability does not imply application availability
- JMX-reported thread pool exhaustion only becomes visible when you actively query JMX, not through passive process monitoring
External monitoring through Vigilmon tests whether your actual application endpoints are responding, not just whether the process is alive.
Step 1: Identify the Right Endpoint to Monitor
Geronimo serves applications under their deployment context roots. Identify the health check endpoint for each deployed application:
# Check if Geronimo itself is up (default HTTP port)
curl -i http://your-geronimo-host:8080/
# Check a specific deployed application
curl -i http://your-geronimo-host:8080/your-app/health
If your deployed application doesn't have a /health endpoint, add one.
Servlet-Based Health Endpoint (Java)
Add a health servlet to your WAR to expose application-level health:
// HealthServlet.java — deploy inside your WAR
package com.example.health;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import java.sql.Connection;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
@javax.servlet.annotation.WebServlet("/health")
public class HealthServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("application/json");
PrintWriter out = resp.getWriter();
// Check 1: JNDI data source lookup
try {
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/AppDS");
// Check 2: Actually acquire a connection from the pool
try (Connection conn = ds.getConnection()) {
conn.isValid(2); // 2-second timeout
}
resp.setStatus(HttpServletResponse.SC_OK);
out.println("{\"status\":\"ok\",\"db\":\"ok\"}");
} catch (Exception e) {
resp.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
out.println("{\"status\":\"down\",\"error\":\"" + e.getMessage().replace("\"", "'") + "\"}");
}
}
}
Register it in web.xml if not using annotations:
<!-- web.xml excerpt -->
<servlet>
<servlet-name>HealthServlet</servlet-name>
<servlet-class>com.example.health.HealthServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HealthServlet</servlet-name>
<url-pattern>/health</url-pattern>
</servlet-mapping>
Sidecar Health Endpoint (Node.js)
If you cannot modify the deployed WAR, use a sidecar that probes the app externally:
// geronimo-health.js — external probe sidecar
const express = require('express');
const axios = require('axios');
const app = express();
const GERONIMO_APP_URL = process.env.GERONIMO_APP_URL || 'http://localhost:8080/your-app';
app.get('/health/geronimo', async (req, res) => {
try {
// Probe the actual application endpoint
const r = await axios.get(`${GERONIMO_APP_URL}/health`, {
timeout: 10000,
validateStatus: null,
});
if (r.status !== 200) {
return res.status(503).json({
status: 'down',
upstream_status: r.status,
upstream_body: r.data,
});
}
// Also check admin console reachability
await axios.get('http://localhost:8443/', {
timeout: 5000,
validateStatus: s => s < 500,
httpsAgent: new (require('https').Agent)({ rejectUnauthorized: false }),
});
return res.status(200).json({ status: 'ok' });
} catch (err) {
return res.status(503).json({ status: 'down', error: err.message });
}
});
app.listen(3001);
Deploy and verify:
curl -i https://your-app.example.com/health/geronimo
# HTTP/1.1 200 OK
# {"status":"ok"}
Step 2: Configure a Vigilmon HTTP Monitor for Apache Geronimo
- Log in to vigilmon.online and go to Monitors → New Monitor
- Choose HTTP / HTTPS
- Set the URL to your health endpoint:
https://your-app.example.com/health/geronimo - Set the check interval to 1 minute
- Under Expected response, configure:
- Status code:
200 - Response body contains:
"status":"ok" - Response time threshold:
5000ms(Java EE startup and JNDI lookups can be slow)
- Status code:
- Under Alert channels, assign your Slack or email channel
- Save the monitor
Vigilmon probes from multiple geographic regions. A transient single-probe failure won't page you — Vigilmon requires multi-region consensus before opening an incident, so alert noise stays low.
Failure Coverage
| Failure Mode | Process Monitor | Vigilmon | |---|---|---| | Geronimo JVM crash | ✓ | ✓ | | Application WAR deploy failure | ✗ | ✓ | | JDBC connection pool exhaustion | ✗ | ✓ | | JNDI resource lookup failure | ✗ | ✓ | | Thread pool saturation | ✗ | ✓ | | OOM in one module | ✗ | ✓ |
Step 3: Heartbeat Monitoring for Geronimo Scheduled Jobs
Geronimo applications often run scheduled EJB timers or Quartz jobs for batch processing, report generation, or data synchronization. These jobs stop silently when the application enters a broken state — and because they're background processes, users may not notice for hours.
Vigilmon's heartbeat monitors detect silent job death: your scheduled job sends a ping to Vigilmon after each successful execution. If the ping stops arriving within the expected window, Vigilmon fires an alert.
Set Up the Heartbeat Monitor
- In Vigilmon, go to Monitors → New Monitor → Heartbeat
- Set the name:
geronimo-batch-job - Set the expected interval to match your job schedule (e.g., 15 minutes)
- Set the grace period: 30 minutes
- Save — copy the heartbeat URL, e.g.
https://vigilmon.online/heartbeat/abc123xyz
Wire It Into Your EJB Timer
// BatchJobBean.java — EJB timer that pings Vigilmon after each run
import javax.ejb.*;
import java.net.HttpURLConnection;
import java.net.URL;
@Stateless
@LocalBean
public class BatchJobBean {
private static final String HEARTBEAT_URL = System.getenv("VIGILMON_HEARTBEAT_URL");
@Schedule(minute = "*/15", hour = "*", persistent = false)
public void runBatchJob() {
try {
// Your batch processing logic here
processBatch();
// Ping Vigilmon only after successful completion
pingVigilmon();
} catch (Exception e) {
// Log but don't ping Vigilmon — the absence of a ping is the alert
log("Batch job failed: " + e.getMessage());
}
}
private void pingVigilmon() {
try {
HttpURLConnection conn = (HttpURLConnection) new URL(HEARTBEAT_URL).openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.getResponseCode();
conn.disconnect();
} catch (Exception ignored) {}
}
}
Quartz-Based Scheduler
// VigilmonHeartbeatListener.java — Quartz job listener
import org.quartz.*;
import java.net.HttpURLConnection;
import java.net.URL;
public class VigilmonHeartbeatListener implements JobListener {
@Override
public String getName() { return "VigilmonHeartbeat"; }
@Override
public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
if (jobException != null) return; // Don't ping on failure
try {
String url = System.getenv("VIGILMON_HEARTBEAT_URL");
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(3000);
conn.getResponseCode();
} catch (Exception ignored) {}
}
@Override public void jobToBeExecuted(JobExecutionContext context) {}
@Override public void jobExecutionVetoed(JobExecutionContext context) {}
}
Step 4: Monitor Multiple Applications on Geronimo
Geronimo can host multiple WARs and EARs simultaneously. Each deployed application should have its own Vigilmon monitor:
[geronimo] /app-one/health
[geronimo] /app-two/health
[geronimo] /app-three/health
[geronimo-admin] :8443/console/
Name monitors with the application name in brackets so alert notifications immediately identify which application is down.
Group all Geronimo application monitors into a single Vigilmon Status Page so your team has one view of the entire Geronimo deployment tier.
Step 5: Alert Routing for Java EE Outages
Java EE application server outages have long blast radii — a single JDBC pool exhaustion event can take down every application deployed on the server simultaneously.
Configure alert channels in Vigilmon:
- Application health monitors → immediate Slack + PagerDuty (P1 — user-facing impact)
- Admin console monitor → Slack (P2 — reduced ops visibility)
- Scheduled job heartbeats → Slack + email (P2 — batch processing failure)
Set a response time threshold of 3000ms on application health monitors. Java EE response time degradation (thread pool saturation, JDBC wait times) precedes full failure — catching latency spikes early lets your team scale or recycle the pool before users see errors.
Summary
Apache Geronimo's modular architecture means applications fail independently of the server process. Vigilmon catches application-level failures that process monitors miss entirely.
| Monitor Type | What It Covers |
|---|---|
| HTTP monitor on /your-app/health | Application availability, JNDI, connection pool |
| HTTP monitor on admin console | Ops tool availability |
| Heartbeat monitor | Scheduled EJB timer and batch job liveness |
Get started free at vigilmon.online — your first Geronimo application monitor takes under two minutes to configure.