This document delivers a comprehensive, highly granular technical breakdown of the iRonoc architecture. It spans the system architecture, frontend structure, granular backend service layer, and showcases deep functional flow sections for Donate Items, Portfolio Items, and Brews/Coffee subsystems.
The iRonoc portfolio platform is structured as a decoupled, multi-tier full-stack application. It integrates a high-performance Java 25 / Spring Boot backend (embedded Tomcat) with a responsive, client-side routed React 19 single-page application (SPA).
+---------------------------------------------------------------------------------------------------+
| Client Web Browser |
| - Renders UI elements (React 19, Material UI 7, Bootstrap 5) |
| - Triggers Client-Side Routes, REST Calls, and real-time GraphQL Subscription streams |
+-------------------------------------------------+-------------------------------------------------+
|
| HTTP / HTTPS / WSS (WebSockets)
v
+---------------------------------------------------------------------------------------------------+
| Gateway / Proxy Layer |
| - Serves compiled, static frontend bundles (.js, .css, .html) from Tomcat /static mapping |
| - Reverse-proxies API endpoints (/api/*) and GraphQL gateways (/graphql) to active servlet hooks |
+-------------------------------------------------+-------------------------------------------------+
|
v
+---------------------------------------------------------------------------------------------------+
| Spring Boot Backend (Tomcat) |
| |
| +---------------------------------------+ +-------------------------------------------+ |
| | REST Controllers | | GraphQL Controllers | |
| | - DonateRestController | | - DonateGraphqlController (Sinks.Many) | |
| | - CoffeeController | | - BrewGraphqlController | |
| | - ActivityTrackingController | | - PortfolioItemsResolver (QueryMapping) | |
| +-------------------+-------------------+ +-------------------+-----------------------+ |
| | | |
| +-----------------------+-----------------------+ |
| | |
| v |
| +-------------------------------------------------------------------------------------------+ |
| | Granular Backend Service & Resolver Layer | |
| | - GitDetailsService (GitHub REST engine) | |
| | - CoffeesService (REST Coffee parser) / GraphQLClientService (Custom GraphQL Client) | |
| | - In-Memory Caches: GitRepoCacheService, GitProjectCacheService, CoffeeCacheService | |
| | - Resolvers: DonateItemsResolver, PortfolioItemsResolver | |
| +-------------------------------------------+-----------------------------------------------+ |
| | |
+-----------------------------------------------v---------------------------------------------------+
|
+-------------------------+-------------------------+
| |
v v
+---------------------------------------+ +---------------------------------------+
| AWS Secrets Manager | | Third-Party APIs |
| - Retrieves GitHub personal keys | | - GitHub API (Issues, Repositories) |
| - Secures backend configurations | | - External Coffee API REST/GraphQLs |
+---------------------------------------+ +---------------------------------------+
These diagrams can be visualized natively inside IntelliJ IDEA (using the diagram viewer plugin), GitHub, or standard markdown readers.
This container blueprint details the precise boundaries, filter intercepts, servlet mappings, and multi-thread caching layers inside the Spring Boot container.
flowchart TB
subgraph ClientContainer [Client Browser Container]
SPA[React 19 SPA]
Apollo[Apollo Client Link Splitter]
Axios[Axios / sendBeacon Client]
end
subgraph SecurityFilterLayer [Tomcat Servlet Security & Mapping Layer]
CORS[CorsRegistry Filter Mappings]
Limiter[Bucket4j Rate Limiting Interceptor]
Dispatcher[Spring DispatcherServlet]
SockHandler[GraphQlWebSocketHandler]
end
subgraph ControllerLayer [Controller Endpoint Mappings]
REST[REST API Endpoints: Coffee, Donate, Activity]
GraphQL[GraphQL Engine Mappings: @QueryMapping, @MutationMapping]
end
subgraph ServiceCore [Granular Backend Service & Cache Engines]
GitService[GitDetailsService]
CoffeeService[CoffeesService]
CacheManager[In-Memory ConcurrentHashMap Cache Managers]
GitRepoCache[GitRepoCacheService]
GitProjCache[GitProjectCacheService]
CoffeeCache[CoffeeCacheService]
DonResolver[DonateItemsResolver]
PortResolver[PortfolioItemsResolver]
Sink[Reactor Sinks.Many Multicast Channel]
end
subgraph Datastore [Classpath JSON Datastore Layer]
DiskDonate[(json/donate-items.json)]
DiskBrews[(json/brews.json)]
DiskPortfolio[(json/portfolio-items.json)]
DiskWhitelist[(graphql/charities.txt)]
end
subgraph External [External Network boundaries]
AWS[AWS Secrets Manager API]
GitAPI[GitHub REST API v3]
CoffeeAPI[Third-Party Coffee REST / GraphQL APIs]
end
SPA -->|GraphQL Queries| Apollo
SPA -->|HTTP / Telemetry Beacons| Axios
Apollo -->|POST /graphql| CORS
Apollo -->|WS ws://localhost:8080/graphql| CORS
Axios -->|PUT/GET /api/*| CORS
CORS --> Limiter
Limiter --> Dispatcher
Limiter --> SockHandler
Dispatcher --> REST
Dispatcher --> GraphQL
SockHandler --> GraphQL
REST --> GitService
REST --> CoffeeService
GraphQL --> DonResolver
GraphQL --> PortResolver
GraphQL --> Sink
GitService --> GitRepoCache
GitService --> GitProjCache
CoffeeService --> CoffeeCache
GitRepoCache --> CacheManager
GitProjCache --> CacheManager
CoffeeCache --> CacheManager
DonResolver --> DiskDonate
DonResolver --> DiskWhitelist
PortResolver --> DiskPortfolio
GitService -->|GET Request / Bearer Token| GitAPI
GitService -->|Query Access Tokens| AWS
CoffeeService -->|GET Request| CoffeeAPI
This flowchart maps the sequential UX transitions, modal interactions, loading states, and live interface updates available to the user.
flowchart TD
Start([User Opens App]) --> Home[Renders Landing Page - Consistent Navy Theme]
Home --> NavProjects{Navigates App}
%% Projects UX Flow
NavProjects -->|Projects Link| Projects[Renders RepoDetails]
Projects --> LoadProjects[Check Cached Repository Data]
LoadProjects -->|Miss / Load| ShowSpinner1[Display LoadingSpinner]
ShowSpinner1 --> Hydrated1[Render Grid Cards with Repo Details]
LoadProjects -->|Hit| Hydrated1
Hydrated1 --> ClickRepo[User Clicks Specific Repo Card]
ClickRepo --> Issues[Open RepoIssues Backlog]
Issues --> Recharts[Display Interactive Recharts Bar Chart of Active Issues]
%% Brews UX Flow
NavProjects -->|Brews Link| CoffeeHome[Renders CoffeeHome]
CoffeeHome --> LoadRecipes[Check In-Memory CoffeeCacheService]
LoadRecipes -->|Miss| GetExtRecipes[Fetch Recipes from External Coffee API]
GetExtRecipes --> JacksonParser[Deserialize & Map to CoffeeDomain via Jackson]
JacksonParser --> Hydrated2[Render Coffee Carousel with preparation cards]
LoadRecipes -->|Hit| Hydrated2
%% Donate UX Flow
NavProjects -->|Donate Link| Donate[Renders Donate Carousel]
Donate --> HydrateDonate[Execute GET_DONATE_ITEMS Query]
HydrateDonate --> LoadWhitelist[Filter On-Disk Charities via charities.txt Allowed List]
LoadWhitelist --> RenderCarousel[Render Red Carousel Cards with Verified Charities]
RenderCarousel --> OpenModal[User Clicks 'Add Charity' Button]
OpenModal --> InputDetails[Input Charity Details in Registration Form]
InputDetails --> ValidateForm{Form Fields Validated?}
ValidateForm -->|Invalid format/year/protocol| FormError[Display Specific Warning message inside form]
FormError --> InputDetails
ValidateForm -->|Valid details| DispatchMutation[Submit addCharityOption Mutation to GraphQL Server]
DispatchMutation --> CheckServerWhitelist{Name is Whitelisted in charities.txt?}
CheckServerWhitelist -->|No / Fraud attempt| ServerError[Reject transaction & throw Validation error]
ServerError --> Donate
CheckServerWhitelist -->|Yes| PersistServer[Append details to json/donate-items.json]
PersistServer --> SinkEmit[Emit next charity to Multicast Sink]
SinkEmit --> PushWS[Push Event pushed instantly over ws://localhost:8080/graphql]
PushWS --> UpdateState[Client subscription state appends new card dynamically]
UpdateState --> RenderCarousel
This sequence diagram tracks the full transactional life cycle when a user registers a new charity, from validation to real-time sync.
sequenceDiagram
autonumber
actor Client as Client Browser
participant Controller as DonateGraphqlController
participant Resolver as DonateItemsResolver
participant Sink as Sinks.Many (Multicast Buffer)
participant Disk as JSON Datastore
Client->>Controller: Mutation: addCharityOption(...)
activate Controller
Controller->>Resolver: addDonateItem(Item)
activate Resolver
Resolver->>Resolver: Validate URL, Founding Year, & Email
Resolver->>Resolver: Check charities.txt whitelist
alt Item is Malformed or Exists
Resolver-->>Controller: Return false (invalid transaction)
Controller-->>Client: Return Failure Message
else Item is Valid & New
Resolver->>Disk: Persist payload to JSON datastore
Resolver-->>Controller: Return true (success)
deactivate Resolver
Controller->>Sink: tryEmitNext(newItem)
activate Sink
Sink-->>Controller: Confirmed Emit to Multicast buffer
deactivate Sink
par Broadcast real-time WebSocket update
Controller-->>Client: WebSocket push: donateItemsSubscription (newItem)
and Acknowledge original client request
Controller-->>Client: Return Success Message / DTO
deactivate Controller
end
end
This sequence diagram details the fallback and deserialization pipeline when querying coffee brewing instructions.
sequenceDiagram
autonumber
actor Client as Client Browser
participant Controller as CoffeeController
participant Cache as CoffeeCacheService
participant Service as CoffeesService / GraphQLClient
participant Ext as External Coffee APIs (REST/GraphQL)
Client->>Controller: GET /api/coffees
activate Controller
Controller->>Cache: get()
activate Cache
alt Cache Hit (In-Memory Available)
Cache-->>Controller: Return Cached CoffeeDomain List
Controller-->>Client: Return JSON payload (<50ms response)
else Cache Miss (Empty / Evicted)
Cache-->>Controller: Return null
deactivate Cache
Controller->>Service: getCoffeeDetails() / fetchCoffeeDetails()
activate Service
Service->>Ext: Query remote REST/GraphQL resources
activate Ext
Ext-->>Service: Return raw payload (ingredients as text array)
deactivate Ext
Service->>Service: Custom Deserialization (IngredientsDeserializer)
Service->>Service: Map payload to CoffeeDomain collection
Service-->>Controller: Return mapped list
deactivate Service
Controller->>Cache: put(coffeeDomains)
activate Cache
Cache-->>Controller: Confirmed hydrate cache
deactivate Cache
Controller-->>Client: Return newly compiled JSON payload
deactivate Controller
end
The Charity and Donation subsystem is a primary component of the iRonoc platform. It delivers real-time charity registration, cryptographic verification, and reactive synchronization between multiple client browsers and the datastore.
[ Client: Donate.js ] [ Spring Controllers ] [ DonateItemsResolver ] [ Datastore / Disk ]
| | | |
|---- GraphQL Query -------->| | |
| (getDonateItems) |---- getDonateItems() ------>| |
| | |---- load classpath ------>| [ donate-items.json ]
| | |---- validate year/URLs -->| [ charities.txt ]
|<--- JSON Charity List -----|<--- filtered list ----------| |
| | | |
| | | |
|---- GraphQL Mutation ----->| | |
| (addCharityOption) |---- addDonateItem(Item) --->| |
| | |--- write to class resource| [ donate-items.json ]
| | | |
| |--- Sink: tryEmitNext() | |
|<--- Mutated Confirmation --| (Broadcast to WS) | |
| | | |
The React frontend component renders a responsive Material-UI and Bootstrap grid layout of active, trusted charity options:
- Presentation: Renders card tiles featuring custom logos (
img), summary descriptions (overview), founding years, and validated telephone lines. Clicking a card directs the browser to the charity's official donation portal. - Initial Query Hydration: Uses Apollo Client's query executor (
client.query) on mounting to perform initial pull-hydration of charity cards directly from/graphql. - Active Subscription Stream: Implements a persistent, real-time WebSocket GraphQL Subscription (
client.subscribelistening toDONATE_ADDED_SUBSCRIPTIONmapping todonateItemsSubscription). This dynamically appends new cards pushed by the backendSinks.Manymulticast sink to the browser carousel list instantly without requiring full page fetches, polling, or Axios requests. - Dynamic Registration Form: Renders a dedicated modal with validation warnings matching the backend regex engines (valid year between 1000–2100, valid telephone format or email structure, and HTTP/HTTPS links).
- GraphQL Resolver Gateway (
DonateGraphqlController.java):@QueryMappingondonateItems: Fetches all validated charities.@MutationMappingonaddCharityOption: Initiates registration, validations, and disk-persistance.@SubscriptionMappingondonateItemsSubscription: Connects client WebSocket listeners to a Project Reactor multicast Sink (Sinks.Manywith an backpressure buffer size of 256) to push real-time broadcasts.
- REST Endpoints (
DonateRestController.java):- Exposes
GET /api/donate-itemsreturning the list of active charities as a raw JSON array for legacy browser integrations.
- Exposes
To preserve the security of the application and mitigate spam or malicious scripts (e.g. cross-site scripting inputs), the backend enforces strict validation criteria in DonateItemsResolver.java:
- The Trusted Allowed List (
charities.txt): Located atsrc/main/resources/graphql/charities.txt. This contains the exact, trimmed, case-insensitive names of charities permitted to be displayed on the platform. If an added name does not exist in this list, registration is blocked. - The JSON Datastore (
donate-items.json): Located atsrc/main/resources/json/donate-items.json. Stores the details of the active, whitelisted charities in JSON format:{ "alt": "Jack and Jill Foundation", "name": "The Jack and Jill Children's Foundation", "link": "https://www.jackandjill.ie", "donate": "https://www.jackandjill.ie/how-you-can-help/donate/", "img": "jack-and-jill-logo.png", "overview": "Provides direct funding and home nursing care to children with highly complex medical conditions.", "founded": 1997, "phone": "+353 (0) 45 894 538" } - Structured Verification Engines:
- Founding Year: Must be between
1000and2100. - URL Integrity: Links (
linkanddonate) are parsed and verified using a strictHTTP/HTTPSpattern. - Contact Format: Phone numbers and emails are run through explicit formatting regex engines (checking international prefix structures and standard email structures).
- Founding Year: Must be between
To register and demonstrate your charity on this platform:
- Ensure your charity's name is whitelisted inside
charities.txt. - Add your charity's detailed JSON block to
json/donate-items.jsonor submit it via the frontend Donation portal.
📢 Important Security Notice: To protect users, only trusted charities are permitted. If your desired charity is not currently supported, please reach out directly to conorheffron on GitHub (username:
conorheffron/@conorheffron) to submit your charity's credentials and request to have its name appended to the trusted whitelisted (charities.txt) file.
The frontend is built using React 19 (ES6+) as a Single-Page Application (SPA). It manages routing in the browser using React Router 7, performs data queries via REST (Axios/Fetch) or GraphQL (Apollo Client), and utilizes modern reactive UI controls.
+-------------------+
| App.js Entry |
| (Router Engine) |
+---------+---------+
|
+---------v---------+
| AppNavbar.js |
| (Bootstrap/MUI 7) |
+---------+---------+
|
+-------------------------+-------------------------+
| |
v (Static/View routes) v (Dynamic/Functional routes)
+---------+-----------+ +---------+---------+
| Static Presentation | | State & API Driven|
+---------+-----------+ +---------+---------+
| |
+-------------+-------------+ +-------------+-------------+
| | | | | |
v v v v v v
About.js Home.js NotFound.js Donate.js CoffeeHome.js RepoDetails.js
(Profile) (Landing) (404 Page) (Charity Grid) (Brews list) (Backlog View)
| | |
v v v
[Apollo Client] [Fetch API] [Axios REST]
App.js(Core Orchestrator): Houses the centralRouterand registers the app's dynamic view routes. It also declares and initializes the Apollo Client instance specifically wrapped around theDonateroute.AppNavbar.js&Footer.js: Core layout elements. They offer fully responsive toggles and structural grids styled with MUI 7 and Bootstrap 5.components/Home.js(The Landing Page): Renders the central entry point. Integrates custom background asset loaders (loadCameraRollImages) to serve a consistent, stylized Navy theme (darkblue-bg.png).components/Donate.js: Connecting endpoint for charitable contributions. Leverages Apollo Client'suseQuery,useMutation, and real-time WebSocketsuseSubscriptionto synchronize charity registers instantly.components/CoffeeHome.js&ControlledCarousel.js: Interactive hubs. Render dynamic coffee preparation cards, pulling brewing instructions and graphics either from Spring REST interfaces or mock JSON arrays.components/RepoDetails.js&components/RepoIssues.js: Backlog management panels. Perform REST requests using Axios to pull cached, rate-limited GitHub repositories, displaying active project issue backlogs using Recharts graphic plots.
The backend uses a service-driven, cache-optimized structure to coordinate Spring Controllers with third-party networks and filesystem records.
+---------------------------------------------------------------------------------+
| Spring Controllers |
+-------+-------------------------+------------------------+------------------+---+
| | | |
v v v v
+--------------+--------------+ +--------+--------+ +-------------+-------------+ +--+----------------+
| GitDetailsService | | BrewsResolver | | DonateItemsResolver | |ActivityTracking |
| - Coordinates git calls | | - Loads brews | | - Loads, validates, lists | | Service |
| - Thread-safe repository | | local JSON | | permitted charities | | - Receives click |
+--------------+--------------+ +--------+--------+ +-------------+-------------+ | beacons |
| | | +--+----------------+
+------+------+ v v |
| | +-----------------+ +-----------------+ v
v v | Brews Datastore| | Charity Files | +------+------+
+-----+---+ +-----+---+ | (json/brews.json| | (charities.txt | | Activity |
|GitRepo | |GitProj | +-----------------+ | donate-items) | | Datastore |
| Cache | | Cache | +-----------------+ +-------------+
+---------+ +---------+
GitDetailsService: Coordinates queries hitting the GitHub API. Uses Java's template endpoints to resolve usernames, fetch backlogs, and convert complex GitHub REST payloads into serializableRepositoryDetailDtorecords.GitRepoCacheService/GitProjectCacheService: High-performance caching layers. Built with thread-safe ConcurrentHashMap collections. When scheduled cron jobs (GitDetailsJob) sync Git data in the background, these services hold the data to avoid hitting GitHub's strict API rate limits.CoffeeCacheService: Stores serialized coffee preparation listings. It supports rapid memory fetches and implements explicit cleanup via@PreDestroymethods during Spring application context teardowns.ActivityTrackingService: Monitors user interaction telemetry. Receives asynchronous clicks/beacons dispatched by client browsers, processing them for usage reports.
DonateItemsResolver: Manages the charity registry. Loadsjson/donate-items.jsonfrom classpath resources, filters them against the strictgraphql/charities.txtwhitelist, and validates each entity's structure (URL format, founding year, phone/email syntax) before exposing them.PortfolioItemsResolver: Parsesjson/portfolio-items.jsonto resolve, filter, and deliver structured portfolio records directly to GraphQL mapping queries.
GitClient: Integrates with the remote GitHub REST endpoints. It implements robust HTTP headers, authentication tokens, and custom timeouts (connectTimeout/readTimeout) to ensure reliable network requests.AwsSecretManager: Integrates with AWS Secrets Manager via the AWS SDK. It retrieves Git API credentials dynamically at runtime, removing the need for hardcoded keys in the repository.
This section details how the platform executes its core workflows across the React client, Spring Controllers, Service Layer, and Datastores.
This module parses and delivers static portfolio metrics and highlight carousels.
[ Client: Portfolio.js ] [ PortfolioController ] [ PortfolioItemsResolver ] [ Datastore / Disk ]
| | | |
|---- GraphQL Query ---------->| | |
| (portfolioItems) |---- getPortfolioItems() ---->| |
| | |--- load from classpath --->| [ portfolio-items.json ]
|<--- JSON Portfolio list -----|<--- map to response List ----| |
- Flow steps:
- The React client executes a
portfolioItemsGraphQL query. PortfolioControllercaptures the query and callsPortfolioItemsResolver.getPortfolioItems().- The resolver reads
json/portfolio-items.jsonfrom the disk resources. - The data is parsed into a list of portfolio items and mapped to a schema list (
PortfolioItemtypes), which is sent back to the browser to render the highlight cards and carousels.
- The React client executes a
The coffee subsystem coordinates external APIs, in-memory caches, local configurations, and custom Jackson deserializers to serve detailed brewing instructions.
[ Client: CoffeeHome.js ] [ CoffeeController ] [ Coffee Services ] [ Ext. Web / GraphQL ]
| | | |
|---- GET /api/coffees ------>| | |
| |--- check cache --------->| |
| | (CoffeeCacheService) | |
| | [Hit: return list] | |
| | | |
| | [Miss: fetch rest]--->| |
| | |=== REST: fetch hot/ice ==>| [ https://api.sampleapis.com ]
| | |<== Map to CoffeeDomain ===|
| | | |
| | [Miss: fetch Graph]-->| |
| | |=== GraphQL Client =======>| [ GraphQL Coffee Server ]
| | |<== Map to Map<Str,Obj> ===|
|<--- JSON Coffee Domain -----|<--- Update Cache --------| |
- The Data Pipeline:
- User Action: The user opens the Coffee brewing portal.
- Cache Check: The frontend dispatches a
GETrequest to/api/coffees.CoffeeControllerchecks theCoffeeCacheServicefirst.- Cache Hit: If coffee details are already cached in-memory, they are returned immediately, reducing load on external APIs.
- Cache Miss (REST Pathway): If the cache is empty, the controller calls
CoffeesService.getCoffeeDetails(). This service performs REST requests to external endpoints (e.g.https://api.sampleapis.com/coffee/hotandhttps://api.sampleapis.com/coffee/iced). - Cache Miss (GraphQL Pathway): Alternatively, the controller can call
getCoffeeDetailsGraphQl(), which runsGraphQLClientService.fetchCoffeeDetails(). This service usesRestTemplateto send a structured GraphQL query to a coffee API.
- Data Deserialization & Mapping:
- Raw responses contain ingredients as raw text arrays. The application uses a custom Jackson Deserializer (
IngredientsDeserializer) to clean and format the ingredients into standardized list models. - The parsed details are mapped to Java
CoffeeDomainobject models.
- Raw responses contain ingredients as raw text arrays. The application uses a custom Jackson Deserializer (
- Cache Hydration: The populated
CoffeeDomainlist is stored inCoffeeCacheServiceand returned to the client browser as a JSON array. - UI Rendering: The React component renders the updated data into interactive card layouts using the
CoffeeCarouselcomponent.
To guarantee build safety and code correctness, the project enforces strict test coverage limits (Minimum 80% coverage on all modifications):
- Java Backend (JUnit 5, Mockito, Jacoco): Maintains an overall instruction coverage of ~92% and line coverage of ~92%.
- React Frontend (Jest, React Testing Library): Maintains overall statement and line coverage above ~91%.