WebApps – Migration von MyFaces zu Primefaces, REST, JPA 2, JEE7 auf JBoss WildFly 10

Die Motivation

Dem vorigen Blog-Eintrag zur Migration von RichFaces oder MyFaces-Implementierungen auf Primefaces folgend soll in diesem Blog-Eintrag hier die Migration der MyFaces JSF 2.2 Beispiel-Applikation library auf die sehr vorteilhafte Primefaces-Technologie beschrieben werden. Die migrierte library-primefaces ermöglicht dann die leichte Pflege von und die Suche nach Ausleihen von Kunden, d. h. diese Beispielapplikation ermöglicht die Bearbeitung und Präsentation der Stammdaten (Kunden), Bestandsdaten (E-Books) und Bewegungsdaten (Ausleihen) einer Bibliothek. Hatten die MyFaces-Beispiel-Applikationen noch extra Suchfelder und Schwächen bei der Sortierung der Ergebnislisten, bieten nach der Umstellung die Primefaces-Views das Durchsuchen, Sortieren und eine wählbare Pagination der Ergebnisliste bereits als Komfortfunktionen der robusten, aber stets elegant gestylten, etablierten, optimalen Primefaces Frontend-Technologie und deren Standard Primefaces-Funktionalitäten an.

Die Beispiel-Applikation library-primefaces wird dann wird dann auf den JBoss WildFly 9 Final, WildFly 10 Final und WildFly 11 Final Servern deployt und kann hier getestet werden. Die Verwendung der JBoss WildFly JEE7-Application Server wurde in diesem Blog bereits einmal beschrieben. Dabei liefern die JEE6- und JEE7-Beispielapplikationen hier mit Hilfe eines EJB 3-getriebenen Backends (Session Beans als DAOs, „DAO“-Pattern) unter Anbindung der JPA 2 Entities („Table-Per-Class“-Pattern) mit Hilfe von DTOs über fachliche RESTful ServiceInterfaces oder per Microservices mit Docker, Spring Boot, siehe auch „ServiceBroker“-Pattern hier, die benötigten Daten zur Präsentation und Bearbeitung (Änderung, Löschen, Neuanlage) in den Web-Frontends, welche die WebServices konsumieren („ServiceConsumer“-Pattern).

Erstellung der Beispiel Applikation auf dem Datenmodell

Mittels DBeaver wird das Klassendiagramm der Entities aus den Datenbank-Objekten erstellt und aus diesen, nach dem Anlegen der Datenbank per Hibernate Envers während dem WildFly 10 Undertow Deployment mittels JBoss Forge Eclipse PlugIn im JBoss Developer Studio erst der REST-WebService mit den Endpoints generiert und danach die Primefaces 6 WebApp auf diesem RESTful WebService. Hier das E-R-Diagramm der Bibliotheks-Datenbank:

E-R-diagram
(E-R-Diagramm der Beispiel-Datenbank „library“ ohne die MySQL-Sequence-Tabellen.)

Dabei darf positiv erwähnt werden, dass man mittels JBoss Forge eine saubere, stringente Architektur in die JEE7-Applikation einbringt, die beim Weiterentwickeln der App sehr hilfreich ist und sowohl die Entwicklungszeit-Performance als auch die Codequalität deutlich steigert. Danke, JBoss Rockstars!

Bei dieser Gelegenheit darf auch das sehr effektive, interessante und erfolgreiche Seminar

“TDD mit Java”

von Binaris Informatik erwähnt werden.

Es werden in der pom.xml die folgenden Maven Dependencies identifiziert, verwendet und importiert:

Maven JEE 7 JBoss-Artefakte und Maven Dependencies

WildFly JBoss Java EE 7 Specification APIs with Tools:
– jboss-javaee-7.0-with-tools
WildFly JBoss Java EE 7 Specification APIs with Resteasy:
– jboss-javaee-7.0-with-resteasy
WildFly JBoss Java EE 7 Specification APIs with Hibernate:
– jboss-javaee-7.0-with-hibernate

Weiterhin werden die folgenden JEE Dependencies (für das Servlet API, Annotationen, JAX-RS Implementierungen, JBoss RESTEasy, Jackson, Hibernate, JPA und EJB) verwendet:

– jboss-annotations-api_1.1_spec
– jboss-jaxrs-api_2.0_spec
– resteasy-jackson2-provider

– hibernate-jpa-2.1-api
– jboss-ejb-api_3.2_spec
– hibernate-jpamodelgen
– jboss-servlet-api_3.1_spec

Und ebenfalls die CDI 1.1 Dependency:

– cdi-api_1.1

Dabei erfolgt die Aktivierung von CDI mittels beans.xml im WEB-INF Verzeichnis.

über die Architektur und die verwendeten Design Patterns der Beispiel-Applikationen gibt es bereits Informationen in diesem Blog-Eintrag hier und bereits vorausgegangenen Blog-Einträgen.

Einsatz von Primefaces

Die Einbindung der erforderlichen Primefaces-UI-Bibliothek primefaces-6.0.jar erfolgt ganz simpel über die entsprechende Maven Primefaces Dependency in der pom.xml. Es ist also kein extra /lib-Verzeichnis und keine build.xml für einen Ant Build-Prozess erforderlich, denn es wird einfach der folgende Eintrag zur pom.xml für den Maven Build hinzugefügt:

<dependency>
      <groupId>org.primefaces</groupId>
      <artifactId>primefaces</artifactId>
      <version>6.0</version>
    </dependency>

Allein durch Änderung dieses Eintrags in der pom.xml kann jederzeit auch auf die gewünschte Primefaces-Version umgestellt werden. Bei der Umstellung der ca. 80 XHTML-Views von MyFaces auf Primefaces sind der Primefaces Showcase und der Primefaces Users Guide (PDF) sehr hilfreich. Der größte Aufwand der Migration besteht hierbei im Austausch der Standard MyFaces-Tags (h: Präfix) durch die Primefaces-Tags (p: Präfix) ist also für die simplen Beispiel-Applikationen leicht umsetzbar. Ebenfalls wurde das sehr gute bei DZone erhältliche PDF zur JSTL (Java Server Pages Template Library) verwendet und zwei weitere Dokumente über genauere Details zum JSF 2-Lifecycle, die sich hier und hier zum Download finden.

Aktiviert werden die Primefaces-Tags in der gewünschten XHTML-Seite mittels folgendem Eintrag im Dokumenten-Kopf der XHTML-View xmlns:p=“http://primefaces.org/ui und die zusätzliche Funktionalität der JSTL-Tags wird entsprechend, wie in den MyFaces-Views auch, per xmlns:c=“http://java.sun.com/jsp/jstl/core verfügbar gemacht.

Durch die Verwendung von CDI 1.1 haben die JSF ManagedBeans stattdessen die Annotation @Named und bleiben, bis auf ein paar Helper-Methoden zur Ausgabeformatierung, nahezu identisch zu den ManagedBeans der MyFaces-Applikation library.

Weitere Informationen zu JSF 2.2, CDI und dem @ViewScope gibt es auch auf stackoverflow.com. Die dort beschriebenen Themen finden sich auch in den ManagedBeans der JSF 2.2 Beispiel-Applikation wieder.

Für die Migration von RichFaces 4 Applikationen auf Primefaces gibt es in diesem Blog hier ebenfalls eine sehr nützliche Anleitung. Es wird hierzu auch noch einen Blog-Eintrag geben. Hier noch eine weitere SPA (Single Page Appliction) Beispiel-Applikation, bei der das Testen des Backends mittels Arquillian und das integrative Testen des Frontends mittels Selenium (Workflow und UX Elemente) und QUnit (Javascript-Framework zum Test-Aufruf der REST-Endpoints aus einer Browser-View) ausführlich beschrieben ist.

Weitere Informationen zu JSF 2.2, CDI und Primefaces finden sich auch hier im Blog von Balus C. Detail-Informationen zur JavaScript-Bibliothek jQuery, die vom Primefaces-Framework sehr intensiv verwendet wird, finden sich hier: jquery.org

forge.taglib.xml:

Die in den Beispiel-Applikationen verwendete, moderne Forge TagLib kann sehr einfach erweitert werden, indem die zusätzlich benötigten Methoden in der ViewUtils-Klasse ergänzt werden und deren Signaturen in der forge.taglib.xml im Verzeichnis src/main/webapp/WEB-INF/classes/META-INF/ bekanntgemacht werden, also genau wie bei klassischen TagLibs mit dem Unterschied, dass die verwendeten Tags innerhalb der Applikation in der ViewUtils-Klasse implementiert werden, was für die Applikation zusätzliche Sicherheit bringt. Diese Tags sind für jede Applikation sehr leicht adaptierbar und können genau auf die Applikation zugeschnitten werden. Die TagLib wird in der entsprechenden .xhtml-View über den Eintrag xmlns:forgeview=“http://jboss.org/forge/view“ mit dem Prefix forgeview unter der DOCTYPE-Definition im ui:composition eingebunden und mittels forgeview-Prefix per Expression Language (EL) an der gewünschten Stelle mit den richtigen Input-Parametern aufgerufen. Hier die forge.taglib.xml für die Beispiel-Applikation library-primefaces:

<?xml version=“1.0“ encoding=“UTF-8“?>
<!DOCTYPE facelet-taglib PUBLIC “-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN“ “http://java.sun.com/dtd/facelet-taglib_1_0.dtd“>
<facelet-taglib xmlns=“http://java.sun.com/JSF/Facelet“>
<namespace>http://jboss.org/forge/view</namespace>
<function>
<function-name>asList</function-name>
<function-class>de.binaris.library.view.ViewUtils</function-class>
<function-signature>
java.util.List asList(java.util.Collection)
</function-signature>
</function>

<function>
<function-name>display</function-name>
<function-class>de.binaris.library.view.ViewUtils</function-class>
<function-signature>
java.lang.String display(java.lang.Object)
</function-signature>
</function>

<function>
<function-name>count</function-name>
<function-class>de.binaris.library.view.ViewUtils</function-class>
<function-signature>
int count(java.util.Collection)
</function-signature>
</function>

<function>
<function-name>displayShort</function-name>
<function-class>de.binaris.library.view.ViewUtils</function-class>
<function-signature>
java.lang.String displayShort(java.lang.Object, int)
</function-signature>
</function>

<function>
<function-name>displayRange</function-name>
<function-class>de.binaris.library.view.ViewUtils</function-class>
<function-signature>
java.lang.String displayRange(java.lang.Object,java.lang.Object)
</function-signature>
</function>

<function>
<function-name>displayFirst</function-name>
<function-class>de.binaris.library.view.ViewUtils</function-class>
<function-signature>
java.lang.String displayFirst(java.lang.Object)
</function-signature>
</function>

<function>
<function-name>listExcludingSelectedOne</function-name>
<function-class>de.binaris.library.view.ViewUtils</function-class>
<function-signature>
java.util.List listExcludingSelectedOne(java.util.Collection,java.lang.Object)
</function-signature>
</function> 
</facelet-taglib>

Mit entsprechenden Implementierungen der Tag-Funktionalitäten in der ViewUtils-Klasse unter Verwendung generischer Typen T und Collections List<T>.

Durch die soeben gezeigten Beispiele ist erkennbar, wie simpel es ist, eigene Tags für die .xhtml-Views heutiger JSF 2-Applikationen zu definieren und deren Utility functions-Signaturen im WEB-INF/classes/META-INF-Verzeichnis des classpaths als *name*-taglib.xml mit dem genannten XML Document-Header und dem jboss-forge-view namespace zu deklarieren (s.o. forge.taglib.xml).

Alle XML und XHTML-Dateien der Primefaces-Beispielapplikation finden sich im Deployment-Archiv library-primefaces.war im /target-Unterverzeichnissen des Projekts library-primefaces.

WildFly Anbindung an MySQL5, Postgres 9 und deklarative WildFly 11 Hibernate-Konfiguration

Die Konfiguration des JBoss WildFly Application Servers 11 Final erfolgt analog der Konfigurationen der JBoss Application Server WildFly 8.1, 8.2, 9 und 10 Final und betrifft die Datasource, die MySQL-Datenbank Inno DB 5.x, Hibernate 5, das Logging und den Connection Pool und ist, genau wie die Test-Frameworks und die Aktivierung der RESTful WebService-Schnittstelle ein wichtiges Thema, welches noch genauer beschrieben werden wird. Die Anbindung an die relationale Datenbank MySQL 5 erfolgt übrigens analog für die JBoss Application Server WildFly 8.1, 8.2, 9, 10 und WildFly 11.

Je nach verwendeter Datenbank kann in der persistence.xml im Deployment-Paket der Beispiel-App library-primefaces ein entsprechender Dialekt eingetragen werden:

Hier die /META-INF/persistence.xml der Beispiel-Applikation für MySQL5:

<xml version=“1.0″ encoding=“UTF-8″?>
    <persistence version=“2.0″ xmlns=“http://java.sun.com/xml/ns/persistence“  xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance“
    xsi:schemaLocation=“http://java.sun.com/xml/ns/persistence
    http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd“>
    <persistence-unit name=“LibraryPU“>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>
            java:jboss/datasources/LibraryDatasource
    </jta-data-source>
    <properties>
    <property name=“hibernate.hbm2ddl.auto“ value=“none“/>
    <property name=“hibernate.show_sql“ value=“false“/>
    </properties>
    </persistence-unit>
    </persistence>

Dafür wird je Datenbank die folgende Datasource benötigt und ist in der standalone/configuration/standalone.xml des JBoss WildFly Servers unter den <datasources> einzutragen:

Für MySQL 5:

    <datasource jndi-name=“java:jboss/datasources/LibraryDatasource“ pool-name=“LibraryDS“
    enabled=“true“>
    <connection-url>jdbc:mysql://localhost:3306/library</connection-url>
    <driver>mysql-connector-java-5.1.34.jar</driver>
    <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
    <pool>
    <min-pool-size>10</min-pool-size>
    <max-pool-size>100</max-pool-size>
    <prefill>true</prefill>
    </pool>
    <security>
    <user-name>root</user-name>
    <password>das entsprechende Passwort</password>
    </security>
    <statement>
    <prepared-statement-cache-size>32</prepared-statement-cache-size>
    <share-prepared-statements>true</share-prepared-statements>
    </statement>
    </datasource>

Für Postgres 9:

    <datasource jndi-name=“java:jboss/datasources/LibraryDatasource“ pool-name=“LibraryDS“ enabled=“true“>
    <connection-url>jdbc:postgresql://localhost:5432/library</connection-url>
    <driver>postgresql-9.4.1209.jar</driver>
    <transaction-isolation>TRANSACTION_READ_COMMITTED
    </transaction-isolation>
    <pool>
    <min-pool-size>10</min-pool-size>
    <max-pool-size>100</max-pool-size>
    <prefill>true</prefill>
    </pool>
    <security>
    <user-name>root</user-name>
    <password>[das entsprechende Password]</password>
    </security>
    <statement>
    <prepared-statement-cache-size>32</prepared-statement-cache-size>
    <share-prepared-statements>true</share-prepared-statements>
    </statement>
    </datasource>

Für die erfolgreiche Anbindung der soeben deklarierten Datasoures werden die Datenbank-Treiber auf Modul-Ebene des JBoss WildFly konfiguriert, wie hier für den MySQL JDBC4 Treiber beispielhaft auf dem WildFly 8.2 beschrieben wurde.

Damit die Datasources die soeben konfigurierten Treiber auch finden, werden diese in der /standalone/configuration/standalone.xml bei den <datasources> deklariert:

Für Postgres 9:

<driver name=“postgresql-java-9.4.1209.jar“ module=“org.postgresql“>
   <driver-class>org.postgresql.Driver</driver-class>
   <xa-datasource-class>org.postgresql.xa.PGXADataSource
   </xa-datasource-class>
</driver>

Für MySQL 5:

<driver name=“mysql-connector-java-5.1.34.jar“ module=“com.mysql“>
   <driver-class>com.mysql.jdbc.Driver</driver-class>
   <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
   </xa-datasource-class>
</driver>

Hier auch der komplette MySQL-Export der Beispiel-Applikation library-primefaces:

Für MySQL 5: export_library_database.sql

Die Hibernate-Konfiguration des WildFly 11 Final Servers ist ebenfalls leicht durchführbar. Hierfür werden im WildFly11 Server-Verzeichnis wildfly-11.0.0.Final/modules/system/layers/base/org/hibernate/main folgende Dateien hinterlegt:

– hibernate-core-5.1.10.Final.jar
– hibernate-entitymanager-5.1.10.Final.jar
– hibernate-envers-5.1.10.Final.jar
– hibernate-java8-5.1.10.Final.jar
– jipijapa-hibernate5-11.0.0.Final.jar
– module.xml
– mysql-connector-java-5.1.34.jar
– mysql-connector-java-5.1.34.jar.index

Die fertige Beispiel-Applikation library-primefaces kann zusammen mit den anderen Beispiel-Applikationen hier betrachtet werden (MySQL5 Server, Postgres 9 auf Linux).

Hier der WildFly 10 Final als Zip-Archiv zum Download und Entpacken: Für Linux hier und für Windows hier. Voraussetzung ist jeweils Java 8.

Die fertig konfigurierte Version des WildFly 10.Final mit vielen Beispiel-Applikationen der vorigen Blog-Einträge hier zum Download bereit kann runtergeladen, entpackt und gestartet werden. Dabei ist nur der Pfad für JAVA_HOME in der standalone.xml anzupassen, wie in diesem Blog-Eintrag hier beschrieben wurde, damit dieser auf das tatsächliche JDK 8-Verzeichnis des Server-Systems zeigt und auch der Pfad für das log-Dateien Verzeichnis in der Datei [server]/standalone/configuration/logging.properties.

Hier auch der WildFly 11 Final als Zip-Archiv zum Download und Entpacken: Für Linux hier und für Windows hier. Minimale Voraussetzung ist jeweils Java 8, er wird hier aber auch mit Java 9 betrieben. Der fertig konfigurierte WildFly 11 mit vielen weiteren Beispiel-Applikationen ist hier zum Download verfügbar, kann runtergeladen, entpackt und gestartet werden.

Auch hier ist nur der Pfad des JAVA_HOME anzupassen, damit dieser auf das tatsächliche JDK 9 – Verzeichnis des Server-Systems zeigt und ebenfalls der Pfad für das log-Dateien Verzeichnis in der logging.properties.

Mehr Informationen zum Java 9 Release gibt es hier:

https://www.technotification.com/2017/09/java-9-is-finally-released.html

Herunterladen kann man sich z. B. Java 9 für die gewünschte Betriebssystem-Plattform hier:

http://www.oracle.com/technetwork/java/javase/downloads/jdk9-downloads-3848520.html

In Fällen mit Migrations-Bedarf gibt es hier weitere Informationen.

Hier die Release-Notes zu Java 9:

http://www.oracle.com/technetwork/java/javase/9-relnotes-3622618.html

Hier auch nochmal die ausführliche Dokumentation einer weiteren JEE Beispielapplikation mit Selenium-Tests und Javascript QUnit-Tests.

Hier das Beispiel-Projekte für die Eclipse-Entwicklungsumgebung JBoss Developer Studio: library-primefaces

Die Primefaces Beispiel-Applikation dieses Blog-Eintrags kann danach selbst erneut deployt werden, ohne den bereits gestarteten WildFly 11 Application Server überhaupt stoppen oder erneut starten zu müssen. Bei laufendem Server das library-primefaces.war einfach ins Server-Unterverzeichnis /standalone/deployments kopieren.

– Wenn das Deployment des library-primefaces.war Archivs nicht zeitnah startet, kann eine leere Textdatei namens library-primefaces.war.dodeploy gespeichert werden. Dann wird die Beispiel-Applikation sofort deployt und in wenigen Sekunden gestartet und kann aufgerufen werden:

http://[domainname z. B. localhost]:[http-port, z. B. 8080]/library-primefaces

Fazit: Wie man sieht, macht es einfach viel Freude, z.B. mittels JBoss Forge und JPA 2 Entities robuste, komfortable, Browser-basierte Primefaces 6-Fontends oder eben die responsiven Angular JS Apps auf dem Datenmodell zu erzeugen und weiterzuentwickeln und diese an einen neuen, die JEE7-Spezifikation erfüllenden JBoss WildFly (WildFly 9, WildFly 10 und 11) anzubinden. Die Blog-Einträge dazu können hier nach Stichworten und Erscheinungsmonat leicht durchsucht werden.

Somit besteht durchaus die Möglichkeit, dass noch weitere Blog-Einträge zu Webframeworks wie Primefaces 6, Angular JS und Bootstrap, sowie den die JEE7-Spezifikation implementierenden WebService-und Backend-Technologien folgen. Allen interessierten Leserinnen und Lesern weiterhin viel Freude bei der agilen Softwareentwicklung mittels Scrum und dem Test-Driven Development mit Java, sowie eine schöne Sommerzeit.