Files
pi_mcps/java/mss-failsafe/.github/manager_controller_pattern.instructions.md
Patrick Plate 1a0a56a626 chore(java): consolidate mss-failsafe to single canonical copy
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.
2026-06-13 19:55:28 +02:00

4.1 KiB
Executable File

Manager/Controller Pattern Instructions

Aktualisiert: 2025-10-20

Ziele

Klare Trennung zwischen UI-Zustand (Controller) und Geschäftslogik/Persistenz (Manager).

Verantwortlichkeiten

Controller:

  • Zustände: selected, created, entities.
  • UI Nachrichten (FacesMessage).
  • Dialogsteuerung (PrimeFaces Widgets schließen).
  • Hilfsfunktionen (PDF, Fake-ID-Erzeugung).

Manager:

  • CRUD Operationen (create, edit, save, saveAll, remove, removeAllIn, find, findAll).
  • Fachspezifische Queries / Reload.
  • Fehlerlogging.

Interaktion

  • Controller ruft Manager.save / saveAll auf für Persistenz.
  • Nach Änderungen: Controller.refrehSelected() (Tippfehler) -> aktualisiert ausgewähltes Objekt.
  • Kein direkter EntityManager Zugriff im Controller.

Fake-ID Ablauf

  1. Controller erzeugt neue Entität (id == null).
  2. Falls Sammlung benötigt: setzt negative ID über createFakeID.
  3. Bei Save: Manager erkennt id < 0 (nach vorherigem Nullsetzen) -> persist.

Methoden-Namenskonventionen

  • Manager: Verb + Domänenobjekt (addQuestionnaireToSecurityArea, removeQuestionnaireFromSecurityArea).
  • Controller: UI Aktionen (saveSelected, createNew, openDialog, closeDialogs).

Edge Cases

  • selected == null bei refresh -> no-op.
  • entities Liste leer -> UI Tabelle zeigt keine Einträge; Null vermeiden (immer leere Liste).

Messaging

  • Erfolg: successMessage(); Fehler: errorMessage().
  • Spezifische Warnungen über sendWarnMessage.

Verbesserungen

  • Umbenennung refrehSelected() -> refreshSelected() in Basisklasse + alle Verwendungen.
  • Einführung eines BasePDFController oder Utility zur Auslagerung PDF Logik.

Generator Leitplanken

  • Zusätzliche Logik (berechnete Felder, Validierungen) zuerst im Manager statt im Controller (besser testbar, wiederverwendbar).
  • Controller schlank halten: keine komplexe Businessregeln.

Persistence Instructions

Aktualisiert: 2025-10-20

Ziele

Konsistente JPA Nutzung (Java EE 8, Hibernate Provider) mit klaren Regeln für IDs, Lazy Loading und Flush.

Grundsätze

  • Entities extend AbstractEntity (Long id, creationDate, changedDate, outdated Flag).
  • Identity Generation: @GeneratedValue(strategy = GenerationType.IDENTITY) -> Kein manuelles Setzen positiver IDs.
  • Equals/HashCode nur auf ID (Basis-Klasse bereitgestellt).

ID & Fake-ID Handling

  • Temporäre neue Objekte können negative IDs erhalten (Fake) zur UI-Differenzierung.
  • Vor persist: if id != null && id < 0 -> setId(null) damit JPA eine echte ID generiert.
  • Niemals persist mit negativer ID ausführen.

Lebenszyklus

  1. Konstruktor setzt creationDate & changedDate.
  2. Bei Änderungen Fachlogik: changedDate aktualisieren (TODO: zentralisieren via EntityListener).
  3. Persist -> flush direkt in AbstractManager.save / saveAll.

Lazy Loading

  • Vermeide direkte Iteration über nicht initialisierte Collections außerhalb Transaktion.
  • Nutzung AbstractManager.refresh(entity) initialisiert das Entity (Hibernate.initialize(entity)).
  • Für Collections eigene Reload-Methoden in spezialisierten Managern implementieren.

Named Queries & Criteria

  • Bevorzugt Criteria API für dynamische Filter.
  • Häufig verwendete, statische Abfragen als @NamedQuery in der Entity definieren.

Performance Hinweise

  • saveAll(Collection<T>) nutzt einen Flush am Ende; reduziert DB Roundtrips.
  • Bulk Delete oder Update lieber über JPQL statt Einzelloops (aktuell: removeAllIn loop; Optimierungspotential).

Edge Cases

  • save(null) => false (kein Fehlerwurf, Logging im Manager).
  • Leere Collections in saveAll => true (no-op).
  • remove(entity) mit entity.getId()==null => false; vorher persistieren oder ignorieren.

Verbesserungs-Ideen

  • EntityListener für Timestamps.
  • Soft Delete (outdated Flag) statt physischem Löschen für Audit.
  • Einführung eines Version-Feldes für Optimistic Locking.

Generator Leitplanken

  • Keine Änderung der ID-Strategie ohne umfassende Migration.
  • Bei neuen Entities standardisierte Felder aus AbstractEntity nutzen.
  • Collections initialisieren (z.B. new ArrayList<>()) im Entity-Konstruktor.