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.
This commit is contained in:
+84
@@ -0,0 +1,84 @@
|
||||
# AI Context Instructions
|
||||
|
||||
## Essentials
|
||||
- Base Classes: AbstractEntity, AbstractManager<T>, AbstractController<E>
|
||||
- Fake ID Mechanismus für neue Objekte
|
||||
- Hibernate.initialize für Lazy Collections
|
||||
# Architecture Instructions
|
||||
## Typical Generation Tasks
|
||||
1. Neue Domain (Entity/Manager/Controller/XHTML)
|
||||
2. PDF Utility Erweiterung (iText7)
|
||||
3. Sammel-Speichern (saveAll) bereitstellen
|
||||
4. Klon-Operationen (IDs null setzen, Collections duplizieren kontrolliert)
|
||||
5. Fragebogen Zuordnung (add/remove, available list)
|
||||
|
||||
## Edge Cases
|
||||
- Null Entities im save -> return false
|
||||
- Negative IDs beim remove -> zuerst persistieren oder aus UI entfernen
|
||||
- Concurrency Refresh: Nach batch Änderungen refreshSelected()
|
||||
|
||||
## Do / Don't
|
||||
- DO: Logging bei jeder Exception
|
||||
- DO: Konsistente Nutzung von @Transactional bei Schreiboperationen
|
||||
- DON'T: System.out oder ungefangene Exceptions durchreichen ohne Logging
|
||||
- DON'T: Business Logik direkt in XHTML Event Handler schreiben
|
||||
|
||||
## Upgrade Ideas
|
||||
- Exception Layer
|
||||
- Bean Validation
|
||||
- Service Layer zwischen Controller und Manager falls Logik wächst
|
||||
|
||||
---
|
||||
Aktualisiert: 2025-10-20
|
||||
|
||||
## Purpose
|
||||
Verdichtete Architekturhinweise für automatische Code-Generierung und schnelle Orientierung.
|
||||
|
||||
## Stack
|
||||
- Java EE 8 (javax), WAR
|
||||
- JSF 2.3 + PrimeFaces 11 + PrimeFlex 2.0
|
||||
- Hibernate JPA (Persistence Unit: pu_person)
|
||||
- Log4j2
|
||||
|
||||
## Layer
|
||||
1. View (XHTML)
|
||||
2. Controller (JSF/CDI Beans, extends AbstractController<E>)
|
||||
3. Business (Stateless EJB Manager, extends AbstractManager<T>)
|
||||
4. Persistence (JPA Entities, extends AbstractEntity)
|
||||
|
||||
## Base Classes
|
||||
- AbstractManager<T>: CRUD (save, saveAll, refresh, remove), flush nach Persist/Merge.
|
||||
- AbstractController<E>: UI State (selected, created, entities), Messages, PDF Utilities, Fake-ID-Erzeugung.
|
||||
|
||||
## Entity Lifecycle UI
|
||||
- Neue Objekte: erhalten negative Fake-ID
|
||||
- Vor Persist: negative IDs -> null setzen
|
||||
- save/saveAll entscheidet anhand id == null zwischen persist/merge
|
||||
|
||||
## Lazy Loading
|
||||
- Refresh via AbstractManager.refresh(entity) + Hibernate.initialize(entity)
|
||||
- Für Collections: dedizierte reload Methoden (z.B. SecurityAreaManager.reloadWithQuestionnaires)
|
||||
|
||||
## PDF
|
||||
- iText7 bevorzugt; Altbestand iText5 (itextpdf 5.5.13) kann später entfernt werden.
|
||||
|
||||
## Logging & Fehler
|
||||
- LOGGER.error(e) bei Fehlern
|
||||
- Aktuell viele bool Rückgaben; Verbesserungspotential: BusinessException
|
||||
|
||||
## Erweiterung Pattern
|
||||
Entity -> Manager -> Controller -> XHTML
|
||||
|
||||
## Schulden / Verbesserungen
|
||||
- Mischung iText5/7
|
||||
- Inkonsistente Fehlerbehandlung
|
||||
- Kein DTO Layer
|
||||
- Wenige Tests
|
||||
|
||||
## Empfehlungen für Generator
|
||||
- Bestehende Signaturen unverändert lassen
|
||||
- @Transactional nur bei Schreibmethoden hinzufügen
|
||||
- Collections initialisieren bevor darauf iteriert wird
|
||||
|
||||
---
|
||||
Aktualisiert: 2025-10-20
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
# Architecture Instructions
|
||||
|
||||
Aktualisiert: 2025-10-20
|
||||
|
||||
## Überblick
|
||||
Das System folgt einer klassischen 4-Layer Struktur:
|
||||
1. View: JSF 2.3 / PrimeFaces 11 / XHTML Seiten (Formulare, Tabellen, Dialoge)
|
||||
2. Controller: CDI/JSF Managed Beans, Zustandsverwaltung & UI-Aktionen (extends AbstractController<E>)
|
||||
3. Business: Stateless EJB Manager mit CRUD + Fachlogik (extends AbstractManager<T>)
|
||||
4. Persistence: JPA Entities (extends AbstractEntity)
|
||||
|
||||
## Basisklassen Rollen
|
||||
- AbstractEntity: Basis-ID (Long, Identity), Timestamps, outdated Flag, equals/hashCode nur über ID.
|
||||
- AbstractManager<T>: CRUD, save vs saveAll, remove / removeAllIn, refresh (Hibernate.initialize), Fehlerlogging.
|
||||
- AbstractController<E>: UI State (selected, created, entities), Fake-ID-Erzeugung für neue temporäre Objekte, Messaging, PDF Utilities.
|
||||
|
||||
## Lebenszyklus eines neuen Objekts
|
||||
1. UI erzeugt neues Objekt (id == null) -> Controller kann negative Fake-ID setzen falls in Collections benötigt.
|
||||
2. Vor persist: Falls id < 0 -> setId(null) damit JPA Identity funktioniert.
|
||||
3. save(): id == null => persist + flush, sonst merge + flush.
|
||||
4. 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<E>) 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)
|
||||
1. Entity erstellen (extends AbstractEntity). Optional Named Queries.
|
||||
2. Manager: @Stateless extends AbstractManager<NewEntity>; spezifische Queries / Reload Methoden.
|
||||
3. Controller: @Named + Scope (ViewScoped/SessionScoped) extends AbstractController<NewEntity>.
|
||||
4. XHTML Seite inkl. Referenzen zu Controller (DataTable, Dialoge, Commands).
|
||||
5. 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.
|
||||
|
||||
---
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
# Cloning Instructions
|
||||
|
||||
Aktualisiert: 2025-10-20
|
||||
|
||||
## Ziel
|
||||
Sicheres Klonen von komplexen Domains (z.B. SecurityArea inkl. Sub-Entities) ohne ID-Kollisionen oder versehentliches Persistieren historischer Referenzen.
|
||||
|
||||
## Grundprinzipien
|
||||
- Nur persistente Quelle klonen (ID > 0) -> Vorher `refresh` zur Initialisierung Lazy Collections.
|
||||
- Neue Instanzen erhalten `id = null` (oder negative Fake-ID falls im UI direkt angezeigt).
|
||||
- Child-Entitäten ebenfalls mit `id = null` erzeugen.
|
||||
|
||||
## Vorgehen (Muster)
|
||||
1. Quelle laden (Manager.find) & `refresh`.
|
||||
2. Copy-Konstruktor oder Factory-Methode: Primitive Felder kopieren, Collections iterieren.
|
||||
3. Collections: Neue Collection erzeugen, für jedes Kind tiefes Copy erstellen (kein Reuse Managed Instanz!).
|
||||
4. IDs aller Kinder null setzen.
|
||||
5. Optionale Anpassungen (Name -> "Kopie von <original>").
|
||||
6. Rückgabe unverpersistiertes Root-Objekt an Controller.
|
||||
|
||||
## Tiefe vs. Flache Kopie
|
||||
- Tiefe Kopie: Notwendig wenn Kinder eigenständige persistente Entities sind.
|
||||
- Flache Kopie: Ausreichend falls nur Referenzen (Read-Only) erhalten bleiben sollen; aktuell bevorzugt tiefe Kopie für isolierte Bearbeitung.
|
||||
|
||||
## Edge Cases
|
||||
- Quelle == null -> abort.
|
||||
- Quelle mit Lazy Collections nicht initialisiert -> Gefahr LazyInitializationException.
|
||||
- Zyklische Referenzen -> sorgfältig verhindern Endlosschleifen (ggf. bereits geklonte Instanzen in Map tracken).
|
||||
|
||||
## Fake IDs
|
||||
- Wenn Klon direkt in UI Collection erscheint: negative ID via `createFakeID` generieren.
|
||||
- Vor persist -> ID auf null setzen.
|
||||
|
||||
## Verbesserungen
|
||||
- Einführung eines generischen `CloneService` mit rekursiver Strategie und Zyklus-Erkennung.
|
||||
- Annotation @SkipClone für Felder die nicht übernommen werden sollen.
|
||||
|
||||
## Generator Leitplanken
|
||||
- Keine Reflection-Magie für tiefe Kopien; lieber explizite Copy-Konstruktoren für Lesbarkeit.
|
||||
- Reihenfolge: zuerst Root, dann Kinder.
|
||||
|
||||
---
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
# Coding Guidelines Instructions
|
||||
|
||||
## Naming
|
||||
- Manager: *Manager
|
||||
- Controller: *Controller
|
||||
- Entities: Singular Substantive
|
||||
- Negative IDs: temporäre Objekte
|
||||
|
||||
## Style
|
||||
- 4 Spaces
|
||||
- Logger statt System.out
|
||||
- Deutsche UI-Texte, Englisch im Code
|
||||
|
||||
## Error Handling
|
||||
- Log + Rückgabe (bestehend); für neue komplexe Logik optional BusinessException
|
||||
|
||||
## Persistenz
|
||||
- Neue Entity: id == null vor persist
|
||||
- refresh(entity) nutzen um Lazy Collections zu initialisieren
|
||||
|
||||
## Transaktionen
|
||||
- Schreibmethoden: @Transactional (oder rely auf EJB Container)
|
||||
|
||||
## Performance
|
||||
- Sammeloperationen: saveAll(Collection<T>)
|
||||
|
||||
## UI
|
||||
- PrimeFaces Dialoge schließen mit closeDialogs
|
||||
- Negative IDs in Listen bis Sammelspeichern
|
||||
|
||||
## PDF
|
||||
- Neue Funktionen nur mit iText7 API
|
||||
|
||||
## Tests (Empfehlung)
|
||||
- CRUD Manager Tests
|
||||
- Klon & Fragebogen Zuordnung
|
||||
|
||||
## Anti-Pattern
|
||||
- Logik nicht direkt im Controller wenn generell wiederverwendbar
|
||||
- Keine duplizierten Query Strings -> Named Queries
|
||||
|
||||
---
|
||||
Aktualisiert: 2025-10-20
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
# Error Handling Instructions
|
||||
|
||||
Aktualisiert: 2025-10-20
|
||||
|
||||
## Aktueller Zustand
|
||||
- Fehler werden in Managern primär über `LOGGER.error(e)` geloggt.
|
||||
- Rückgabe bool (true/false) signalisiert Erfolg/Misserfolg.
|
||||
- Keine differenzierte Fehlerklassifikation (Business vs. System).
|
||||
|
||||
## Ziele
|
||||
- Konsistente Behandlung & klare Trennung der Fehlerarten.
|
||||
- Verbesserte Diagnose für Nutzer & Logs.
|
||||
|
||||
## Kategorien
|
||||
1. Validation Errors (Bean Validation zukünftig) -> Nutzerfeedback.
|
||||
2. Business Rule Violations -> eigene Exception (z.B. `BusinessException`).
|
||||
3. System Errors (DB Down, Hibernate Exceptions) -> Logging + generische Fehlermeldung.
|
||||
|
||||
## Kurzfristige Empfehlungen
|
||||
- Bei allen catch-Blöcken: `LOGGER.error("<Kontext>", e)` statt nur `LOGGER.error(e)`.
|
||||
- Controller: Nach boolean false -> `errorMessage()` anzeigen.
|
||||
|
||||
## Einführung BusinessException (geplant)
|
||||
- Checked oder Runtime? Vorschlag: Runtime zur vereinfachten Nutzung.
|
||||
- Manager Methoden können `throw new BusinessException("Message")` statt false.
|
||||
- Controller fängt BusinessException und zeigt spezifische Nachricht.
|
||||
|
||||
## Log Format
|
||||
- Kontext + Entity-ID + Operation.
|
||||
Beispiel: `LOGGER.error("Failed to persist SecurityArea id={} name={}", area.getId(), area.getName(), e);`
|
||||
|
||||
## Edge Cases
|
||||
- Null Übergaben -> früh validieren & BusinessException werfen (später) / false zurückgeben (jetzt).
|
||||
- Sammeloperation: Teilfehler -> aktuell Abort bei erstem Fehler. Optional Sammeln & Aggregatfehler.
|
||||
|
||||
## Verbesserungen
|
||||
- Central Exception Mapper (JSF PhaseListener / CDI Interceptor).
|
||||
- Korrelation IDs in Logs (Request ID, User ID).
|
||||
|
||||
## Generator Leitplanken
|
||||
- Logging immer, auch bei ignorable Exceptions.
|
||||
- Keine System.out Nutzung.
|
||||
- Fehler nicht stillschweigend verschlucken (mindestens loggen).
|
||||
|
||||
---
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
# Extend Project Instructions
|
||||
|
||||
## Pattern
|
||||
Entity -> Manager -> Controller -> XHTML -> Navigation
|
||||
|
||||
## Steps (Template)
|
||||
1. Entity: @Entity extends AbstractEntity
|
||||
2. Manager: @Stateless extends AbstractManager<Entity>
|
||||
3. Controller: @Named + Scope extends AbstractController<Entity>
|
||||
4. UI: xhtml mit #{controller}
|
||||
5. Tests: CRUD + Spezialmethoden
|
||||
|
||||
## Fake IDs
|
||||
- Neue Objekte in Collections: negative ID (createFakeID)
|
||||
- Vor Persist: setId(null)
|
||||
|
||||
## Klonen
|
||||
- Quelle laden & initialisieren
|
||||
- Copy-Konstruktor
|
||||
- Child IDs null
|
||||
|
||||
## Checklist
|
||||
- [ ] Named Queries falls benötigt
|
||||
- [ ] Logging bei Fehlern
|
||||
- [ ] @Transactional bei Schreibmethoden
|
||||
- [ ] Keine System.out
|
||||
|
||||
## Common Pitfalls
|
||||
- LazyInitializationException -> refresh
|
||||
- Vergessen negative IDs zurückzusetzen -> Persist fehlschlägt
|
||||
|
||||
---
|
||||
Aktualisiert: 2025-10-20
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
# General Project Instructions
|
||||
|
||||
## Quick Facts
|
||||
- Java EE 8 (javax) / Java 11 / WAR
|
||||
- JSF + PrimeFaces + PrimeFlex
|
||||
- Persistence Unit: pu_person
|
||||
- Logging: Log4j2
|
||||
|
||||
## Build
|
||||
mvn clean package -> target/mss-1.0-SNAPSHOT.war
|
||||
|
||||
## Core Patterns
|
||||
- Manager: CRUD + Fachmethoden (extends AbstractManager)
|
||||
- Controller: UI State + Messages + PDF (extends AbstractController)
|
||||
- Negative IDs für temporäre Objekte
|
||||
|
||||
## PDF
|
||||
- iText7 bevorzugen; Legacy iText5 entfernen später
|
||||
|
||||
## Improvements Roadmap
|
||||
- Vereinheitlichte Exception Strategie
|
||||
- Test Suite aufbauen
|
||||
- Migration nach Jakarta EE (Namespace Wechsel)
|
||||
|
||||
## AI Generation Hints
|
||||
- Halte Signaturen stabil
|
||||
- Keine neuen Frameworks
|
||||
- Initialisiere Lazy Collections vor Nutzung
|
||||
|
||||
---
|
||||
Aktualisiert: 2025-10-20
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
# Index Instructions
|
||||
|
||||
Aktualisiert: 2025-10-20
|
||||
|
||||
Zentraler Überblick über alle *.instructions.md Dateien im Ordner `.github` für automatische Nutzung.
|
||||
|
||||
## Übersicht Bestehend
|
||||
- Architektur: `architecture.instructions.md`
|
||||
- Coding Guidelines: `coding_guidelines.instructions.md`
|
||||
- Domain (Security Area): `security_area_domain.instructions.md`
|
||||
- Fragebogen Workflow: `questionnaire_workflow.instructions.md`
|
||||
- Projekt Erweiterung: `extend_project.instructions.md`
|
||||
- Refresh & Fake-ID Mechanismus: `refresh_fake_id.instructions.md`
|
||||
- Allgemeine Projektinfo: `general_project.instructions.md`
|
||||
- AI Kontext / Generatorhinweise: `ai_context.instructions.md`
|
||||
|
||||
## Neue Spezial-Themen
|
||||
- Persistence Layer: `persistence.instructions.md`
|
||||
- PDF Generierung (iText7): `pdf_generation.instructions.md`
|
||||
- Klon-Strategien: `cloning.instructions.md`
|
||||
- Fehler & Logging: `error_handling.instructions.md`
|
||||
- Test-Strategie: `testing_strategy.instructions.md`
|
||||
- Transaktionen: `transactions.instructions.md`
|
||||
- Manager/Controller Muster: `manager_controller_pattern.instructions.md`
|
||||
|
||||
## Verwendung (Automatisierung)
|
||||
1. Start: `general_project.instructions.md` + `architecture.instructions.md` lesen.
|
||||
2. Bei neuen Entities: `extend_project.instructions.md` + `persistence.instructions.md`.
|
||||
3. Bei UI/Business Verkettung: `manager_controller_pattern.instructions.md`.
|
||||
4. Für Fragebogenfunktionen: `questionnaire_workflow.instructions.md` + `security_area_domain.instructions.md`.
|
||||
5. Für temporäre IDs & Refresh: `refresh_fake_id.instructions.md`.
|
||||
6. Für PDF Features: `pdf_generation.instructions.md`.
|
||||
7. Für Klon-Operationen: `cloning.instructions.md`.
|
||||
8. Für Fehlerstrategie: `error_handling.instructions.md`.
|
||||
9. Für Transaktionsregeln: `transactions.instructions.md`.
|
||||
10. Für Qualitätsstil: `coding_guidelines.instructions.md`.
|
||||
|
||||
## Priorität bei Unklarheiten
|
||||
1. `general_project.instructions.md`
|
||||
2. `architecture.instructions.md`
|
||||
3. `coding_guidelines.instructions.md`
|
||||
4. Spezialthema betreffende Datei
|
||||
|
||||
## Pflegehinweise
|
||||
- Beim Ändern von Basisklassen (AbstractManager / AbstractController / AbstractEntity) entsprechende Dateien aktualisieren.
|
||||
- Tippfehler Methode `refrehSelected()` bei Umbenennung in Code auch in `refresh_fake_id.instructions.md` und `architecture.instructions.md` anpassen.
|
||||
- Neue fachliche Domains erhalten eigene `<domain>.instructions.md` Datei mit Operations-, Entity- und Edge Case Liste.
|
||||
|
||||
## Roadmap Dokumentation
|
||||
- Nach Einführung eines Exception Layers: `error_handling.instructions.md` erweitern.
|
||||
- Nach Migration zu Jakarta: Alle Dateien Namespace Hinweis aktualisieren.
|
||||
|
||||
---
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
# 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.
|
||||
|
||||
---
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
# PDF Generation Instructions
|
||||
|
||||
Aktualisiert: 2025-10-20
|
||||
|
||||
## Kontext
|
||||
PDF-Erstellung erfolgt aktuell über Hilfsmethoden in `AbstractController` mittels iText7.
|
||||
|
||||
## Kern-Hilfsmethoden
|
||||
- `loadCompanyLogo()` -> Lädt Logo aus LOGO_PATH.
|
||||
- `generateSorroundingTable(String header, float maxWidth)` -> Einspaltige Rahmen-Tabelle mit Header.
|
||||
- `generateInnerTable(Text header, boolean last, String... values)` -> 2-Spalten Tabelle mit alternierender Hintergrundfarbe.
|
||||
- `generateInnerTable(Text header, int nrColumns, boolean last, String... values)` -> Generisch n-Spalten Tabelle.
|
||||
- `addInnerCells(Table table, String name, String value, boolean isGray)` / Overload -> Fügt Datenzeilen hinzu.
|
||||
- `addPagenumbers(Document document, String ticketNr, Image nextPagesCompanyLogo)` -> Fügt Seitenzahlen & Logo hinzu.
|
||||
|
||||
## Gestaltungsrichtlinien
|
||||
- Fonts: Standard Helvetica / Bold (Konstanten `FONT_NORMAL`, `FONT_BOLD`).
|
||||
- Schriftgrößen klein (8F Inhalte, 11F Header, 12F Hauptheader) für konsistente Layouts.
|
||||
- Wechselnde Hintergrundfarbe (LIGHT_GRAY) zur besseren Lesbarkeit.
|
||||
|
||||
## Erweiterung
|
||||
Neue Tabellen-/Layout-Funktionen:
|
||||
1. Prüfen ob existierende Methoden erweiterbar statt neue Variante.
|
||||
2. Konsistenz in Font & Spaltenbreiten wahren.
|
||||
3. Kein Hardcode von absoluten Positionen außer bei Kopf-/Fußzeilen.
|
||||
|
||||
## Ressourcen Pfade
|
||||
- LOGO_PATH statisch: `/rundata/logo.png`. Anpassungen zentral vornehmen.
|
||||
|
||||
## Fehlerhandhabung
|
||||
- Aktuell wenige try/catch Blöcke; bei Erweiterung: Fehler loggen (`LOGGER.error(e)`) und Benutzer über Controller Messages informieren.
|
||||
|
||||
## Edge Cases
|
||||
- Leere Werte -> `-/-` Platzhalter.
|
||||
- Null Tabelleninstanz in addInnerCells -> early return.
|
||||
|
||||
## Verbesserungen
|
||||
- Einführung eines PDFUtility Service zur Entkopplung vom Controller.
|
||||
- Parameterobjekt für dynamische Tabellenkonfiguration (Spaltenbreiten, Farben, Größen).
|
||||
|
||||
## Generator Leitplanken
|
||||
- iText7 API weiterverwenden; keine neuen PDF Libraries.
|
||||
- Wiederverwendbare Logik nicht direkt im konkreten Controller implementieren -> Utility / Service.
|
||||
|
||||
---
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
# Questionnaire Workflow Instructions
|
||||
|
||||
## Add
|
||||
areaManager.addQuestionnaireToSecurityArea(area, questionnaire)
|
||||
- area ggf. re-laden
|
||||
- Wrapper erzeugen
|
||||
- Persist wrapper + merge area
|
||||
- Rückgabe: aktualisierte Area
|
||||
|
||||
## Remove
|
||||
areaManager.removeQuestionnaireFromSecurityArea(area, wrapper)
|
||||
- area & wrapper re-laden
|
||||
- Collection remove, em.remove(wrapper), em.merge(area)
|
||||
|
||||
## Available List
|
||||
getAvailableQuestionnaires(area): SELECT q FROM Questionaire q ORDER BY q.name
|
||||
- Filter: bereits zugeordnete Namen
|
||||
|
||||
## Edge Cases
|
||||
- Null area/questionnaire -> Fehlermeldung
|
||||
- Race condition -> nach Add/Remove refreshSelected()
|
||||
|
||||
## Verbesserungen
|
||||
- ID statt Name für Filter
|
||||
- Duplikatprüfung direkt im Manager
|
||||
|
||||
---
|
||||
Aktualisiert: 2025-10-20
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
# Refresh & Fake ID Instructions
|
||||
|
||||
## Fake ID
|
||||
- Negative Long Werte (<0) = temporär
|
||||
- Sequenz: -1, -2, -3 ... (kleinste negative - 1)
|
||||
- Erzeugung: AbstractController.createFakeID(Collection<E>)
|
||||
|
||||
## Persist
|
||||
- Vor Speichern: if id < 0 -> setId(null)
|
||||
- save/saveAll: id == null => persist, sonst merge
|
||||
|
||||
## Refresh
|
||||
- AbstractController.refrehSelected() (Tippfehler) -> getManager().refresh(selected)
|
||||
- AbstractManager.refresh(entity): if id == null -> save(entity); merge + Hibernate.initialize(entity)
|
||||
|
||||
## Best Practices
|
||||
- Nach Add/Remove Child Collections refresh
|
||||
- Beim Klonen zuerst Quelle laden
|
||||
|
||||
## Verbesserungen
|
||||
- Methode umbenennen zu refreshSelected()
|
||||
- JavaDoc für createFakeID
|
||||
|
||||
---
|
||||
Aktualisiert: 2025-10-20
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
# Security Area Domain Instructions
|
||||
|
||||
## Entities
|
||||
- SecurityArea
|
||||
- SecurityDevice / DangerPoint / SwitchingDevice
|
||||
- SecurityAreaQuestionnaire (Wrapper) + Questionaire
|
||||
|
||||
## Operations
|
||||
- cloneArea(SecurityArea)
|
||||
- addQuestionnaireToSecurityArea(area, questionnaire)
|
||||
- removeQuestionnaireFromSecurityArea(area, wrapper)
|
||||
- getAvailableQuestionnaires(area)
|
||||
- reloadWithQuestionnaires(area)
|
||||
|
||||
## Workflow (Add Questionnaire)
|
||||
1. Area laden (falls id > 0)
|
||||
2. Wrapper erstellen & area setzen
|
||||
3. Persist Wrapper, merge Area
|
||||
4. Refresh im Controller
|
||||
|
||||
## Deletion Pattern
|
||||
- Beziehungen lösen (Kinder area = null setzen)
|
||||
- Kinder entfernen (Manager.removeAllIn)
|
||||
- Area per Named Query löschen
|
||||
|
||||
## Edge Cases
|
||||
- Duplicate questionnaire by name -> aktuell Filter per Name
|
||||
- Verbesserung: Filter per ID
|
||||
|
||||
## Klonen
|
||||
- Persistente Quelle re-laden, initialisieren
|
||||
- Copy-Konstruktor & alle Child IDs auf null
|
||||
|
||||
## Verbesserungen
|
||||
- CascadeSettings prüfen
|
||||
- Bean Validation einsetzen
|
||||
|
||||
---
|
||||
Aktualisiert: 2025-10-20
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
# Testing Strategy Instructions
|
||||
|
||||
Aktualisiert: 2025-10-20
|
||||
|
||||
## Ziele
|
||||
Testabdeckung für kritische Pfade: CRUD, Clone, Fragebogen Zuordnung, Fake-ID Mechanismus.
|
||||
|
||||
## Testarten
|
||||
1. Unit Tests (reine Logik, z.B. createFakeID, Klon Copy-Konstruktoren).
|
||||
2. Integration Tests (Persistence + Manager Methoden gegen Test-DB). Möglich mit in-memory H2 + angepasster persistence.xml.
|
||||
3. UI/Controller Smoke Tests (Optional, z.B. mit Selenium/Arquillian Graphene).
|
||||
|
||||
## Prioritäten
|
||||
- AbstractManager.save / saveAll Edge Cases.
|
||||
- remove / removeAllIn (Null, nicht persistierte Entities).
|
||||
- createFakeID Sequenz (-1, -2, -3 ...).
|
||||
- Fragebogen Add/Remove Workflow (Wrapper Persistenz, Filterliste).
|
||||
- Klonen tiefer Objektgraph.
|
||||
|
||||
## Beispiel Unit Test Fälle
|
||||
- createFakeID(null) => -1.
|
||||
- createFakeID(leere Liste) => -1.
|
||||
- createFakeID([id=-1]) => -2.
|
||||
- createFakeID([id=-3, id=-1]) => -4.
|
||||
|
||||
## Integration Tests (CRUD)
|
||||
- Persist neue Entity -> ID != null.
|
||||
- Merge vorhandene Entity -> unverändert Fachfelder korrekt übernommen.
|
||||
- saveAll mit gemischten (neue + vorhandene) -> alle persistent.
|
||||
|
||||
## Fehlerpfade
|
||||
- save(null) -> false.
|
||||
- remove(null) -> false.
|
||||
- remove(entity ohne ID) -> false.
|
||||
|
||||
## Klon Tests
|
||||
- Quelle & Klon dürfen nicht gleiche ID haben.
|
||||
- Child Collections tief kopiert (Referenzen ungleich, Werte gleich).
|
||||
|
||||
## Tooling Vorschlag
|
||||
- JUnit 5, Mockito für isolierte Tests von Controller-Hilfsmethoden.
|
||||
- Testcontainers (Optional später) für realistischere DB.
|
||||
|
||||
## Generator Leitplanken
|
||||
- Für neue Fachlogik minimal 1-2 Unit Tests + 1 Integration Test.
|
||||
- Keine Abhängigkeit auf Produktionspfade in Unit Tests; Test-spezifische Testdaten-Builder.
|
||||
|
||||
---
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
# Transactions Instructions
|
||||
|
||||
Aktualisiert: 2025-10-20
|
||||
|
||||
## Kontext
|
||||
Container-Managed Transaktionen (Java EE). Verwendung von `@Transactional` auf Manager-Methoden für Schreiboperationen.
|
||||
|
||||
## Grundsätze
|
||||
- Jede persistierende Operation (create, edit, remove) innerhalb einer Transaktion.
|
||||
- `save` und `saveAll` bereits mit `@Transactional` versehen.
|
||||
- Leseoperationen können ohne Annotation auskommen (Default: kein Write-Lock nötig).
|
||||
|
||||
## Batch Operationen
|
||||
- `saveAll(Collection<T>)`: Ein Transaktionskontext für gesamte Collection -> entweder komplett erfolgreich oder Abbruch beim Fehler.
|
||||
- Optimierungspotential: Fehler sammeln, nicht sofort abbrechen.
|
||||
|
||||
## Refresh
|
||||
- `refresh(entity)` führt merge aus; wenn `id == null` vorher persist -> bleibt innerhalb Transaktion falls aufgerufen durch `save`/`saveAll`.
|
||||
|
||||
## Remove
|
||||
- `remove(entity)` ohne `@Transactional` in Basisklasse -> Empfehlung: Annotation hinzufügen in konkretem Manager wenn Delete-Fachlogik erweitert wird.
|
||||
|
||||
## Edge Cases
|
||||
- Verschachtelte Aufrufe (save -> intern create/edit): Container handhabt Propagation (`REQUIRED`).
|
||||
- LazyInitializationException vermeiden: innerhalb Transaktion initialisieren.
|
||||
|
||||
## Empfohlene Annotationen
|
||||
- Zusätzliche fachliche Write-Methoden stets mit `@Transactional` versehen.
|
||||
- Pure Read: Performancekritisch -> ggf. explizit `@Transactional(Transactional.TxType.SUPPORTS)` oder weglassen.
|
||||
|
||||
## Fehlerfall Verhalten
|
||||
- Ungefangene RuntimeException -> Rollback durch Container.
|
||||
- Aktuell Exceptions geloggt & boolean false -> verhindert Rollback. Verbesserung: BusinessException throw + Rollback.
|
||||
|
||||
## Generator Leitplanken
|
||||
- Keine eigenen manuell geöffneten Transaktionen (kein `UserTransaction`).
|
||||
- Konsistenz: Schreibmethoden annotieren, Leseoperationen nur bei Bedarf.
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user