1a0a56a626
Replace the stale multi-module java/mss-failsafe skeleton (old user-management prototype) with the active single-module machine-safety inspection app that was living in its own standalone repo at the repo root. - Remove old java/mss-failsafe/ multi-module tree (mss, userdata, userManagement, mssfailsafe.datalayer, mssfailsafeWeblayer) incl. committed build artifacts - Add the active app (PrimeFaces 11 / JSF 2.3 / Hibernate 5.6 / iText / POI) flattened into java/mss-failsafe/ as the only mss-failsafe in git - Working tree captured = master tip 2a142b5 + in-progress uncommitted work (incl. .github/*.instructions.md AI-context files) - Archive the standalone repo's 33-commit history in GIT_HISTORY_ARCHIVE.md since its .git was not migrated This is the source of truth / base for the upcoming upgraded rewrite.
3.7 KiB
Executable File
3.7 KiB
Executable File
Architecture Instructions
Aktualisiert: 2025-10-20
Überblick
Das System folgt einer klassischen 4-Layer Struktur:
- View: JSF 2.3 / PrimeFaces 11 / XHTML Seiten (Formulare, Tabellen, Dialoge)
- Controller: CDI/JSF Managed Beans, Zustandsverwaltung & UI-Aktionen (extends AbstractController)
- Business: Stateless EJB Manager mit CRUD + Fachlogik (extends AbstractManager)
- Persistence: JPA Entities (extends AbstractEntity)
Basisklassen Rollen
- AbstractEntity: Basis-ID (Long, Identity), Timestamps, outdated Flag, equals/hashCode nur über ID.
- AbstractManager: CRUD, save vs saveAll, remove / removeAllIn, refresh (Hibernate.initialize), Fehlerlogging.
- AbstractController: UI State (selected, created, entities), Fake-ID-Erzeugung für neue temporäre Objekte, Messaging, PDF Utilities.
Lebenszyklus eines neuen Objekts
- UI erzeugt neues Objekt (id == null) -> Controller kann negative Fake-ID setzen falls in Collections benötigt.
- Vor persist: Falls id < 0 -> setId(null) damit JPA Identity funktioniert.
- save(): id == null => persist + flush, sonst merge + flush.
- refresh(): sorgt für Managed Entity + Initialisierung Lazy Properties.
Negative Fake IDs
- Zweck: Temporäre Unterscheidung mehrerer neu angelegter Einträge im UI bevor persist.
- Erzeugung: createFakeID(Collection) nimmt kleinste vorhandene negative ID - 1.
- Vor persist unbedingt auf null setzen.
Lazy Loading & Refresh
- Manager.refresh(entity) -> merge + Hibernate.initialize(entity) für Entität.
- Für Collections: spezielle Reload-Methoden in fachlichen Managern (z.B. reloadWithQuestionnaires).
- Nach Batch-Operationen Controller.refrehSelected() (Tippfehler) nutzen; perspektivisch in refreshSelected() umbenennen.
Transaktionen
- Schreiboperationen annotiert mit @Transactional (Container-managed) in AbstractManager.save / saveAll.
- Fachmethoden, die persistieren oder mergen, sollten ebenfalls @Transactional erhalten (Konsistenz).
Fehlerbehandlung
- Aktuell: Logging (LOGGER.error) + bool Rückgabe.
- Geplant: Einführung BusinessException für differenzierte Fehlerpfade.
Erweiterungsmuster (Domain hinzufügen)
- Entity erstellen (extends AbstractEntity). Optional Named Queries.
- Manager: @Stateless extends AbstractManager; spezifische Queries / Reload Methoden.
- Controller: @Named + Scope (ViewScoped/SessionScoped) extends AbstractController.
- XHTML Seite inkl. Referenzen zu Controller (DataTable, Dialoge, Commands).
- Tests: CRUD & fachliche Spezialfunktionen.
Typische Fachfunktionen
- Klonen: Quelle re-laden + initialisieren; neue Instanz mit Copy-Konstruktor; Child IDs null; Collections duplizieren kontrolliert.
- Zuordnungen (z.B. Fragebogen): Add/Remove Pattern über Wrapper Entity.
PDF-Erstellung
- iText7 Nutzung über Hilfsmethoden in AbstractController (Tabellen, Inner Cells, Paginierung).
- Keine neuen Features mehr mit iText5 API implementieren.
Querschnittsthemen & Roadmap
- Vereinheitlichte Exception Layer.
- Bean Validation (javax.validation) für Eingaben & persistente Konsistenz.
- Test Suite (JUnit + ggf. Arquillian / Integrationstests) ausbauen.
- Migration nach Jakarta EE (Namespace Wechsel javax -> jakarta) perspektivisch.
Edge Cases & Hinweise
- save(null) => false zurückgeben.
- remove(entity) ohne persistierte ID => false.
- Batch Speichern: leere Liste => true (no-op) statt Fehler.
- Collections initialisieren vor Iteration (Avoid LazyInitializationException).
Generator Leitplanken
- Bestehende Signaturen respektieren.
- Keine neuen Frameworks ohne Notwendigkeit.
- Logging immer via LOGGER, niemals System.out.
- Für neue Write-Methoden @Transactional hinzufügen.