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

JavaServer Faces

🗺️ Deine Position im Kurs

TagThemaStatus
1Filter im Webcontainer✅ Abgeschlossen
2Listener im Webcontainer✅ Abgeschlossen
3Authentifizierung über Datenbank✅ Abgeschlossen
4Container-Managed Security & Jakarta Security API✅ Abgeschlossen
5Custom Tags & Tag Handler (SimpleTag)✅ Abgeschlossen
6Custom Tag Handler mit BodyTagSupport✅ Abgeschlossen
7JPA vs JDBC – Konfiguration & Provider✅ Abgeschlossen
8JPA Relationen (1): @OneToOne & @ManyToOne✅ Abgeschlossen
9JPA Relationen (2): @OneToMany & @ManyToMany✅ Abgeschlossen
→ 10JSF Ü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?

ScopeUse-CaseMuss Serializable?
@RequestScopedSuchanfragen, einmalige ActionsNein
@ViewScopedFormulare mit Validierung, CRUD-SeitenJa!
@SessionScopedWarenkorb, User-Session-DatenJa!
@ApplicationScopedConfig, Caches, Shared DataNein

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:

  1. Liste aller Produkte (product-list.xhtml)
    • DataTable mit ID, Name, Price, Stock
    • Link zu Edit-Seite für jedes Produkt
    • Button „Add New Product“
  2. 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“
  3. Managed Bean
    • @ViewScoped
    • CDI-Injection von ProductService
    • Methods: save(), cancel(), delete()
  4. 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:

  1. Bean ist nicht Serializable: // FALSCH: @Named @ViewScoped public class UserBean { ... } // RICHTIG: @Named @ViewScoped public class UserBean implements Serializable { ... }
  2. 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! }
  3. 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:

  1. web.xml – Development Stage: <context-param> <param-name>jakarta.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param>
  2. FacesMessages prüfen: for (FacesMessage msg : FacesContext.getCurrentInstance().getMessageList()) { System.out.println("Message: " + msg.getDetail()); }
  3. 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:

  1. Facelets (View-Layer)
    • XHTML-basierte Templates
    • JSF-Component-Tags
    • Expression Language für Data Binding
  2. Managed Beans (Controller + Model)
    • CDI-Beans mit Scopes
    • Action-Methoden für Events
    • Properties für Data Binding
  3. JSF-Lifecycle (Framework-Layer)
    • FacesServlet verarbeitet 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:

ScopeLebensdauerUse-Case
@RequestScopedEin RequestSuchanfragen
@ViewScopedSolange View aktivCRUD-Forms
@SessionScopedGanze SessionWarenkorb

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:

  1. User tippt
  2. AJAX-Request
  3. Nur searchBean.term wird gesendet
  4. Nur results wird neu gerendert
  5. 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:

  1. Browser-Console (F12): JavaScript-Fehler?
  2. Server-Log: FacesServlet läuft?
  3. web.xml: FacesServlet korrekt?
  4. File-Extension: .xhtml statt .jsf?

Problem: Bean-Werte nicht sichtbar

Lösung:

  1. @Named vorhanden?
  2. Getter korrekt? public String getName()?
  3. EL-Syntax: #{userBean.name}?
  4. <h:messages/> für Fehler?

Problem: Validation funktioniert nicht

Lösung:

  1. Bean Validation Dependencies im Classpath?
  2. <h:messages/> vorhanden?
  3. immediate="true" auf Button?

Problem: AJAX funktioniert nicht

Lösung:

  1. Browser-Console: Fehler?
  2. <h:head> statt <head>?
  3. render-Target: ID korrekt?
  4. 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

Autor

  • Elyndra Valen

    28 Jahre alt, wurde kürzlich zur Senior Entwicklerin befördert nach 4 Jahren intensiver Java-Entwicklung. Elyndra kennt die wichtigsten Frameworks und Patterns, beginnt aber gerade erst, die tieferen Zusammenhänge und Architektur-Entscheidungen zu verstehen. Sie ist die Brücke zwischen Junior- und Senior-Welt im Team.