Java Web Aufbau – Tag 10 von 10
Von Elyndra Valen, Senior Developer bei Java Fleet Systems Consulting

🗺️ Deine Position im Kurs
| Tag | Thema | Status |
|---|---|---|
| 1 | Filter im Webcontainer | ✅ Abgeschlossen |
| 2 | Listener im Webcontainer | ✅ Abgeschlossen |
| 3 | Authentifizierung über Datenbank | ✅ Abgeschlossen |
| 4 | Container-Managed Security & Jakarta Security API | ✅ Abgeschlossen |
| 5 | Custom Tags & Tag Handler (SimpleTag) | ✅ Abgeschlossen |
| 6 | Custom Tag Handler mit BodyTagSupport | ✅ Abgeschlossen |
| 7 | JPA vs JDBC – Konfiguration & Provider | ✅ Abgeschlossen |
| 8 | JPA Relationen (1): @OneToOne & @ManyToOne | ✅ Abgeschlossen |
| 9 | JPA Relationen (2): @OneToMany & @ManyToMany | ✅ Abgeschlossen |
| → 10 | JSF Überblick – Component-Based UI | 👉 DU BIST HIER! |
Modul: Java Web Aufbau
Gesamt-Dauer: 10 Arbeitstage (je 8 Stunden)
Dauer heute: 8 Stunden
Dein Ziel: JSF-Architektur verstehen und erste Facelets-Anwendung erstellen
📋 Voraussetzungen für diesen Tag
Du brauchst:
- ✅ JDK 21 LTS installiert
- ✅ Apache NetBeans 22 (oder neuer)
- ✅ Payara Server 6.x konfiguriert und lauffähig
- ✅ MariaDB ab Version 11.6.2 (XAMPP oder Standalone)
- ✅ Java Web Basic Kurs abgeschlossen (Servlets, JSP, JSTL)
- ✅ Tag 1-9 vom Aufbau-Kurs abgeschlossen
- ✅ CDI und Bean Validation verstanden (aus Basic-Kurs Tag 8-9)
- ✅ JPA-Kenntnisse für Datenbankzugriff (Tag 7-9)
Tag verpasst?
Spring zurück zu Tag 9, um JPA-Relationen (@OneToMany, @ManyToMany) zu verstehen. JSF nutzt JPA für Datenpersistenz!
Setup-Probleme?
Schreib uns: support@java-developer.online
⚡ Das Wichtigste in 30 Sekunden
Was ist JSF? JavaServer Faces (JSF) ist ein komponentenbasiertes Web-Framework für Java EE/Jakarta EE. Im Gegensatz zu Servlets + JSP + JSTL (die du im Basic-Kurs gelernt hast) bietet JSF eine höhere Abstraktionsebene mit UI-Komponenten, Event-Handling und automatischem Data Binding.
Was lernst du heute? Du verstehst die JSF-Architektur, den Request-Lifecycle, Facelets (die View-Technologie), Managed Beans, und baust deine erste JSF-Anwendung mit CRUD-Operationen.
Warum ist das wichtig? JSF ist ein etabliertes Enterprise-Framework für komplexe Webanwendungen. Es abstrahiert HTTP-Details weg und lässt dich in Komponenten und Events denken – ähnlich wie Desktop-UI-Frameworks (Swing, JavaFX).
👋 Willkommen zu Tag 10 – Dem Finale!
Hi! 👋
Elyndra hier. Wow, Tag 10! Du hast es bis zum Ende des Java Web Aufbau Kurses geschafft! 🎉
Kurzwiederholung: Challenge von Tag 9
Gestern solltest du eine bidirektionale @ManyToMany-Beziehung zwischen Student und Course implementieren. Falls du es noch nicht gemacht hast, hier die Musterlösung:
// Student Entity
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private Set<Course> courses = new HashSet<>();
// Helper-Methoden für bidirektionale Beziehung
public void addCourse(Course course) {
courses.add(course);
course.getStudents().add(this);
}
public void removeCourse(Course course) {
courses.remove(course);
course.getStudents().remove(this);
}
// Getter/Setter
}
// Course Entity
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
@ManyToMany(mappedBy = "courses")
private Set<Student> students = new HashSet<>();
// Getter/Setter
}
Geschafft? ✅
Super! Heute schließen wir den Kurs mit JSF ab – einem mächtigen Framework für Enterprise-Webanwendungen!
Was dich heute erwartet:
Heute lernst du JSF – JavaServer Faces. Das ist ein Paradigmenwechsel:
Was du bisher kanntest (Servlets + JSP):
- Du schreibst Controller-Servlets
- Du verarbeitest Requests manuell
- Du forwardest zu JSPs
- Du nutzt JSTL für UI-Logik
Was JSF macht:
- Komponenten-basiert (wie Swing/JavaFX für Web!)
- Event-driven (Button-Click → Java-Methode)
- Automatic Data Binding (Formular ↔ Bean)
- Kein manuelles Request-Handling (Framework macht das!)
JSF ist ideal für:
- ✅ Komplexe Enterprise-Anwendungen
- ✅ Formulare mit vielen Validierungen
- ✅ CRUD-Operationen
- ✅ State-Management über Views hinweg
Aber:
- ❌ Nicht für REST-APIs (dafür JAX-RS)
- ❌ Nicht für Single-Page-Apps (dafür React/Angular)
- ❌ Lernkurve ist steiler als Servlets
Los geht’s! 🚀
🟢 GRUNDLAGEN: Was ist JSF?
Definition und Einordnung
JSF = JavaServer Faces
Ein komponentenbasiertes Web-Framework in Jakarta EE, das:
- UI-Komponenten bereitstellt (Buttons, Forms, Tables, etc.)
- Event-Handling ermöglicht (wie Desktop-Apps!)
- Data Binding automatisiert (Bean ↔ View)
- Request-Lifecycle managed
Wichtig zu verstehen:
JSF ist KEIN Ersatz für Servlets. JSF BASIERT auf Servlets!
Unter der Haube läuft ein spezielles Servlet (FacesServlet), das den JSF-Lifecycle steuert.
Der große Unterschied: Servlet+JSP vs. JSF
Servlet + JSP (was du im Basic-Kurs gelernt hast):
// Controller (Servlet)
@WebServlet("/user/edit")
public class UserEditServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String idParam = request.getParameter("id");
int id = Integer.parseInt(idParam);
UserDAO dao = new UserDAO();
User user = dao.findById(id);
request.setAttribute("user", user);
request.getRequestDispatcher("/WEB-INF/views/user-edit.jsp")
.forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
int id = Integer.parseInt(request.getParameter("id"));
String name = request.getParameter("name");
String email = request.getParameter("email");
User user = new User();
user.setId(id);
user.setName(name);
user.setEmail(email);
UserDAO dao = new UserDAO();
dao.update(user);
response.sendRedirect("list");
}
}
<!-- View (JSP) -->
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<form method="post" action="edit">
<input type="hidden" name="id" value="${user.id}"/>
<label>Name:</label>
<input type="text" name="name" value="${user.name}"/>
<label>Email:</label>
<input type="text" name="email" value="${user.email}"/>
<button type="submit">Save</button>
</form>
Viel manuelles HTTP-Handling!
Mit JSF:
// Managed Bean (Controller + Model)
@Named
@ViewScoped
public class UserEditBean implements Serializable {
@Inject
private UserService userService;
private User user;
@PostConstruct
public void init() {
// Parameter wird automatisch geholt!
Map<String, String> params =
FacesContext.getCurrentInstance()
.getExternalContext()
.getRequestParameterMap();
int id = Integer.parseInt(params.get("id"));
this.user = userService.findById(id);
}
// Action-Methode (wird bei Button-Click aufgerufen)
public String save() {
userService.update(user); // user ist automatisch gefüllt!
return "list?faces-redirect=true";
}
// Getter/Setter
public User getUser() { return user; }
public void setUser(User user) { this.user = user; }
}
<!-- View (Facelet - XHTML) -->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="jakarta.faces.html"
xmlns:f="jakarta.faces.core">
<h:head>
<title>Edit User</title>
</h:head>
<h:body>
<h:form>
<h:inputHidden value="#{userEditBean.user.id}"/>
<h:outputLabel value="Name:"/>
<h:inputText value="#{userEditBean.user.name}"/>
<h:outputLabel value="Email:"/>
<h:inputText value="#{userEditBean.user.email}"/>
<h:commandButton value="Save" action="#{userEditBean.save}"/>
</h:form>
</h:body>
</html>
Viel weniger Code! Automatisches Data Binding! Event-Handling!
JSF-Architektur: Die drei Säulen
┌─────────────────────────────────────────────────┐ │ JSF APPLICATION │ ├─────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ FACELETS │ │ MANAGED │ │ │ │ (View) │──│ BEANS │ │ │ │ │ │ (Controller │ │ │ │ *.xhtml │ │ + Model) │ │ │ └──────────────┘ └──────────────┘ │ │ │ │ │ │ │ │ ┌──────▼──────┐ │ │ │ MODEL │ │ │ │ (Entities │ │ │ │ + JPA) │ │ │ └─────────────┘ │ │ │ ├─────────────────────────────────────────────────┤ │ JSF LIFECYCLE (FacesServlet) │ ├─────────────────────────────────────────────────┤ │ SERVLET CONTAINER │ └─────────────────────────────────────────────────┘
1. Facelets (View-Layer):
- XHTML-basierte Templates
- JSF-Component-Tags (
<h:form>,<h:inputText>, etc.) - Expression Language für Data Binding (
#{bean.property})
2. Managed Beans (Controller + Model):
- CDI-Beans mit Scopes (
@ViewScoped,@SessionScoped, etc.) - Action-Methoden für Events
- Properties für Data Binding
3. JSF-Lifecycle:
- Verarbeitet Requests in 6 Phasen
- Managed automatisch Component-Tree
- Führt Validation/Conversion durch
Der JSF Request-Lifecycle (6 Phasen)
Das Herzstück von JSF:
HTTP Request kommt rein
│
▼
┌──────────────────────────────────────────┐
│ Phase 1: Restore View │
│ - Component-Tree wiederherstellen │
│ - Oder neu erstellen (erster Request) │
└──────────────────┬───────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Phase 2: Apply Request Values │
│ - HTTP-Parameter → Component-Werte │
│ - Input-Felder füllen │
└──────────────────┬───────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Phase 3: Process Validations │
│ - Validatoren ausführen │
│ - Bei Fehler → direkt zu Phase 6 │
└──────────────────┬───────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Phase 4: Update Model Values │
│ - Component-Werte → Bean-Properties │
│ - Data Binding! │
└──────────────────┬───────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Phase 5: Invoke Application │
│ - Action-Methoden aufrufen │
│ - Business-Logik ausführen │
└──────────────────┬───────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Phase 6: Render Response │
│ - View rendern │
│ - HTML erzeugen │
│ - An Client schicken │
└──────────────────────────────────────────┘
│
▼
HTTP Response
Wichtig:
Du musst diesen Lifecycle nicht manuell steuern – JSF macht das automatisch! Aber du solltest verstehen, wann was passiert, um Fehler zu debuggen.
🟡 PROFESSIONALS: JSF in der Praxis
Managed Bean Scopes
JSF bietet verschiedene Scopes für Beans:
// Request-Scope: Bean lebt nur für einen Request
@Named
@RequestScoped
public class SearchBean {
private String searchTerm;
// Wird nach Request gelöscht
}
// View-Scope: Bean lebt solange View (Seite) aktiv ist
@Named
@ViewScoped
public class UserEditBean implements Serializable {
private User user;
// Bleibt erhalten bei Postbacks zur selben Seite
// WICHTIG: Muss Serializable sein!
}
// Session-Scope: Bean lebt während ganzer Session
@Named
@SessionScoped
public class ShoppingCartBean implements Serializable {
private List<Product> items = new ArrayList<>();
// Bleibt über alle Seiten hinweg erhalten
}
// Application-Scope: Bean ist Singleton für alle User
@Named
@ApplicationScoped
public class ConfigBean {
private Properties config;
// Geteilt zwischen allen Usern!
}
Wann welchen Scope?
| Scope | Use-Case | Muss Serializable? |
|---|---|---|
@RequestScoped | Suchanfragen, einmalige Actions | Nein |
@ViewScoped | Formulare mit Validierung, CRUD-Seiten | Ja! |
@SessionScoped | Warenkorb, User-Session-Daten | Ja! |
@ApplicationScoped | Config, Caches, Shared Data | Nein |
Pro-Tipp: @ViewScoped ist meist die beste Wahl für CRUD-Forms!
Facelets: Die View-Technologie
Facelets = XHTML + JSF-Tags
Grundstruktur:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="jakarta.faces.html"
xmlns:f="jakarta.faces.core"
xmlns:ui="jakarta.faces.facelets">
<h:head>
<title>My JSF Page</title>
</h:head>
<h:body>
<h:form>
<!-- JSF-Komponenten hier -->
</h:form>
</h:body>
</html>
Wichtigste Tag-Libraries:
<!-- HTML-Tags (h:) --> xmlns:h="jakarta.faces.html" <!-- Core-Tags (f:) --> xmlns:f="jakarta.faces.core" <!-- Facelets-Tags (ui:) --> xmlns:ui="jakarta.faces.facelets" <!-- Composite Components (cc:) --> xmlns:cc="jakarta.faces.composite"
Die wichtigsten JSF-Komponenten
Input-Komponenten:
<!-- Text-Input -->
<h:inputText value="#{userBean.name}"/>
<!-- Password -->
<h:inputSecret value="#{userBean.password}"/>
<!-- Textarea -->
<h:inputTextarea value="#{userBean.description}"/>
<!-- Checkbox -->
<h:selectBooleanCheckbox value="#{userBean.active}"/>
<!-- Radio Buttons -->
<h:selectOneRadio value="#{userBean.gender}">
<f:selectItem itemValue="M" itemLabel="Male"/>
<f:selectItem itemValue="F" itemLabel="Female"/>
</h:selectOneRadio>
<!-- Dropdown -->
<h:selectOneMenu value="#{userBean.countryId}">
<f:selectItems value="#{userBean.countries}"
var="country"
itemValue="#{country.id}"
itemLabel="#{country.name}"/>
</h:selectOneMenu>
Output-Komponenten:
<!-- Text ausgeben -->
<h:outputText value="#{userBean.fullName}"/>
<!-- Label -->
<h:outputLabel value="Name:" for="nameInput"/>
<!-- Link -->
<h:link outcome="home" value="Go Home"/>
<h:link outcome="user" value="Edit User">
<f:param name="id" value="#{user.id}"/>
</h:link>
Command-Komponenten:
<!-- Submit-Button -->
<h:commandButton value="Save" action="#{userBean.save}"/>
<!-- Link mit Action -->
<h:commandLink value="Delete" action="#{userBean.delete}"/>
<!-- AJAX-Button -->
<h:commandButton value="Check" action="#{userBean.check}">
<f:ajax execute="@form" render="result"/>
</h:commandButton>
Data-Table:
<h:dataTable value="#{userBean.users}" var="user">
<h:column>
<f:facet name="header">ID</f:facet>
#{user.id}
</h:column>
<h:column>
<f:facet name="header">Name</f:facet>
#{user.name}
</h:column>
<h:column>
<f:facet name="header">Actions</f:facet>
<h:link outcome="edit" value="Edit">
<f:param name="id" value="#{user.id}"/>
</h:link>
</h:column>
</h:dataTable>
Validation in JSF
Built-in Validators:
<!-- Required -->
<h:inputText value="#{userBean.name}" required="true"
requiredMessage="Name is required"/>
<!-- Length -->
<h:inputText value="#{userBean.username}">
<f:validateLength minimum="3" maximum="20"/>
</h:inputText>
<!-- Regex -->
<h:inputText value="#{userBean.email}">
<f:validateRegex pattern="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"/>
</h:inputText>
<!-- Range -->
<h:inputText value="#{userBean.age}">
<f:validateLongRange minimum="18" maximum="99"/>
</h:inputText>
Bean Validation (empfohlen!):
@Named
@ViewScoped
public class UserBean implements Serializable {
@NotNull
@Size(min = 3, max = 50)
private String name;
@Email
private String email;
@Min(18)
@Max(99)
private Integer age;
// Getter/Setter
}
<!-- Automatische Validierung durch Bean Validation -->
<h:inputText value="#{userBean.name}"/>
<h:inputText value="#{userBean.email}"/>
<h:inputText value="#{userBean.age}"/>
<!-- Fehler anzeigen -->
<h:messages/>
Navigation in JSF
Outcome-basierte Navigation:
@Named
@RequestScoped
public class UserBean {
public String save() {
// Save user...
return "user-list"; // Navigiert zu user-list.xhtml
}
public String cancel() {
return "home"; // Navigiert zu home.xhtml
}
public String delete() {
// Delete user...
return "user-list?faces-redirect=true"; // Mit Redirect!
}
}
<h:commandButton value="Save" action="#{userBean.save}"/>
<h:commandButton value="Cancel" action="#{userBean.cancel}" immediate="true"/>
🔵 BONUS: Templates & AJAX
Facelets Templates
Master-Template (template.xhtml):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="jakarta.faces.html"
xmlns:ui="jakarta.faces.facelets">
<h:head>
<title><ui:insert name="title">Default Title</ui:insert></title>
<h:outputStylesheet library="css" name="style.css"/>
</h:head>
<h:body>
<div id="header">
<h1>My Application</h1>
</div>
<div id="content">
<ui:insert name="content">
Default Content
</ui:insert>
</div>
<div id="footer">
© 2025 My Company
</div>
</h:body>
</html>
Page mit Template (user-list.xhtml):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="jakarta.faces.facelets"
xmlns:h="jakarta.faces.html">
<ui:composition template="/WEB-INF/templates/template.xhtml">
<ui:define name="title">User List</ui:define>
<ui:define name="content">
<h2>Users</h2>
<h:dataTable value="#{userBean.users}" var="user">
<!-- ... -->
</h:dataTable>
</ui:define>
</ui:composition>
</html>
AJAX in JSF
Partial Page Updates:
<h:form>
<h:inputText id="searchInput" value="#{searchBean.term}">
<f:ajax event="keyup" listener="#{searchBean.search}"
render="results"/>
</h:inputText>
<h:panelGroup id="results">
<h:dataTable value="#{searchBean.results}" var="item">
<h:column>#{item.name}</h:column>
</h:dataTable>
</h:panelGroup>
</h:form>
AJAX-Attribute:
event: Wann AJAX-Call? (keyup,change,click, etc.)execute: Was soll submitted werden? (@this,@form,fieldId)render: Was soll neu gerendert werden? (@this,@form,componentId)listener: Welche Bean-Methode aufrufen?
💬 Real Talk: JSF vs. moderne Frameworks
Java Fleet Büro, Kaffeemaschine, 16:00 Uhr. Nova scrollt durch eine JSF-Tutorial-Seite.
Nova: „Elyndra, ehrliche Frage: Warum sollte ich JSF lernen, wenn alle React und Vue.js machen?“
Elyndra: „Gute Frage! Lass mich dir die Realität zeigen.“
Cassian (kommt dazu): „Oh, die ‚Warum nicht SPA?‘-Diskussion. Die hab ich mindestens 50 Mal gehört.“
Nova: „Und? Was ist die Antwort?“
Elyndra: „Es kommt drauf an. JSF ist nicht tot – aber es hat einen spezifischen Use-Case.“
Nova: „Nämlich?“
Cassian: „Enterprise-Anwendungen mit komplexen Formularen. Banking, Insurance, ERP, Healthcare. Dort, wo du hunderte von Feldern, verschachtelte Validierungen und state-management brauchst.“
Nova: „Aber das geht doch auch mit React?“
Elyndra: „Klar. Aber dann brauchst du:
- Separates Backend (Spring REST)
- State-Management Library (Redux, MobX)
- Form-Library (Formik, React Hook Form)
- Validation-Library (Yup, Zod)
- Auth-Handling auf Client UND Server
- CORS-Config
- Deployment von zwei Apps“
Cassian: „Mit JSF ist das ALLES integriert. Ein WAR-File. Deploy. Done.“
Nova: „Okay, aber JSF sieht aus wie 2005…“
Elyndra (lacht): „Fair! JSF ist nicht ’sexy‘. Es ist pragmatisch. Du schreibst weniger Code, hast weniger Moving Parts, und es läuft stabil.“
Cassian: „Ich hab letztens ein Projekt migriert: Vue.js Frontend + Spring REST Backend → JSF + PrimeFaces. Weißt du was? 50% weniger Code. 30% schneller entwickelt. Und der Product Owner war happy, weil keine zwei Deployments mehr.“
Nova: „Warte, PrimeFaces? Was ist das?“
Elyndra: „Ein UI-Component-Library für JSF. Gibt dir fertige Komponenten: DataTable mit Pagination, Autocomplete, File-Upload, Charts – alles out-of-the-box.“
Nova: „Hmm… klingt eigentlich praktisch.“
Cassian: „Ist es auch. Aber hier ist die Wahrheit: Für interne Enterprise-Tools? JSF. Für öffentliche Consumer-Apps? React/Vue.„
Nova: „Also JSF für langweilige Backoffice-Sachen?“
Elyndra: „Genau! Und weißt du was? Die zahlen am besten. Banking, Insurance, Pharma – die brauchen solide, wartbare Enterprise-Apps. Nicht fancy Animationen.“
Cassian: „Plus: JSF-Entwickler sind rar. Wenn du beides kannst – React UND JSF – bist du goldwert für Consulting-Firmen.“
Nova: „Okay, ihr habt mich überzeugt. Also lernen, aber nicht als Hauptfokus?“
Elyndra: „Exactly! Es ist ein Tool in deiner Toolbox. Für den richtigen Job.“
Cassian: „Und wenn du JSF verstehst, verstehst du auch komponentenbasierte Frameworks besser – das Prinzip ist überall gleich.“
Nova: „Alright, dann lass uns JSF machen! Aber danach will ich PrimeFaces sehen – ich mag fancy Components.“
Elyndra (lacht): „Deal! PrimeFaces kommt im nächsten Kurs.“
✅ Checkpoint: Hast du es verstanden?
Quiz:
Frage 1: Was sind die drei Hauptbestandteile der JSF-Architektur?
Frage 2: Erkläre die 6 Phasen des JSF Request-Lifecycle.
Frage 3: Was ist der Unterschied zwischen @RequestScoped, @ViewScoped und @SessionScoped?
Frage 4: Warum muss ein @ViewScoped Bean Serializable implementieren?
Frage 5: Was macht <f:ajax>? Erkläre die Attribute execute und render.
Mini-Challenge:
Aufgabe: Erstelle eine JSF-CRUD-Anwendung für ein Product-Entity mit folgenden Features:
Requirements:
- Liste aller Produkte (product-list.xhtml)
- DataTable mit ID, Name, Price, Stock
- Link zu Edit-Seite für jedes Produkt
- Button „Add New Product“
- Produkt hinzufügen/bearbeiten (product-edit.xhtml)
- Form mit: Name, Description, Price, Stock
- Validierung:
- Name: Required, Min 3 Zeichen
- Price: Required, Min 0.01
- Stock: Required, Min 0
- Button „Save“ + „Cancel“
- Managed Bean
@ViewScoped- CDI-Injection von
ProductService - Methods:
save(),cancel(),delete()
- Template
- Master-Template mit Header und Footer
- Beide Pages nutzen Template
Bonus:
- AJAX-Suche auf Product-List-Seite
- Delete-Confirmation mit JavaScript
- PrimeFaces-Komponenten nutzen (wenn verfügbar)
Lösung:
Die Lösung zu dieser Challenge findest du im Maven-Projekt! 🚀
Alternativ kannst du die Musterlösung im GitHub-Projekt checken: Java Fleet – Tag 10 Challenge Solution
Geschafft? 🎉
Dann bist du bereit für die FAQ-Sektion!
❓ Häufig gestellte Fragen
Frage 1: JSF vs. Spring MVC – was ist besser?
JSF:
- ✅ Komponentenbasiert
- ✅ State-Management integriert
- ✅ Weniger Boilerplate-Code
- ✅ Built-in AJAX
- ❌ Steile Lernkurve
- ❌ Weniger flexibel
- ❌ Komplexer Lifecycle
Spring MVC:
- ✅ Flexibler
- ✅ Einfacher Lifecycle
- ✅ Besser für REST-APIs
- ✅ Größere Community
- ❌ Mehr Boilerplate-Code
- ❌ Kein State-Management
- ❌ AJAX manuell
Empfehlung:
- Komplexe Formulare, State-Management? → JSF
- REST-APIs, Microservices? → Spring MVC
- Hybrid: Spring Boot + JSF (geht auch!)
Frage 2: Muss ich JSP können, um JSF zu lernen?
Nein!
JSF und JSP sind zwei verschiedene Technologien:
- JSP = Scriptlets + Tag-Libraries (Basic-Kurs)
- JSF = Komponenten + Managed Beans (Aufbau-Kurs)
JSF nutzt Facelets (XHTML), NICHT JSP!
Aber: Du solltest Servlets verstehen, weil JSF auf Servlets basiert.
Frage 3: Warum funktioniert mein @ViewScoped Bean nicht?
Häufigste Fehler:
- Bean ist nicht
Serializable:// FALSCH: @Named @ViewScoped public class UserBean { ... } // RICHTIG: @Named @ViewScoped public class UserBean implements Serializable { ... } - Bean hat nicht-serializable Felder:
@Named @ViewScoped public class UserBean implements Serializable { @Inject private UserService service; // OK - CDI-Proxy ist serializable private HttpServletRequest request; // NICHT OK! } - Passivation-fähig?
- Server speichert ViewScoped-Beans im Session
- Bei Cluster-Failover muss Bean serialisierbar sein
Frage 4: Wie debugge ich JSF-Lifecycle-Probleme?
Best Practices:
- web.xml – Development Stage:
<context-param> <param-name>jakarta.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param> - FacesMessages prüfen:
for (FacesMessage msg : FacesContext.getCurrentInstance().getMessageList()) { System.out.println("Message: " + msg.getDetail()); } - Browser Console (F12): JavaScript-Fehler?
Frage 5: Kann ich JSF mit REST-APIs kombinieren?
Ja!
Option 1: JAX-RS in selber App:
@Path("/api/users")
@RequestScoped
public class UserResource {
@Inject
private UserService userService;
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<User> getAll() {
return userService.findAll();
}
}
Best Practice:
- JSF für UI
- JAX-RS für REST-API
- Shared Services über CDI
Frage 6: Was sind PrimeFaces und sollte ich sie nutzen?
PrimeFaces ist eine UI-Component-Library für JSF.
Was du bekommst:
- 100+ fertige Komponenten
- DataTable mit Pagination, Sorting, Filtering
- Autocomplete, File-Upload, Charts
- Dialog-System, Mobile-Support, Themes
Solltest du PrimeFaces nutzen?
Ja, wenn:
- ✅ Du schnell schöne UIs brauchst
- ✅ Du Enterprise-Apps baust
- ✅ Du DataTables mit Features brauchst
Nein, wenn:
- ❌ Du maximale Kontrolle über HTML brauchst
- ❌ Du JSF erst lernen willst (erst Basics!)
Frage 7: Bernd meinte mal, „JSF ist wie ein Tank – langsam, aber unkaputtbar.“ Hat er recht?
Lowkey ja! 😂
JSF ist nicht das schnellste Framework. Der Lifecycle hat Overhead. Aber:
Pro:
- ✅ Stabil: Jahrelang in Production getestet
- ✅ Wartbar: Code ist strukturiert
- ✅ Feature-Complete: Alles integriert
- ✅ Fehlertoleranz: Validation, Conversion, Error-Handling
Contra:
- ❌ Performance: Overhead durch Lifecycle
- ❌ Lernkurve: Komplexer als Servlets
- ❌ Modernität: Nicht „hip“ wie React
Real talk:
F�r Banking-Apps, Insurance-Portale, ERP-Systeme ist JSF perfekt. Für Consumer-Apps würde ich React/Vue nehmen.
Bernd’s Analogie ist gut: JSF ist ein Tank. Nicht sexy, aber macht den Job. Und wenn du unter Beschuss gerätst (komplexe Requirements, Legacy-Code, Time-Pressure), bist du froh, dass du einen Tank hast. 🚜
📚 Quiz-Lösungen
Hier sind die Antworten zum Quiz von oben:
Frage 1: Was sind die drei Hauptbestandteile der JSF-Architektur?
Antwort:
- Facelets (View-Layer)
- XHTML-basierte Templates
- JSF-Component-Tags
- Expression Language für Data Binding
- Managed Beans (Controller + Model)
- CDI-Beans mit Scopes
- Action-Methoden für Events
- Properties für Data Binding
- JSF-Lifecycle (Framework-Layer)
FacesServletverarbeitet alle Requests- 6-Phasen-Lifecycle
- Component-Tree-Management
Frage 2: Erkläre die 6 Phasen des JSF Request-Lifecycle.
Antwort:
Phase 1: Restore View
- Component-Tree wiederherstellen (aus Session)
- Oder neu erstellen (erster Request)
Phase 2: Apply Request Values
- HTTP-Parameter → Components
- Conversion (String → Object)
Phase 3: Process Validations
- Validatoren ausführen
- Bei Fehler → Phase 6
Phase 4: Update Model Values
- Component-Werte → Bean-Properties
- Data Binding passiert hier!
Phase 5: Invoke Application
- Action-Methoden aufrufen
- Business-Logik ausführen
Phase 6: Render Response
- View rendern
- HTML erzeugen
Frage 3: Was ist der Unterschied zwischen @RequestScoped, @ViewScoped und @SessionScoped?
Antwort:
| Scope | Lebensdauer | Use-Case |
|---|---|---|
@RequestScoped | Ein Request | Suchanfragen |
@ViewScoped | Solange View aktiv | CRUD-Forms |
@SessionScoped | Ganze Session | Warenkorb |
RequestScoped: Bean wird nach jedem Request gelöscht
ViewScoped: Bleibt bei Postbacks zur selben Seite
SessionScoped: Über alle Pages hinweg
Frage 4: Warum muss ein @ViewScoped Bean Serializable implementieren?
Antwort:
Grund 1: Session-Persistence
ViewScoped-Beans werden in HTTP-Session gespeichert. Bei:
- Server-Restart
- Cluster-Failover
- Passivation
…muss das Bean serialisiert werden!
Grund 2: Postbacks
Bei Postbacks muss JSF das Bean über mehrere Requests erhalten:
Request 1: Form anzeigen
↓ (Bean in Session)
Request 2: Submit mit Fehler
↓ (Bean aus Session - Deserialisierung!)
Request 3: Erfolg
Ohne Serializable: Fehler bei Passivation!
Frage 5: Was macht <f:ajax>? Erkläre die Attribute execute und render.
Antwort:
<f:ajax> macht partielle Page-Updates ohne Reload.
<h:inputText value="#{searchBean.term}">
<f:ajax event="keyup"
execute="@this"
render="results"/>
</h:inputText>
event: Wann? (keyup, change, click)
execute: Was senden? (@this, @form, id)
render: Was neu rendern? (@this, @form, id)
Was passiert:
- User tippt
- AJAX-Request
- Nur
searchBean.termwird gesendet - Nur
resultswird neu gerendert - Kein Full-Reload!
🎉 Tag 10 geschafft – Kurs abgeschlossen!
GRATULATION! 🎊
Du hast den Java Web Aufbau Kurs erfolgreich abgeschlossen!
Was du erreicht hast:
- ✅ Filter und Listener gemeistert
- ✅ Security mit Container-Auth & Jakarta Security API implementiert
- ✅ Custom Tags mit SimpleTag & BodyTagSupport erstellt
- ✅ JPA mit komplexen Relationships beherrscht (@OneToOne, @ManyToOne, @OneToMany, @ManyToMany)
- ✅ JSF-Grundlagen gelernt
Du kannst jetzt:
- Production-Ready Enterprise-Apps bauen
- Komplexe Datenbankmodelle mit JPA umsetzen
- JSF-Anwendungen entwickeln
- Filter und Security richtig einsetzen
- Custom Tags für Wiederverwendbarkeit erstellen
Du bist bereit für:
- ✅ Spring Boot (nutzt ähnliche Konzepte!)
- ✅ Microservices mit Jakarta EE
- ✅ REST-APIs mit JAX-RS
- ✅ Enterprise-Projekte
- ✅ PrimeFaces (advanced JSF)
Slay! 🔥
Du hast 10 Tage durchgezogen und bist jetzt ein Java Web Aufbau-Experte!
🚀 Wie geht’s weiter?
Nächster Kurs könnte sein:
PrimeFaces Kurs (falls verfügbar)
- UI-Component-Library für JSF
- DataTables, Charts, Dialogs
- Moderne JSF-UIs bauen
JAX-RS REST-APIs
- RESTful Services mit Jakarta EE
- JSON-Handling
- Integration mit JSF-Frontend
Spring Boot
- Ähnliche Konzepte wie CDI
- Microservices
- Cloud-Native Apps
Was dich erwartet:
- PrimeFaces DataTable mit Lazy Loading
- AJAX Push/WebSocket
- Advanced Validation Techniques
- File-Upload & Download
- Export zu Excel/PDF
- Das wird dein Game-Changer für Enterprise-UIs! 🔥
Brauchst du eine Pause?
Mach sie! 10 Tage intensives Lernen sind hart. Lass das Wissen setzen.
Tipp für heute Abend:
Feiere deinen Erfolg! Du hast etwas Großes geschafft! 🍾
Und dann: Bau ein eigenes Projekt. Das ist die beste Übung!
Learning by doing! 🔧
🔧 Troubleshooting
Problem: JSF-Seite zeigt nur weißen Bildschirm
Lösung:
- Browser-Console (F12): JavaScript-Fehler?
- Server-Log: FacesServlet läuft?
web.xml: FacesServlet korrekt?- File-Extension:
.xhtmlstatt.jsf?
Problem: Bean-Werte nicht sichtbar
Lösung:
@Namedvorhanden?- Getter korrekt?
public String getName()? - EL-Syntax:
#{userBean.name}? <h:messages/>für Fehler?
Problem: Validation funktioniert nicht
Lösung:
- Bean Validation Dependencies im Classpath?
<h:messages/>vorhanden?immediate="true"auf Button?
Problem: AJAX funktioniert nicht
Lösung:
- Browser-Console: Fehler?
<h:head>statt<head>?render-Target: ID korrekt?- Component in
<h:form>?
📚 Resources & Links
JSF:
- Jakarta Faces Spec: https://jakarta.ee/specifications/faces/
- JSF Tutorial: https://www.baeldung.com/jsf
- Facelets: https://www.oracle.com/technical-resources/articles/java/facelets.html
PrimeFaces:
- Homepage: https://www.primefaces.org/
- Showcase: https://www.primefaces.org/showcase/
Best Practices:
- JSF Best Practices: https://www.oracle.com/technical-resources/articles/java/jsf-best-practices.html
💬 Feedback?
War der Java Web Aufbau Kurs hilfreich? Zu schwer? Zu einfach?
Schreib uns: feedback@java-developer.online
Wir wollen, dass du erfolgreich lernst!
Du hast es geschafft! 🎊
Bis zum nächsten Kurs! 👋
Elyndra
elyndra@java-developer.online
Senior Developer bei Java Fleet Systems Consulting
Java Web Aufbau – Tag 10 von 10
Teil der Java Fleet Learning-Serie
© 2025 Java Fleet Systems Consulting

