Erstellen einer Timeline für Beiträge mit JavaServerFaces

In diesem Beitrag möchte ich gerne das kleine Webprojekt „Timeline“ vorstellen. Mit diesem Projekt möchte ich erläutern wie man ein Webprojekt mit einer Datenbankanbindung und JavaServerFaces realisiert. 

Ziel des Webprojektes

Ziel dieses Webprojektes soll es sein Beiträge für eine Zeitlinie zu erstellen.

Ein solcher Eintrag enthält:

  • Zeitstempel,
  • Titel,
  • Text,
  • Bild,
  • Video,
  • Hyperlinks
  • usw.

Einrichten des Webprojektes

Als erstes wollen wir das JSF Projekt einrichten, dazu habe ich bereits den Beitrag Erstellen eines JavaServerFaces 2.2 Projektes mit Eclipse & Apache Maven erstellt. 

Maven Projekt - Metadaten zum Projekt
Maven Projekt – Metadaten zum Projekt

Anpassungen an der Projektstruktur

Anders als im zuvor genannten „HelloWorld“ Projekt möchte ich eine etwas andere Projektstruktur verwenden, dieses liegt viel mehr daran das Apache Maven eine bestimmte Struktur für Webprojekte bzw. Java Projekte verlangt. Im einfachen „HelloWorld“ Projekt war dieses nicht so kritisch da keine externen Resourcen wie CSS, Bilder oder JavaScript Dateien benötigt wurden, jedoch nun wollen wir etwas tiefer in JSF eintauchen.

Das Projekt „Timeline“ gibt es hier zum Download.

Texte und Übersetzungen

Damit wir unsere Anwendung später in mehreren Sprachen pflegen können benötigen wir im Hintergrund ein java.util.ResourceBundle. Für jede Sprache wird ein eigenes ResourceBundle im Format <Anwendungsbezeichnung>_<language_code> angelegt. Eine Liste von Language Codes findest du an der Klasse java.util.Locale bzw. über die ISO 639 (jedoch haben sich dort einige Codes geändert).

ResourceBundle Editor

Zum leichteren bearbeiten von mehreren ResourceBundle Dateien (*.properties) nutze ich ein zusätzliches Plugin.

Eclipse Plugin - ResourceBundle Editor
Eclipse Plugin – ResourceBundle Editor

Dieses Plugin kann über den Marketplace installiert werden. Den Marketplace findest du unter dem Menüpfad „Help“ > „Eclipse Marketplace…“.

Als erstes muss nach einem Begriff eingegrenzt werden ich nutze dazu das Wort „resource“ (1), danach wird auch schon das Plugin angezeigt, nun kann dieses über die Schaltfläche „Install“ (2)installiert werden.

Nachdem das Plugin erfolgreich installiert wurde, kann die Propertiesdatei über das Kontextmenü mit dem Plugin geöffnet werden.

Pfad im Kontextmenü zum öffnen der Propertiesdatei mit dem Resourcebundle Editor
Pfad im Kontextmenü zum öffnen der Propertiesdatei mit dem Resourcebundle Editor

Anlegen der Dateien

Wollen wir nun 3 Propertiedateien im Ordner „src“ > „main“ > „resources“ anlegen. Für eine bessere Projektorganisation packe ich diese beiden Dateien in ein Unterverzeichniss „i18n“.

Propertiesdateien für das Projekt "Timeline"
Propertiesdateien für das Projekt „Timeline“

Einmal für die deutschen und einmal für die englischen Texte sowie einmal eine Datei (ohne Language Code) für den Fallback falls der Browser keine Sprache liefert bzw. wenn eine Sprache geliefert wird welche noch nicht unterstützt wird.

Einbinden in der faces-config.xml

Als nächstes müssen wir nun in der Datei „faces-config.xml“ diese Dateien „einbinden“. Dazu müssen wir den Pfad zu den Resources definieren und eine Bezeichnung „var“ für diese vergeben.

Verwenden der ResourceBundle in XHTML Dateien

Wir haben nun das ResourceBundle in der Datei „faces-config.xml“ definiert und den Variablennamen „text“ definiert.

Um auf die Werte in der Propertiesdatei zugreifen zu können gibt es zwei Möglichkeiten:

Formular zum eintragen von Datensätze

Wollen wir im nächsten Schritt ein Formular erzeugen in welchem wir einen ersten einfachen Datensatz (Zeitstempel, Titel und Text) erzeugen wollen. 

Damit wir diese Daten speichern können, benötigen wir eine Bean und zusätzlich ein Objekt in welchem wir diese Daten speichern und abrufen können.

Aufbau einer Java Bean

Bevor wir unsere erste Java Bean erzeugen wollen wir auf den Aufbau und die Lebensdauer einer Java Bean eingehen.

Eine Java Bean (im nachfolgenden nur noch als Bean bezeichnet) wird mit der Annotation @ManagedBean über dem definieren des Klassennamens eingeleitet.

Lebensdauer & Reichweite einer Bean

Des Weiteren muss noch der Scope angegeben werden in welchem sich die Bean befindet. Der Scope definiert zeitgleich die Lebensdauer und Reichweite der Bean.

@ApplicationScoped

Diese Bean lebt solange wie die Anwendung gestartet ist und alle Daten in dieser Bean stehen allen Benutzern zur Verfügung. Wenn sich Daten in dieser Bean ändern, werden alle Benutzer davon betroffen sein. Daher sollte so eine Bean immer mit bedacht angelegt werden.

 @SessionScoped

Diese Bean wird für den Benutzer beim ersten Aufruf einer Seite / Aktion angelegt und existiert solange  wie die Session des Benutzers nicht abgelaufen ist. Die Dauer der Session ist solange diese nicht in der Datei „web.xml“ angepasst wurde 30min. 

Möchte man diesen Wert ändern so kann man in der Datei „web.xml“ mit folgenden 3 Zeilen den Timeout ändern.

Der Sessiontimeout wird bei jeder Kommunikation mit dem Server (Seitenwechsel, Speichern, Aktualisieren) zurück gesetzt.

@RequestScoped

Eine Bean im RequestScope  existiert nur solange bis eine neue Seite aufgerufen oder eine Aktion (wie Speichern, Aktualisieren) ausgeführt wird.

Erzeugen der Bean

Erzeugen wir also nun eine Bean im SessionScope mit den Feldern „title“ & „text“. Des Weiteren benötigen wir eine Methode zum speichern dieser Daten.

Value Binding

Im nächsten Schritt muss nun eine Verbindung von den Eingabefeldern aus der XHTML Datei zur Java Bean hergestellt werden. Dieses nennt man Value Binding. 

Der Bezeichner „timelineFormular“ ist unser Klassenname der Bean und „title“ ist  ein Feld aus genau dieser Klasse. 

Wichtig ist das zu den Feldern welche man benötigt / verwenden möchte getter & setter nach der Java Beans Konvention existieren. Am einfachsten ist es hier sich diese von der IDE erzeugen zu lassen.

Actions

Zum speichern und ablegen der Daten benötigen wir an den CommandButtons den Aufruf einer Aktion auf dem Server, dieses Attribut nennt sich „action“.

Die aufrufende Methode in der Bean wird ohne zusätzliche Parameter erstellt.

Im ersten Schritt dieses Webprojektes speichern wir die Daten in einer java.util.List im flüchtigen Speicher, d.h. wenn der Applicationserver heruntergefahren, neugestartet wird oder der Browser vom Benutzer geschlossen wird, werden alle Daten gelöscht. Damit wir die Daten in einer Liste ablegen können benötigen wir eine Klasse. Als ersten Schritt wollen wir den Titel, den Text sowie einen Zeitstempel speichern. 

Speichern der Daten

java.util.List

Das einfachste ist die Daten in einer java.util.List zu speichern. Dazu nutze ich eine Klasse welche diese Liste beinhaltet.

Der Vorteil daran ist das bei einer späteren Erweiterung (zbsp. zu einer Datenbank) nicht viel geändert werden muss. 

Ausgeben der gespeicherten Daten

Nachdem wir die Daten aufgenommen haben, wollen wir diese auch wieder ausgeben.
Hier nutze ich die „forEach“ Schleife:

Den gespeicherten Zeitstempel formatiere ich in mit hilfe von „convertDateTime“ in das deutsche Format „01.12.20018 12:58:34“.
Das Pattern kann man fast beliebig aufbauen, eine Liste mit den gültigen Patternzeichen findest du unter Oracle Java API – SimpleDateFormat.

Webprojekt "Timeline" mit einem Eintrag.
Webprojekt „Timeline“ mit einem Eintrag.

Wie man erkennen kann wird der Zeilenumbruch nicht angezeigt. Dieses liegt  vielmehr daran das ein Zeilenumbruch in einem HTML Dokument mit „<br/>“ dargestellt wird.
Wir müssen nun also alle „\n“ (Sonderzeichen für einen Zeilenumbruch) durch ein „<br/>“ ersetzen.
Das ersetzen kann man „einfach“ lösen indem man den getter am Text wiefolgt modifiziert:

Der Code ersetzt alle Zeilenumbrüche durch einen HTML  Zeilenumbruch. Dieses ist jedoch nur eine „Quick and Dirty Lösung“.

TextConverter

Es gibt in JSF verschiedene Converter, da es für unseren Fall keinen passenden Converter gibt, schreiben wir uns diesen kurzerhand selbst.
Dazu erzeuge ich eine Klasse „TextConverter“ und implementiere das Interface javax.faces.convert.Converter. 

Die Methode „replaceLineBreaks“ hat als Parameter den Wert als Object. Auf dieses Objekt wird die Methode „toString()“ aufgeführt, diese Methode liefert dann einen String. Wenn das Objekt ein String ist (wie in unserem Fall) dann wird der Wert dahinter geliefert ansonsten muss vorher einen Cast auf ein Datentyp erfolgen.

Verwenden des TextConverters

Nachdem wir den TextConverter erzeugt haben, können wir diesen wiefolgt in unserem JSF Tag „outputText“ verwenden:

Der Converter muss dabei zwischen dem geöffneten sowie dem geschlossenen Tag „h:outputText“ befinden. Zusätzlich muss man noch das Attribut „escape“ auf „false“ setzen da sonst der HTML LineBreak umgewandelt und dann als Text angezeigt wird.

Das Ergebnis bleibt gleich jedoch haben wir nun einen TextConverter welcher an mehreren Stellen verwendet werden kann und wir unsere DAO’s nicht anpassen müssen. 

Upload von Bilder

Nachdem wir nun mit den ersten Schritten zu dem Webprojekt fertig sind, können wir einen einfachen Beitrag erstellen und nachdem speichern darstellen.
Als nächstes wollen wir nun ein Bild zu dem Beitrag hochladen.

Allgemeines zum Upload von Daten

Wenn ein Benutzer eine Datei auf einen Server hochläd, sollte diese nicht unverändert abgelegt werden. Denn es gibt nicht nur gute Benutzer, jede Datei kann Schadsoftware enthalten welche von außen benutzt werden kann. Am einfachsten ist es den Dateinamen der Datei zu modifizieren (bei einem späteren Download kann dieser Name wieder angepasst werden). Zusätzlich sollte man prüfen ob der Dateityp der Datei welche hochgeladen wird, dem erwarteten Dateityp entspricht. In unserem Fall würden wir prüfen ob es sich um Bilder im jpg, jpeg, png handelt. 

JSF Tag

Wie in HTML gibt es einen speziellen Tag auch für JSF, dieser ist „h:inputFile“.

Als Value wird ein Objekt vom Typ javax.servlet.http.Part erwartet. Des Weiteren müssen wir dem umgebenen Formular ein zusätzliches Attribut hinzufügen:

Dieses sorgt dafür das wir mehrere Datentypen zum Server senden können.

Damit wir später den Dateinamen in die originale Bezeichnung wieder zurück ändern müssen wir den neuen sowie den „alten“ Dateinamen speichern. Erzeugen wir also nun ein Objekt um diese Daten zu speichern.

Extrahieren des Dateinamens

Den Dateinamen kann man mit reinem JavaServerFaces nicht so einfach. Jedoch findet man Header Informationen an dem Part Objekt.

Die Header Informationen sind mit einem Semikolon separiert.

Somit müssen wir diese Zeichenkette erstmal splitten.

Da wir den Dateinamen haben wollen müssen wir mit einer Schleife über dieses Array iterieren. Wenn der Wert mit der Zeichenkette „filename“ beginnt so wird der Wert nachdem Gleichheitszeichen als Dateiname extrahiert und sofort zurück geliefert.

Die ganze Methode:

Für den Datentyp javax.servlet.http.Part müssen wir zusätzlich eine Java EE Abhängigkeit in der Datei „pom.xml“ einfügen.

Nun können wir unsere Beans’s sowie das DAO „TimelineEntry“ um dieses Feld erweitern. (Dabei sollten die getter & setter Methoden nicht vergessen werden.)

Anpassen der Tomcat server.xml

Damit wir die Dateien in einem bestimmten Ordner ablegen können müssen wir den Context der Anwendung anpassen.

Hier wird zusätzlich das Attribut „aliases“ eingefügt, der Wert zeigt auf einen Absoluten Pfad auf der Festplatte wo der Apache Tomcat Server läuft.

Methode zum speichern der Datei

An dem Objekt „Part“ gibt es die Methode „write“, diese Methode erwartet einen Dateinamen. Da wir einen bestimmten Ordner für die Ablage der Bilder nutzen möchten müssen wir uns hier über den ExternenContext den Pfad holen und vor dem Dateinamen setzen.

In meinem Fall wird nun jedes Bild in den Ordner „C:\temp\images“ gespeichert.

Anzeigen der Bilder

Als nächstes wollen wir nun die Bilder auch anzeigen.
Bevor wir jedoch ein Bild anzeigen lassen, prüfen wir ob zu diesem Datensatz überhaupt ein Bild existiert. 

Wenn dieses Bild existiert so soll dieses aus dem Ordner welchen wir in der Datei server.xml definiert haben geladen werden.

JSF - Timeline Beitrag mit Bild
JSF – Timeline Beitrag mit Bild

Download

Hier nun das gesamte Projekt zum bequemen Download.

 

 

 

 

 

 

 

 

Ein Gedanke zu „Erstellen einer Timeline für Beiträge mit JavaServerFaces

Schreibe einen Kommentar

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