Skip to content
Flag of Europe
Made in the European Union · Independently built · Released under EUPL 1.2

← URL Shortener

Architecture

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.

6-module Maven reactor Plain Java No framework In-memory or EclipseStore
    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

Six modules with explicit boundaries — the shared domain model, the server runtime, a Java client, the Vaadin UI, a CLI and the MCP server.

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 jCustos 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, set_statistics_enabled, update_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<br/><small>interface</small><br/>save(mapping)<br/>findByCode(code)<br/>findAll()<br/>delete(code)"]
    StatisticsStore["StatisticsStore<br/><small>interface</small><br/>record(event)<br/>getHourly(code)<br/>getDaily(code)"]
    InMemoryStore["InMemoryUrlMappingStore<br/><small>ConcurrentHashMap data</small>"]
    EclipseStore["EclipseStoreUrlMappingStore<br/><small>EmbeddedStorageManager manager<br/>DataRoot root</small>"]
    StatisticsImpl["StatisticsStore implementation<br/><small>redirect events and aggregates</small>"]

    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

Next: REST API →