WebApps – mit Angular JS, JQuery, REST, JEE7, JBoss Forge, Java 8, MySQL 5, auf JBoss WildFly 9 und 10

Sonntag, 28. Mai 2017 von  
unter Fachartikel Architektur

Die Motivation

In dem bereits vorhandenen Blog-Eintrag über WebApps – vom Modell zur App, mit JSF 2.2, Angular JS, REST, JPA 2 hier wurde beschrieben, wie von einem Klassen-Diagramm (UML), genauer: Entity-Relationship-Diagramm hier, auch E-R Diagramm genannt, eine JEE7-Applikation erstellt werden kann. Diese JEE6- und JEE7-Beispielapplikationen hier liefern mit Hilfe von 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).

Das Durchsuchen, und die Nutzung einer Pagination der Ergebnisliste ist ebenfalls in der Beispiel-App enthalten, wie auch mit Hilfe des Angular JS Frameworks und des Bootstrap-Frameworks eine dynamische Benutzeroberfläche, die sich an beliebige Auflösungen und Display-Größen responsiv anpasst.

Die ausprogrammierte JEE7-Applikation businessappointments-angularjs mit dem Angular JS-Frontend und dem JEE-Backend mit den JPA 2 Entities kann einfach an verschiedene relationale Datenbanken (z. B. MySQL 5.x oder Postgres 9.x) angebunden werden, weshalb auch benötigte SQL-Export/-Import-Skripte zur Verfügung gestellt werden.

Die Beispiel-Applikation businessappointments-angularjs wird dann auf dem neusten JBoss WildFly 10 Final Server (entspricht dem neuen JBoss EAP 7-Server) und ebenfalls auf dem JBoss WildFly 9 deployt. Dabei ist die Verwendung dieser beiden neuen JBoss WildFly JEE7-Application Server in diesem Blog-Eintrag hier bereits beschrieben worden.

Erstellung der Beispiel Applikation auf dem Datenmodell

Mittels DBeaver wird das Entity-Relationship-Diagramm aus den Datenbank-Objekten erstellt und aus diesen Entities, 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 Angular JS WebApp auf diesem RESTful WebService.

Entity-Relationship Diagram BusinessappointmentsDabei darf positiv erwähnt werden, dass man mittels JBoss Forge eine saubere, stringente Architektur in die JEE7-Applikation einbringt, die beim Weiterentwickeln der responsiven WebApp 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”

hier und hier von Binaris Informatik erwähnt werden.

Maven JEE 7 JBoss-Artefakte und Maven Dependencies

Es werden in der pom.xml die folgenden Maven Dependencies verwendet:

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

 Einsatz von CDI

Und ebenfalls die CDI 1.1 Dependency:

– cdi-api_1.1

Über CDI und JavaEE gibt es bereits Blog-Einträge in diesem Blog hier und hier. Die Aktivierung von CDI erfolgt, wie beschrieben, mittels beans.xml im WEB-INF Verzeichnis.

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

JBoss WildFly 10 Anbindung an MySQL 5

Die Konfiguration des JBoss WildFly Application Servers 10 Final erfolgt analog der Konfigurationen der JBoss Application Server WildFly 8.1, 8.2 und 9 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 in diesem Blog-Eintrag hier und vorigen Blog-Einträgen bereits beschrieben. Die Anbindung an die relationalen Datenbanken Postgres 9 und MySQL 5 ist in diesem Blog-Eintrag hier bereits beschrieben.

Je nach verwendeter Datenbank kann in der persistence.xml im Deployment-Paket der Beispiel-App businessappointments-angularjs.war ein anderer Datenbank-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=“BusinessappointmentsPU“>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>
            java:jboss/datasources/BusinessappointmentsDatasource
    </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/BusinessappointmentsDatasource“ pool-name=“BusinessappointmentsDS“
    enabled=“true“>
    <connection-url>jdbc:mysql://localhost:3306/businessappointments</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 die erfolgreiche Anbindung der soeben deklarierten Datasoures werden die Datenbank-Treiber auf Modul-Ebene des JBoss WildFly konfiguriert, wie in diesem Blog-Eintrag hier bereits beschrieben.

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

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 businessappointments-angularjs:

Für MySQL 5: mysql_export_businessappointments_database_sql.txt

Die fertige Beispiel-Applikation businessappointements-angularjs kann zusammen mit den anderen Beispiel-Applikationen hier betrachtet werden (MySQL5 Server auf Linux).

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

businessappointments-angularjs

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 ebenfalls der Pfad für das log-Dateien Verzeichnis in der logging.properties.

Die Angular JS Beispiel-Applikation dieses Blog-Eintrags kann danach selbst erneut deployt werden, ohne den bereits gestarteten WildFly 10 Application Server überhaupt stoppen oder erneut starten zu müssen. Bei laufendem Server einfach ins Server-Unterverzeichnis /standalone/deployments

– eine leere Textdatei namens businessappointments-angularjs.war.dodeploy speichen und
– das Archiv businessappointments-angularjs.war aus dem businessappointments-angularjs/target-Verzeichnis speichern

Sofort wird die Beispiel-Applikation deployt und in wenigen Sekunden gestartet und kann aufgerufen werden:

http://localhost:8080/businessappointments-angularjs

Fazit: Wie man sieht, macht es einfach viel Freude, z.B. mittels JBoss Forge und JPA 2 Entities die responsiven Angular JS Apps auf dem Datenmodell zu erzeugen und weiterzuentwickeln oder eben robuste, komfortable, Browser-basierte Primefaces 6-Fontends, sei es nun für mobile IMS (Informations-Management-Systeme) oder für PIMS (Product Information Management Systems) und diese an einen neuen, die JEE7-Spezifikation erfüllenden JBoss WildFly (WildFly 9, WildFly 10) anzubinden.

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 weiterhin eine schöne Sommerzeit.

WebApps – Primefaces 6, JPA 2, EJB 3, PDFs parsen, iText, MySQL, REST, JEE7, WildFly

Sonntag, 23. April 2017 von  
unter Fachartikel Architektur

Die Motivation

Über Beispiel-Applikationen zu der sehr vorteilhaften Primefaces-Technologie gibt es bereits Blog-Einträge in diesem Blog hier. Im Blog-Eintrag über WebApps – vom Modell zur App, mit JSF 2.2, Angular JS, REST, JPA 2 hier wurde beschrieben, wie leicht es ist, von einem Entity-Relationship-Diagramm zu einer JEE7-Applikation zu kommen. In diesem Blog-Eintrag soll nun die nach dem zugrundeliegenden relationalen Datenmodell im vorigen Blog-Eintrag hier besprochene Primefaces Beispiel-Webapplikation jobapplicationadmin-primefaces ergänzt werden.

Diese weiterentwickelte, um das Such-Formular und den PDF FileParser erweiterte Admin-Applikation jobapplicationadmin-primefaces ist die Admin-Sicht für einen HR-Mitarbeiter, welcher die über die Applikation jobapplication-primefaces eingegangenen Bewerbungen (“Job Applications“) mit den zugehörigen hochgeladenen PDF-Dokumenten und einem Profilbild weiterbearbeiten möchte. Hierfür sieht er nach dem Einloggen alle Bewerber und deren persönliche Daten, Zusatzinformationen sowie hochgeladene Dokumente und kann diese öffnen, zur Weiterverarbeitung herunterladen, oder über das zusätzliche Such-Formular nach den interessierenden Suchworten durchsuchen. Die PDFs mit den gefundenen Suchworten werden dann in einer Ergebnis-Tabelle präsentiert. Falls keine PDFs mit den Suchworten gefunden werden, bleibt diese Tabelle leer (“No records found“).

Erstellung der Beispiel Applikation nach Datenmodell

Die Beispiel-Applikation jobapplicationadmin-primefaces wurde bereits im vorigen Blog-Eintrag hier nach dem Datenmodell erstellt und dann auf den JBoss WildFly 9 Final und JBoss WildFly 10 Final Application Servern deployt und getestet. Die Verwendung der JBoss WildFly JEE7-Application Server wurde in diesem Blog-Eintrag hier 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 die benötigten Daten zur Präsentation und Bearbeitung (Änderung, Löschen, Neuanlage) in den Web-Frontends, welche die WebServices konsumieren (ServiceConsumer-Pattern). Der JPA-Provider ist dabei Hibernate von JBoss, welches auf dem WildFly zu konfigurieren ist, was bereits in diesem Blog-Eintrag hier beschrieben wurde.

In der pom.xml des Beispielprojekts jobapplicationadmin-primefaces1 ist nach erfolgtem Download erkennbar, dass auch hier die bekannten JEE 7 Artefakte für den JBoss WildFly verwendet und importiert wurden:

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

Einsatz von CDI

Über CDI und JavaEE gibt es bereits Blog-Einträge in diesem Blog hier und hier. Die Aktivierung von CDI erfolgt, wie beschrieben, mittels beans.xml im WEB-INF Verzeichnis.

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

Primefaces 6 und iText Dependencies:

Hat man erst einmal die JPA 2.2 Entities definiert und, wie beschrieben, mittels JBoss Forge die Beispiel-Webapplikationen für die ausgewählte Frontend-Technologie (Angular JS oder Faces) erzeugt und rebrandet, ist z. B. auch die Migration einer Faces Beispiel-Applikation auf Primefaces leicht durchführbar und wurde bereits in einem vorigen Blog-Eintrag hier beschrieben.

Die Einbindung der erforderlichen Primefaces-UI-Bibliothek primefaces-6.0.jar erfolgt dabei ganz simpel übers Hinzufügen der entsprechenden Maven Primefaces Dependency in der pom.xml.

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

Zusätzlich sind für das Durchsuchen der hochgeladenen PDFs die folgende BouncyCastle– und die iText-Dependency erforderlich:

<dependency>
     <groupId>org.bouncycastle</groupId>
     <artifactId>bcprov-jdk15on</artifactId>
     <version>1.48</version>
</dependency>

<dependency>
     <groupId>com.itextpdf</groupId>
     <artifactId>itextpdf</artifactId>
     <version>5.4.5</version>
</dependency>

(Bouncy Castle wird vom PDF FileParser benötigt, um kodierte ASN.1 Objekte aus dem PDF zu lesen und in lesbare Text-Fragmente zu dekodieren.)

Allein durch Änderung dieser Einträge in der pom.xml kann jederzeit auch auf die gewünschte Primefaces-Version umgestellt werden, ebenso auf eine höhere iText- und BouncyCastle-Version. Bei der Ausprogrammierung der XHTML-Views auf Primefaces sind der Primefaces Showcase und der neue Primefaces 6.0 Users Guide (PDF) sehr hilfreich. Ebenfalls wurde das sehr gute bei DZone erhältliche PDF zur JSTL (Java Server Pages Template Library) verwendet. Der größte Aufwand einer 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 hier leicht umsetzbar. Weitere Informationen zur Migration auf Primefaces sind bereits in einem vorigen Blog-Eintrag hier vorhanden.

Aktiviert werden die Primefaces-Tags in der gewünschten XHTML-Seite mittels folgendem Namespace 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 ansonsten nahezu identisch zu den ManagedBeans der MyFaces-Applikationen. 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

Hier die search.xhtml-Seite mit dem Suchwort-Formular und der Ergebnis-Tabelle. Und hier ebenfalls die erforderlichen Erweiterungen der FileUploadBean mit der Such-Methode und deren Hilfsmethoden, die sich auch leicht in eine PDFFileParser-Utility Klasse refaktorisieren lassen.

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

Konfiguration des JBoss WildFly Application Servers

Die Konfiguration des JBoss WildFly Application Servers 10 Final erfolgt analog der Konfigurationen der JBoss Application Server WildFly 8.1, 8.2 und 9 Final und betrifft die Datasource, das Logging und den Connection Pool und ist, genau wie die Test-Frameworks und die Aktivierung der RESTful WebService-Schnittstelle in diesem Blog-Eintrag hier und in vorigen Blog-Einträgen bereits beschrieben. Wie die MySQL-Datenbank Inno DB 5.x zu konfigurieren ist, wurde in einem bereits vorhandenen Blog-Eintrag hier bereits beschrieben.

Die Primefaces Beispiel-Applikationen jobapplicationadmin-primefaces und jobapplication-primefaces arbeiten über die RESTful WebService-Schnittstelle auf derselben MySQL-InnoDB. Für die Primefaces Beispiel-Applikationen kann folgendes MySQL 5.x Datenbank-Skript verwendet werden. Hier auch die Datasource Definition:

<datasource jndi-name=“java:jboss/datasources/JobapplicationDatasource“ pool-name=“JobapplicationDS“ enabled=“true“>
<connection-url>jdbc:mysql://localhost:3306/jobapplication</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>

Die Hibernate-Konfiguration des WildFly Servers ist ebenfalls leicht durchführbar und wurde bereits in einem Blog-Eintrag in diesem Blog hier beschrieben.

Die fertige Beispiel-Applikation jobapplicationadmin-primefaces kann leicht selbst deployt werden und wird ebenfalls nicht auf dem Test-Server deployt, um den Eindruck zu vermeiden, man könnte sich darüber real bewerben oder reale Bewerbungen bearbeiten. Aus demselben Grund wurden in der Beispiel-Applikation auch das Firmen-Logo durch ein neutrales Emblem ersetzt und der Link auf binaris.de entfernt. Denn bei Binaris Informatik bewirbt man sich nach wie vor am besten hier.

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

“TDD mit Java”

hier und hier von Binaris Informatik ebenfalls positiv erwähnt werden.

Hier die Beispiel-Projekte für die Entwicklungsumgebungen JBoss Developer Studio und intelliJ 15:

JBoss Developer Studio Projekt:

jobapplicationadmin-primefaces

intelliJ Projekt:

jobapplicationadmin-primefaces

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. Über die Konfiguration von Hibernate, der Datasource und der MySQL 5.x Datenbank für den WildFly 9 und den WildFly 10 gibt es hier mehr Informationen in diesem Blog.

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, damit dieser auf das tatsächliche JDK 8-Verzeichnis des Server-Systems zeigt.

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

– eine leere Textdatei namens jobapplicationadmin-primefaces.war.dodeploy speichen und
– das Archiv jobapplicationadmin-primefaces.war aus dem jobapplicationadmin-primefaces1/target-Verzeichnis speichern

Wie man sieht, macht es viel Freude, JEE-Applikationen mit der vorteilhaften Primefaces-Technologie zu entwickeln und ebenfalls, zuvor die Faces-Beispielapplikationen mittels JBoss Forge auf dem Datenmodell zu erzeugen und weiterzuentwickeln.

Es ist also sehr wahrscheinlich, dass noch weitere Blog-Einträge zu Webframeworks wie Primefaces, Angular JS und Faces und den die JEE-Spezifikation implementierenden Technologien folgen.

Allen interessierten Leserinnen und Lesern weiterhin viel Freude bei der agilen Softwareentwicklung mittels Scrum und dem Test Driven Development mit Java, sowie einen angenehmen Frühling und eine schöne Sommerzeit.

WebApps – JSF 2, Primefaces, FileDownloads, JPA 2, EJB 3, JEE7, REST, MySQL, WildFly

Sonntag, 26. März 2017 von  
unter Fachartikel Architektur

Die Motivation

Über Beispiel-Applikationen zu der der sehr vorteilhaften Primefaces 6-Technologie gibt es bereits Blog-Einträge in diesem Blog hier. Im Blog-Eintrag über WebApps – vom Modell zur App, mit JSF 2.2, Angular JS, REST, JPA 2 hier wurde beschrieben, wie leicht es ist, von einem Klassen-Diagramm (UML), genauer: Entity-Relationship-Diagramm, auch E-R Diagramm genannt, zu einer JEE7-Applikation zu kommen. In diesem Blog-Eintrag soll nun nach dem zugrundeliegenden relationalen Datenmodell eine Primefaces 6 Beispiel-Webapplikation jobapplicationadmin-primefaces für eine MySQL 5 Datenbank erstellt werden. Dabei werden als Basis-Frontendtechnologien JSF 2 und Primefaces 6 verwendet. Weiterhin wird der Einsatz moderner Tag-Libs in den XHTML-Seiten der JEE7-Applikation erklärt.

Erstellung der Beispiel Applikation nach Datenmodell

Mittels JBoss Forge Eclipse PlugIn wird die Primefaces 6 Beispiel-Applikation jobapplicationadmin-primefaces auf dem Datenmodell mit den JPA 2 Entities erstellt unter Einsatz von JSF 2 und der robusten, elegant gestylten, etablierten, optimalen Primefaces Frontend-Technologie. Hier das mittels DBeaver erstellte Entity-Relationship Diagramm der jobapplication-MySQL Datenbank:

E-R Diagramm jobapplication

(Anm.: Die Tabelle Customer, welche den Bewerber („Job Applicant“) darstellt enthält dabei die Adresse, welche physisch in die Tabelle integriert ist und deshalb auf der Entity „Customer“ als @Embeddable Adresse annotiert wird. Zu JPA und der @Embeddable Annotationen gibt es bereits einen Eintrag in diesem Blog hier.)

Die weiterentwickelte Beispiel-Applikation jobapplicationadmin-primefaces wird dann auf den JBoss WildFly 9 Final und JBoss WildFly 10 Final Application Servern deployt und getestet. Die Verwendung der JBoss WildFly JEE7-Application Server wurde in diesem Blog-Eintrag hier 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 die benötigten Daten zur Präsentation und Bearbeitung (Änderung, Löschen, Neuanlage) in den Web-Frontends, welche die WebServices konsumieren (ServiceConsumer-Pattern). Der JPA-Provider ist dabei Hibernate von JBoss, welches auf dem WildFly zu konfigurieren ist.

Wie die Applikation jobapplication-primefaces mittels JBoss Forge erstellt werden kann, ist bereits in diesem Blog-Eintrag hier beschrieben worden, und wie in der pom.xml des jeweiligen Beispielprojekts nach erfolgtem Download erkennbar ist, wurden auch in der Applikation jobapplicationadmin-primefaces die folgenden JEE 7 Artefakte für den JBoss WildFly 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

Einsatz von CDI

Über CDI und JavaEE gibt es bereits Blog-Einträge in diesem Blog hier und hier. Die Aktivierung von CDI erfolgt, wie beschrieben, mittels beans.xml im WEB-INF Verzeichnis.

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

Primefaces 6:

Hat man erst einmal die JPA 2.2 Entities definiert und mittels JBoss Forge die Beispiel-Webapplikationen für die ausgewählte Frontend-Technologie (Angular JS oder Faces) erzeugt und rebrandet, ist die Migration der Faces Beispiel-Applikation leicht durchführbar und wurde bereits in den vorigen Blog-Einträgen beschrieben.

Die Einbindung der erforderlichen Primefaces-UI-Bibliothek primefaces-6.0.jar erfolgt dabei ganz simpel übers Hinzufügen der entsprechenden Maven Primefaces Dependency in der pom.xml.

<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 Ausprogrammierung der XHTML-Views auf Primefaces sind der Primefaces Showcase und der neue Primefaces 6.0 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.

Aktiviert werden die Primefaces-Tags in der gewünschten XHTML-Seite mittels folgendem Namespace 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 ansonsten nahezu identisch zu den ManagedBeans der MyFaces-Applikationen. 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 jobapplicationadmin-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.jobapplication.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.jobapplication.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.jobapplication.view.ViewUtils</function-class>
       <function-signature>
             int count(java.util.Collection)
       </function-signature>
   </function>
               
   <function>
       <function-name>displayShort</function-name>
       <function-class>de.binaris.jobapplication.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.jobapplication.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.jobapplication.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.jobapplication.view.ViewUtils</function-class>
       <function-signature>
             java.util.List listExcludingSelectedOne(java.util.Collection,java.lang.Object)
       </function-signature>
   </function>  
</facelet-taglib>

Hier auch die ViewUtils-Klasse unter Verwendung generischer Typen T und Collections List<T>:

ViewUtils:

package de.binaris.jobapplication.view;
 
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
 
import javax.persistence.Id;
 
/**
* Utilities for working with Java Server Faces views.
*/
public final class ViewUtils {
 
   public static <T> List<T> asList(Collection<T> collection) {
     if (collection == null) {
         return null;
     }
     return new ArrayList<T>(collection);
   }
 
   public static String display(Object object) {
     if (object == null) {
         return null;
     }
     try {
         // Invoke toString if declared in the class. If not found,
         // the NoSuchMethodException is caught and handled
         object.getClass().getDeclaredMethod(“toString“);
         return object.toString();
     }
     catch (NoSuchMethodException noMethodEx) {
         try {
           for (Field field : object.getClass().getDeclaredFields()) {
               // Find the primary key field and display it
               if (field.getAnnotation(Id.class) != null) {
                 // Find a matching getter and invoke it to display the key
                 for (Method method : object.getClass().getDeclaredMethods()) {
                     if (method.equals(new PropertyDescriptor(field.getName(),                    
                                         object.getClass()).getReadMethod()))
                     {
                       return method.invoke(object).toString();
                     }
                 }
               }
           }
           for (Method method : object.getClass().getDeclaredMethods()) {
               // Find the primary key as a property instead of a field, and display it
               if (method.getAnnotation(Id.class) != null) {
                 return method.invoke(object).toString();
               }
           }
         } catch (Exception ex) {
           // Unlikely, but abort and stop view generation if any exception is thrown
           throw new RuntimeException(ex);
         }
     }
     return null;
   }
 
   public static <T> int count(Collection<T> collection) {
     if (collection == null) {
               return 0;
     }
     return collection.size();
   }
 
   public static String displayRange(Object object1, Object object2) {
     String text1 = display(object1);
     String text2 = display(object2);
      if (text1 == null || text2 == null
          || text1.trim() == null || text2.trim() == null) {
           return null;
      }
     return (text1 + “-“ + text2);
   }
               
   public static String displayFirst(Object object) {
     String text = display(object);
      if (text == null || text.split(“\\s+“) == null
          || text.split(“\\s+“)[0] == null) {
           return null;
      }
     return (text.split(“\\s+“)[0] + “…“);
   }
 
   public static String displayShort(Object object, int length) {
     String text = display(object);
      if (text == null || text.split(“[‚.‘]“) == null
           || text.split(“[‚.‘]“)[0] == null) {
           return null;
      }
     String[] elements = text.split(“[‚.‘]“);
     String result = ““;
      if (text.length() < length) {
         return text;
      } else {
         result = text.substring(0,length-4) + „…“;
         return result;
      }
   }

   public static <T> List<T> listExcludingSelectedOne(Collection<T> collection, T selected) {
     if (collection == null) {
         return null;
     }
     if (selected == null) {
       return new ArrayList<T>(collection);
     }
     List<T> list = new ArrayList<T>(collection);
     list.remove(selected);
     return list;
   }
 
   private ViewUtils() {
     // Can never be called, only by getInstance – Singleton pattern
   }

   public static ViewUtils getInstance() {
      return new ViewUtils();
   }
}

Über Tags, TagLibs und die Erweiterung bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und 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 jobapplicationadmin-primefaces.war im /target-Unterverzeichnissen des Projekts jobapplicationadmin-primefaces.

Primefaces File Download

Die Admin-Applikation jobapplicationadmin-primefaces stellt nun die Admin-Sicht für einen HR-Mitarbeiter dar, welcher die über die Applikation jobapplication-primefaces eingegangenen Bewerbungen (“Job Applications“) mit den zugehörigen hochgeladenene PDF-Dokumenten und einem Profilbild weiterbearbeiten möchte. Hierfür sieht der eingeloggte Admin alle Bewerber und deren persönliche Daten, Zusatzinformationen sowie hochgeladenen Dokumente und kann diese öffnen oder zur Weiterverarbeitung herunterladen. Hierfür gibt es in der webapp/fileUpload/view.xhtml, um z. B. einen CV herunterzuladen das folgende Element:

<h:commandButton value=“Open/Download“>
        <p:fileDownload value=“#{fileUploadBean.cvStream}“ />
</h:commandButton>

Und in der Session Bean “FileUploadBean“ wird der StreamedContent cvStream über einen entsprechenden getter getCvStream() verfügbar. Folgendermaßen wird der DefaultStreamedContent erhältlich, der mittels ByteArrayInputStream den byte[]-Inhalt der MEDIUMBLOB-Column “cv“ der MySQL-Tabelle file_upload (Entity FileUpload) konvertiert:

public StreamedContent getCvStream() {

        String contentType = „application/pdf“;
        StreamedContent cvStream = new DefaultStreamedContent(
new ByteArrayInputStream(
fileUpload.getCv()),                                                                                      contentType,
                                                                                     fileUpload.getCvPath());
         return cvStream;
}

Konfiguration des JBoss WildFly Application Servers

Die Konfiguration des JBoss WildFly Application Servers 10 Final erfolgt analog der Konfigurationen der JBoss Application Server WildFly 8.1, 8.2 und 9 Final und betrifft die Datasource, das Logging und den Connection Pool und ist, genau wie die Test-Frameworks und die Aktivierung der RESTful WebService-Schnittstelle in diesem Blog-Eintrag hier und in vorigen Blog-Einträgen bereits beschrieben. Wie die MySQL-Datenbank Inno DB 5.x zu konfigurieren ist, wurde in einem bereits vorhandenen Blog-Eintrag hier bereits beschrieben.

Die Primefaces Beispiel-Applikationen jobapplicationadmin-primefaces und jobapplication-primefaces arbeiten über die RESTful WebService-Schnittstelle auf derselben MySQL-InnoDB. Für die Primefaces Beispiel-Applikationen kann folgendes MySQL 5.x Datenbank-Skript verwendet werden. Hier auch die Datasource Definition:

<datasource jndi-name=“java:jboss/datasources/JobapplicationDatasource“ pool-name=“JobapplicationDS“ enabled=“true“>
<connection-url>jdbc:mysql://localhost:3306/jobapplication</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>

Die Hibernate-Konfiguration des WildFly Servers ist ebenfalls leicht durchführbar und wurde bereits in einem Blog-Eintrag in diesem Blog hier beschrieben.

Die fertige Beispiel-Applikation jobapplicationadmin-primefaces kann leicht selbst deployt werden und wird ebenfalls nicht auf dem Test-Server deployt, um den Eindruck zu vermeiden, man könnte sich darüber real bewerben oder reale Bewerbungen bearbeiten. Aus demselben Grund wurden in der Beispiel-Applikation auch das Firmen-Logo durch ein neutrales Emblem ersetzt und der Link auf binaris.de entfernt. Denn bei Binaris Informatik bewirbt man sich nach wie vor am besten hier.

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

“TDD mit Java”

hier und hier von Binaris Informatik ebenfalls positiv erwähnt werden.

Hier die Beispiel-Projekte für die Entwicklungsumgebungen JBoss Developer Studio und intelliJ 15:

JBoss Developer Studio Projekt:

jobapplicationadmin-primefaces

intelliJ Projekt:

jobapplicationadmin-primefaces

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. Über die Konfiguration von Hibernate, der Datasource und der MySQL 5.x Datenbank für den WildFly 9 und den WildFly 10 gibt es hier mehr Informationen in diesem Blog.

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, damit dieser auf das tatsächliche JDK 8-Verzeichnis des Server-Systems zeigt.

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

– eine leere Textdatei namens jobapplicationadmin-primefaces.war.dodeploy speichen und
– das Archiv jobapplicationadmin-primefaces.war aus dem jobapplicationadmin-primefaces/target-Verzeichnis speichern

Wie man sieht, macht es viel Freude, JEE-Applikationen mit der vorteilhaften Primefaces-Technologie zu entwickeln und ebenfalls, zuvor die Faces-Beispielapplikationen mittels JBoss Forge auf dem Datenmodell zu erzeugen und weiterzuentwickeln.

Es ist also sehr wahrscheinlich, dass noch weitere Blog-Einträge zu Webframeworks wie Primefaces, Angular JS und Faces und den die JEE-Spezifikation implementierenden 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 angenehme Sommerzeit.

WebApps – Primefaces 6, FileUploads, JSF 2, JPA 2, EJB 3, JEE7, REST, AngularJS, WildFly

Mittwoch, 22. Februar 2017 von  
unter Fachartikel Architektur

Die Motivation

Über Beispiel-Applikationen zu der der sehr vorteilhaften Primefaces 6-Technologie gibt es bereits Blog-Einträge in diesem Blog hier. In diesem Blog-Eintrag soll nun nach dem zugrundeliegenden relationalen Datenmodell eine Primefaces 6 Beispiel-Webapplikation jobapplication-primefaces für eine MySQL 5 Datenbank erstellt werden. Dabei werden als Basis-Frontendtechnologien JSF 2 und Primefaces 6 verwendet. Weiterhin wird der Einsatz moderner Tag-Libs in den XHTML-Seiten der JEE7-Applikation erklärt.

Über die JSF Technologie gibt es bereits einen Blog-Eintrag in diesem Blog hier, worin die Generierung einer JSF 1.2-Applikation auf Basis der JPA-Entities für den JPA-Provider EclipseLink mittels der NetBeans IDE für das Deployment auf dem GlassFish 3 Application Server erklärt wurde. Mittels JBoss Forge Eclipse PlugIn wird die Primefaces 6 Beispiel-Applikation jobapplication-primefaces auf dem Datenmodell mit den JPA 2 Entities erstellt unter Einsatz von JSF 2 und der robusten, elegant gestylten, etablierten, optimalen Primefaces Frontend-Technologie.

Die Beispiel-Applikation jobapplication-primefaces wird dann auf den JBoss WildFly 9 Final und JBoss WildFly 10 Final Application Servern deployt und getestet. Die Verwendung der JBoss WildFly JEE7-Application Server wurde in diesem Blog-Eintrag hier 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 die benötigten Daten zur Präsentation und Bearbeitung (Änderung, Löschen, Neuanlage) in den Web-Frontends, welche die WebServices konsumieren (ServiceConsumer-Pattern). Der JPA-Provider ist dabei Hibernate von JBoss, welches auf dem WildFly zu konfigurieren ist.

Erstellung der Beispiel Applikation nach Datenmodell

Wie die Applikation jobapplication-primefaces mittels JBoss Forge erstellt werden kann, ist bereits analog in diesem Blog-Eintrag hier für die Applikation recipeadmin-primefaces beschrieben worden, und wie in der pom.xml des jeweiligen Beispielprojekts nach erfolgtem Download erkennbar ist, wurden auch in der Applikation jobapplication-primefaces die folgenden JEE 7 Artefakte für den JBoss WildFly 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

Einsatz von CDI

Über CDI und JavaEE gibt es bereits Blog-Einträge in diesem Blog hier und hier. Die Aktivierung von CDI erfolgt, wie beschrieben, mittels beans.xml im WEB-INF Verzeichnis.

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

Primefaces 6:

Hat man erst einmal die JPA 2.2 Entities definiert und mittels JBoss Forge die Beispiel-Webapplikationen für die ausgewählte Frontend-Technologie (Angular JS oder Faces) erzeugt und rebrandet, ist die Migration der Faces Beispiel-Applikation leicht durchführbar und wurde bereits in den vorigen Blog-Einträgen beschrieben.

Die Einbindung der erforderlichen Primefaces-UI-Bibliothek primefaces-6.0.jar erfolgt dabei ganz simpel übers Hinzufügen der entsprechenden Maven Primefaces Dependency in der pom.xml.

<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 Ausprogrammierung der XHTML-Views auf Primefaces sind der Primefaces Showcase und der neue Primefaces 6.0 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.

Aktiviert werden die Primefaces-Tags in der gewünschten XHTML-Seite mittels folgendem Namespace 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 ansonsten nahezu identisch zu den ManagedBeans der MyFaces-Applikationen. 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 jobapplication-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.jobapplication.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.jobapplication.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.jobapplication.view.ViewUtils</function-class>
       <function-signature>
             int count(java.util.Collection)
       </function-signature>
   </function>
               
   <function>
       <function-name>displayShort</function-name>
       <function-class>de.binaris.jobapplication.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.jobapplication.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.jobapplication.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.jobapplication.view.ViewUtils</function-class>
       <function-signature>
             java.util.List listExcludingSelectedOne(java.util.Collection,java.lang.Object)
       </function-signature>
   </function>  
</facelet-taglib>

Hier auch die ViewUtils-Klasse unter Verwendung generischer Typen T und Collections List<T>:

ViewUtils:

package de.binaris.jobapplication.view;
 
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
 
import javax.persistence.Id;
 
/**
* Utilities for working with Java Server Faces views.
*/
public final class ViewUtils {
 
   public static <T> List<T> asList(Collection<T> collection) {
     if (collection == null) {
         return null;
     }
     return new ArrayList<T>(collection);
   }
 
   public static String display(Object object) {
     if (object == null) {
         return null;
     }
     try {
         // Invoke toString if declared in the class. If not found,
         // the NoSuchMethodException is caught and handled
         object.getClass().getDeclaredMethod(“toString“);
         return object.toString();
     }
     catch (NoSuchMethodException noMethodEx) {
         try {
           for (Field field : object.getClass().getDeclaredFields()) {
               // Find the primary key field and display it
               if (field.getAnnotation(Id.class) != null) {
                 // Find a matching getter and invoke it to display the key
                 for (Method method : object.getClass().getDeclaredMethods()) {
                     if (method.equals(new PropertyDescriptor(field.getName(),                    
                                         object.getClass()).getReadMethod()))
                     {
                       return method.invoke(object).toString();
                     }
                 }
               }
           }
           for (Method method : object.getClass().getDeclaredMethods()) {
               // Find the primary key as a property instead of a field, and display it
               if (method.getAnnotation(Id.class) != null) {
                 return method.invoke(object).toString();
               }
           }
         } catch (Exception ex) {
           // Unlikely, but abort and stop view generation if any exception is thrown
           throw new RuntimeException(ex);
         }
     }
     return null;
   }
 
   public static <T> int count(Collection<T> collection) {
     if (collection == null) {
               return 0;
     }
     return collection.size();
   }
 
   public static String displayRange(Object object1, Object object2) {
     String text1 = display(object1);
     String text2 = display(object2);
      if (text1 == null || text2 == null
          || text1.trim() == null || text2.trim() == null) {
           return null;
      }
     return (text1 + “-“ + text2);
   }
               
   public static String displayFirst(Object object) {
     String text = display(object);
      if (text == null || text.split(“\\s+“) == null
          || text.split(“\\s+“)[0] == null) {
           return null;
      }
     return (text.split(“\\s+“)[0] + “…“);
   }
 
   public static String displayShort(Object object, int length) {
     String text = display(object);
      if (text == null || text.split(“[‚.‘]“) == null
           || text.split(“[‚.‘]“)[0] == null) {
           return null;
      }
     String[] elements = text.split(“[‚.‘]“);
     String result = ““;
      if (text.length() < length) {
         return text;
      } else {
         result = text.substring(0,length-4) + „…“;
         return result;
      }
   }

   public static <T> List<T> listExcludingSelectedOne(Collection<T> collection, T selected) {
     if (collection == null) {
         return null;
     }
     if (selected == null) {
       return new ArrayList<T>(collection);
     }
     List<T> list = new ArrayList<T>(collection);
     list.remove(selected);
     return list;
   }
 
   private ViewUtils() {
     // Can never be called, only by getInstance – Singleton pattern
   }

   public static ViewUtils getInstance() {
      return new ViewUtils();
   }
}

Über Tags, TagLibs und die Erweiterung bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und 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 jobapplication-primefaces.war im /target-Unterverzeichnissen des Projekts jobapplication-primefaces.

Als zusätzliche Abhängigkeiten für den FileUpload wurden sicherheitshalber auch die im Primefaces Users Guide genannten folgenden optionalen Apache Bibliotheken (commons) für den FileUpload hinzugefügt:

commons-fileupload 1.3
commons-io 2.2

Um optional einen FileUploadFilter zu aktivieren, wurden zusätzlich zu seiner Deklaration in der web.xml auch die Methoden doFilter(…) und init(FilterConfig) überschrieben. Hier die web.xml:

<?xml version=“1.0″ encoding=“UTF-8″ standalone=“no“?>
<web-app xmlns=“http://java.sun.com/xml/ns/javaee“ xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance“ version=“3.0″ xsi:schemaLocation=“http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd“>
  <display-name>HR Job Application</display-name>
  <filter>
    <filter-name>FileUploadFilter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
    <init-param>
       <param-name>thresholdSize</param-name>
       <param-value>8000000</param-value>
    </init-param>
    <init-param>
       <param-name>uploadDirectory</param-name>
       <param-value>/Temp</param-value>
    </init-param>
  </filter>
  <session-config>
      <session-timeout>30</session-timeout>
  </session-config>
  <servlet>
    <servlet-name>javax.ws.rs.core.Application</servlet-name>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>javax.ws.rs.core.Application</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
  <error-page>
    <error-code>404</error-code>
    <location>/faces/error.xhtml</location>
  </error-page>
  <error-page>
    <error-code>500</error-code>
    <location>/faces/error.xhtml</location>
  </error-page>
  <context-param>
    <param-name>

  javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE

</param-name>
    <param-value>true</param-value>
  </context-param>
</web-app>

Ein Hinweis zur web.xml und dem Parameter threshold. Wenn der Upload-Inhalt größer als der angegebene threshold ist, wird die Datei automatisch im genannten Upload-Verzeichnis gespeichert, weshalb hier ein entsprechend großer Wert zu wählen ist.

Noch ein Hinweis zur Speicherung der hochgeladenen PDF- oder Bild-Dateien in der MySQL. Wenn man beim Klick auf die “Step 3 Speichern“-Schaltfläche und der anschließenden Ausführung der update()-Methode der FileUploadBean-EJB den folgenden LogFile-Eintrag über eine com.mysql.jdbc.PacketTooBigException bekommt, kann in der MySQL-Konfigurationsdatei das Attribut max_allowed_packet = 16M gesetzt werden. Danach ist die MySQL-Datenbank neu zu starten, oder man setzt das Attibut nur temporär über die Kommandozeile: mysql> SET GLOBAL max_allowed_packet=16M. Dabei ist das Limit für max_allowed_packet 1GB, was einer Deklaration von max_allowed_packet=1G entspricht. Danach wird die FileUpload-Entity auch in der file_upload InnoDb-Tabelle der MySQL-Datenbank jobapplication gespeichert. Die Columns zum Speichern eines Bildes oder PDFs in der Datenbank-Tabelle file_upload sollten anstatt mit dem Typ BLOB mit dem Datentyp MEDIUMBLOB definiert werden, welcher Dateien der max. Größe 16MB aufnehmen kann.

Konfiguration des JBoss WildFly Application Servers:

Die Konfiguration des JBoss WildFly Application Servers 10 Final erfolgt analog der Konfigurationen der JBoss Application Server WildFly 8.1, 8.2 und 9 Final und betrifft die Datasource, das Logging und den Connection Pool und ist, genau wie die Test-Frameworks und die Aktivierung der RESTful WebService-Schnittstelle in diesem Blog-Eintrag hier und in vorigen Blog-Einträgen bereits beschrieben. Wie die MySQL-Datenbank Inno DB 5.x zu konfigurieren ist, wurde in einem bereits vorhandenen Blog-Eintrag hier bereits beschrieben.

Die Primefaces Beispiel-Applikation arbeitet über die RESTful WebService-Schnittstelle auf der MySQL-InnoDB. Für die Primefaces Beispiel-Applikationen kann folgendes mit HeidiSQL erstellte MySQL 5.x Datenbank-Skript verwendet werden. Hier auch die Datasource Definition:

<datasource jndi-name=“java:jboss/datasources/JobapplicationDatasource“ pool-name=“JobapplicationDS“ enabled=“true“>
                    <connection-url>jdbc:mysql://localhost:3306/jobapplication</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>

Die Hibernate-Konfiguration des WildFly Servers ist ebenfalls leicht durchführbar und wurde bereits in einem Blog-Eintrag in diesem Blog hier beschrieben.

Die fertige Beispiel-Applikation jobapplication-primefaces kann leicht selbst deployt werden und wird diesmal nicht auf dem Test-Server deployt, um den Eindruck zu vermeiden, man könnte sich darüber real bewerben. Aus demselben Grund wurden in der Beispiel-Applikation auch das Firmen-Logo durch ein neutrales Emblem ersetzt und der Link auf binaris.de entfernt. Denn bei Binaris Informatik bewirbt man sich nach wie vor am besten hier.

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

“TDD mit Java”

hier und hier von Binaris Informatik ebenfalls positiv erwähnt werden.

Hier die Beispiel-Projekte für die Entwicklungsumgebungen JBoss Developer Studio und intelliJ 15:

JBoss Developer Studio Projekt:

jobapplication-primefaces

intelliJ Projekt:

jobapplication-primefaces

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. Über die Konfiguration von Hibernate, der Datasource und der MySQL 5.x Datenbank für den WildFly 9 und den WildFly 10 gibt es hier mehr Informationen in diesem Blog.

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, damit dieser auf das tatsächliche JDK 8-Verzeichnis des Server-Systems zeigt.

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

– eine leere Textdatei namens jobapplication-primefaces.war.dodeploy speichen und
– das Archiv jobapplication-primefaces.war aus dem jobapplication-primefaces/target-Verzeichnis speichern

Ein Hinweis zum FileUpload mit Angular JS: Der FileUpload geht, z. B. gecroppt, ebenfalls mit Angular JS, was auch in eimem der nächsten Blog-Einträge thematisiert werden wird. Hier schonmal ein Croppie-Beispiel (Basis-Projekt) unter Verwendung von zusätzlichen angularjs und file-upload Javascript-Dateien, welches gerne ausgebaut werden kann.

Wie man sieht, macht es viel Freude, JEE-Applikationen mit der vorteilhaften Primefaces-Technologie zu entwickeln und ebenfalls, zuvor die Faces-Beispielapplikationen mittels JBoss Forge auf dem Datenmodell zu erzeugen und weiterzuentwickeln.

Es ist also sehr wahrscheinlich, dass noch weitere Blog-Einträge zu Webframeworks wie Primefaces, Angular JS und Faces und den die JEE-Spezifikation implementierenden 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, fröhliche und verantwortungsvolle Karnevals-Session.

WebApps – JSF 2, RichFaces 4, Primefaces 6, REST, JPA 2, EJB 3, JEE7, JBoss WildFly

Samstag, 28. Januar 2017 von  
unter Fachartikel Architektur

Die Motivation

Über die Migration von JBoss RichFaces Beispiel-Applikationen auf die sehr vorteilhafte Primefaces 6-Technologie gibt es bereits Blog-Einträge in diesem Blog hier. In diesem Blog-Eintrag soll nun passend zum Datenmodell des vorigen Blog-Eintrags mit der Angular JS Beispiel-Applikation restaurantguide-angularjs eine Primefaces 6 Beispiel-Webapplikation restaurantguide-primefaces erstellt werden. Dabei werden als Basis-Frontendtechnologien JSF 2 und Primefaces 6 verwendet. Weiterhin wird der Einsatz moderner Tag-Libs in den XHTML-Seiten der JEE7-Applikation erklärt.

Über die JSF Technologie gibt es bereits einen Blog-Eintrag in diesem Blog hier, worin die Generierung einer JSF 1.2-Applikation auf Basis der JPA-Entities für den JPA-Provider EclipseLink mittels der NetBeans IDE für das Deployment auf dem GlassFish 3 Application Server erklärt wurde. Die in diesem Blog-Eintrag hier mittels JBoss Forge Eclipse PlugIn erstellte Applikation restaurantguide-angularjs wurde auf dem Datenmodell mit den JPA 2 Entities erstellt, und es wird eine weitere Primefaces 6 Beispiel-Applikation restaurantguide-primefaces entwickelt, unter Einsatz von JSF 2 und der robusten und elegant gestylten, etablierten, optimalen Primefaces Frontend-Technologie.

Die Beispiel-Applikation restaurantguide-primefaces wird dann auf den JBoss WildFly 9 Final und JBoss WildFly 10 Final Application Servern deployt und kann hier getestet werden. Die Verwendung der JBoss WildFly JEE7-Application Server wurde in diesem Blog-Eintrag hier 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 die benötigten Daten zur Präsentation und Bearbeitung (Änderung, Löschen, Neuanlage) in den Web-Frontends, welche die WebServices konsumieren (ServiceConsumer-Pattern). Der JPA-Provider ist dabei Hibernate von JBoss, welches auf dem WildFly zu konfigurieren ist.

Erstellung der Beispiel Applikation aus dem Datenmodell

Wie die Applikationen restaurantguide-primefaces und restaurantguide-angularjs mittels JBoss Forge erstellt werden können, ist bereits analog in diesem Blog-Eintrag hier für die Applikationen recipeadmin-primefaces und recipeadmin-angularjs beschrieben worden, und wie in der pom.xml des jeweiligen Beispielprojekts nach erfolgtem Download erkennbar ist, wurden auch in den Applikationen restaurantguide-primefaces und restaurantguide-angularjs die folgenden JEE 7 Artefakte für den JBoss WildFly 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

Einsatz von CDI

Über CDI und JavaEE gibt es bereits Blog-Einträge in diesem Blog hier und hier. Die Aktivierung von CDI erfolgt, wie beschrieben, mittels beans.xml im WEB-INF Verzeichnis.

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

Primefaces 6:

Hat man erst einmal die JPA 2.2 Entities definiert und mittels JBoss Forge die Beispiel-Webapplikationen für die ausgewählte Frontend-Technologie (Angular JS oder Faces) erzeugt und rebrandet, ist die Migration der Faces Beispiel-Applikation leicht durchführbar und wurde bereits in den vorigen Blog-Einträgen beschrieben.

Die Einbindung der erforderlichen Primefaces-UI-Bibliothek primefaces-6.0.jar erfolgt dabei ganz simpel übers Hinzufügen der entsprechenden Maven Primefaces Dependency in der pom.xml.

    <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 XHTML-Views von MyFaces auf Primefaces sind der Primefaces Showcase und der neue Primefaces 6.0 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.

Aktiviert werden die Primefaces-Tags in der gewünschten XHTML-Seite mittels folgendem Namespace 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 ansonsten nahezu identisch zu den ManagedBeans der MyFaces-Applikationen. 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

Auf einige Details, die bei der Migration von RichFaces auf Primefaces zu berücksichtigen sind, soll kurz eingegangen werden:

Die folgenden RichFaces Dependencies sind nicht mehr erforderlich und können aus der Maven pom.xml entfernt und durch die oben angegebene Primefaces 6.0-Dependency ersetzt werden:

<dependencyManagement>
   <dependencies>
     <dependency>
       <groupId>org.richfaces</groupId>
       <artifactId>richfaces-bom</artifactId>
       <version>4.3.5.Final</version>
       <type>pom</type>
       <scope>import</scope>
     </dependency>
   </dependencies>
</dependencyManagement>
[…]
<!– https://mvnrepository.com/artifact/org.richfaces/richfaces –>
<dependency>
   <groupId>org.richfaces.ui</groupId>
   <artifactId>richfaces-components-ui</artifactId>
</dependency>
<dependency>
   <groupId>org.richfaces.core</groupId>
   <artifactId>richfaces-core-impl</artifactId>
</dependency>

Das Theming und Skinning der RichFaces-View in der web.xml

<context-param>
   <param-name>org.richfaces.core</param-name>
   <param-value>skin_name</param-value>
</context-param>

kann optional durch folgendes Primefaces-Theme ersetzt werden, oder ganz entfallen:

<context-param>
   <param-name>primefaces.THEME</param-name>
   <param-value>theme_name</param-value>
</context-param>

Ajax Tags:

Alle Ajax-verwendenden RichFaces-Komponenten nutzen Attribute zur Definition der abschließend zu rendernden Komponente und der Ausführung von Methoden innerhalb des partiellen Requests, z. B. wie der folgende Action Button, welcher nur die Felder einer bestimmten ID im Request auf den Click Event an die Backing Bean übermittelt und nur ein bestimmtes Element der .xhtml-View nach der Ausführung der genannten Action Methode rendert, wenn das execute-Attribut überschrieben wird, anstatt bei Fehlen des Attributs den execute=“@form“ Default zu verwenden.

<a4j:commandButton render=“selectMenuId“ execute=“@this“
                     action=“#{userBean.handleChanges}“ />

In PrimeFaces, welches nicht das JSF2 Default Naming für diese zwei Attribute verwendet, wird statt render das update-Attribut verwendet und anstatt execute das process-Attribut, somit lautet der Code nach der Migration:

<p:commandButton update=”outputTextId” process=”@this”
                     actionListener=”#{userBean.handleChanges}” />

Der p:commandButton bietet die Möglichkeit anstatt bei Fehlen des Attributs und dem Default Verhalten (ajax=”true”) stattdessen Nicht-Ajax Verhalten mittels den Attribut-Kombinationen immediate=“true“ und ajax=“false“ zu konfigurieren.

Javascript Functions in JSF Ajax Calls verwenden:

Das RichFaces-Tag a4j:jsFunction, ermöglicht das Ausführen von Ajax Requests direkt von JavaScript aus, um mittels der Ajax-Requests Daten vom Server zu holen und z. B. als JSON Format in der Response zurückzugeben, um diese dann im Client-seitigen JavaScript Call weiterzuverwenden.

Dies ermöglicht den Bind einer Action oder eines Action Listeners (z. B. ValueChangeListener für den Event Change) und das abschießende erneute partielle Rendering, wie bei jeder anderen Ajax-Komponente auch.

Das entspechende PrimeFaces-Tag ist p:remoteCommand und bietet dieselbe Funktionalität, wenn auch mit anderen Attributnamen.

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 restaurantguide-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.restaurantguide.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.restaurantguide.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.restaurantguide.view.ViewUtils</function-class>
       <function-signature>
             int count(java.util.Collection)
       </function-signature>
   </function>
               
   <function>
       <function-name>displayShort</function-name>
       <function-class>de.binaris.restaurantguide.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.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.restaurantguide.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.restaurantguide.view.ViewUtils</function-class>
       <function-signature>
             java.util.List listExcludingSelectedOne(java.util.Collection,java.lang.Object)
       </function-signature>
   </function>  
</facelet-taglib>

Hier auch die ViewUtils-Klasse unter Verwendung generischer Typen T und Collections List<T>:

ViewUtils:

package de.binaris.restaurantguide.view;
 
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
 
import javax.persistence.Id;
 
/**
* Utilities for working with Java Server Faces views.
*/
public final class ViewUtils {
 
   public static <T> List<T> asList(Collection<T> collection) {
     if (collection == null) {
         return null;
     }
     return new ArrayList<T>(collection);
   }
 
   public static String display(Object object) {
     if (object == null) {
         return null;
     }
     try {
         // Invoke toString if declared in the class. If not found,
         // the NoSuchMethodException is caught and handled
         object.getClass().getDeclaredMethod(“toString“);
         return object.toString();
     }
     catch (NoSuchMethodException noMethodEx) {
         try {
           for (Field field : object.getClass().getDeclaredFields()) {
               // Find the primary key field and display it
               if (field.getAnnotation(Id.class) != null) {
                 // Find a matching getter and invoke it to display the key
                 for (Method method : object.getClass().getDeclaredMethods()) {
                     if (method.equals(new PropertyDescriptor(field.getName(),                    
                                         object.getClass()).getReadMethod()))
                     {
                       return method.invoke(object).toString();
                     }
                 }
               }
           }
           for (Method method : object.getClass().getDeclaredMethods()) {
               // Find the primary key as a property instead of a field, and display it
               if (method.getAnnotation(Id.class) != null) {
                 return method.invoke(object).toString();
               }
           }
         } catch (Exception ex) {
           // Unlikely, but abort and stop view generation if any exception is thrown
           throw new RuntimeException(ex);
         }
     }
     return null;
   }
 
   public static <T> int count(Collection<T> collection) {
     if (collection == null) {
               return 0;
     }
     return collection.size();
   }
 
   public static String displayRange(Object object1, Object object2) {
     String text1 = display(object1);
     String text2 = display(object2);
      if (text1 == null || text2 == null
          || text1.trim() == null || text2.trim() == null) {
           return null;
      }
     return (text1 + “-“ + text2);
   }
               
   public static String displayFirst(Object object) {
     String text = display(object);
      if (text == null || text.split(“\\s+“) == null
          || text.split(“\\s+“)[0] == null) {
           return null;
      }
     return (text.split(“\\s+“)[0] + “…“);
   }
 
   public static String displayShort(Object object, int length) {
     String text = display(object);
      if (text == null || text.split(“\\s+“) == null
           || text.split(“\\s+“)[0] == null) {
           return null;
      }
     String[] elements = text.split(“\\s+“);
     String result = ““;
      int i = 0;
      while ((result+elements[i]).length() < length) {
          result += elements[i] + “ “;
          i++;
      }
      return (result.trim() + “…“);
   }

   public static <T> List<T> listExcludingSelectedOne(Collection<T> collection, T selected) {
     if (collection == null) {
         return null;
     }
     if (selected == null) {
       return new ArrayList<T>(collection);
     }
     List<T> list = new ArrayList<T>(collection);
     list.remove(selected);
     return list;
   }
 
   private ViewUtils() {
     // Can never be called, only by getInstance – Singleton pattern
   }

   public static ViewUtils getInstance() {
      return new ViewUtils();
   }
}

Über Tags, TagLibs und die Erweiterung bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und 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 folgenden 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 restaurantguide-primefaces.war im /target-Unterverzeichnissen des Projekts restaurantguide-primefaces.

JSF Komponenten aus Javascript aufrufen:

Sowohl PrimeFaces als auch RichFaces haben eine JavaScript-Schnittstelle für ihre JSF Komponenten. Dadurch kann auf dem Laufzeit-Objekt einer Komponente im DOM eine JavaScript Function aufgerufen werden.

RichFaces bietet die Function rich:component(‘ID’), um das JavaScript Object einer RichFaces Komponente der genannten ID zu erhalten und auf diesem JavaScript-Functions aufzurufen:

<h:outputLink value=“#“ onclick=“#{rich:component(‚popup‘)}.hide(); return false;“>
        Confirmation Dialog
</h:outputLink>
<rich:popup id=”popup”>…</rich:popup>

Hierbei is ‚popup‘ die ID der rich:popup Komponente innerhalb derselben View oder SubView.

Bei PrimeFaces wird das JavaScript Object einer Komponente per Defintion in dem widgetVar Tag Attribute erhältlich:

<h:outputLink value=“#“ onclick=”confirmationDialog.hide(); return false;“>
        Confirmation Dialog
</h:outputLink>
<p:dialog id=”basicDialog” widgetVar=”confimationDialog”>…</p:dialog>

Verwendung der Client ID einer Komponente (EL Extensions):

In JSF werden mit Client-IDs die generierten IDs der HTML Elemente bezeichnet. Diese ID wird oft verwendet, wenn per JavaScript (z. B. in jQuery) ein Element referenziert wird. In RichFaces gibt es hierfür die rich:clientId(‘id’) Function.

In PrimeFaces geht dies mit der p:component(‘id’) Function, die syntaktisch der RichFaces rich:component Function ähnelt:

// RichFaces:
<h:form id=“form1″>
    <h:button id=“infoButton1″ value=“Info“ />
    
    // returns ‘form1:infoButton1′:
    <h:outputText value=“RichFaces: client ID : #{rich:clientId(‚infoButton‘)}“ />
</h:form>

// PrimeFaces:
<h:form id=“form2″>
    <h:button id=“infoButton2″ value=“Info“ />
    
    // returns ‘form2:infoButton2′:
    <h:outputText value=“PrimeFaces: client ID : #{p:component(‚infoButton‘)}“ />
</h:form>

Verwendung von jQuery:

Bei der Verwendung von jQuery mit JSF ist zu beachten, dass das Default JSF ID Trennzeichen (‘:’) escaped werden muss, da es in jQuery für Selektoren reserviert ist:

$(‘#formPerson:part1:inputFirstname’)

wird also in RichFaces zu

$(‘#formPerson\\:part1\\:inputFirstname’)

PrimeFaces bietet hierfür die PrimeFaces.escapeClientId(clientId) Function um die client ID zu escapen. Somit würde der jQuery-Selektor folgendermaßen lauten:

$(PrimeFaces.escapeClientId(‘#formPerson:part1:inputFirstname’))

Komponenten über Client IDs referenzieren:

Bei der Migration von RichFaces auf PrimeFaces, tritt der Fall auf, dass Komponenten, die über ihre ID referenziert werden, um Attribute zu übermitteln oder zu aktualisieren, nicht mehr gefunden weden. Dies liegt an dem leicht unterschiedlichen Komponenten-Suchalgorithmus, welcher beachtet werden muss. Um Komponenten über ihre Client-ID zu finden, verwendet PrimeFaces ebenfalls den Standard JSF Algorithmus, wie er im Funktionen-Aufruf UIComponent#findComponent() verwendet wird.

RichFaces verwendet den selben Algorithmus, allerdings mit Erweiterungen, wodurch relative Komponenten-IDs nicht nur im übergeordneten Container, sondern auch in der gesamten Composite-View gesucht und gefunden werden. Das bedeutet, dass bei der Migration von RichFaces auf PrimeFaces diese Client IDs angepasst werden müssen, damit sie über den Standard Algorithmus gefunden werden können.

Konfiguration des JBoss WildFly Application Servers:

Die Konfiguration des JBoss WildFly Application Servers 10 Final erfolgt analog der Konfigurationen der JBoss Application Server WildFly 8.1, 8.2 und 9 Final und betrifft die Datasource, das Logging und den Connection Pool und ist, genau wie die Test-Frameworks und die Aktivierung der RESTful WebService-Schnittstelle in diesem Blog-Eintrag hier und in vorigen Blog-Einträgen bereits beschrieben. Wie die MySQL-Datenbank Inno DB 5.x zu konfigurieren ist, wurde in einem bereits vorhandenen Blog-Eintrag hier bereits beschrieben.

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

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

Die WildFly10 module.xml für die Hibernate-Konfiguration kann hier angesehen werden.

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

“TDD mit Java”

hier und hier von Binaris Informatik ebenfalls positiv erwähnt werden.

Die Primefaces Beispiel-Applikation arbeitet über die RESTful WebService-Schnittstelle auf derselben Datenbank, wie die AngularJS Beispiel-Applikation restaurantguide-angularjs, weshalb für die Primefaces Beispiel-Applikationen dasselbe mit HeidiSQL erstellte MySQL 5.x Datenbank-Skript verwendet werden kann.

Die fertige Beispiel-Applikation restaurantguide-primefaces kann hier betrachtet werden.

Hier die Beispiel-Projekte für die Entwicklungsumgebungen JBoss Developer Studio und intelliJ 15:

JBoss Developer Studio Projekt:

restaurantguide-primefaces

intelliJ Projekt:

restaurantguide-primefaces

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. Über die Konfiguration von Hibernate, der Datasource und der MySQL 5.x Datenbank für den WildFly 9 und den WildFly 10 gibt es hier mehr Informationen in diesem Blog.

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, damit dieser auf das tatsächliche JDK 8-Verzeichnis des Server-Systems zeigt.

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

– eine leere Textdatei namens restaurantguide-primefaces.war.dodeploy speichen und
– das Archiv restaurantguide-primefaces.war aus dem restaurantguide-primefaces/target-Verzeichnis speichern

Wie man sieht, macht es viel Freude, die XHTML-Views der beschriebenen Beispiel-Applikation RichFaces oder MyFaces auf die vorteilhafte Primefaces-Technologie umzustellen und ebenfalls, zuvor die Angular JS und Faces-Beispielapplikationen mittels JBoss Forge auf dem Datenmodell zu erzeugen und weiterzuentwickeln.

Es ist also sehr wahrscheinlich, dass noch weitere Blog-Einträge zu Webframeworks wie Primefaces, Angular JS und Faces und den die JEE-Spezifikation implementierenden 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, fröhliche und verantwortungsvolle Karnevals-Session.

WebApps – Generativ mit Angular JS, REST, JEE7, Java 8 auf JBoss WildFly 9 und 10

Donnerstag, 29. Dezember 2016 von  
unter Fachartikel Architektur

Die Motivation

Im Blog-Eintrag über WebApps – vom Modell zur App, mit JSF 2.2, Angular JS, REST, JPA 2 hier wurde beschrieben, wie leicht es ist, von einem Klassen-Diagramm (UML), genauer: Entity-Relationship-Diagramm hier, auch E-R Diagramm genannt, zu einer JEE7-Applikation zu kommen. Diese JEE6- und JEE7-Beispielapplikationen hier liefern 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).

Die Beispiel-Applikation restaurantguide-angularjs wird dann auf dem neusten JBoss WildFly 10 Final Server (entspricht dem neuen JBoss EAP 7-Server) deployt. Dabei ist die Verwendung der beiden neuen JBoss WildFly JEE7-Application Server in diesem Blog-Eintrag hier und die Konfiguration verschiedener Datenbanken in diesem Blog hier bereits beschrieben worden.

Das Durchsuchen, und die Nutzung einer Pagination der Ergebnisliste ist ebenfalls in der Beispiel-App enthalten, wie auch mit Hilfe des Angular JS Frameworks und des Bootstrap-Frameworks eine dynamische Benutzeroberfläche, die sich an beliebige Auflösungen und Display-Größen responsiv anpasst.

Die UI Frameworks

a) jQuery oder Angular JS

Die oft hierüber geführte Diskussion ist inzwischen eigentlich obsolet geworden, da es meiner Erfahrung nach eher unproblematisch ist, beide JavaScript-Frameworks in derselben Browser-Applikation zu verwenden und solange man nicht versucht, beide Frameworks auf ein und demselben HTML-Element anzuwenden, kommen diese sich auch weder bei der Event-Triggerung noch beim Event-Handling in die Quere. Hier ist ein funktionierendes Beispiel dazu mit einem jQuery-Accordion und jQuery-Carousel auf der Startseite und zusätzlich einer verlinkten Angular JS Such-Applikation im Events Header-Menü.

b) RichFaces oder Primefaces

Auch diese beiden Frameworks können parallel in einer .xhtml-Seite verwendet werden. Somit könnte eine RichFaces-richDataTable auch ein Element eines Primefaces-rating enthalten, was aber anhand der Primefaces-Beispielapplikation restaurantguide-primefaces im Bezug auf die Bewertung eines Restaurants im nächsten Blog-Eintrag gesondert besprochen werden soll.

Erstellung der Beispiel Applikation aus dem Datenmodell

Mittels Eclipse-PlugIn Umlet wird das Klassendiagramm der Entities und Datenbank-Objekte erstellt und aus diesem, nach dem Anlegen der Datenbank restaurantguide per Hibernate Envers während dem WildFly 10 Undertow Deployment mittels JBoss Forge PlugIn im JBoss Developer Studio erst der REST-WebService mit den Endpoints generiert und danach die Angular JS WebApp auf diesem RESTful WebService.

Maven JEE 7 JBoss-Artefakte und Maven Dependencies

Dabei werden in der pom.xml die folgenden Maven Dependencies verwendet und es soll nicht vergessen werden, dass die heute in Java 8 enthaltenen javax.ws.rs REST-Packages ohne die bereits vor vielen Jahren erfolgte sehr gute Vorarbeit der Entwickler des jboss-resteasy REST-Frameworks wohl in der heutigen Form noch nicht im JDK vorhanden wären. Danke, JBoss Rockstars!

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

Einsatz von CDI

Und ebenfalls die CDI 1.1 Dependency:

– cdi-api_1.1

Über CDI und JavaEE gibt es bereits Blog-Einträge in diesem Blog hier und hier. Die Aktivierung von CDI erfolgt, wie beschrieben, mittels beans.xml im WEB-INF Verzeichnis.

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

Die Konfiguration des JBoss WildFly Application Servers 10 Final erfolgt analog der Konfigurationen der JBoss Application Server WildFly 8.1, 8.2 und 9 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, in diesem Blog-Eintrag hier und diesem Blog-Eintrag hier bereits beschrieben.

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

“TDD mit Java”

hier und hier von Binaris Informatik erwähnt werden.

Hier auch die /META-INF/persistence.xml der Beispiel-Applikation:

    <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=“RestaurantguidePU“>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>
    java:jboss/datasources/RestaurantguideDatasource
    </jta-data-source>
    <properties>
    <property name=“hibernate.hbm2ddl.auto“ value=“none“/>
    <property name=“hibernate.show_sql“ value=“false“/>
    </properties>
    </persistence-unit>
    </persistence>

Zum Erzeugen der Datenbank wird das folgende Property gesetzt:

<property name=“hibernate.hbm2ddl.auto“ value=“create-drop“/>

Damit die Datenbank danach nicht bei jedem Server-Neustart gelöscht und neuangelegt wird, wurde das Property “hibernate.hbm2ddl.auto“ danach auf den unwirksamen Wert “none“ gesetzt.

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

    <datasource jndi-name=“java:jboss/datasources/RestaurantguideDatasource“ pool-name=“RestaurantguideDS“
    enabled=“true“>
    <connection-url>jdbc:mysql://localhost:3306/restaurantguide</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>

Die fertige Beispiel-Applikation restaurantguide-angularjs kann zusammen mit den anderen Beispiel-Applikationen hier betrachtet werden.

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

restaurantguide-angularjs

Und hier das intelliJ Projekt:

restaurantguide-angularjs

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, damit dieser auf das tatsächliche JDK 8-Verzeichnis des Server-Systems zeigt.

Die Angular JS Beispiel-Applikation dieses Blog-Eintrags kann danach selbst erneut deployt werden, ohne den bereits gestarteten WildFly 10 Application Server überhaupt stoppen oder erneut starten zu müssen. Bei laufendem Server einfach ins Server-Unterverzeichnis /standalone/deployments

– eine leere Textdatei namens restaurantguide-angularjs.war.dodeploy speichen und
– das Archiv logisticsadmin-angularjs.war aus dem restaurantguide-angularjs/target-Verzeichnis speichern

Sofort wird die Beispiel-Applikation deployt und in wenigen Sekunden gestartet und kann aufgerufen werden:

http://localhost:8080/restaurantguide-angularjs

Wie man sieht, macht es einfach Spaß, die responsiven Angular JS-Beispielapplikationen mittels JBoss Forge auf dem Datenmodell zu erzeugen und für die Umsetzung der Anforderungen weiterzuentwickeln.

Es besteht also durchaus die Möglichkeit, dass noch weitere Blog-Einträge zu Webframeworks wie Angular JS und Bootstrap auf 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 weiterhin viel Spaß beim Silvesterfeiern und viel Erfolg im neuen Jahr 2017.

WebApps – RESTful mit JSF 2, Primefaces 6, JPA 2, EJB 3, JEE7, Java 8 auf JBoss WildFly

Sonntag, 27. November 2016 von  
unter Fachartikel Architektur

Die Motivation

Über die Migration von RichFaces und MyFaces Beispiel-Applikationen auf die sehr vorteilhafte Primefaces 6-Technologie gibt es bereits Blog-Einträge in diesem Blog hier. In diesem Blog-Eintrag soll nun passend zum Datenmodell des vorigen Blog-Eintrags mit der Angular JS Beispiel-Applikation eine Primefaces 6 Beispiel-Webapplikation erstellt werden. Dabei werden als Basis-Frontendtechnologien JSF 2 und Primefaces 6 verwendet. Weiterhin wird der Einsatz moderner Tag-Libs in den XHTML-Seiten der JEE7-Applikation erklärt.

Über die JSF Technologie gibt es bereits einen Blog-Eintrag in diesem Blog hier, worin die Generierung einer JSF 1.2-Applikation auf Basis der JPA-Entities für den JPA-Provider EclipseLink mittels der NetBeans IDE für das Deployment auf dem GlassFish 3 Application Server erklärt wurde. Die in diesem Blog-Eintrag hier mittels JBoss Forge Eclipse PlugIn erstellte Applikation partyadmin-angularjs wurde auf dem Datenmodell mit den JPA 2 Entities erstellt, und es wird eine weitere Primefaces 6 Beispiel-Applikation partyadmin-primefaces entwickelt, unter Einsatz der robusten und elegant gestylten, etablierten, optimalen Primefaces Frontend-Technologie.

Die Beispiel-Applikation partyadmin-primefaces wird dann auf den neuen JBoss WildFly 9 Final und JBoss WildFly 10 Final Test-Servern deployt und kann hier getestet werden. Die Verwendung der beiden neuen JBoss WildFly JEE7-Application Server wurde in diesem Blog-Eintrag hier 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 aus dem Datenmodell

Wie die Applikationen partyadmin-primefaces und partyadmin-angularjs mittels JBoss Forge erstellt werden können, ist bereits analog in diesem Blog-Eintrag hier für die Applikationen recipeadmin-primefaces und recipeadmin-angularjs beschrieben worden, und wie in der pom.xml des jeweiligen Beispielprojekts nach erfolgtem Download erkennbar ist, wurden auch in den Applikationen partyadmin-primefaces und partyadmin-angularjs die folgenden JEE 7 Artefakte für den JBoss WildFly 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

Einsatz von CDI

Über CDI und JavaEE gibt es bereits Blog-Einträge in diesem Blog hier und hier. Die Aktivierung von CDI erfolgt, wie beschrieben, mittels beans.xml im WEB-INF Verzeichnis.

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

Primefaces 6:

Hat man erst einmal die JPA 2.2 Entities definiert und mittels JBoss Forge die Beispiel-Webapplikationen für die ausgewählte Frontend-Technologie (Angular JS oder Faces) erzeugt und rebrandet, ist die Migration der Faces Beispiel-Applikation leicht durchführbar und wurde bereits in den vorigen Blog-Einträgen beschrieben.

Die Einbindung der erforderlichen Primefaces-UI-Bibliothek primefaces-6.0.jar erfolgt dabei ganz simpel übers Hinzufügen der entsprechenden Maven Primefaces Dependency in der pom.xml.

    <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 XHTML-Views von MyFaces auf Primefaces sind der Primefaces Showcase und der neue Primefaces 6.0 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.

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 ansonsten nahezu identisch zu den ManagedBeans der MyFaces-Applikationen. 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 partyadmin-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.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.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.view.ViewUtils</function-class>
       <function-signature>
             int count(java.util.Collection)
       </function-signature>
   </function>
               
   <function>
       <function-name>displayShort</function-name>
       <function-class>de.binaris.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.view.ViewUtils</function-class>
       <function-signature>
             java.lang.String displayRange(java.lang.Object,java.lang.Object)
       </function-signature>
   </function>

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

Hier auch die ViewUtils-Klasse unter Verwendung generischer Typen T und Collections List<T>:

ViewUtils:

package de.binaris. view;
 
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
 
import javax.persistence.Id;
 
/**
* Utilities for working with Java Server Faces views.
*/
public final class ViewUtils {
 
   public static <T> List<T> asList(Collection<T> collection) {
     if (collection == null) {
         return null;
     }
     return new ArrayList<T>(collection);
   }
 
   public static String display(Object object) {
     if (object == null) {
         return null;
     }
     try {
         // Invoke toString if declared in the class. If not found,
         // the NoSuchMethodException is caught and handled
         object.getClass().getDeclaredMethod(“toString“);
         return object.toString();
     }
     catch (NoSuchMethodException noMethodEx) {
         try {
           for (Field field : object.getClass().getDeclaredFields()) {
               // Find the primary key field and display it
               if (field.getAnnotation(Id.class) != null) {
                 // Find a matching getter and invoke it to display the key
                 for (Method method : object.getClass().getDeclaredMethods()) {
                     if (method.equals(new PropertyDescriptor(field.getName(),                    
                                         object.getClass()).getReadMethod()))
                     {
                       return method.invoke(object).toString();
                     }
                 }
               }
           }
           for (Method method : object.getClass().getDeclaredMethods()) {
               // Find the primary key as a property instead of a field, and display it
               if (method.getAnnotation(Id.class) != null) {
                 return method.invoke(object).toString();
               }
           }
         } catch (Exception ex) {
           // Unlikely, but abort and stop view generation if any exception is thrown
           throw new RuntimeException(ex);
         }
     }
     return null;
   }
 
   public static <T> int count(Collection<T> collection) {
     if (collection == null) {
               return 0;
     }
     return collection.size();
   }
 
   public static String displayRange(Object object1, Object object2) {
     String text1 = display(object1);
     String text2 = display(object2);
      if (text1 == null || text2 == null
          || text1.trim() == null || text2.trim() == null) {
           return null;
      }
     return (text1 + “-“ + text2);
   }
               
   public static String displayFirst(Object object) {
     String text = display(object);
      if (text == null || text.split(“\\s+“) == null
          || text.split(“\\s+“)[0] == null) {
           return null;
      }
     return (text.split(“\\s+“)[0] + “…“);
   }
 
   public static String displayShort(Object object, int length) {
     String text = display(object);
      if (text == null || text.split(“\\s+“) == null
           || text.split(“\\s+“)[0] == null) {
           return null;
      }
     String[] elements = text.split(“\\s+“);
     String result = ““;
      int i = 0;
      while ((result+elements[i]).length() < length) {
          result += elements[i] + “ “;
          i++;
      }
      return (result.trim() + “…“);
   }

   public static <T> List<T> listExcludingSelectedOne(Collection<T> collection, T selected) {
     if (collection == null) {
         return null;
     }
     if (selected == null) {
       return new ArrayList<T>(collection);
     }
     List<T> list = new ArrayList<T>(collection);
     list.remove(selected);
     return list;
   }
 
   private ViewUtils() {
     // Can never be called, only by getInstance – Singleton pattern
   }

   public static ViewUtils getInstance() {
      return new ViewUtils();
   }
}

Über Tags, TagLibs und die Erweiterung bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und 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 functions-Signaturen (als TagLib-Definitionen) im WEB-INF/classes/META-INF-Verzeichnis des classpaths als forge.taglib.xml mit dem 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 partyadmin-primefaces.war im /target-Unterverzeichnissen des Projekts partyadmin-primefaces.

Die Konfiguration des JBoss WildFly Application Servers 10 Final erfolgt analog der Konfigurationen der JBoss Application Server WildFly 8.1, 8.2 und 9 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 in diesem Blog-Eintrag hier und in vorigen Blog-Einträgen bereits beschrieben.

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

“TDD mit Java”

hier und hier von Binaris Informatik ebenfalls positiv erwähnt werden.

Die Primefaces Beispiel-Applikation arbeitet über die RESTful WebService-Schnittstelle auf derselben Datenbank, wie die AngularJS Beispiel-Applikation partyadmin-angularjs, weshalb für die Primefaces Beispiel-Applikationen dasselbe mit HeidiSQL erstellte MySQL 5.x Datenbank-Skript verwendet werden kann.

Die fertige Beispiel-Applikation partyadmin-primefaces kann hier betrachtet werden.

Hier die Beispiel-Projekte für die Entwicklungsumgebungen JBoss Developer Studio und intelliJ 15:

JBoss Developer Studio Projekt:

partyadmin-primefaces

intelliJ Projekt:

partyadmin-primefaces

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. Über die Konfiguration der MySQL 5.x Datenbank für den WildFly 9 und den WildFly 10 gibt es hier mehr Informationen in diesem Blog.

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, damit dieser auf das tatsächliche JDK 8-Verzeichnis des Server-Systems zeigt.

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

– eine leere Textdatei namens partyadmin-primefaces.war.dodeploy speichen und
– das Archiv partyadmin-primefaces.war aus dem partyadmin-primefaces/target-Verzeichnis speichern

Wie man sieht, macht es viel Freude, die XHTML-Views der beschriebenen Beispiel-Applikation RichFaces oder MyFaces auf die vorteilhafte Primefaces-Technologie umzustellen und ebenfalls, zuvor die Angular JS und Faces-Beispielapplikationen mittels JBoss Forge auf dem Datenmodell zu erzeugen und weiterzuentwickeln.

Es besteht also durchaus die Möglichkeit, dass noch weitere Blog-Einträge zu Webframeworks wie Primefaces, Angular JS und Faces und den die JEE7-Spezifikation implementierenden 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 Vorweihnachtszeit, und schonmal ein fröhliches Weihnachtsfest.

WebApps – mit Angular JS, JQuery, REST, JEE7, Java 8, MySQL 5, Postgres 9, auf JBoss WildFly

Samstag, 29. Oktober 2016 von  
unter Fachartikel Architektur

Die Motivation

In dem bereits vorhandenen Blog-Eintrag über WebApps – vom Modell zur App, mit JSF 2.2, Angular JS, REST, JPA 2 hier wurde beschrieben, wie von einem Klassen-Diagramm (UML), genauer: Entity-Relationship-Diagramm, auch E-R Diagramm genannt, eine JEE7-Applikation erstellt werden kann. Diese JEE6- und JEE7-Beispielapplikationen hier liefern mit Hilfe von 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).

Das Durchsuchen, und die Nutzung einer Pagination der Ergebnisliste ist ebenfalls in der Beispiel-App enthalten, wie auch mit Hilfe des Angular JS Frameworks und des Bootstrap-Frameworks eine dynamische Benutzeroberfläche, die sich an beliebige Auflösungen und Display-Größen responsiv anpasst.

Die ausprogrammierte JEE7-Applikation partyadmin-angularjs mit dem Angular JS-Frontend und dem JEE-Backend mit den JPA 2 Entities kann einfach an verschiedene relationale Datenbanken (z. B. MySQL 5.x oder Postgres 9.x) angebunden werden, weshalb auch die benötigten kompletten SQL-Export/-Import-Skripte zur Verfügung gestellt werden.

Die Beispiel-Applikation partyadmin-angularjs wird dann auf dem neusten JBoss WildFly 10 Final Server (entspricht dem neuen JBoss EAP 7-Server) und ebenfalls auf dem JBoss WildFly 9 deployt. Dabei ist die Verwendung dieser beiden neuen JBoss WildFly JEE7-Application Server in diesem Blog-Eintrag hier bereits beschrieben worden.

Erstellung der Beispiel Applikation auf dem Datenmodell

Mittels Eclipse-PlugIn Umlet wird das Klassendiagramm der Entities und Datenbank-Objekte erstellt und aus diesem, 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 Angular JS WebApp auf diesem RESTful WebService. 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”

hier und hier von Binaris Informatik erwähnt werden.

Maven JEE 7 JBoss-Artefakte und Maven Dependencies

Dabei werden in der pom.xml die folgenden Maven Dependencies verwendet:

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

Einsatz von CDI

Und ebenfalls die CDI 1.1 Dependency:

– cdi-api_1.1

Über CDI und JavaEE gibt es bereits Blog-Einträge in diesem Blog hier und hier. Die Aktivierung von CDI erfolgt, wie beschrieben, mittels beans.xml im WEB-INF Verzeichnis.

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

JBoss WildFly 10 Anbindung an Postgres 9 und MySQL 5

Die Konfiguration des JBoss WildFly Application Servers 10 Final erfolgt analog der Konfigurationen der JBoss Application Server WildFly 8.1, 8.2 und 9 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 in diesem Blog-Eintrag hier und vorigen Blog-Einträgen bereits beschrieben. Die Anbindung an die relationalen Datenbanken Postgres 9 und MySQL 5 ist in diesem Blog-Eintrag hier bereits beschrieben.

Je nach verwendeter Datenbank wird in der persistence.xml im Deployment-Paket der Beispiel-App partyadmin-angularjs.war ein anderer Datenbank-Dialekt eingetragen:

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

<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=“PartyadminPU“>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>
java:jboss/datasources/PartyadminDatasource
</jta-data-source>
<properties>
<property name=“hibernate.hbm2ddl.auto“ value=“none“/>
<property name=“hibernate.show_sql“ value=“false“/>
</properties>
</persistence-unit>
</persistence>

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

<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=“PartyadminPU“>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>
java:jboss/datasources/PartyadminDatasource
</jta-data-source>
<properties>
<property name=“hibernate.hbm2ddl.auto“ value=“none“/>
<property name=“hibernate.dialect“ value=“org.hibernate.dialect.PostgreSQLDialect“ />
<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:

Entweder für MySQL 5:

<datasource jndi-name=“java:jboss/datasources/PartyadminDatasource“ pool-name=“PartyadminDS“
enabled=“true“>
<connection-url>jdbc:mysql://localhost:3306/partyadmin</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>

Oder für Postgres 9:

<datasource jndi-name=“java:jboss/datasources/PartyadminDatasource“ pool-name=“PartyadminDS“
enabled=“true“>
<connection-url>jdbc:postgresql://localhost:5432/partyadmin</connection-url>
<driver>org.postgresql</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>postgres</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 die erfolgreiche Anbindung der soeben deklarierten Datasoures werden die Datenbank-Treiber auf Modul-Ebene des JBoss WildFly konfiguriert, wie in diesem Blog-Eintrag hier bereits beschrieben.

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

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>

Für Postgres 9:

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

Hier auch das Datenbank-Skript zum Anlegen der Postgres-Datenbank und der komplette MySQL-Export der Beispiel-Applikation partyadmin-angularjs:

Für MySQL 5: mysql_export_database_partyadmin_sql.txt
Für Postgres 9: postgres_export_database_partyadmin_sql.txt

Die fertige Beispiel-Applikation partyadmin-angularjs kann zusammen mit den anderen Beispiel-Applikationen hier betrachtet werden (MySQL5 Server auf Ubuntu Server).

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

partyadmin-angularjs

Hier das intelliJ Projekt:

partyadmin-angularjs

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 ebenfalls der Pfad für das log-Dateien Verzeichnis in der logging.properties.

Die Angular JS Beispiel-Applikation dieses Blog-Eintrags kann danach selbst erneut deployt werden, ohne den bereits gestarteten WildFly 10 Application Server überhaupt stoppen oder erneut starten zu müssen. Bei laufendem Server einfach ins Server-Unterverzeichnis /standalone/deployments

– eine leere Textdatei namens partyadmin-angularjs.war.dodeploy speichen und
– das Archiv partyadmin-angularjs.war aus dem partyadmin-angularjs/target-Verzeichnis speichern

Sofort wird die Beispiel-Applikation deployt und in wenigen Sekunden gestartet und kann aufgerufen werden:

http://localhost:8080/partyadmin-angularjs

Für die Adress-Auflösung per Googlemaps wude in die Party-Detailansicht der deployten Version (Angular JS HTML5-View) unten auch ein Link für eine Anfahrtsbeschreibung integriert, dessen sinnvolle Erweiterung in der Übergabe der benötigten Adressdaten (Straße, Hausnummer, Postleitzahl und Ort) z. B. per Request-Parameter, im JSON-Format für das anfahrt.html-Template bestehen könnte, da diese Daten für den jQuery-Aufruf des googlemaps-apis benötigt werden.

Fazit: Wie man sieht, macht es einfach viel Freude, z.B. mittels JBoss Forge und JPA 2 Entities die responsiven Angular JS Apps auf dem Datenmodell zu erzeugen und weiterzuentwickeln oder eben robuste, komfortable, Browser-basierte Primefaces 6-Fontends, sei es nun für mobile IMS (Informations-Management-Systeme) oder für PIMS (Product Information Management Systems) und diese an einen neuen, die JEE7-Spezifikation erfüllenden JBoss WildFly (WildFly 9 + 10) anzubinden.

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 weiterhin schönen Halloween und einen schönen Herbst.

WebApps – mit JPA 2, JSF 2.2, Primefaces 6, REST, JEE7, Java 8 auf JBoss WildFly 9 und WildFly 10

Sonntag, 25. September 2016 von  
unter Fachartikel Architektur

Die Motivation

Über die Migration von RichFaces und MyFaces Beispiel-Applikationen auf die sehr vorteilhafte Primefaces 6-Technologie gibt es bereits Blog-Einträge in diesem Blog hier. In diesem Blog-Eintrag soll nun passend zum Datenmodell des vorigen Blog-Eintrags mit der Angular JS Beispiel-Applikation eine Primefaces 6 Beispiel-Webapplikation erstellt werden. Dabei werden als Basis-Frontendtechnologien JSF 2.2 und Primefaces 6 verwendet. Weiterhin wird der Einsatz moderner Tag-Libs in den XHTML-Seiten der JEE7-Applikation erklärt.

Über die JSF Technologie gibt es bereits einen Blog-Eintrag in diesem Blog hier, worin die Generierung einer JSF 1.2-Applikation auf Basis der JPA-Entities für den JPA-Provider EclipseLink mittels der NetBeans IDE für das Deployment auf dem GlassFish 3 Application Server erklärt wurde. Die in diesem Blog-Eintrag hier mittels JBoss Forge Eclipse PlugIn erstellte Applikation cultureadmin-angularjs wurde auf diesem Datenmodell hier erstellt, und es wird eine weitere Primefaces 6 Beispiel-Applikation cultureadmin-primefaces entwickelt, unter Einsatz der robusten, aber stets elegant gestylten, etablierten, optimalen Primefaces Frontend-Technologie.

Die Beispiel-Applikation cultureadmin-primefaces wird dann auf den neuen JBoss WildFly 9 Final und JBoss WildFly 10 Final Test-Servern deployt und kann mittels Test-Account (showfinder, finder) getestet werden. Dabei ist die Verwendung der beiden neuen JBoss WildFly JEE7-Application Server in diesem Blog-Eintrag hier bereits beschrieben worden.

Erstellung der Beispiel Applikation aus dem Datenmodell

Wie die Applikationen cultureadmin-primefaces und cultureadmin-angularjs mittels JBoss Forge erstellt werden können, ist bereits analog in diesem Blog-Eintrag hier für die Applikationen recipeadmin-primefaces und recipeadmin-angularjs beschrieben worden, und wie in der pom.xml des jeweiligen Beispielprojekts nach erfolgtem Download erkennbar ist, wurden auch in den Applikationen cultureadmin-primefaces und cultureadmin-angularjs die folgenden JEE 7 Artefakte für den JBoss WildFly 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

Einsatz von CDI

Über CDI und JavaEE gibt es bereits Blog-Einträge in diesem Blog hier und hier. Die Aktivierung von CDI erfolgt, wie beschrieben, mittels beans.xml im WEB-INF Verzeichnis.

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

Primefaces 6:

Hat man erst einmal die JPA 2.2 Entities definiert und mittels JBoss Forge die Beispiel-Webapplikationen für die ausgewählte Frontend-Technologie (Angular JS oder Faces) erzeugt und rebrandet, ist die Migration der Faces Beispiel-Applikation leicht durchführbar und wurde bereits in den vorigen Blog-Einträgen beschrieben.

Die Einbindung der erforderlichen Primefaces-UI-Bibliothek primefaces-6.0.jar erfolgt dabei ganz simpel übers Hinzufügen der entsprechenden Maven Primefaces Dependency in der pom.xml.

    <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 XHTML-Views von MyFaces auf Primefaces sind der Primefaces Showcase und der neue Primefaces 6.0 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.

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 ansonsten nahezu identisch zu den ManagedBeans der MyFaces-Applikationen. 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 cultureadmin-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.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.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.view.ViewUtils</function-class>
       <function-signature>
             int count(java.util.Collection)
       </function-signature>
   </function>
               
   <function>
       <function-name>displayShort</function-name>
       <function-class>de.binaris.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.view.ViewUtils</function-class>
       <function-signature>
             java.lang.String displayRange(java.lang.Object,java.lang.Object)
       </function-signature>
   </function>

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

Hier auch die ViewUtils-Klasse unter Verwendung generischer Typen T und Collections List<T>:

ViewUtils:

package de.binaris. view;
 
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
 
import javax.persistence.Id;
 
/**
* Utilities for working with Java Server Faces views.
*/
public final class ViewUtils {
 
   public static <T> List<T> asList(Collection<T> collection) {
     if (collection == null) {
         return null;
     }
     return new ArrayList<T>(collection);
   }
 
   public static String display(Object object) {
     if (object == null) {
         return null;
     }
     try {
         // Invoke toString if declared in the class. If not found,
         // the NoSuchMethodException is caught and handled
         object.getClass().getDeclaredMethod(“toString“);
         return object.toString();
     }
     catch (NoSuchMethodException noMethodEx) {
         try {
           for (Field field : object.getClass().getDeclaredFields()) {
               // Find the primary key field and display it
               if (field.getAnnotation(Id.class) != null) {
                 // Find a matching getter and invoke it to display the key
                 for (Method method : object.getClass().getDeclaredMethods()) {
                     if (method.equals(new PropertyDescriptor(field.getName(),                    
                                         object.getClass()).getReadMethod()))
                     {
                       return method.invoke(object).toString();
                     }
                 }
               }
           }
           for (Method method : object.getClass().getDeclaredMethods()) {
               // Find the primary key as a property instead of a field, and display it
               if (method.getAnnotation(Id.class) != null) {
                 return method.invoke(object).toString();
               }
           }
         } catch (Exception ex) {
           // Unlikely, but abort and stop view generation if any exception is thrown
           throw new RuntimeException(ex);
         }
     }
     return null;
   }
 
   public static <T> int count(Collection<T> collection) {
     if (collection == null) {
               return 0;
     }
     return collection.size();
   }
 
   public static String displayRange(Object object1, Object object2) {
     String text1 = display(object1);
     String text2 = display(object2);
      if (text1 == null || text2 == null
          || text1.trim() == null || text2.trim() == null) {
           return null;
      }
     return (text1 + “-“ + text2);
   }
               
   public static String displayFirst(Object object) {
     String text = display(object);
      if (text == null || text.split(“\\s+“) == null
          || text.split(“\\s+“)[0] == null) {
           return null;
      }
     return (text.split(“\\s+“)[0] + “…“);
   }
 
   public static String displayShort(Object object, int length) {
     String text = display(object);
      if (text == null || text.split(“\\s+“) == null
           || text.split(“\\s+“)[0] == null) {
           return null;
      }
     String[] elements = text.split(“\\s+“);
     String result = ““;
      int i = 0;
      while ((result+elements[i]).length() < length) {
          result += elements[i] + “ “;
          i++;
      }
      return (result.trim() + “…“);
   }

   public static <T> List<T> listExcludingSelectedOne(Collection<T> collection, T selected) {
     if (collection == null) {
         return null;
     }
     if (selected == null) {
       return new ArrayList<T>(collection);
     }
     List<T> list = new ArrayList<T>(collection);
     list.remove(selected);
     return list;
   }
 
   private ViewUtils() {
     // Can never be called, only by getInstance – Singleton pattern
   }

   public static ViewUtils getInstance() {
      return new ViewUtils();
   }
}

Über Tags, TagLibs und die Erweiterung bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und durch die soeben gezeigten Beispiele ist erkennbar, wie simpel es ist, eigene Tags für die .xhtml-Views heutiger JSF 2-Applikationen zu definieren.

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

Die Konfiguration des JBoss WildFly Application Servers 10 Final erfolgt analog der Konfigurationen der JBoss Application Server WildFly 8.1, 8.2 und 9 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 in diesem Blog-Eintrag hier und in vorigen Blog-Einträgen bereits beschrieben.

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

“TDD mit Java”

hier und hier von Binaris Informatik ebenfalls erwähnt werden.

Die Primefaces Beispiel-Applikation arbeitet über die RESTful WebService-Schnittstelle auf derselben Datenbank, wie die AngularJS Beispiel-Applikation cultureadmin-angularjs, weshalb für die Primefaces Beispiel-Applikationen dasselbe mit HeidiSQL erstellte MySQL 5.x Datenbank-Skript verwendet werden kann.

Die fertige Beispiel-Applikation cultureadmin-primefaces kann hier betrachtet werden.

Hier die Beispiel-Projekte für die Entwicklungsumgebungen JBoss Developer Studio und intelliJ 15:

JBoss Developer Studio Projekt:

cultureadmin-primefaces

intelliJ Projekt:

cultureadmin-primefaces

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. Über die Konfiguration der MySQL 5.x Datenbank für den WildFly 9 und den WildFly 10 gibt es hier mehr Informationen in diesem Blog.

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, damit dieser auf das tatsächliche JDK 8-Verzeichnis des Server-Systems zeigt.

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

– eine leere Textdatei namens cultureadmin-primefaces.war.dodeploy speichen und
– das Archiv cultureadmin-primefaces.war aus dem cultureadmin-primefaces/target-Verzeichnis speichern

Wie man sieht, macht es viel Freude, die XHTML-Views der beschriebenen Beispiel-Applikation RichFaces oder MyFaces auf die vorteilhafte Primefaces-Technologie umzustellen und ebenfalls, zuvor die Angular JS und Faces-Beispielapplikationen mittels JBoss Forge auf dem Datenmodell zu erzeugen und weiterzuentwickeln.

Es besteht also durchaus die Möglichkeit, dass noch weitere Blog-Einträge zu Webframeworks wie Primefaces, Angular JS und Faces und den die JEE7-Spezifikation implementierenden Technologien folgen.

Allen interessierten Leserinnen und Lesern weiterhin viel Freude bei der agilen Softwareentwicklung mittels Scrum und dem Test Driven Development mit Java, sowie einen schönen Herbstanfang, ein fröhliches Erntedankfest und ein spaßiges Halloween.

WebApps – mit Angular JS, REST, JEE7, JBoss Forge, Java 8, MySQL 5, Postgres 9, MSSQL Server 2016 auf JBoss WildFly 9 und 10

Freitag, 19. August 2016 von  
unter Fachartikel Architektur

Die Motivation

Im Blog-Eintrag über WebApps – vom Modell zur App, mit JSF 2.2, Angular JS, REST, JPA 2 hier wurde beschrieben, wie leicht es ist, von einem Klassen-Diagramm (UML), genauer: Entity-Relationship-Diagramm hier, auch E-R Diagramm genannt, zu einer JEE7-Applikation zu kommen. Diese JEE6- und JEE7-Beispielapplikationen hier liefern 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).

Das Durchsuchen, und die Nutzung einer Pagination der Ergebnisliste ist ebenfalls in der Beispiel-App enthalten, wie auch mit Hilfe des Angular JS Frameworks und des Bootstrap-Frameworks eine dynamische Benutzeroberfläche, die sich an beliebige Auflösungen und Display-Größen responsiv anpasst.

Die besondere Motivation besteht diesmal darin, wie in der JBoss Webinar-Beispielapplikation hier beschrieben, die ausprogrammierte JEE7-Applikation cultureadmin-angularjs mit dem Angular JS-Frontend und dem JEE-Backend mit den JPA 2 Entities an verschiedene relationale Datenbanken (MySQL 5.x, Postgres 9.x und MSSQL Server 2016) anzubinden und auch die benötigten kompletten SQL-Export/-Import-Skripte zur Verfügung zu stellen.

Die Beispiel-Applikation cultureadmin-angularjs wird dann auf dem neusten JBoss WildFly 10 Final Server (entspricht dem neuen JBoss EAP 7-Server) und ebenfalls auf dem JBoss WildFly 9 deployt. Dabei ist die Verwendung dieser beiden neuen JBoss WildFly JEE7-Application Server in diesem Blog-Eintrag hier bereits beschrieben worden.

Erstellung der Beispiel Applikation aus dem Datenmodell

Mittels Eclipse-PlugIn Umlet wird das Klassendiagramm der Entities und Datenbank-Objekte erstellt und aus diesem, nach dem Anlegen der Datenbank per Hibernate Envers während dem WildFly 10 Undertow Deployment mittels JBoss Forge PlugIn im JBoss Developer Studio erst der REST-WebService mit den Endpoints generiert und danach die Angular JS WebApp auf diesem RESTful WebService. Dabei soll nicht vergessen 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!

Maven JEE 7 JBoss-Artefakte und Maven Dependencies

Dabei werden in der pom.xml die folgenden Maven Dependencies verwendet:

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

 Einsatz von CDI

Und ebenfalls die CDI 1.1 Dependency:

– cdi-api_1.1

Über CDI und JavaEE gibt es bereits Blog-Einträge in diesem Blog hier und hier. Die Aktivierung von CDI erfolgt, wie beschrieben, mittels beans.xml im WEB-INF Verzeichnis.

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

JBoss WildFly 10 und MSSQL Server 2016 mit JDBC 4

Die Konfiguration des JBoss WildFly Application Servers 10 Final erfolgt analog der Konfigurationen der JBoss Application Server WildFly 8.1, 8.2 und 9 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 in diesem Blog-Eintrag hier und vorigen Blog-Einträgen bereits beschrieben.

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

“TDD mit Java”

hier und hier von Binaris Informatik erwähnt werden.

Das Besondere ist, wie erwähnt, diesmal die Anbindung an den MSSQL Server 2016, wogegen die Installation, Konfiguration und Anbindung an die Open Source Datenbanken MySQL 5.x (oder z. B. auch an eine MariaDB) und an die Postgres 9.x Datenbank wie ein Picknick erscheinen.

Betriebssystemvoraussetzung für MSSQL Server 2016: Windows 8 oder besser 10
Betriebssystemvoraussetzung für MySQL 5.x oder Postgres 9.x: Linux oder Windows.

Datenbank-Installationen und Administrations-Tools

MySQL 5/HeidiSQL 10: http://dev.mysql.com, http://heidisql.com (HeidiSQL_9.3.0.4984_Setup.exe)

Nach dem Download der MySQL von Oracle und den Installationen verbindet man sich einfach mit dem MySQL-Server (MySQL-Standard Port 3306) und legt die Datenbank an, entweder per Kontextmenü oder per SQL-Skript hier.

Postgres 9: http://postgresql.com

Die DB-Installations-.exe, z.B. postgresql-9.2.17-1-windows-x64.exe, herunterladen und starten. Bei der Installation kann das Passwort für den Administrator (“postgres“) selbst bestimmt werden.

pgAdmin 3: www.pgadmin.org/download

pgadmin3-1.22.1.zip herunterladen (und entpacken), dann auf Windows pgadmin3.msi installieren.

Nach der Installation verbindet man sich mit der Kombination (postgres, gewähltes Passwort) einfach mit der Datenbank. Der Port für die JDBC-Connection url ist ebenfalls bereits bekannt und wurde bei der Installation eingegeben. Dann wird die Datenbank angelegt, entweder per Kontextmenü oder per SQL-Skript hier.

MSSQL Server 2016 (180 Tage Probeversion): https://technet.microsoft.com/en-us/library/dn876712.aspx#bkmk_rc1_setup

Hierbei wurde bei der SQLServer2016-SSEI-Eval.exe-Installation die Custom Installation mit der SQL Server basierten Authentifizierung ausgewählt, um das Passwort des Server Admins selbst festlegen zu können. Dieses wird nachher bei der Datasource-Definition benötigt. Es wurden alle Optionen des Installations-Shields installiert.

Management Studio SQL Server 2008-2016: https://msdn.microsoft.com/library/mt238290.aspx

Nach der Installation des SSMS-Setup-***.exe verbindet man sich mittels impliziter Windows Authentifizierung am RDBMS des SQL Servers und legt dann die neue Datenbank an, entweder per Kontextmenü oder per SQL-Skript hier. Für den Port der JDBC-Connection ist die Tatsache von großer Bedeutung, dass hier der Server Admin-User für die JDBC-Connection verwendet wird, weshalb auch der für diesen in der Windows Registry eingetragene TCP-Port (1434) zu verwenden ist. Alle Ports, auf denen der MSSQL Server lauscht, können auf der Command Line mittels “netstat -a“ ermittelt werden.

(Siehe hierzu auch mittels regedit.exe: der TCP-Port des Admins unter

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL10.[Instance Name]\MSSQLServer\SuperSocketNetLib\…..)

Für den MSSQL Server 2016 ist zusätzlich die Installation des JDBC4-Treibers im Betriebssystem erforderlich: sqljdbc_6.0.7507.100_enu.exe starten und die Anweisungen im install.txt beachten.

Je nach verwendeter Datenbank wird in der persistence.xml im Deployment-Paket der Beispiel-App cultureadmin-angularjs.war ein anderer Datenbank-Dialekt eingetragen:

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

    <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=“ShowadminPU“>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>
    java:jboss/datasources/ShowadminDatasource
    </jta-data-source>
    <properties>
    <property name=“hibernate.hbm2ddl.auto“ value=“create-drop“/>
    <property name=“hibernate.show_sql“ value=“false“/>
    </properties>
    </persistence-unit>
    </persistence>

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

    <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=“ShowadminPU“>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>
    java:jboss/datasources/ShowadminDatasource
    </jta-data-source>
    <properties>
    <property name=“hibernate.hbm2ddl.auto“ value=“create-drop“/>
   <property name=“hibernate.dialect“ value=“org.hibernate.dialect.PostgreSQLDialect“ />
   <property name=“hibernate.show_sql“ value=“false“/>
    </properties>
    </persistence-unit>
    </persistence>

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

    <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=“ShowadminPU“>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>
    java:jboss/datasources/ShowadminDatasource
    </jta-data-source>
    <properties>
    <property name=“hibernate.hbm2ddl.auto“ value=“create-drop“/>
   <property name=“hibernate.dialect“ value=“org.hibernate.dialect.SQLServer2012Dialect“ />
   <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/ShowadminDatasource“ pool-name=“ShowadminDS“
    enabled=“true“>
    <connection-url>jdbc:mysql://localhost:3306/showadmin</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/ShowadminDatasource“ pool-name=“ShowadminDS“
    enabled=“true“>
   <connection-url>jdbc:postgresql://localhost:5432/showadmin</connection-url>
    <driver>org.postgresql</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>postgres</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 MSSQL Server 2016:

    <datasource jndi-name=“java:jboss/datasources/ShowadminDatasource“ pool-name=“ShowadminDS“
    enabled=“true“>
<connection-url>
    jdbc:sqlserver://127.0.0.1:1434;databaseName=showadmin;integratedSecurity=false
</connection-url>
    <driver>sqljdbc42.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>sa</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 die erfolgreiche Anbindung der soeben deklarierten Datasoures werden die Datenbank-Treiber auf Modul-Ebene des JBoss WildFly konfiguriert:

Für MySQL 5: im Verzeichnis wildfly-10.0.0.Final\modules\system\layers\base\com\mysql\main

Hier gibt es die Dateien

– module.xml
– mysql-connector-java-5.1.34.jar (JDBC4-Treiber)
– mysql-connector-java-5.1.34.jar.index

Hier die module.xml:

<?xml version=“1.0″ encoding=“UTF-8″?>
<module xmlns=“urn:jboss:module:1.1″ name=“com.mysql“>
 
   <resources>
       <resource-root path=“mysql-connector-java-5.1.34.jar“/>
   </resources>
   <dependencies>
       <module name=“javax.api“/>
       <module name=“javax.transaction.api“/>
   </dependencies>
</module>
 

Die mysql-connector-java-5.1.34.jar.index hat folgenden Inhalt:

com
com/mysql/jdbc
org/gjt/mm/mysql
com/mysql/jdbc/log
com/mysql/jdbc/jdbc2
org/gjt/mm
com/mysql/jdbc/profiler
com/mysql/jdbc/integration/jboss
org
org/gjt
com/mysql/jdbc/jmx
META-INF
com/mysql/jdbc/integration/c3p0
com/mysql/jdbc/configs
com/mysql/jdbc/exceptions
com/mysql/jdbc/jdbc2/optional
com/mysql
com/mysql/jdbc/integration
com/mysql/jdbc/interceptors
com/mysql/jdbc/util
com/mysql/jdbc/exceptions/jdbc4
META-INF/services

Für Postgres 9: im Verzeichnis wildfly-10.0.0.Final\modules\system\layers\base\org\postgres\main

Hier gibt es die Dateien

– module.xml
– postgresql-9.4.1209.jar (JDBC-Treiber)

Hier die module.xml:

<?xml version=“1.0″ encoding=“UTF-8″?>
<module xmlns=“urn:jboss:module:1.1″ name=“org.postgresql“>
 
   <resources>
       <resource-root path=“postgresql-9.4.1209.jar“/>
   </resources>
   <dependencies>
       <module name=“javax.api“/>
       <module name=“javax.transaction.api“/>
   </dependencies>
</module>

Für SQLServer: im Verzeichnis wildfly-10.0.0.Final\modules\system\layers\base\com\microsoft\main

Hier gibt es die Dateien

– module.xml
– sqljdbc42.jar (JDBC4-Treiber)

Hier die module.xml:

<?xml version=“1.0″ encoding=“UTF-8″?>
<module xmlns=“urn:jboss:module:1.1″ name=“com.microsoft“>
 
   <resources>
       <resource-root path=“sqljdbc42.jar“/>
   </resources>
   <dependencies>
       <module name=“javax.api“/>
       <module name=“javax.transaction.api“/>
   </dependencies>
</module>

Wenn diese Verzeichnisse mit den Konfigurationsdateien noch nicht vorhanden sind, müssen diese angelegt werden und die Treiber und .xml-Dateien dort hinterlegt werden.

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

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>

Für Postgres 9:

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

Für MSSQL Server 2016:                  

<driver name=“sqljdbc42.jar“ module=“com.microsoft“>
   <driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class>
   <xa-datasource-class>com.microsoft.sqlserver.jdbc.SQLServerXADataSource
   </xa-datasource-class>
</driver>

Seit der Version 2012 kann der MSSQL Server auch mit den JEE JPA-Sequences arbeiten. Deshalb hier noch ein paar nützliche Links zu diesem Thema:

Verwendung von Sequences mit dem MSSQL Server:

https://msdn.microsoft.com/en-us/library/ff878058.aspx

Sowohl für die MySQL als auch für die Postgres Datenbank ist es mit den Admin-Tools HeidiSQL bzw. pdAdmin3 leicht möglich den next_value einer Sequence zu ändern,

Das Ändern des current_value einer Sequence erfolgt beim MSSQL Server per TSQL-Script:

http://stackoverflow.com/questions/13702471/get-current-value-from-a-sql-server-sequence

https://msdn.microsoft.com/en-us/library/ff878352.aspx

Das bedeutet beispielhaft die folgenden SQL-Skripte, um die Sequence auf den richtigen Wert erhöhen, nachdem z. B. die Daten der zugehörigen Tabellen per SQL-Skript eingespielt wurden:

Inkrementierung des current_value der sequence_category:

USE [showadmin]
GO

DECLARE @range_first_value sql_variant ,
               @range_first_value_output sql_variant ;

EXEC sp_sequence_get_range
@sequence_name = N’sequence_category‘
, @range_size = 1
, @range_first_value = @range_first_value_output OUTPUT

select @range_first_value_output AS FirstNumber;

select current_value from sys.sequences where name=’sequence_category‘;

Inkrementierung des current_value der sequence_venue:

USE [showadmin]
GO

DECLARE @range_first_value sql_variant ,
               @range_first_value_output sql_variant ;

EXEC sp_sequence_get_range
@sequence_name = N’sequence_venue‘
, @range_size = 1
, @range_first_value = @range_first_value_output OUTPUT

select @range_first_value_output AS FirstNumber;

select current_value from sys.sequences where name=’sequence_venue‘;

Wie das Auslesen des next_value einer Sequence beim MSSQL Server erfolgt, ist hier beschrieben:

https://msdn.microsoft.com/en-us/library/ff878370.aspx

Hier auch die kompletten Datenbank SQL-Exporte der Beispiel-Applikation cultureadmin-angularjs:

Für MySQL 5: mysql_export_database_sql.txt
Für Postgres 9: postgres_export_database_sql.txt
Für MSSQL Server 2016: mssqlserver_export_database_sql.txt

Die fertige Beispiel-Applikation cultureadmin-angularjs kann zusammen mit den anderen Beispiel-Applikationen hier betrachtet werden (MySQL5 Server auf Linux).

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

cultureadmin-angularjs

Hier das intelliJ Projekt:

cultureadmin-angularjs

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 ebenfalls der Pfad für das log-Dateien Verzeichnis in der logging.properties.

Die Angular JS Beispiel-Applikation dieses Blog-Eintrags kann danach selbst erneut deployt werden, ohne den bereits gestarteten WildFly 10 Application Server überhaupt stoppen oder erneut starten zu müssen. Bei laufendem Server einfach ins Server-Unterverzeichnis /standalone/deployments

– eine leere Textdatei namens cultureadmin-angularjs.war.dodeploy speichen und
– das Archiv cultureadmin-angularjs.war aus dem cultureadmin-angularjs/target-Verzeichnis speichern

Sofort wird die Beispiel-Applikation deployt und in wenigen Sekunden gestartet und kann aufgerufen werden:

http://localhost:8080/cultureadmin-angularjs

Wie man sieht, macht es einfach Spaß, die responsiven Angular JS-Beispielapplikationen mittels JBoss Forge auf dem Datenmodell zu erzeugen und weiterzuentwickeln.

Fazit: Der MSSQL Server 2016 ist beileibe keine Open Source Datenbank, sondern kostet inzwischen richtig Lizenzen je Core (Rechenkern). Dies ist jedoch, wie gezeigt wurde, kein Hinderungsgrund, wenn der MSSQL Server 2016 im Unternehmen sowieso lizensiert im Einsatz ist, diesen an einen neuen, die JEE7-Spezifikation erfüllenden JBoss WildFly (WildFly 9 + 10) anzubinden und mittels JBoss Forge und JPA 2 Entities zu einer MSSQL Server Datenbank responsive Angular JS Apps zu entwickeln oder eben robuste, komfortable, Browser-basierte Primefaces 6-Fontends, sei es nun für mobile IMS (Informations-Management-Systeme) oder für PIMS (Product Information Management Systems).

Es besteht somit 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 weiterhin schöne Sommerferien.

Nächste Seite »