PAR-282
[chestshop] Migrate to a service/DAO architecture (strangler-fig away from the event-bus pipelines)
ChestShop is upstream's "Bukkit events as internal middleware" design: a single buy/sell is orchestrated across ~15 listeners coordinated only by @EventHandler(priority) ordering and a giant mutable PreTransactionEvent/TransactionEvent bag — no atomic boundary (ADT-4), untestable, the lone outlier vs. the monorepo's entrypoint→service→DAO. Persistence is SQLite/ORMlite via static God-classes (NameManager, ItemDatabase).
Strangler-fig migration (each phase ships independently, plugin works throughout). Storage stays SQLite for now behind storage-agnostic DAO interfaces (swap to shared MariaDB later = a new impl).
- Phase 0 (done, PoC): Stood up the seam — a
ChestShopModule(Guice),ItemCodeRepository(DAO interface) +SqliteItemCodeRepository(impl over the ORMlite items.db), and anItemCodeServicethat owns the serialise/find-or-create/metadata-migration logic. Deleted theItemDatabaseGod-class; callers go throughChestShop.itemCodes(). Faithful refactor (item codes byte-identical). Enables cleanly. - Phase 1 (next):
TransactionService.execute(...)owning money+items+record atomically, collapsing the post-transaction listener chain. - Phase 2:
ShopServicefor creation/removal. Phase 3: delete the dead event scaffolding. Account domain (NameManager/users.db) gets the same DAO/service treatment.
Resources
- PR#2 Last major release ParadauxIO/hibernia-economy
- commit0e659ef Migrate logging to slf4j (@Slf4j); drop the shop file-log (PAR-309)ParadauxIO/hibernia-economy
- commit30b408e Refresh the ChestShopModule binding comment: the graph is fully acyclic (PAR-282)ParadauxIO/hibernia-economy
- commit843ef1e Dissolve the AccountService<->EconomyService cycle via a leaf BusinessAccountService (PAR-282)ParadauxIO/hibernia-economy
- commit272e23f Split ShopBlockUtil into a pure util + ShopBlockService, dissolving the ChestShopSign cycle (PAR-282)ParadauxIO/hibernia-economy
- commite66ef05 Split InventoryUtil into a pure util + InventoryService (PAR-282)ParadauxIO/hibernia-economy
- commitc17e659 Split MaterialUtil into a pure util + MaterialService (PAR-282)ParadauxIO/hibernia-economy
- commit6ee9d39 Break the MaterialUtil<->InventoryUtil DI cycle: extract ShowItemHook (PAR-282)ParadauxIO/hibernia-economy
- commit4564558 Collapse small chestshop packages into model/ + utils/ (PAR-282)ParadauxIO/hibernia-economy
- commit296eecf Flatten the chestshop listeners package (PAR-282)ParadauxIO/hibernia-economy
- commit107a2de Port native Nexo/ItemsAdder custom-item support into ChestShop (PAR-291)ParadauxIO/hibernia-economy
- commit44f218f Delete the static Properties config mirror; route all config through injected ChestShopConfiguration (PAR-282)ParadauxIO/hibernia-economy
- commitf2ff580 Move AdminBypass to permission/ and de-static TransactionService's singleton state (PAR-282)ParadauxIO/hibernia-economy
- commit3fbbf7b Re-home the economy providers and the persistence-row POJOs (PAR-282)ParadauxIO/hibernia-economy
- commit0d2686c Reorganise misleading names and relocate non-root classes (PAR-282)ParadauxIO/hibernia-economy
- commit49f245c Rename the events/ carriers to context/*Context — they aren't Bukkit events (PAR-282)ParadauxIO/hibernia-economy
- commit492ce2a Remove dead/deprecated code left after the service/DAO migration (PAR-282)ParadauxIO/hibernia-economy
- commitc6ed176 Delete the static ChestShop.<service>() service-locator surface (PAR-282)ParadauxIO/hibernia-economy
- commit3a4110a Move the DB-backed item naming into ItemCodeService; MaterialUtil is now pure (PAR-282)ParadauxIO/hibernia-economy
- commite143839 Document MaterialUtil's item-code locator as the one principled DI boundary (PAR-282)ParadauxIO/hibernia-economy
- commit0d0270a Drop two more MaterialUtil locator hops: parseMaterial round-trip + Show message (PAR-282)ParadauxIO/hibernia-economy
- commit5f214e5 Move sign-format validation onto ChestShopSign; drop the isValid locator (PAR-282)ParadauxIO/hibernia-economy
- commit65a2d43 Move ChestShopSign's account predicates into AccountService (PAR-282)ParadauxIO/hibernia-economy
- commitb683825 Fold ItemUtil into ItemService; inject the market helpers (PAR-282)ParadauxIO/hibernia-economy
- commit52f7930 Make Security an injected ProtectionService facade (PAR-282)ParadauxIO/hibernia-economy
- commit9ce9422 Inject the framework Message bean into ChestShop's DI-managed classes (PAR-282)ParadauxIO/hibernia-economy
- commitb123ab3 Register ChestShop listeners via the framework ListenerManager (PAR-282)ParadauxIO/hibernia-economy
- commit770803b Inject services into the entrypoint listeners instead of the static locator (PAR-282)ParadauxIO/hibernia-economy
- commitc63665f Fold the vestigial static Economy facade into EconomyService (PAR-282)ParadauxIO/hibernia-economy
- commitcfb18c9 Delete the Permission enum; gate commands with @Permission directly (PAR-282)ParadauxIO/hibernia-economy
- commit12eb1a8 Inject services into the ChestShop commands instead of the static locator (PAR-282)ParadauxIO/hibernia-economy
- commit37617c8 Inject collaborators into the ChestShop services instead of the static locator (PAR-282)ParadauxIO/hibernia-economy
- commitbcd1315 Migrate ChestShop persistence from ORMlite to MyBatis (still SQLite) (PAR-282)ParadauxIO/hibernia-economy
- commita575b01 Subsume the item-resolution pipeline into ItemService; delete the item event carriers (PAR-282)ParadauxIO/hibernia-economy
- commita3181ec Subsume the shop-creation validation pipeline into ShopService (PAR-282/PAR-288)ParadauxIO/hibernia-economy
- commit05a870d Subsume the pre-transaction validation pipeline into TransactionService (PAR-282/PAR-288)ParadauxIO/hibernia-economy
- commitf88f658 Subsume the post-transaction reaction listeners into TransactionService (PAR-282)ParadauxIO/hibernia-economy
- commitd6f3117 Subsume the post-shop-creation/removal reaction listeners into ShopService (PAR-282)ParadauxIO/hibernia-economy
- commitb33fe59 Subsume the info listeners into InfoService; drop the ItemInfo/ShopInfo event carriers (PAR-282)ParadauxIO/hibernia-economy
- commit09f5c46 Close the highest-risk test-coverage gaps (ADT-50)ParadauxIO/hibernia-economy
- commit5d68858 Delete the NameManager facade; callers use ChestShop.accounts() (PAR-282)ParadauxIO/hibernia-economy
- commit2f8e28f Extract a ShopService for the shop-lifecycle money logic (PAR-282)ParadauxIO/hibernia-economy
- commit7d0dc3f Migrate the ChestShop account domain to a repository/service (PAR-282)ParadauxIO/hibernia-economy
- commitcd3a329 Phase 1: ChestShop TransactionService owns the atomic goods+money legs (PAR-282)ParadauxIO/hibernia-economy
- commita6254e3 Phase 0: introduce ChestShop service/DAO layer for item codes (PAR-282)ParadauxIO/hibernia-economy
Comments
tesks · Jun 26, 2026, 6:30 PM
Phase 2 done (commit 7d0dc3f): account domain migrated. NameManager static God-class split into AccountRepository + SqliteAccountRepository (users.db persistence behind a storage-agnostic contract) and AccountService (@Singleton: caches, get-or-create, shortened-name allocation, admin/server-economy accounts, canUseName, load()), reached via ChestShop.accounts(). NameManager is now a thin Listener (the AccountQuery/AccountAccess events stay — Treasury integration points) plus a delegating static facade so the ~25 callers compile unchanged. Added AccountServiceTest (row-count + shortened-name disambiguation now unit-testable over a fake repo). Builds + tests green.
Remaining: ShopService for creation/removal (Phase 2-shops), migrate the ~25 callers off the NameManager facade and delete it, then delete the dead event scaffolding (Phase 3).
tesks · Jun 26, 2026, 7:28 PM
Phase 2-shops done (commit 2f8e28f): ShopService extracted. Shops have no ChestShop-owned persistence (sign+chest world state; only DB is Treasury's external MarketApi), so no repository — just a service owning the lifecycle money logic that was embedded in listeners: chargeCreationFee(player, signLines) (fee + server-economy credit + message, returns whether creation proceeds) and refundOnRemoval(destroyer, sign) (refund + server-economy debit + message). CreationFeeGetter and ShopRefundListener are now thin entrypoints delegating via ChestShop.shops(). Money still flows through the Currency*Event integration points. The 12-listener creation-validation pipeline + market sync stay as events (deliberately — integration/coordination, Phase 3). Builds + tests green.
Remaining: migrate the ~25 callers off the NameManager static facade and delete it (split its 2 @EventHandlers into a thin AccountListener); then Phase 3 — assess collapsing the internal-only validation scaffolding (PreShopCreationEvent pipeline) now that the money logic is out.
tesks · Jun 26, 2026, 7:40 PM
NameManager facade deleted (commit 5d68858): account-domain migration complete. The ~25 callers across the economy/sign-creation/removal/command paths now call AccountService directly via ChestShop.accounts(); the two account @EventHandlers moved to a thin AccountListener (registered in place of the old NameManager listener). Pure delegator removal, no behaviour change. Builds + tests green.
Remaining: Phase 3 — assess whether the now internal-only shop-creation validation scaffolding (PreShopCreationEvent + the 12 preshopcreation listeners) is worth collapsing into the ShopService, now that the money logic is out and the genuine integration events (AccountQuery/AccountAccess, Currency*, ShopCreated/Destroyed→Market) are clearly separated.
Activity
- ParadauxIO linked a pull request — PR #2 open — Last major release
- ParadauxIO linked a pull request — PR #2 open — Last major release
- ParadauxIO linked a pull request — PR #2 open — Last major release
- ParadauxIO linked a pull request — PR #2 open — Last major release
- ParadauxIO linked a pull request — PR #2 open — Last major release
- ParadauxIO linked a pull request — PR #2 open — Last major release
- ParadauxIO linked a pull request — PR #2 open — Last major release
- ParadauxIO linked a commit — Commit 0e659ef — Migrate logging to slf4j (@Slf4j); drop the shop file-log (PAR-309)
- ParadauxIO linked a commit — Commit 30b408e — Refresh the ChestShopModule binding comment: the graph is fully acyclic (PAR-282)
- ParadauxIO linked a commit — Commit 843ef1e — Dissolve the AccountService<->EconomyService cycle via a leaf BusinessAccountService (PAR-282)
- ParadauxIO linked a commit — Commit 272e23f — Split ShopBlockUtil into a pure util + ShopBlockService, dissolving the ChestShopSign cycle (PAR-282)
- ParadauxIO linked a commit — Commit e66ef05 — Split InventoryUtil into a pure util + InventoryService (PAR-282)
- ParadauxIO linked a commit — Commit c17e659 — Split MaterialUtil into a pure util + MaterialService (PAR-282)
- ParadauxIO linked a commit — Commit 6ee9d39 — Break the MaterialUtil<->InventoryUtil DI cycle: extract ShowItemHook (PAR-282)
- ParadauxIO linked a commit — Commit 4564558 — Collapse small chestshop packages into model/ + utils/ (PAR-282)
- ParadauxIO linked a commit — Commit 296eecf — Flatten the chestshop listeners package (PAR-282)
- ParadauxIO linked a commit — Commit 107a2de — Port native Nexo/ItemsAdder custom-item support into ChestShop (PAR-291)
- ParadauxIO linked a commit — Commit 44f218f — Delete the static Properties config mirror; route all config through injected ChestShopConfiguration (PAR-282)
- ParadauxIO linked a commit — Commit f2ff580 — Move AdminBypass to permission/ and de-static TransactionService's singleton state (PAR-282)
- ParadauxIO linked a commit — Commit 3fbbf7b — Re-home the economy providers and the persistence-row POJOs (PAR-282)
- ParadauxIO linked a commit — Commit 0d2686c — Reorganise misleading names and relocate non-root classes (PAR-282)
- ParadauxIO linked a commit — Commit 49f245c — Rename the events/ carriers to context/*Context — they aren't Bukkit events (PAR-282)
- ParadauxIO linked a commit — Commit 492ce2a — Remove dead/deprecated code left after the service/DAO migration (PAR-282)
- ParadauxIO linked a commit — Commit c6ed176 — Delete the static ChestShop.<service>() service-locator surface (PAR-282)
- ParadauxIO linked a commit — Commit 3a4110a — Move the DB-backed item naming into ItemCodeService; MaterialUtil is now pure (PAR-282)
- ParadauxIO linked a commit — Commit e143839 — Document MaterialUtil's item-code locator as the one principled DI boundary (PAR-282)
- ParadauxIO linked a commit — Commit 0d0270a — Drop two more MaterialUtil locator hops: parseMaterial round-trip + Show message (PAR-282)
- ParadauxIO linked a commit — Commit 5f214e5 — Move sign-format validation onto ChestShopSign; drop the isValid locator (PAR-282)
- ParadauxIO linked a commit — Commit 65a2d43 — Move ChestShopSign's account predicates into AccountService (PAR-282)
- ParadauxIO linked a commit — Commit b683825 — Fold ItemUtil into ItemService; inject the market helpers (PAR-282)
- ParadauxIO linked a commit — Commit 52f7930 — Make Security an injected ProtectionService facade (PAR-282)
- ParadauxIO linked a commit — Commit 9ce9422 — Inject the framework Message bean into ChestShop's DI-managed classes (PAR-282)
- ParadauxIO linked a commit — Commit b123ab3 — Register ChestShop listeners via the framework ListenerManager (PAR-282)
- ParadauxIO linked a commit — Commit 770803b — Inject services into the entrypoint listeners instead of the static locator (PAR-282)
- ParadauxIO linked a commit — Commit c63665f — Fold the vestigial static Economy facade into EconomyService (PAR-282)
- ParadauxIO linked a commit — Commit cfb18c9 — Delete the Permission enum; gate commands with @Permission directly (PAR-282)
- ParadauxIO linked a commit — Commit 12eb1a8 — Inject services into the ChestShop commands instead of the static locator (PAR-282)
- ParadauxIO linked a commit — Commit 37617c8 — Inject collaborators into the ChestShop services instead of the static locator (PAR-282)
- ParadauxIO linked a commit — Commit bcd1315 — Migrate ChestShop persistence from ORMlite to MyBatis (still SQLite) (PAR-282)
- tesks changed status to Status → Pending Release
- ParadauxIO linked a commit — Commit a575b01 — Subsume the item-resolution pipeline into ItemService; delete the item event carriers (PAR-282)
- ParadauxIO linked a commit — Commit a3181ec — Subsume the shop-creation validation pipeline into ShopService (PAR-282/PAR-288)
- ParadauxIO linked a commit — Commit 05a870d — Subsume the pre-transaction validation pipeline into TransactionService (PAR-282/PAR-288)
- ParadauxIO linked a commit — Commit f88f658 — Subsume the post-transaction reaction listeners into TransactionService (PAR-282)
- ParadauxIO linked a commit — Commit d6f3117 — Subsume the post-shop-creation/removal reaction listeners into ShopService (PAR-282)
- ParadauxIO linked a commit — Commit b33fe59 — Subsume the info listeners into InfoService; drop the ItemInfo/ShopInfo event carriers (PAR-282)
- ParadauxIO linked a commit — Commit 09f5c46 — Close the highest-risk test-coverage gaps (ADT-50)
- ParadauxIO linked a commit — Commit 5d68858 — Delete the NameManager facade; callers use ChestShop.accounts() (PAR-282)
- ParadauxIO linked a commit — Commit 2f8e28f — Extract a ShopService for the shop-lifecycle money logic (PAR-282)
- ParadauxIO linked a commit — Commit 7d0dc3f — Migrate the ChestShop account domain to a repository/service (PAR-282)
- tesks commented
- tesks commented
- tesks commented
- ParadauxIO linked a commit — Commit cd3a329 — Phase 1: ChestShop TransactionService owns the atomic goods+money legs (PAR-282)
- ParadauxIO linked a commit — Commit a6254e3 — Phase 0: introduce ChestShop service/DAO layer for item codes (PAR-282)
- tesks created the issue