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

JakartaServer 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 professionell einsetzen mit Templates, Navigation, Validation und AJAX


📋 Voraussetzungen für diesen Tag

Du brauchst:

  • Tag 9 abgeschlossen! (JakartaServer Faces Basics mit @Named Beans)
  • ✅ Funktionierendes JSF-Projekt von Tag 9
  • ✅ Entweder:
    • Apache Tomcat 10.x (Tag9-JSF-Tomcat) ODER
    • Payara Server 6.x (Tag9-JSF-Payara)
  • ✅ Verständnis von @Named Beans, @Transactional, JSF Facelets

Tag 9 verpasst?
Spring zurück! Tag 10 baut direkt auf Tag 9 auf. Ohne JSF-Basics wird heute schwer.

Hinweis: Alle heutigen Beispiele funktionieren auf beiden Servern (Tomcat UND Payara)!


⚡ Das Wichtigste in 30 Sekunden

Was du gestern gelernt hast (Tag 9):

  • JSF Facelets (.xhtml)
  • @Named Beans + @Transactional
  • OrderController + OrderDAO
  • Einfaches JSF DataTable
  • JSF Basics verstanden

Was du heute lernst:

  • Facelets Templates für wiederverwendbare Layouts
  • Navigation zwischen JSF-Pages
  • Validation (Built-in + Bean Validation)
  • AJAX für Partial Page Updates
  • Best Practices für Production

Warum ist das wichtig? Gestern hast du JSF-Grundlagen gelernt. Heute machst du daraus production-ready Enterprise-Anwendungen mit professionellen Features.


👋 Willkommen zu Tag 10 – Dem Finale!

Hi! 👋

Elyndra hier. Letzter Tag des Java Web Aufbau Kurses! 🎉

Recap Tag 9:

Gestern hast du deine erste JSF-Anwendung gebaut:

java

// OrderDAO mit @Named + @Transactional
@Named
@RequestScoped
@Transactional
public class OrderDAO {
    @PersistenceContext
    private EntityManager em;
    
    public Order createOrder(...) { ... }
}

// OrderController für JSF
@Named
@SessionScoped
public class OrderController implements Serializable {
    @Inject
    private OrderDAO orderDAO;
    
    public String createTestData() { ... }
}

xml

<!-- index.xhtml mit JSF DataTable -->
<h:dataTable value="#{orderController.orders}" var="order">
    <h:column>
        <f:facet name="header">Order#</f:facet>
        #{order.orderNumber}
    </h:column>
</h:dataTable>

Das war gestern. Heute geht’s weiter! 🚀


Was dich heute erwartet:

Heute lernst du JSF Professional Features:

Was fehlt noch in deiner Tag 9 App?

❌ Kein Seitenlayout (Header, Footer, Navigation)
❌ Keine Navigation zwischen Pages
❌ Keine Validierung
❌ Keine dynamischen Updates (alles lädt neu)
❌ Keine Error-Handling

Das ändern wir heute!

Templates – Wiederverwendbare Layouts
Navigation – Between Pages ohne URL-Hackerei
Validation – Client + Server
AJAX – Partial Updates ohne Reload
Best Practices – Production-Ready Code

Los geht’s! 🚀


🟢 GRUNDLAGEN: Facelets Templates

Warum Templates?

Problem ohne Templates:

xml

<!-- order-list.xhtml -->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="jakarta.faces.html">
<h:head>
    <title>Order List</title>
    <h:outputStylesheet library="css" name="style.css"/>
</h:head>
<h:body>
    <div id="header">
        <h1>My Application</h1>
        <nav><!-- Navigation --></nav>
    </div>
    
    <div id="content">
        <!-- Order List Content -->
    </div>
    
    <div id="footer">
        © 2025 Java Fleet
    </div>
</h:body>
</html>

<!-- order-edit.xhtml -->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="jakarta.faces.html">
<h:head>
    <title>Order Edit</title>
    <h:outputStylesheet library="css" name="style.css"/>
</h:head>
<h:body>
    <div id="header">
        <h1>My Application</h1>  <!-- KOPIERT! -->
        <nav><!-- Navigation --></nav>  <!-- KOPIERT! -->
    </div>
    
    <div id="content">
        <!-- Order Edit Content -->
    </div>
    
    <div id="footer">
        © 2025 Java Fleet  <!-- KOPIERT! -->
    </div>
</h:body>
</html>

Problem: Header, Footer, Navigation auf JEDER Seite kopiert! 😱

Lösung: Templates!


Master-Template erstellen

Datei: /WEB-INF/templates/layout.xhtml

xml

<!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>☕ Java Fleet Order Management</h1>
        <nav>
            <h:link outcome="order-list" value="Orders"/>
            <h:link outcome="order-edit" value="New Order"/>
        </nav>
    </div>
    
    <div id="content">
        <ui:insert name="content">
            Default Content
        </ui:insert>
    </div>
    
    <div id="footer">
        © 2025 Java Fleet Systems Consulting
    </div>
</h:body>
</html>

Wichtige Elemente:

  • <ui:insert name="title"> – Platzhalter für Title
  • <ui:insert name="content"> – Platzhalter für Content
  • Default-Werte wenn Page nichts definiert

Page mit Template erstellen

Datei: order-list.xhtml

xml

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="jakarta.faces.facelets"
      xmlns:h="jakarta.faces.html"
      xmlns:f="jakarta.faces.core">
      
<ui:composition template="/WEB-INF/templates/layout.xhtml">
    
    <ui:define name="title">Order List</ui:define>
    
    <ui:define name="content">
        <h2>📋 Orders</h2>
        
        <h:form>
            <h:commandButton value="Create Test Data" 
                            action="#{orderController.createTestData}"/>
        </h:form>
        
        <h:dataTable value="#{orderController.orders}" var="order"
                     styleClass="orders-table">
            <h:column>
                <f:facet name="header">Order#</f:facet>
                #{order.orderNumber}
            </h:column>
            <h:column>
                <f:facet name="header">User</f:facet>
                #{order.user.username}
            </h:column>
            <h:column>
                <f:facet name="header">Amount</f:facet>
                €#{order.totalAmount}
            </h:column>
            <h:column>
                <f:facet name="header">Actions</f:facet>
                <h:link outcome="order-edit" value="Edit">
                    <f:param name="id" value="#{order.id}"/>
                </h:link>
            </h:column>
        </h:dataTable>
    </ui:define>
    
</ui:composition>
</html>

Was passiert:

  1. <ui:composition template="..."> – Nutzt Template
  2. <ui:define name="title"> – Füllt Title-Platzhalter
  3. <ui:define name="content"> – Füllt Content-Platzhalter
  4. Header, Footer, Navigation kommen automatisch vom Template!

Vorteile von Templates

DRY – Don’t Repeat Yourself
Konsistenz – Alle Pages sehen gleich aus
Wartbarkeit – Navigation ändern = nur Template ändern
Schnellere Entwicklung – Nur Content schreiben


🟡 PROFESSIONALS: Navigation in JSF

Outcome-basierte Navigation

Gestern (Tag 9) hattest du:

java

@Named
@SessionScoped
public class OrderController implements Serializable {
    
    public String createTestData() {
        // Create data...
        return null;  // Bleibt auf selber Seite
    }
}

Heute: Navigation zwischen Pages!

java

@Named
@ViewScoped
public class OrderEditBean implements Serializable {
    
    @Inject
    private OrderDAO orderDAO;
    
    private Order order;
    
    @PostConstruct
    public void init() {
        // Get ID from URL parameter
        String idParam = FacesContext.getCurrentInstance()
            .getExternalContext()
            .getRequestParameterMap()
            .get("id");
        
        if (idParam != null) {
            Long id = Long.parseLong(idParam);
            this.order = orderDAO.findById(id);
        } else {
            this.order = new Order();
        }
    }
    
    public String save() {
        if (order.getId() == null) {
            orderDAO.create(order);
        } else {
            orderDAO.update(order);
        }
        
        // Navigate to order-list.xhtml
        return "order-list?faces-redirect=true";
    }
    
    public String cancel() {
        // Navigate without saving
        return "order-list?faces-redirect=true";
    }
    
    public String delete() {
        orderDAO.delete(order.getId());
        return "order-list?faces-redirect=true";
    }
}

Navigation-Outcomes:

Return ValueWas passiert?
nullBleibt auf selber Page
"order-list"Forward zu order-list.xhtml (URL ändert sich NICHT)
"order-list?faces-redirect=true"Redirect zu order-list.xhtml (URL ändert sich!)

Wann Forward vs. Redirect?

  • Forward – Innerhalb selber Flow (z.B. Validierungsfehler)
  • Redirect – Nach erfolgreicher Aktion (Post-Redirect-Get Pattern!)

Programmatic Navigation

java

FacesContext context = FacesContext.getCurrentInstance();
context.getApplication()
    .getNavigationHandler()
    .handleNavigation(context, null, "order-list?faces-redirect=true");

🔵 BONUS: Validation in JSF

Problem: Deine Tag 9 App hat keine Validation!

Was passiert wenn User scheiße eingibt?

xml

<!-- Aktuell in deiner Tag 9 App: -->
<h:inputText value="#{orderBean.orderNumber}"/>
<h:inputText value="#{orderBean.amount}"/>

User kann eingeben:

  • Leeren Order-Number ❌
  • Negativen Amount ❌
  • SQL-Injection ❌

Lösung: Validation!


Bean Validation (empfohlen!)

OrderBean mit Validation:

java

@Named
@ViewScoped
public class OrderEditBean implements Serializable {
    
    @Inject
    private OrderDAO orderDAO;
    
    private Order order;
    
    // Order Entity mit Validation:
    @NotNull(message = "Order number is required")
    @Size(min = 5, max = 50, message = "Order number must be 5-50 characters")
    @Pattern(regexp = "ORD-[0-9]+", message = "Format: ORD-12345")
    private String orderNumber;
    
    @NotNull(message = "Amount is required")
    @DecimalMin(value = "0.01", message = "Amount must be positive")
    @DecimalMax(value = "999999.99", message = "Amount too large")
    private BigDecimal amount;
    
    // Getters/Setters
}

View mit Error Messages:

xml

<h:form>
    <h:messages globalOnly="true" styleClass="error-messages"/>
    
    <h:panelGrid columns="3">
        <h:outputLabel value="Order#:" for="orderNumber"/>
        <h:inputText id="orderNumber" 
                     value="#{orderEditBean.orderNumber}"
                     required="true"/>
        <h:message for="orderNumber" styleClass="error"/>
        
        <h:outputLabel value="Amount:" for="amount"/>
        <h:inputText id="amount" 
                     value="#{orderEditBean.amount}"
                     required="true">
            <f:convertNumber type="currency" currencySymbol="€"/>
        </h:inputText>
        <h:message for="amount" styleClass="error"/>
    </h:panelGrid>
    
    <h:commandButton value="Save" action="#{orderEditBean.save}"/>
    <h:commandButton value="Cancel" action="#{orderEditBean.cancel}" 
                     immediate="true"/>
</h:form>

Was passiert:

  1. User gibt Daten ein
  2. JSF validiert automatisch (Bean Validation Annotations!)
  3. Bei Fehler: <h:message> zeigt Fehler an
  4. save() wird NUR aufgerufen wenn Validation OK!

Built-in JSF Validators

xml

<!-- Required -->
<h:inputText value="#{bean.name}" 
             required="true"
             requiredMessage="Name is required"/>

<!-- Length -->
<h:inputText value="#{bean.username}">
    <f:validateLength minimum="3" maximum="20"/>
</h:inputText>

<!-- Regex -->
<h:inputText value="#{bean.email}">
    <f:validateRegex pattern="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"/>
</h:inputText>

<!-- Range -->
<h:inputText value="#{bean.age}">
    <f:validateLongRange minimum="18" maximum="99"/>
</h:inputText>

<!-- Double Range -->
<h:inputText value="#{bean.price}">
    <f:validateDoubleRange minimum="0.01" maximum="9999.99"/>
</h:inputText>

Empfehlung: Nutze Bean Validation (@NotNull, @Size, etc.) statt JSF Validators! Reason: Funktioniert auch für REST-APIs!


🔵 BONUS: AJAX in JSF

Problem: Deine Tag 9 App lädt immer komplett neu!

Was nervt:

xml

<!-- Aktuell: -->
<h:commandButton value="Create Test Data" 
                action="#{orderController.createTestData}"/>

Bei Klick:

  1. Komplette Seite lädt neu ⏳
  2. Scroll-Position verloren 😡
  3. Focus verloren 😡
  4. Slow! 🐌

Lösung: AJAX!


AJAX Partial Page Update

Nur die Table neu laden:

xml

<h:form>
    <h:commandButton value="Create Test Data" 
                    action="#{orderController.createTestData}">
        <f:ajax execute="@this" render="ordersTable"/>
    </h:commandButton>
    
    <h:dataTable id="ordersTable" 
                 value="#{orderController.orders}" 
                 var="order">
        <!-- Columns -->
    </h:dataTable>
</h:form>

AJAX-Attribute:

  • execute="@this" – Was soll submitted werden? (nur dieser Button)
  • render="ordersTable" – Was soll neu gerendert werden? (nur die Table)

Magic IDs:

  • @this – Diese Komponente
  • @form – Das gesamte Formular
  • @all – Die ganze Page (wie ohne AJAX)
  • @none – Nichts

AJAX Search (Live!)

xml

<h:form>
    <h:outputLabel value="Search:" for="searchInput"/>
    <h:inputText id="searchInput" 
                 value="#{orderController.searchTerm}">
        <f:ajax event="keyup" 
                listener="#{orderController.search}" 
                render="searchResults"/>
    </h:inputText>
    
    <h:panelGroup id="searchResults">
        <h:dataTable value="#{orderController.searchResults}" 
                     var="order">
            <h:column>#{order.orderNumber}</h:column>
            <h:column>#{order.user.username}</h:column>
        </h:dataTable>
    </h:panelGroup>
</h:form>

Bean:

java

@Named
@ViewScoped
public class OrderController implements Serializable {
    
    @Inject
    private OrderDAO orderDAO;
    
    private String searchTerm;
    private List<Order> searchResults;
    
    public void search() {
        if (searchTerm != null && searchTerm.length() >= 3) {
            searchResults = orderDAO.searchByOrderNumber(searchTerm);
        } else {
            searchResults = new ArrayList<>();
        }
    }
    
    // Getters/Setters
}

Result: Live-Search während Tippen! ⚡


AJAX Best Practices

Nutze render – Nur nötige Komponenten updaten
Nutze execute – Nur nötige Daten submitten
Nutze listener – Für Logik ohne Navigation
Nutze event – keyup, change, click, blur
Nicht übertreiben – Zu viel AJAX = kompliziert


💬 Real Talk: JSF in 2025 – Lohnt sich das?

Java Fleet Büro, Kaffeemaschine, 16:00 Uhr. Nova scrollt durch ihre fertigen Tag 9 + 10 Projekte.


Nova: „Elyndra, ehrliche Frage: Ich hab jetzt JSF gelernt. Aber alle machen React und Vue.js. Hab ich meine Zeit verschwendet?“

Elyndra: „Gute Frage! Erinner dich an gestern: Wie lange hast du gebraucht für die Order-Liste mit JSF?“

Nova: „Mit JSF? 30 Minuten. Mit React hätte ich…“

Cassian (kommt dazu): „…Stunden gebraucht. Npm install, Webpack Config, State Management, REST API, CORS, Auth…“

Nova: „Ja, aber JSF sieht aus wie 2005…“

Elyndra: „Fair! JSF ist nicht ’sexy‘. Es ist pragmatisch. Lass mich dir die Realität zeigen.“

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. Und es läuft auf deinem Tomcat von gestern!“

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. Ich krieg 850€/Tag für JSF-Projekte.“

Nova: „Wait, 850 pro Tag?!“

Elyndra (lacht): „Ja. React-Entwickler gibt’s wie Sand am Meer. JSF + Jakarta EE Experten? Selten.“

Nova: „Okay, ihr habt mich überzeugt. Also lernen, aber nicht als Hauptfokus?“

Cassian: „Exactly! Es ist ein Tool in deiner Toolbox. Für den richtigen Job.“

Nova: „Alright! Und was kommt nach diesem Kurs?“

Elyndra: „Spring Boot! Ähnliche Konzepte wie CDI, aber größere Community. Oder PrimeFaces für fancy JSF-UIs.“

Nova: „Deal! Aber heute erstmal Tag 10 Challenge fertig machen.“


🎯 Mini-Challenge: Erweitere deine Tag 9 App!

Aufgabe: Mach aus deiner Tag 9 Order-App eine Production-Ready Anwendung!

Requirements:

1. Template erstellen (/WEB-INF/templates/layout.xhtml)

  • Header mit Logo + Navigation
  • Content-Area (Platzhalter)
  • Footer mit Copyright

2. Order-List erweitern (order-list.xhtml)

  • Nutze Template
  • AJAX-Suche nach Order-Number (keyup-Event)
  • Status-Filter Dropdown (AJAX, render Table)
  • „New Order“ Button → Navigate zu order-edit

3. Order-Edit Page (order-edit.xhtml)

  • Nutze Template
  • Form mit Bean Validation:
    • Order Number: Required, Pattern ORD-[0-9]+
    • Amount: Required, Min 0.01
    • User: Required (Dropdown)
  • <h:messages/> für Fehler
  • Save Button → Navigate zu order-list
  • Cancel Button → Navigate zu order-list (immediate!)

4. Navigation

  • save()"order-list?faces-redirect=true"
  • cancel()"order-list?faces-redirect=true"
  • delete() → mit JavaScript Confirmation

5. Bonus (optional)

  • Delete-Confirmation mit <p:confirmDialog> (PrimeFaces)
  • Export zu PDF/Excel
  • Pagination auf Order-List

Lösung:

Die Lösung findest du im Download-Bereich am Ende! 🚀

Jakarta Web Aufbau - Tag 10

Tag 10 Quiz

Frage 1 von 10

Was ist JSF (JavaServer Faces)?

Frage 2 von 10

Was ist ein Managed Bean in JSF?

Frage 3 von 10

Welche Template-Sprache verwendet JSF standardmäßig?

Frage 4 von 10

Was macht die Expression Language (EL) in JSF?

Frage 5 von 10

Was ist ein Vorteil von JSF gegenüber Servlets/JSP?

Frage 6 von 10

Welche Annotation markiert eine Klasse als JSF Managed Bean?

Frage 7 von 10

Was ist der JSF Request-Processing-Lifecycle?

Frage 8 von 10

Welche JSF-Komponente erstellt ein Eingabefeld?

Frage 9 von 10

Was bewirkt <h:commandButton action="#{bean.method}" />?

Frage 10 von 10

Was sind Scopes in JSF Managed Beans?


❓ Häufig gestellte Fragen

Frage 1: Tag 9 vs. Tag 10 – Was ist der Unterschied?

Tag 9: JSF-Basics eingeführt

  • Erste JSF-Anwendung
  • @Named Beans + @Transactional
  • Einfaches DataTable
  • Fokus: „JSF verstehen“

Tag 10: JSF-Vertiefung

  • Templates & Layouts
  • Navigation & Routing
  • Validation (Built-in + Bean Validation)
  • AJAX & Partial Updates
  • Fokus: „JSF produktiv nutzen“

Bottom line: Tag 9 = Foundation, Tag 10 = Pro-Features


Frage 2: Warum funktioniert mein @ViewScoped Bean nicht?

Häufigste Fehler:

  1. Bean ist nicht Serializable:

java

// FALSCH:
@Named
@ViewScoped
public class UserBean { ... }

// RICHTIG:
@Named
@ViewScoped
public class UserBean implements Serializable { ... }
  1. Bean hat nicht-serializable Felder:

java

@Named
@ViewScoped
public class UserBean implements Serializable {
    @Inject
    private UserDAO dao;  // OK - CDI-Proxy ist serializable
    
    private HttpServletRequest request;  // NICHT OK!
}

Frage 3: Template wird nicht angewendet – was tun?

Checkliste:

xml

<!-- 1. ui:composition statt html-Body? -->
<ui:composition template="/WEB-INF/templates/layout.xhtml">
    <!-- Kein <h:body>! -->
</ui:composition>

<!-- 2. Template-Pfad korrekt? -->
template="/WEB-INF/templates/layout.xhtml"  <!-- Absolut! -->

<!-- 3. ui:define Name matcht ui:insert? -->
<!-- Template: -->
<ui:insert name="content"/>
<!-- Page: -->
<ui:define name="content"/>  <!-- Muss matchen! -->

Frage 4: AJAX funktioniert nicht – Browser Console?

Debug-Steps:

  1. Browser Console (F12): JavaScript-Fehler?
  2. <h:head> statt <head>?

xml

<!-- FALSCH: -->
<head>
    <title>My Page</title>
</head>

<!-- RICHTIG: -->
<h:head>
    <title>My Page</title>
</h:head>
  1. render-Target: ID korrekt?

xml

<h:dataTable id="ordersTable" ...>  <!-- ID hier! -->

<f:ajax render="ordersTable"/>  <!-- Muss matchen! -->
  1. Component in <h:form>?

xml

<!-- FALSCH: -->
<h:commandButton ...>
    <f:ajax .../>
</h:commandButton>

<!-- RICHTIG: -->
<h:form>
    <h:commandButton ...>
        <f:ajax .../>
    </h:commandButton>
</h:form>

Frage 5: Kann ich JSF auf Tomcat UND Payara deployen?

Ja! Deine Tag 9 Projekte:

  • Tag9-JSF-Tomcat: Läuft auf Tomcat 10.x
  • Tag9-JSF-Payara: Läuft auf Payara 6.x

Heute (Tag 10) funktioniert auf BEIDEN!

Unterschied:

FeatureTomcatPayara
CDIWeld (extern)Built-in
JTAAtomikos (extern)Built-in
JPAHibernate (extern)EclipseLink (built-in)
DeploymentWAR mit DependenciesWAR klein

Empfehlung:

  • Development: Tomcat (schneller Restart)
  • Production: Payara (Full Jakarta EE)

Frage 6: Was ist PrimeFaces und sollte ich es 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!)

Für Tag 10 Challenge: Vanilla JSF reicht! PrimeFaces kommt in separatem Kurs.


🎉 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
  • ✅ JSF-Grundlagen UND Advanced Features gelernt
  • ✅ Production-Ready Enterprise-Apps bauen können

Du kannst jetzt:

  • Jakarta EE Web Profile nutzen
  • @Named Beans + @Transactional richtig einsetzen
  • JSF-Anwendungen mit Templates, Navigation, AJAX entwickeln
  • JPA-Relations (@OneToOne, @OneToMany, @ManyToMany) implementieren
  • Tomcat UND Payara deployen

Du bist bereit für:

  • ✅ Spring Boot (nutzt ähnliche Konzepte!)
  • ✅ PrimeFaces (advanced JSF UI)
  • ✅ JAX-RS (REST-APIs)
  • ✅ Enterprise-Projekte
  • ✅ Microservices mit Jakarta EE

Slay! 🔥


🚀 Wie geht’s weiter?

Nächste Kurse:

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

Tipp: Bau ein eigenes Projekt! Das ist die beste Übung!

Learning by doing! 🔧


🔧 Troubleshooting

Problem: Template wird nicht angewendet

Lösung:

  1. Pfad korrekt? /WEB-INF/templates/layout.xhtml
  2. <ui:composition> statt <h:body>?
  3. <ui:define name> matcht <ui:insert name>?

Problem: Navigation funktioniert nicht

Lösung:

  1. Return-Value korrekt? "order-list?faces-redirect=true"
  2. .xhtml-File existiert?
  3. FacesServlet läuft? (web.xml / @FacesConfig)

Problem: AJAX lädt nicht neu

Lösung:

  1. <h:head> statt <head>?
  2. render-Target ID korrekt?
  3. Component in <h:form>?
  4. Browser Console: Fehler?

📚 Downloads

Tag 10 Maven-Projekte:


📚 Resources & Links

JSF:

PrimeFaces:

Best Practices:


Du hast es geschafft! 🎊

Bis zum nächsten Kurs! 👋

Elyndra

elyndra.valen@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.