# vasiliy-spb/tennis_scoreboard architecture

> Architecture diagram of the GitHub repository vasiliy-spb/tennis_scoreboard, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-02). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/vasiliy-spb/tennis_scoreboard
- Repository: https://github.com/vasiliy-spb/tennis_scoreboard

## Overview

#### Purpose and Runtime
A Java web application for creating, scoring, viewing, and persisting tennis matches. It is built with Gradle and deployed as a servlet/JSP application; the HTTP deployment descriptor is `src/main/webapp/WEB-INF/web.xml`. UI pages are server-rendered JSPs under `src/main/webapp/WEB-INF/jsp`.

#### Application Bootstrap and Dependency Wiring
Startup configuration initializes application-scoped dependencies, Hibernate, and optional data initialization. `src/main/java/dev/chearcode/config/AppInitializer.java`, `src/main/java/dev/chearcode/config/ApplicationConfig.java`, and `src/main/java/dev/chearcode/config/ApplicationContext.java` form a custom bootstrap/bean-access layer. Database settings are supplied through `src/main/resources/application.properties`.

#### HTTP Entry Points and Request Boundary
Servlets implement the user-facing workflow:
- Home: `src/main/java/dev/chearcode/servlet/HomeServlet.java`
- New match creation: `src/main/java/dev/chearcode/servlet/NewMatchServlet.java`
- Ongoing match scoring: `src/main/java/dev/chearcode/servlet/MatchScoreServlet.java`
- Persisted match listing: `src/main/java/dev/chearcode/servlet/MatchesServlet.java`
- Data initialization: `src/main/java/dev/chearcode/servlet/DataInitializationServlet.java`

`src/main/java/dev/chearcode/servlet/BaseServlet.java` supplies shared servlet behavior. JSP views such as `src/main/webapp/WEB-INF/jsp/match-score.jsp` consume DTO-oriented request data.

#### Tennis Scoring Domain
The core domain is an in-memory tennis scoring state machine. `src/main/java/dev/chearcode/model/TennisMatch.java` coordinates players, sets, and point progression; `src/main/java/dev/chearcode/model/TennisSet.java` and `src/main/java/dev/chearcode/model/Game.java` model normal scoring; `src/main/java/dev/chearcode/model/TieBreak.java` handles tie-break progression. Score-level abstractions in `src/main/java/dev/chearcode/model/TennisLevel.java` and `src/main/java/dev/chearcode/model/CompositeTennisLevel.java` separate nested score levels from match orchestration.

#### Ongoing-Match Lifecycle
Active matches are held outside the database through `src/main/java/dev/chearcode/service/InMemoryOngoingMatchStorage.java`, behind `src/main/java/dev/chearcode/service/OngoingMatchStorage.java`. `src/main/java/dev/chearcode/service/OngoingMatchServiceImpl.java` creates/retrieves active matches and advances their score based on servlet actions. This is a material boundary: active score state is process-local and will not survive application restart or scale across instances.

#### Persistence and Mapping
Completed or stored matches are represented by Hibernate entities `src/main/java/dev/chearcode/entity/Match.java` and `src/main/java/dev/chearcode/entity/Player.java`. `src/main/java/dev/chearcode/repository/MatchRepositoryImpl.java` is the database access layer, while `src/main/java/dev/chearcode/service/PersistenceMatchServiceImpl.java` owns persistence-facing use cases. Mapping layers translate among web DTOs, domain models, and entities, notably `src/main/java/dev/chearcode/mapper/DtoModelMatchMapper.java`, `src/main/java/dev/chearcode/mapper/ModelEntityMatchMapper.java`, and `src/main/java/dev/chearcode/mapper/EntityDtoMatchMapper.java`.

#### Cross-Cutting Boundaries
Hibernate session infrastructure is managed by `src/main/java/dev/chearcode/config/HibernateManager.java`; transactional request handling is centralized in `src/main/java/dev/chearcode/filter/TransactionManager.java`. `src/main/java/dev/chearcode/filter/ExceptionHandler.java` converts application failures into error responses/views. Input validation is performed before service/domain use through `src/main/java/dev/chearcode/validation/MatchValidator.java` and `src/main/java/dev/chearcode/validation/UuidValidator.java`.

#### Primary Flow
A user submits player details to `NewMatchServlet`; request DTOs are validated and mapped into `TennisMatch`, then stored in the in-memory active-match service. Score actions reach `MatchScoreServlet`, which updates the domain scoring hierarchy. Match data is mapped for `match-score.jsp`; completed or explicitly saved matches flow through persistence services/repositories to Hibernate-backed storage. `MatchesServlet` retrieves persisted match DTOs, with pagination support via `src/main/java/dev/chearcode/util/PaginationHelper.java`.

Main entry points: [`src/main/java/dev/chearcode/servlet/NewMatchServlet.java`](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/servlet/NewMatchServlet.java) (Workflow servlets), [`src/main/java/dev/chearcode/service/PersistenceMatchServiceImpl.java`](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/service/PersistenceMatchServiceImpl.java) (Persistence match service), [`src/main/java/dev/chearcode/service/OngoingMatchServiceImpl.java`](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/service/OngoingMatchServiceImpl.java) (Ongoing match service), [`src/main/java/dev/chearcode/repository/MatchRepositoryImpl.java`](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/repository/MatchRepositoryImpl.java) (Match repository)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_web["Web request layer"]
  node_webxml["Servlet deployment<br/>web descriptor<br/>[web.xml]"]
  node_servlets["Workflow servlets"]
  node_validation["Request validation<br/>validators"]
  node_jsp["JSP views<br/>server-rendered views<br/>[match-score.jsp]"]
end

subgraph group_scoring["Active scoring"]
  node_ongoingservice["Ongoing match service"]
  node_ongoingstorage[("Active match storage<br/>in-memory storage")]
  node_tennismatch["Tennis match<br/>scoring orchestrator<br/>[TennisMatch.java]"]
  node_tennisset["Set and game scoring<br/>score levels<br/>[TennisSet.java]"]
  node_tiebreak["Tie-break scoring<br/>score level<br/>[TieBreak.java]"]
  node_dtomodel["DTO-to-domain mapper"]
end

subgraph group_persistence["Persistence"]
  node_persistservice["Persistence match service"]
  node_modelentity["Domain-to-entity mapper"]
  node_entitydto["Entity-to-DTO mapper"]
  node_repository["Match repository<br/>Hibernate repository"]
  node_entities["Match and player entities<br/>Hibernate entities<br/>[Match.java]"]
  node_database[("Match database<br/>relational database")]
end

subgraph group_infra["Bootstrap and infrastructure"]
  node_initializer["Application bootstrap<br/>startup configuration"]
  node_context["Application context<br/>custom bean context"]
  node_hibernate["Hibernate manager<br/>session infrastructure"]
  node_properties["Database settings<br/>application properties"]
  node_transaction["Transaction manager<br/>request filter"]
  node_exceptions["Exception handler<br/>error filter"]
end

node_webxml -->|"routes requests"| node_servlets
node_webxml -->|"installs filter"| node_transaction
node_webxml -->|"installs filter"| node_exceptions
node_servlets -->|"validates input"| node_validation
node_servlets -->|"maps creation DTOs"| node_dtomodel
node_dtomodel -->|"creates active match"| node_ongoingservice
node_servlets -->|"scores and retrieves"| node_ongoingservice
node_ongoingservice -->|"stores active state"| node_ongoingstorage
node_ongoingservice -->|"advances"| node_tennismatch
node_tennismatch -->|"coordinates"| node_tennisset
node_tennisset -->|"uses when required"| node_tiebreak
node_servlets -->|"renders DTOs"| node_jsp
node_servlets -->|"saves and lists matches"| node_persistservice
node_persistservice -->|"maps for save"| node_modelentity
node_persistservice -->|"maps for views"| node_entitydto
node_modelentity -->|"produces"| node_entities
node_repository -->|"persists"| node_entities
node_persistservice -->|"uses"| node_repository
node_repository -->|"reads and writes"| node_database
node_initializer -->|"initializes"| node_context
node_initializer -->|"initializes"| node_hibernate
node_properties -->|"configures"| node_hibernate
node_transaction -->|"manages sessions"| node_hibernate
node_hibernate -->|"provides sessions"| node_repository
node_exceptions -.->|"renders failures"| node_jsp

click node_webxml "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/webapp/WEB-INF/web.xml"
click node_servlets "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/servlet/NewMatchServlet.java"
click node_validation "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/validation/MatchValidator.java"
click node_jsp "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/webapp/WEB-INF/jsp/match-score.jsp"
click node_ongoingservice "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/service/OngoingMatchServiceImpl.java"
click node_ongoingstorage "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/service/InMemoryOngoingMatchStorage.java"
click node_tennismatch "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/model/TennisMatch.java"
click node_tennisset "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/model/TennisSet.java"
click node_tiebreak "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/model/TieBreak.java"
click node_dtomodel "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/mapper/DtoModelMatchMapper.java"
click node_persistservice "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/service/PersistenceMatchServiceImpl.java"
click node_modelentity "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/mapper/ModelEntityMatchMapper.java"
click node_entitydto "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/mapper/EntityDtoMatchMapper.java"
click node_repository "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/repository/MatchRepositoryImpl.java"
click node_entities "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/entity/Match.java"
click node_initializer "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/config/AppInitializer.java"
click node_context "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/config/ApplicationContext.java"
click node_hibernate "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/config/HibernateManager.java"
click node_properties "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/resources/application.properties"
click node_transaction "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/filter/TransactionManager.java"
click node_exceptions "https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/filter/ExceptionHandler.java"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_webxml,node_servlets,node_validation,node_jsp toneBlue
class node_ongoingservice,node_ongoingstorage,node_tennismatch,node_tennisset,node_tiebreak,node_dtomodel toneAmber
class node_persistservice,node_modelentity,node_entitydto,node_repository,node_entities,node_database toneMint
class node_initializer,node_context,node_hibernate,node_properties,node_transaction,node_exceptions toneRose
```

## Components

### Web request layer

- [Servlet deployment](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/webapp/WEB-INF/web.xml): web descriptor · `src/main/webapp/WEB-INF/web.xml`
- [Workflow servlets](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/servlet/NewMatchServlet.java): servlets · Home, creation, scoring, listing, and data initialization endpoints. · `src/main/java/dev/chearcode/servlet/NewMatchServlet.java`
- [Request validation](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/validation/MatchValidator.java): validators · `src/main/java/dev/chearcode/validation/MatchValidator.java`
- [JSP views](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/webapp/WEB-INF/jsp/match-score.jsp): server-rendered views · Views consume DTO-oriented request data. · `src/main/webapp/WEB-INF/jsp/match-score.jsp`

### Active scoring

Active match state is process-local.

- [Ongoing match service](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/service/OngoingMatchServiceImpl.java): service · Creates, retrieves, and advances active matches. · `src/main/java/dev/chearcode/service/OngoingMatchServiceImpl.java`
- [Active match storage](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/service/InMemoryOngoingMatchStorage.java): in-memory storage · State does not survive restart or span application instances. · `src/main/java/dev/chearcode/service/InMemoryOngoingMatchStorage.java`
- [Tennis match](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/model/TennisMatch.java): scoring orchestrator · `src/main/java/dev/chearcode/model/TennisMatch.java`
- [Set and game scoring](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/model/TennisSet.java): score levels · `src/main/java/dev/chearcode/model/TennisSet.java`
- [Tie-break scoring](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/model/TieBreak.java): score level · `src/main/java/dev/chearcode/model/TieBreak.java`
- [DTO-to-domain mapper](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/mapper/DtoModelMatchMapper.java): mapper · `src/main/java/dev/chearcode/mapper/DtoModelMatchMapper.java`

### Persistence

- [Persistence match service](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/service/PersistenceMatchServiceImpl.java): service · Owns saved-match use cases. · `src/main/java/dev/chearcode/service/PersistenceMatchServiceImpl.java`
- [Domain-to-entity mapper](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/mapper/ModelEntityMatchMapper.java): mapper · `src/main/java/dev/chearcode/mapper/ModelEntityMatchMapper.java`
- [Entity-to-DTO mapper](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/mapper/EntityDtoMatchMapper.java): mapper · `src/main/java/dev/chearcode/mapper/EntityDtoMatchMapper.java`
- [Match repository](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/repository/MatchRepositoryImpl.java): Hibernate repository · `src/main/java/dev/chearcode/repository/MatchRepositoryImpl.java`
- [Match and player entities](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/entity/Match.java): Hibernate entities · `src/main/java/dev/chearcode/entity/Match.java`
- **Match database**: relational database

### Bootstrap and infrastructure

- [Application bootstrap](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/config/AppInitializer.java): startup configuration · Initializes application dependencies and optional data. · `src/main/java/dev/chearcode/config/AppInitializer.java`
- [Application context](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/config/ApplicationContext.java): custom bean context · `src/main/java/dev/chearcode/config/ApplicationContext.java`
- [Hibernate manager](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/config/HibernateManager.java): session infrastructure · `src/main/java/dev/chearcode/config/HibernateManager.java`
- [Database settings](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/resources/application.properties): application properties · `src/main/resources/application.properties`
- [Transaction manager](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/filter/TransactionManager.java): request filter · Centralizes transactional request handling. · `src/main/java/dev/chearcode/filter/TransactionManager.java`
- [Exception handler](https://github.com/vasiliy-spb/tennis_scoreboard/blob/main/src/main/java/dev/chearcode/filter/ExceptionHandler.java): error filter · Converts failures into error responses or views. · `src/main/java/dev/chearcode/filter/ExceptionHandler.java`

## Connections

- Servlet deployment → Workflow servlets: routes requests
- Servlet deployment → Transaction manager: installs filter
- Servlet deployment → Exception handler: installs filter
- Workflow servlets → Request validation: validates input
- Workflow servlets → DTO-to-domain mapper: maps creation DTOs
- DTO-to-domain mapper → Ongoing match service: creates active match
- Workflow servlets → Ongoing match service: scores and retrieves
- Ongoing match service → Active match storage: stores active state
- Ongoing match service → Tennis match: advances
- Tennis match → Set and game scoring: coordinates
- Set and game scoring → Tie-break scoring: uses when required
- Workflow servlets → JSP views: renders DTOs
- Workflow servlets → Persistence match service: saves and lists matches
- Persistence match service → Domain-to-entity mapper: maps for save
- Persistence match service → Entity-to-DTO mapper: maps for views
- Domain-to-entity mapper → Match and player entities: produces
- Match repository → Match and player entities: persists
- Persistence match service → Match repository: uses
- Match repository → Match database: reads and writes
- Application bootstrap → Application context: initializes
- Application bootstrap → Hibernate manager: initializes
- Database settings → Hibernate manager: configures
- Transaction manager → Hibernate manager: manages sessions
- Hibernate manager → Match repository: provides sessions
- Exception handler → JSP views: renders failures
