NeuStrompreise vergleichen und günstigeren Stromanbieter findenzum Stromvergleich
8°C
1. November 2026
Technik

JavaServer Faces heute: von JSF 2.x zu Jakarta Faces 4

Tobias
  • Oktober 24, 2026
  • 7 min read
  • 359 Views
JavaServer Faces heute: von JSF 2.x zu Jakarta Faces 4

JavaServer Faces hat den Ruf einer Technik aus der Java-EE-Zeit. In Unternehmen und Behörden ist JSF trotzdem weit verbreitet, und die Spezifikation lebt weiter. Zwischenzeitlich hieß sie Jakarta Server Faces, mit Jakarta EE 10 bekam sie den Namen Jakarta Faces, und die aktuelle Version 4.1 gehört zum Plattform-Release EE 11 vom Juni 2025. Dieser Beitrag geht die Fragen durch, die bei Wartung und Migration auf den Tisch kommen. Als Beispiel dient ein kleiner Onlineshop mit Warenkorb und Bestellprozess.

Was ist JavaServer Faces eigentlich?

JSF ist ein serverseitiges Komponenten-Framework nach dem MVC-Prinzip. Jede Seite existiert auf dem Server als Baum von UI-Komponenten, der sogenannten View. Eine Anfrage durchläuft dabei sechs Phasen, von Restore View bis Render Response. Unterwegs werden die Eingaben konvertiert, validiert und in die Bean geschrieben. Zwischen den Phasen feuert das Framework Events, auf die sich eigene Listener registrieren lassen.

Seit JSF 2.0 ist Facelets die View-Technik. Die Seite für den Warenkorb:

<html xmlns:h="jakarta.faces.html">
  <h:form>
    <h:inputText id="menge" type="number" value="#{warenkorb.menge}"/>
    <h:message for="menge"/>
    <h:commandButton value="Aktualisieren" action="#{warenkorb.aktualisieren}"/>
  </h:form>
</html>

Das Attribut type an h:inputText gibt es erst ab 4.0. Dahinter steht eine gewöhnliche CDI-Bean:

@Named @ViewScoped
public class Warenkorb implements Serializable {
    private int menge;
    private List<Position> positionen;
    public void aktualisieren() { /* Preis neu berechnen */ }
}

Die Expression Language (#{...}) verbindet Komponenten mit Properties und Methoden der Bean. Eigene Bausteine entstehen als Composite Component aus einer XHTML-Datei. Für die Ausgabe sorgen Renderer, die aus jedem UIComponent Markup erzeugen.

Wie hat sich JSF seit 2004 entwickelt?

Die Versionsgeschichte erklärt, warum alte Projekte oft mehrere Stile mischen.

Release Jahr JSR / Plattform Wichtigste Neuerung
JSF 1.0 / 1.2 2004 / 2006 JSR 127 / JSR 252 JavaServer Pages (JSP) als View-Technik
JSF 2.0 / 2.1 2009 / 2010 JSR 314 Facelets, Ajax mit f:ajax, Annotationen
JSF 2.2 2013 JSR 344 Faces Flows, Stateless Views, Resource Library Contracts
JSF 2.3 2017 JSR 372 CDI statt eigener Managed Beans, WebSocket
3.0 2020 EE 9 Paketwechsel von javax auf jakarta
4.0 2022 EE 10 JSP und @ManagedBean entfernt, neuer Name
4.1 2024 EE 11 Java SE 17, Full State Saving deprecated

An 5.0 für Jakarta EE 12 wird gearbeitet. Die Eclipse Foundation betreut die Spezifikation, seit Oracle Java EE abgegeben hat.

Infografik zur Versionsgeschichte von JSF 1.0 bis Faces 4.1 als Zeitstrahl
Von JSR 127 bis heute: die wichtigsten Stationen von JSF.

Was ändert sich beim Umstieg auf jakarta.faces?

Die meiste Arbeit macht der Paketwechsel. Ab 3.0 liegen alle API-Klassen unter jakarta.faces statt javax.faces. Mojarra führt intern weiterhin das Package com.sun.faces. Eine Anwendung auf JSF 2.3 braucht diese Schritte:

  1. Imports von javax.faces, javax.inject und javax.enterprise auf das Präfix jakarta umstellen.
  2. Maven-Abhängigkeiten auf die API-Artefakte von 4.1 tauschen.
  3. @ManagedBean durch CDI Managed Beans ersetzen, also @Named plus CDI-Scope. Die nativen Managed Beans gibt es seit 4.0 nicht mehr.
  4. XHTML-Namespaces auf die kurzen URNs umstellen: Aus xmlns:h="http://xmlns.jcp.org/jsf/html" wird xmlns:h="jakarta.faces.html".
  5. Context-Parameter in der web.xml auf das neue Präfix umbenennen.
  6. Verbliebene JSP-Seiten auf XHTML portieren.
  7. PrimeFaces, OmniFaces und andere Komponentenbibliotheken in aktuellen Major-Versionen einbinden.

Einen großen Teil davon erledigen OpenRewrite-Rezepte wie „JSF 2.x to Jakarta Faces 4.x“. Von Hand bleiben meist eigene Komponenten und Bibliotheken übrig, die nie portiert wurden. Solche Altbibliotheken bekommen oft keine Sicherheitsupdates mehr. Spätestens bei Compliance-Anforderungen an Softwareprojekte fällt das auf.

Welche Scopes gibt es, und wann nimmt man welchen?

Alle Scopes kommen seit 2.3 aus CDI (Contexts and Dependency Injection) oder aus der Faces-API selbst. Faustregel: so kurz wie möglich.

  • @RequestScoped lebt eine Anfrage lang, passend für eine Suchmaske.
  • @ViewScoped hält, solange der Nutzer auf derselben Seite bleibt. Für den Warenkorb mit Ajax ist das die richtige Wahl.
  • @FlowScoped gilt für die Dauer eines Flows.
  • @ClientWindowScoped ist neu in 4.0 und trennt nach Browser-Tab. Das Prinzip stammt aus DeltaSpike.
  • @SessionScoped reicht für Login-Daten und Spracheinstellung.
  • @ApplicationScoped hält Kataloge und Konfiguration für alle Nutzer.

Custom Scopes, die man unter JSF 2.0 noch über @CustomScoped baute, entstehen heute als CDI-Extension mit einer eigenen Context-Implementierung. Wenn eine Anwendung zu viel Speicher frisst, liegt es meistens an zu vielen oder zu dicken Session-Beans.

Was sind Faces Flows, und braucht man sie noch?

Flows kamen mit JSF 2.2. Ein Flow bündelt mehrere Seiten mit gemeinsamem Zustand, festem Einstieg und definiertem Ausstieg. Im Onlineshop ist das der Bestellprozess mit Adresse, Versand, Zahlung und Bestätigung. Die Seiten liegen unter /bestellung/, der Zustand steckt in einer @FlowScoped("bestellung")-Bean. Definiert wird der Flow entweder über eine XML-Datei oder in Java mit @FlowDefinition und FlowBuilder.

Wir setzen Flows ein, wenn ein Prozess wirklich über mehrere Seiten geht und von verschiedenen Stellen aus startet. Im einfachen Fall, einem Assistenten mit drei Schritten auf einer Seite, reicht eine @ViewScoped-Bean mit einem Schrittzähler. Eine solche Bean lässt sich leichter testen.

Was bringen Stateless Views?

Zwischen zwei Anfragen speichert das Framework den Zustand des Komponentenbaums. Das kostet Speicher und erzeugt die bekannte ViewExpiredException, sobald die Session abgelaufen ist und der Nutzer trotzdem noch ein altes Formular abschickt. Ab 2.2 lässt sich das pro Seite abschalten:

<f:view transient="true">

Für Login-Seiten und öffentliche Suchformulare passt das gut. Der Preis: @ViewScoped funktioniert dort nicht, und Komponenten merken sich zwischen zwei Postbacks nichts. Partial State Saving ist seit 2.0 der Standard, Full State Saving ist in 4.1 deprecated.

Mojarra oder MyFaces: Welche Implementierung ist schneller?

Zwei vollständige Implementierungen stehen zur Wahl. Mojarra ist die kompatible Implementierung der Spezifikation und steckt etwa in GlassFish und WildFly, während TomEE und Open Liberty auf Apache MyFaces setzen. Bis Mojarra 4.1.9 lag MyFaces in Messungen vorn.

Im Juli 2026 veröffentlichte Mojarra-Maintainer Bauke Scholtz (BalusC) einen Vergleich über alle Lifecycle-Phasen auf sechs Servern. Mojarra 4.1.10 brauchte 64 Prozent weniger Zeit als 4.1.9 und lag insgesamt 18 Prozent vor einem Snapshot von MyFaces 4.1.4. Der Autor ist Partei, seine Messmethode hat er offen dokumentiert. Unsere Empfehlung: die Implementierung des Applikationsservers verwenden und nur nach eigenen Messungen wechseln.

Wie passt JSTL in Facelets?

Die JSTL stammt aus der JSP-Welt, Facelets kennt nur einen Teil davon. Aus der Core-Bibliothek sind das c:if, c:forEach, c:choose, c:when, c:otherwise, c:set und c:catch, dazu kommen die fn:-Funktionen. Formatieren mit fmt: geht nicht, dafür gibt es f:convertNumber und f:convertDateTime. Der Namespace heißt ab 4.0 jakarta.tags.core.

Ein Tag wie c:if ist ein Tag-Handler. Er läuft beim Aufbau des Komponentenbaums, ui:repeat und h:dataTable dagegen erst bei der Ausgabe. Daraus entsteht der häufigste Fehler: Fragt ein c:if die Zeilenvariable einer Tabelle ab, sieht es nur null. In Iterationen gehört die Bedingung deshalb ins rendered-Attribut:

<ui:repeat value="#{warenkorb.positionen}" var="p">
  <h:outputText value="#{p.name}" rendered="#{p.menge gt 0}"/>
</ui:repeat>

Richtig eingesetzt ist c:forEach, wenn tatsächlich Komponenten entstehen sollen, zum Beispiel dynamische Formularfelder.

XHTML-Vorlage im Code-Editor mit zwei farbig markierten Blöcken für Aufbau und Ausgabe der View
JSTL-Tags wirken beim Aufbau der View, ui:repeat erst bei der Ausgabe.

Welche Performance-Tipps gelten nach der Migration noch?

Was unter 2.x half, hilft meist weiter. Die Context-Parameter tragen nur ein neues Präfix, jakarta.faces. statt javax.faces.:

  1. PROJECT_STAGE in Produktion auf Production setzen.
  2. FACELETS_REFRESH_PERIOD auf -1 stellen, damit der Server nicht laufend nach geänderten Dateien sucht.
  3. FACELETS_SKIP_COMMENTS auf true, sonst landen XHTML-Kommentare in der ausgelieferten Seite.
  4. Die Zahl gespeicherter Views pro Session begrenzen (numberOfViewsInSession bei Mojarra, NUMBER_OF_VIEWS_IN_SESSION bei MyFaces).
  5. Getter ohne Logik schreiben. Ein Getter in einem rendered-Attribut wird pro Anfrage mehrfach aufgerufen.
  6. Bei Ajax execute und render eng fassen und auf @form oder @all verzichten.
  7. Große Tabellen lazy laden, PrimeFaces liefert dafür das LazyDataModel.

Lohnt sich JavaServer Faces 2026 noch?

Für bestimmte Anwendungen ja. JSF passt, wenn viele Formulare, Validierung und serverseitige Geschäftslogik zusammenkommen und das Team Java kann, aber kein eigenes Frontend-Team hat.

JSF ist sinnvoll JSF passt eher nicht
Interne Fachanwendungen, Sachbearbeitung Öffentliche Seiten mit viel Traffic und Caching
Bestehende Java-EE-Anwendungen Offline-fähige Mobile-Apps
Teams ohne JavaScript-Spezialisten SPAs mit separatem Frontend-Team
Langlebige Software auf stabiler Spezifikation Mehrere Clients über eine gemeinsame API

Für eine bestehende Anwendung auf 2.3 raten wir zur Migration auf 4.1 statt zur Neuentwicklung. Der Umstieg ist überschaubar, und die über Jahre gewachsene Fachlogik bleibt erhalten. Wer ohnehin Geschäftsanwendungen wirtschaftlich modernisieren will, sollte beide Wege mit echten Aufwänden durchrechnen. Was das aktuelle Release technisch verlangt, etwa Java SE 17, steht in der offiziellen Spezifikation von Jakarta Faces 4.1.

Tobias
About Author

Tobias

Tobias Friedrich, Jahrgang 1971, lebt mit seiner Familie in Berlin. Er absolvierte ein Studium im Bereich Wirtschaftsrecht und arbeitet seither als unabhängiger Journalist. Im Laufe seiner Karriere verfasste er Artikel für renommierte Zeitungen wie die Frankfurter Allgemeine und die Süddeutsche Zeitung.

1 Comment

Leave a Reply

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert