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 alphabet
  • AliasPolicy — validates custom aliases (3–32 chars, [A-Za-z0-9_-])
  • UrlValidator — rejects malformed or unsafe URLs
  • RedirectEvent, HourlyAggregate, DailyAggregate — statistics models

urlshortener-server

The runtime process. Starts two com.sun.net.httpserver.HttpServer instances.

InstancePortHandler
Admin API9090AdminApiHandler — full CRUD + import/export
Redirect8081RedirectHandler — 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:

ViewPathDescription
CreateView/createForm to create/edit short links
OverviewView/overviewGrid with all mappings, filters, pagination
StatisticsView/statisticsHourly/daily charts
StatisticsDetailView/statistics/{code}Per-link deep dive
ProfileView/profileAPI key self-service (create, list, revoke)
AboutView/aboutProject 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 groupTools
Linkscreate_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
Statisticsget_statistics, get_statistics_daily, get_statistics_hourly, get_statistics_timeline, get_statistics_config, export_statistics, import_statistics

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

DecisionChoiceReason
HTTP serverJDK HttpServerZero dependencies, educational clarity
SerializationJackson 3Industry standard, lightweight
PersistenceEclipseStorePure-Java, no SQL schema migration
UIVaadinServer-side Java, no manual JS
BuildMaven multi-moduleStandard Java tooling
Short codesBase62URL-safe, compact, well-understood