docs
Architecture
How the URL Shortener is structured — modules, data flow, and design decisions.
Overview
The URL Shortener is a 6-module Maven reactor (plus root) built on plain Java with zero external framework dependencies. Each module has a single, well-defined responsibility.
graph TB
Browser["🌐 Browser / Client"]
Agent["🤖 AI Agent"]
UI["urlshortener-ui\nVaadin WAR\n:8080"]
Server["urlshortener-server\nREST Admin API\n:9090"]
Redirect["Redirect Server\n:8081"]
MCP["urlshortener-mcp\nMCP Server\n:9091"]
Core["urlshortener-core\nDomain Model"]
Client["urlshortener-client\nJava HTTP Client"]
Store["Storage Layer\nIn-Memory / EclipseStore"]
Browser -->|"Short link GET /{code}"| Redirect
Browser -->|"Manage links"| UI
Agent -->|"JSON-RPC 2.0 POST /mcp"| MCP
UI -->|"HTTP REST"| Client
MCP -->|"HTTP REST"| Client
Client -->|"HTTP/JSON"| Server
Server --> Core
Server --> Store
Redirect --> Store
Modules
urlshortener-core
The shared domain model. Has no dependencies on the other modules.
ShortUrlMapping— the central entity (shortCode, originalUrl, active, expiresAt)Base62Encoder— generates short codes from a 62-character alphabetAliasPolicy— validates custom aliases (3–32 chars,[A-Za-z0-9_-])UrlValidator— rejects malformed or unsafe URLsRedirectEvent,HourlyAggregate,DailyAggregate— statistics models
urlshortener-server
The runtime process. Starts two com.sun.net.httpserver.HttpServer instances.
| Instance | Port | Handler |
|---|---|---|
| Admin API | 9090 | AdminApiHandler — full CRUD + import/export |
| Redirect | 8081 | RedirectHandler — resolves short codes, records events |
Storage is injected via interface:
UrlMappingStore ──→ InMemoryUrlMappingStore
└─→ EclipseStoreUrlMappingStore
urlshortener-client
A pure-Java HTTP client for the Admin API. Used by the UI and useful for scripting or CI pipelines.
Key classes: URLShortenerClient, StatisticsClient, AdminClient, ColumnVisibilityClient
urlshortener-ui
A Vaadin web application packaged as a WAR for Jetty 12.
Views:
| View | Path | Description |
|---|---|---|
| CreateView | /create | Form to create/edit short links |
| OverviewView | /overview | Grid with all mappings, filters, pagination |
| StatisticsView | /statistics | Hourly/daily charts |
| StatisticsDetailView | /statistics/{code} | Per-link deep dive |
| ProfileView | /profile | API key self-service (create, list, revoke) |
| AboutView | /about | Project info |
urlshortener-cli
A command-line interface for scripting and CI pipelines, delegating to the client SDK.
urlshortener-mcp
A Model Context Protocol server exposing the shortener as agent tools over JSON-RPC 2.0 (POST /mcp). Delegates to the client SDK; every call carries the caller’s X-API-Key so jSentinel remains the single authorization point. Ships as a runnable fat-jar; bind host and port are configurable (-Dmcp.host / -Dmcp.port).
| Tool group | Tools |
|---|---|
| Links | create_short_link, resolve_shortcode, edit_link, toggle_active, delete_link, list_links, bulk_create_links, bulk_validate, export_links, import_links_validate, import_links_apply |
| Statistics | get_statistics, get_statistics_daily, get_statistics_hourly, get_statistics_timeline, get_statistics_config, export_statistics, import_statistics |
Data Flow: Creating a Short Link
sequenceDiagram
actor User
participant UI as Vaadin UI
participant Client as URLShortenerClient
participant Server as Admin API :9090
participant Core as Core (AliasPolicy)
participant Store as Storage
User->>UI: Fill form, click "Shorten"
UI->>Client: createShortUrl(originalUrl, alias)
Client->>Server: POST /api/shorten (JSON)
Server->>Core: validate alias + URL
Core-->>Server: OK / ValidationError
Server->>Store: save(ShortUrlMapping)
Store-->>Server: stored
Server-->>Client: 201 Created + ShortUrlMapping
Client-->>UI: ShortUrlMapping
UI-->>User: Display short link
Data Flow: Redirect
sequenceDiagram
actor Visitor
participant Redirect as Redirect Server :8081
participant Store as Storage
participant Stats as StatisticsStore
Visitor->>Redirect: GET /oss-project
Redirect->>Store: lookup("oss-project")
Store-->>Redirect: ShortUrlMapping
Redirect->>Stats: record(RedirectEvent)
Redirect-->>Visitor: 302 → originalUrl
Storage Architecture
flowchart TB
UrlMappingStore["UrlMappingStore
interface
save(mapping)
findByCode(code)
findAll()
delete(code)"]
StatisticsStore["StatisticsStore
interface
record(event)
getHourly(code)
getDaily(code)"]
InMemoryStore["InMemoryUrlMappingStore
ConcurrentHashMap data"]
EclipseStore["EclipseStoreUrlMappingStore
EmbeddedStorageManager manager
DataRoot root"]
StatisticsImpl["StatisticsStore implementation
redirect events and aggregates"]
UrlMappingStore -. implemented by .-> InMemoryStore
UrlMappingStore -. implemented by .-> EclipseStore
StatisticsStore -. implemented by .-> StatisticsImpl
InMemoryStore -->|"development mode"| Runtime["Server runtime"]
EclipseStore -->|"persistent mode"| Runtime
StatisticsImpl --> Runtime
Design Decisions
| Decision | Choice | Reason |
|---|---|---|
| HTTP server | JDK HttpServer | Zero dependencies, educational clarity |
| Serialization | Jackson 3 | Industry standard, lightweight |
| Persistence | EclipseStore | Pure-Java, no SQL schema migration |
| UI | Vaadin | Server-side Java, no manual JS |
| Build | Maven multi-module | Standard Java tooling |
| Short codes | Base62 | URL-safe, compact, well-understood |
