Navigate the crisis. Find the way out.
ECHO is a desktop application built for disaster response scenarios. Traditional GPS and navigation services route users based purely on speed and distance — they have no awareness of active disaster zones. ECHO solves this by allowing field operators to log real-time hazards such as fires, floods, bridge collapses, and infrastructure failures. When an evacuation route is requested, ECHO calculates the safest path, not just the shortest one, dynamically routing around every active incident on record.
- Overview
- Features
- Tech Stack
- Architecture
- Project Structure
- Database Schema
- Getting Started
- Configuration
- How It Works
- UI Overview
- Contributors
ECHO was built as a Java capstone project with a focus on real-world applicability in humanitarian and disaster relief operations. The application is designed to be used by field coordinators, emergency responders, and evacuation teams who need a reliable, offline-capable tool that accounts for dynamic, on-the-ground conditions that commercial navigation apps are blind to.
The core problem ECHO addresses: commercial navigation routes through danger. When a road is flooded, a bridge has collapsed, or a wildfire is spreading, Google Maps and similar tools have no real-time awareness of those hazards unless they are officially reported at a government level — a process that takes hours. ECHO puts that reporting power directly in the hands of the people on the ground, instantly affecting route calculations for everyone on the network.
- Secure user registration and login with BCrypt password hashing
- Password strength enforcement — minimum 6 characters, at least 1 special character
- Real-time password strength indicator during signup (Weak / Fair / Good / Strong)
- Session management — protected routes redirect unauthenticated users to login
- Report any emergency with a title, type, scale, threat level, description, and location
- Four incident scales: Local (500m radius), Moderate (3km), Large (10km), Catastrophic (30km)
- Four threat levels: Low, Moderate, High, Critical
- Geocoding via Nominatim API — type any address and resolve it to coordinates automatically
- Click-to-pin on an embedded mini-map for precise location selection when address is ambiguous
- All incidents persisted to MySQL database with full user attribution
- Incidents remain loaded across app restarts (MySQL primary, JSON fallback)
- Input a departure point and destination in plain text
- Automatically avoids all active incident zones using OpenRouteService API
- Each incident's scale determines its avoidance radius — a Catastrophic event generates a 30km avoidance polygon, a Local event generates a 500km one
- Avoidance zones are computed as 12-point polygon approximations (dodecagons) around each incident center, passed to ORS as a GeoJSON MultiPolygon in the
options.avoid_polygonsfield - Safe route rendered as a green/teal polyline on the live map
- Blocked/alternate paths shown as red dashed polylines
- Step-by-step turn-by-turn directions displayed in the control panel
- Live count of active incidents and routes calculated, pulled from MySQL
- Map preview with real-time incident markers
- Recent incidents feed showing the 3 latest reports with severity color coding
- Zones cleared counter
- Interactive Leaflet.js map embedded inside JavaFX WebView
- OpenStreetMap tiles (CartoDB Positron greyscale style for the Navigator)
- Incident markers with pulsing circle animations color-coded by severity
- Bidirectional Java ↔ JavaScript bridge for seamless map interaction
- Two map modes: Navigator View (full route display) and Mini View (pin drop for reporting)
| Layer | Technology |
|---|---|
| Language | Java 17+ |
| UI Framework | JavaFX (FXML + CSS) |
| Build Tool | Apache Maven |
| Map Rendering | Leaflet.js (inside JavaFX WebView) |
| Map Tiles | OpenStreetMap / CartoDB Positron |
| Routing API | OpenRouteService (ORS) |
| Geocoding API | Nominatim (OpenStreetMap) |
| Database | MySQL 8.0 |
| Connection Pool | HikariCP 5.1.0 |
| Password Security | jBCrypt 0.4 |
| JSON Parsing | org.json |
| Font | Inter (Google Fonts) |
ECHO follows a strictly asynchronous Model-View-Controller (MVC) pattern.
┌─────────────────────────────────────────────────────┐
│ JavaFX UI Layer │
│ (FXML Views + CSS + Scene Manager) │
└────────────────────────┬────────────────────────────┘
│
┌────────────────────────▼────────────────────────────┐
│ Controller Layer │
│ LoginController │ SignupController │
│ DashboardController │ ReportIncidentController │
│ EvacuationNavigatorController │
└──────┬──────────────────────────┬───────────────────┘
│ │
┌──────▼──────┐ ┌────────▼────────────────────┐
│ Services │ │ WebView Bridge │
│ UserService│ │ Java → JS: executeScript() │
│ Geocoding │ │ JS → Java: javaReportBridge │
│ Routing │ │ (JSObject window.setMember) │
│ Incidents │ └─────────────────────────────┘
└──────┬──────┘
│
┌──────▼──────────────────────────────────────────────┐
│ Data Layer │
│ MySQL (HikariCP pool) │ incidents.json fallback │
└─────────────────────────────────────────────────────┘
Key architectural decisions:
- All HTTP calls (Nominatim, ORS) run on background
JavaFX Taskthreads — the UI never freezes - All database calls also run on background threads via
JavaFX Task - The Java-JS bridge is one-way for map commands (
executeScript) and reverse-callback for map click events (JSObject+ registered Java member) - Passwords never leave
UserService.javaas plaintext — BCrypt hash is computed and stored, raw password is discarded immediately after hashing SessionManageris a static singleton that gates access to all post-login screens
ECHO/
├── pom.xml
├── data/
│ └── incidents.json # Fallback local storage
└── src/main/
├── java/
│ ├── Main.java # JavaFX entry point
│ ├── controllers/
│ │ ├── LoginController.java
│ │ ├── SignupController.java
│ │ ├── DashboardController.java
│ │ ├── ReportIncidentController.java
│ │ └── EvacuationNavigatorController.java
│ ├── models/
│ │ ├── User.java
│ │ ├── Incident.java
│ │ ├── Route.java
│ │ └── Location.java
│ ├── services/
│ │ ├── DatabaseService.java
│ │ ├── UserService.java
│ │ ├── GeocodingService.java
│ │ ├── RoutingService.java
│ │ └── IncidentStorageService.java
│ └── utils/
│ ├── SceneManager.java
│ ├── SessionManager.java
│ ├── HttpClientUtil.java
│ └── Validator.java
└── resources/
├── views/
│ ├── login.fxml
│ ├── signup.fxml
│ ├── dashboard.fxml
│ ├── report.fxml
│ └── navigator.fxml
├── map.html # Leaflet.js map
├── styles/
│ └── main.css
└── config.properties # API keys + DB credentials (not committed to Git)
-- Users
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
full_name VARCHAR(100) NOT NULL,
mobile VARCHAR(15),
email VARCHAR(100) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL, -- BCrypt hash only, never plaintext
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Incidents
CREATE TABLE incidents (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
title VARCHAR(150) NOT NULL,
type VARCHAR(50),
scale ENUM('Local','Moderate','Large','Catastrophic'),
threat_level ENUM('Low','Moderate','High','Critical'),
description TEXT,
address VARCHAR(255),
lat DOUBLE,
lng DOUBLE,
reporter VARCHAR(100),
contact VARCHAR(15),
reported_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
-- Routes
CREATE TABLE routes (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
origin VARCHAR(255),
destination VARCHAR(255),
origin_lat DOUBLE,
origin_lng DOUBLE,
dest_lat DOUBLE,
dest_lng DOUBLE,
calculated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);The schema is auto-initialized on every app startup via DatabaseService.initializeSchema() using CREATE TABLE IF NOT EXISTS — safe to run repeatedly.
- Java 17 or higher
- Apache Maven 3.8+
- MySQL 8.0 running locally or on a remote host
- An OpenRouteService API key (free tier available at openrouteservice.org)
-
Clone the repository
git clone https://github.com/your-username/ECHO.git cd ECHO -
Create the MySQL database
CREATE DATABASE echo_db;
The tables are created automatically on first launch.
-
Configure the application
Edit
src/main/resources/config.properties:db.url=jdbc:mysql://localhost:3306/echo_db db.username=your_mysql_username db.password=your_mysql_password ors.api.key=your_openrouteservice_api_key nominatim.user.agent=ECHO-App/1.0
-
Build and run
mvn clean javafx:run
⚠️ Never commitconfig.propertiesto Git. It is listed in.gitignoreand contains your database credentials and API keys.
| Key | Description |
|---|---|
db.url |
JDBC connection string for MySQL |
db.username |
MySQL username |
db.password |
MySQL password |
ors.api.key |
OpenRouteService API key for routing |
nominatim.user.agent |
Custom User-Agent string for Nominatim requests (required by OSM policy) |
When a user submits a route request, RoutingService does the following:
- Fetches all active incidents from the database for the current session
- For each incident, reads its
scalefield and callsincident.getRadiusMeters():- Local → 500m
- Moderate → 3,000m
- Large → 10,000m
- Catastrophic → 30,000m
- Using the incident's center coordinates and computed radius, generates a 12-point polygon (dodecagon approximation of a circle) around the danger zone
- Bundles all polygons into a single GeoJSON MultiPolygon
- Passes this MultiPolygon to the ORS API via the
options.avoid_polygonsfield - ORS returns a route geometry that navigates around every active hazard
- The Java backend parses the returned coordinate arrays and passes them to Leaflet.js via
WebEngine.executeScript()for rendering
- Java → JS:
webEngine.executeScript("functionName(args)")— used for dropping markers, drawing polylines, panning the map - JS → Java: A Java inner class is registered on the JS
windowobject via((JSObject) webEngine.executeScript("window")).setMember("javaReportBridge", bridgeInstance)— the Leaflet map calls methods on this object when the user clicks to drop a location pin
| Screen | Description |
|---|---|
| Login | Split layout — minimal white form panel on the left, 3D wireframe globe with cyan network lines on the right |
| Sign Up | Full dark background with topographic grid and ghost ECHO watermark, centered frosted glass card |
| Dashboard | Navbar + live stats cards + map preview + recent incidents feed |
| Distress Report | Two-card layout — incident form with segmented controls on the left, interactive mini-map with pulsing location pin on the right |
| Route Finder | Large map panel on the left (~70%), incident list + route input controls on the right (~30%) |
The entire UI uses a greyscale-dominant design system with Electric Cyan (#00BCD4) and Teal (#006876) as the primary action colors, and Amber (#fdc003) for warnings. All screens are built with JavaFX FXML and a custom main.css.
| Name | Role |
|---|---|
| Granth | Lead Developer, UI/UX Design, Backend Architecture |
| Sachin Kumar Jha | Collaborator |
Built as a Java Semester 2 capstone project. ECHO is not affiliated with any government or emergency services organization. For demonstration and educational purposes.