#1313: HistoryService.kt

projectforge-business/src/main/kotlin/org/projectforge/framework/persistence/history/HistoryService.kt Core Service, projectforge-business/.../persistence/history/HistoryService.kt 426 lines · 315 code · 87 comments · 24 blank
Primary facade for loading, merging, saving, and deleting history entries including attribute-level change tracking. Also handles access-checked entity resolution and user-comment appending.

Architecture & Role

HistoryService is a singleton @Service that ties together the low-level data access (HistoryEntryDO/HistoryEntryAttrDO) with the display-layer converters. It manages the full lifecycle: creation of history entries via BaseDao adapters, loading with embedded-object recursion, user-comment appending, and forced deletion.

Key Methods

MethodDescription
mergeHistoryEntries(loadContext, entries)Merges entries into the load context, deduplicating by ID.
findEntryAndEntityById(id, checkAccess?)Loads a history entry + its target entity, checking select+update access. Returns EntryInfo with entity class, DAO, and access flags.
appendUserComment(id, comment, checkAccess?)Appends a timestamped user comment to a history entry. Prefixes with ISO datetime and username if the commenter differs from the original modifier.
loadHistory(baseDO, baseDao?)Entry point for loading all history for a given entity. Creates a fresh HistoryLoadContext and invokes the recursive loader.
loadAndMergeHistory(entityClass, entityIds, loadContext)Recursively loads history for a set of entity IDs, following @OneToMany relationships to load history of embedded/child entities. Uses reflection to read actual child collections from loaded entities.
insertUpdateHistoryEntry(entity, property, class, oldVal, newVal)Creates a single-attribute change entry via HistoryBaseDaoAdapter. Checks demo/restricted user before writing.
forceDeletion(historyEntry)Hard-deletes a history entry and all its attributes (for GDPR-style entity purge).
save(em/historyEntry, attrs?)Persists a new history entry with optional attributes, setting modifiedBy and modifiedAt.

Embedded Object Resolution

The private processAndMergeHistory() method scans history entry attributes for @OneToMany property names, extracts entity IDs from both value (added) and oldValue (removed) fields, and recursively loads history for those embedded entities. It also uses reflection on the actual loaded parent entities to find currently-assigned children that may not appear in history diffs.

Inner Class: EntryInfo

Return type for findEntryAndEntityById(). Packs the raw HistoryEntryDO, the resolved entity class, its BaseDao, the loaded entity instance, and read/write access booleans.

Git History

868d6abb7 2025 -> 2026
3808112aa t_pf_history.user_comment varchar(2000) -> varchar(10000), appendUserComment adds timestamp.
749bdd1cd HistoryEntry: user able to append user comments to history entries.
398ac8947 History comments: editing prepared.
b7861b2ff Addresses: forced deletion fixed (after mgc migration).
63081666f Source file headers: 2024-> 2025.
d9d0cc1bf WIP: orderbook storage.
bbc198d03 Migration stuff in progress... (all tests OK).
9e3c523c7 Migration stuff in progress... (all tests OK).
55972f36a Migration stuff in progress...
f189d3418 Migration stuff in progress... (all tests OK).
d18c899b5 Refactoring of history entries.
b79a1edca Migration stuff in progress... (all tests OK).
e3fe7c42b Migration stuff in progress... (all tests OK).
5989b32fd BaseDao: onChangeListener mechanism refactored.
87aaf6a5a BaseDao refactored, internal* methods renamed.
e4f9ca1be Migration stuff in progress...
67805f2fc ThreadLocalUserContext.user -> loggedInUser (renamed).
cb03dc74f Migration stuff in progress... (all tests OK).
68be78d38 Migration stuff in progress... (all tests OK).
85b4e1175 PfPersistenceService: query renamed to executeQuery.
b095e6f7d Big change of Transaction handling: PfPersistenceContext.
95afd297d Migration stuff in progress...
eaa4d9d3a HistoryService -> HistoryFormatService
57f08f175 HistoryService supports registered adapters (User adapter).
f3ed38265 HistoryService (displaying entries) improved.
5f7ef41b8 Copyright 2021 -> 2022
c0f2b9de0 Tenants functionality removed everywhere.
ceb63e8a1 Source code header: (C) 2001-2021.
8b60b4c0a wip: attachments
365059990 HistoryService and I18nEnum: fix for unknown enum values.
7c79f1922 Copyright of source header -> 2020.
8d164f4ad AbstractRest, AbstractDORest, AbstractDTORest refactored.
f1e8cca68 HistoryService supports insert operations.
05244ff19 CopyRight headers created.
bd3a3e824 Module projectforge-jax-rs renamed to projectforge-rest.
0475167da PFUserDO: Code review.
b4f102fe5 Time ago (human readable) for history entries.
2b7abdf0e Typo: modfied -> modified.
8116fa842 Json serialization: camel case.
b0fd52b9f menu moved from jax-rs to business.
895414c05 Kotlin: refactored lateinit.
be8f793fc Auto-layout: refactoring.
91accbd15 Auto-layout: refactoring.
298e24d04 Translation of operation type.
7b4263462 Bugfix in auto translation of property names.
57009fbe8 Auto translation of I18nEnum values in history entries.
cc2c470f9 HistoryEntry: diffEntries as list of historyEntry.
03d2d150d New rest service rs/<entity>/history/id