# europeana/thumbnail-api architecture

> Architecture diagram of the GitHub repository europeana/thumbnail-api, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-30). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/europeana/thumbnail-api
- Repository: https://github.com/europeana/thumbnail-api

## Overview

Thumbnail API serves image thumbnails from configured object stores, falling back through ordered providers, and accepts organization-logo uploads that are resized and stored as WebP. The graph separates HTTP entry points, request processing, storage routing, and storage/image services. The README documents IBM S3, deprecated Amazon S3, and deprecated IIIF fallback; excerpts show the storage iteration, upload processing, and response utilities. Some controller and configuration links rely on SOURCE INDEX references rather than full source excerpts.

Main entry points: [`src/main/java/eu/europeana/thumbnail/web/AbstractController.java`](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/web/AbstractController.java) (Thumbnail retrieval), [`src/main/java/eu/europeana/thumbnail/service/impl/UploadImageServiceImpl.java`](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/impl/UploadImageServiceImpl.java) (Image processing), [`src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV2.java`](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV2.java) (Thumbnail v2), [`src/main/java/eu/europeana/thumbnail/config/StorageRoutes.java`](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/config/StorageRoutes.java) (Storage configuration)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_http["HTTP API"]
  node_thumbnail_v2["Thumbnail v2"]
  node_thumbnail_v3["Thumbnail v3"]
  node_upload_controller["Upload v3"]
end

subgraph group_processing["Request Processing"]
  node_abstract_controller["Thumbnail retrieval"]
  node_response_utils["Response headers"]
  node_ids["Thumbnail IDs<br/>[IdUtils.java]"]
  node_media_stream["Media stream<br/>[MediaStream.java]"]
  node_image_size["Image sizes<br/>[ImageSize.java]"]
end

subgraph group_routing["Storage Routing"]
  node_storages_service["Storage selection"]
  node_storage_routes["Storage configuration<br/>[StorageRoutes.java]"]
end

subgraph group_storage["Storage and Images"]
  node_read_service["Read contract"]
  node_s3_reader["S3 reader"]
  node_iiif_reader["IIIF reader"]
  node_iiif_utils["IIIF utilities<br/>[IiifUtils.java]"]
  node_upload_service["Upload contract"]
  node_image_processor["Image processing"]
end

node_caller(("API caller"))
node_object_store[("S3 object storage")]

node_caller -->|"requests thumbnail"| node_thumbnail_v2
node_caller -->|"requests thumbnail"| node_thumbnail_v3
node_caller -->|"uploads image"| node_upload_controller
node_thumbnail_v2 -->|"delegates retrieval"| node_abstract_controller
node_thumbnail_v3 -->|"delegates retrieval"| node_abstract_controller
node_abstract_controller -->|"selects providers"| node_storages_service
node_storages_service -->|"reads routes"| node_storage_routes
node_abstract_controller -->|"retrieves in order"| node_read_service
node_abstract_controller -->|"computes IDs"| node_ids
node_abstract_controller -->|"checks response headers"| node_response_utils
node_thumbnail_v2 -->|"constructs fallback icon"| node_media_stream
node_thumbnail_v2 -->|"chooses width"| node_image_size
node_read_service -->|"returns stream"| node_media_stream
node_s3_reader -->|"implements"| node_read_service
node_s3_reader -->|"reads objects"| node_object_store
node_s3_reader -->|"wraps retrieved object"| node_media_stream
node_iiif_reader -->|"implements"| node_read_service
node_iiif_reader -->|"uses utilities"| node_iiif_utils
node_iiif_reader -->|"returns stream"| node_media_stream
node_storage_routes -->|"creates provider"| node_s3_reader
node_storage_routes -->|"creates provider"| node_iiif_reader
node_storage_routes -->|"creates upload service"| node_image_processor
node_upload_controller -->|"dispatches upload"| node_upload_service
node_image_processor -->|"implements"| node_upload_service
node_image_processor -->|"builds object IDs"| node_ids
node_image_processor -->|"creates size variants"| node_image_size
node_image_processor -->|"writes variants"| node_object_store

click node_thumbnail_v2 "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV2.java"
click node_thumbnail_v3 "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV3.java"
click node_upload_controller "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/web/UploadControllerV3.java"
click node_abstract_controller "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/web/AbstractController.java"
click node_response_utils "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/utils/ControllerUtils.java"
click node_ids "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/utils/IdUtils.java"
click node_media_stream "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/model/MediaStream.java"
click node_image_size "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/model/ImageSize.java"
click node_storages_service "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/StoragesService.java"
click node_storage_routes "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/config/StorageRoutes.java"
click node_read_service "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/MediaReadStorageService.java"
click node_s3_reader "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/impl/MediaReadStorageServiceImpl.java"
click node_iiif_reader "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/impl/IiifImageReadServerImpl.java"
click node_iiif_utils "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/utils/IiifUtils.java"
click node_upload_service "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/UploadImageService.java"
click node_image_processor "https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/impl/UploadImageServiceImpl.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_thumbnail_v2,node_thumbnail_v3,node_upload_controller toneBlue
class node_abstract_controller,node_response_utils,node_ids,node_media_stream,node_image_size,node_object_store toneAmber
class node_storages_service,node_storage_routes,node_caller toneMint
class node_read_service,node_s3_reader,node_iiif_reader,node_iiif_utils,node_upload_service,node_image_processor toneRose
```

## Components

### HTTP API

- [Thumbnail v2](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV2.java): `src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV2.java`
- [Thumbnail v3](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV3.java): `src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV3.java`
- [Upload v3](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/web/UploadControllerV3.java): `src/main/java/eu/europeana/thumbnail/web/UploadControllerV3.java`

### Request Processing

- [Thumbnail retrieval](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/web/AbstractController.java): `src/main/java/eu/europeana/thumbnail/web/AbstractController.java`
- [Response headers](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/utils/ControllerUtils.java): `src/main/java/eu/europeana/thumbnail/utils/ControllerUtils.java`
- [Thumbnail IDs](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/utils/IdUtils.java): `src/main/java/eu/europeana/thumbnail/utils/IdUtils.java`
- [Media stream](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/model/MediaStream.java): `src/main/java/eu/europeana/thumbnail/model/MediaStream.java`
- [Image sizes](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/model/ImageSize.java): `src/main/java/eu/europeana/thumbnail/model/ImageSize.java`

### Storage Routing

- [Storage selection](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/StoragesService.java): `src/main/java/eu/europeana/thumbnail/service/StoragesService.java`
- [Storage configuration](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/config/StorageRoutes.java): `src/main/java/eu/europeana/thumbnail/config/StorageRoutes.java`

### Storage and Images

- [Read contract](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/MediaReadStorageService.java): `src/main/java/eu/europeana/thumbnail/service/MediaReadStorageService.java`
- [S3 reader](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/impl/MediaReadStorageServiceImpl.java): `src/main/java/eu/europeana/thumbnail/service/impl/MediaReadStorageServiceImpl.java`
- [IIIF reader](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/impl/IiifImageReadServerImpl.java): `src/main/java/eu/europeana/thumbnail/service/impl/IiifImageReadServerImpl.java`
- [IIIF utilities](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/utils/IiifUtils.java): `src/main/java/eu/europeana/thumbnail/utils/IiifUtils.java`
- [Upload contract](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/UploadImageService.java): `src/main/java/eu/europeana/thumbnail/service/UploadImageService.java`
- [Image processing](https://github.com/europeana/thumbnail-api/blob/master/src/main/java/eu/europeana/thumbnail/service/impl/UploadImageServiceImpl.java): `src/main/java/eu/europeana/thumbnail/service/impl/UploadImageServiceImpl.java`

### Other components

- **API caller**
- **S3 object storage**

## Connections

- API caller → Thumbnail v2: requests thumbnail (evidence: `src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV2.java`)
- API caller → Thumbnail v3: requests thumbnail (evidence: `src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV3.java`)
- API caller → Upload v3: uploads image (evidence: `src/main/java/eu/europeana/thumbnail/web/UploadControllerV3.java`)
- Thumbnail v2 → Thumbnail retrieval: delegates retrieval (evidence: `src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV2.java`)
- Thumbnail v3 → Thumbnail retrieval: delegates retrieval (evidence: `src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV3.java`)
- Thumbnail retrieval → Storage selection: selects providers (evidence: `src/main/java/eu/europeana/thumbnail/web/AbstractController.java`)
- Storage selection → Storage configuration: reads routes (evidence: `src/main/java/eu/europeana/thumbnail/service/StoragesService.java`)
- Thumbnail retrieval → Read contract: retrieves in order (evidence: `src/main/java/eu/europeana/thumbnail/web/AbstractController.java`)
- Thumbnail retrieval → Thumbnail IDs: computes IDs (evidence: `src/main/java/eu/europeana/thumbnail/web/AbstractController.java`)
- Thumbnail retrieval → Response headers: checks response headers (evidence: `src/main/java/eu/europeana/thumbnail/web/AbstractController.java`)
- Thumbnail v2 → Media stream: constructs fallback icon (evidence: `src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV2.java`)
- Thumbnail v2 → Image sizes: chooses width (evidence: `src/main/java/eu/europeana/thumbnail/web/ThumbnailControllerV2.java`)
- Read contract → Media stream: returns stream (evidence: `src/main/java/eu/europeana/thumbnail/service/MediaReadStorageService.java`)
- S3 reader → Read contract: implements (evidence: `src/main/java/eu/europeana/thumbnail/service/impl/MediaReadStorageServiceImpl.java`)
- S3 reader → S3 object storage: reads objects (evidence: `src/main/java/eu/europeana/thumbnail/service/impl/MediaReadStorageServiceImpl.java`)
- S3 reader → Media stream: wraps retrieved object (evidence: `src/main/java/eu/europeana/thumbnail/service/impl/MediaReadStorageServiceImpl.java`)
- IIIF reader → Read contract: implements (evidence: `src/main/java/eu/europeana/thumbnail/service/impl/IiifImageReadServerImpl.java`)
- IIIF reader → IIIF utilities: uses utilities (evidence: `src/main/java/eu/europeana/thumbnail/service/impl/IiifImageReadServerImpl.java`)
- IIIF reader → Media stream: returns stream (evidence: `src/main/java/eu/europeana/thumbnail/service/impl/IiifImageReadServerImpl.java`)
- Storage configuration → S3 reader: creates provider (evidence: `src/main/java/eu/europeana/thumbnail/config/StorageRoutes.java`)
- Storage configuration → IIIF reader: creates provider (evidence: `src/main/java/eu/europeana/thumbnail/config/StorageRoutes.java`)
- Storage configuration → Image processing: creates upload service (evidence: `src/main/java/eu/europeana/thumbnail/config/StorageRoutes.java`)
- Upload v3 → Upload contract: dispatches upload (evidence: `src/main/java/eu/europeana/thumbnail/web/UploadControllerV3.java`)
- Image processing → Upload contract: implements (evidence: `src/main/java/eu/europeana/thumbnail/service/impl/UploadImageServiceImpl.java`)
- Image processing → Thumbnail IDs: builds object IDs (evidence: `src/main/java/eu/europeana/thumbnail/service/impl/UploadImageServiceImpl.java`)
- Image processing → Image sizes: creates size variants (evidence: `src/main/java/eu/europeana/thumbnail/service/impl/UploadImageServiceImpl.java`)
- Image processing → S3 object storage: writes variants (evidence: `src/main/java/eu/europeana/thumbnail/service/impl/UploadImageServiceImpl.java`)
