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

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 in den Implementierungen RichFaces und Primefaces gibt es bereits mehrere Blog-Einträge in diesem Blog. In diesem Blog-Eintrag wird nun mittels JBoss Forge Eclipse PlugIn 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 und JBoss WildFly 11 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. Hier auch das Entity-Relationship Diagramm:

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

Erstellung der Beispiel Applikation nach Datenmodell

Wie die Applikation jobapplication-primefaces mittels JBoss Forge erstellt werden kann, ist bereits analog in vorherigen Blog-Einträgen 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

Die Aktivierung von CDI erfolgt, wie beschrieben, mittels beans.xml im WEB-INF Verzeichnis der Beispielapplikation.

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>

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 wird es noch einen Blog-Eintrag hier in diesem Blog geben 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 jobapplication-primefaces.war im /target-Unterverzeichnissen des Projekts jobapplication-primefaces.

Als zusätzliche Abhängigkeiten für den FileUpload wurden ebenfalls die im Primefaces Users Guide genannten folgenden optionalen Apache Bibliotheken (commons) 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 Primefaces Beispiel-Applikation arbeitet über die RESTful WebService-Schnittstelle auf der MySQL-InnoDB. Für die Primefaces Beispiel-Applikationen kann das mit HeidiSQL erstellte MySQL 5.x Datenbank-Skript verwendet werden.

WildFly Anbindung an MySQL5 und deklarative WildFly 11 Hibernate-Konfiguration

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

Je nach verwendeter Datenbank kann in der persistence.xml im Deployment-Paket der Beispiel-App jobapplication-primefaces.war ein entsprechender 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=“JobapplicationPU“>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>
            java:jboss/datasources/JobapplicationDatasource
    </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/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>

Für die erfolgreiche Anbindung der soeben deklarierten Datasoures werden die Datenbank-Treiber auf Modul-Ebene des JBoss WildFly konfiguriert, wie noch genauer beschrieben wird.

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>

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

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

Die fertige Beispiel-Applikation 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 ebenfalls 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 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 9 Final als Zip-Archiv zum Download und Entpacken: Für Linux hier und für Windows hier. Voraussetzung ist jeweils Java 7.

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

Hier auch der WildFly 11 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 wird ebenfalls auf bereits vorhandene Blog-Einträge hier verwiesen, da die Konfigurationen analog zum WildFly 9 und WildFly 10 durchzuführen sind.

Der fertig konfigurierte WildFly 11 mit vielen Beispiel-Applikationen der vorangegangenen Blog-Einträge ist hier zum Download verfügbar, kann runtergeladen, entpackt und gestartet werden. Auch hier ist nur der Pfad des JAVA_HOME anzupassen, damit dieser auf das tatsächliche JDK 9 – Verzeichnis des Server-Systems zeigt.

Mehr Informationen zum Java 9 Release gibt es hier:

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

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

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

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

Hier die Release-Notes zu Java 9:

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

Oracle Support für das Oracle JDK 8:
Nach January 2019 läuft nun der Oracle Support für das Oracle JDK 8 aus, weshalb es dann keine Updates mehr für Java SE 8 geben wird. Weiterhin wird ein entsprechender Oracle Support Vertrag für die produktive Verwendung der Java Versionen 6, 7, 9, 10 und 11 erforderlich werden. Mehr information gibt es in diesem Blog hier.

Oracle Java wird also ab Februar 2019 produktiv nicht mehr gebührenfrei einsetzbar sein, weshalb es von RedHat frei einsetzbare OpenJDK Java Versionen gibt, welche von RedHat auch für Endanwender und Unternehmen kostenfrei supportet werden. Hierfür ist lediglich eine Red Hat Enterprise Linux oder Middleware Subscription erforderlich.

Die SQL-Skripte zum Anlegen und Befüllen der MySQL Beispiel-Datenbanken finden sich verlinkt in den Blog-Einträgen wieder, die hier durchsucht werden können, durch Eingabe eines Stichworts des Titels oder Blog-Eintrag Texts im Feld Suche… der Eingabemaske.

Hier auch nochmal die ausführliche Dokumentation einer weiteren JEE Beispielapplikation mit REST-Webservices getriebenem Angular JS Frontend. Und hier noch eine weitere SPA (Single Page Appliction) Beispiel-Applikation, bei der das Testen des Backends mittels Arquillian und das integrative Testen des Frontends mittels Selenium (Workflow und UX Elemente) und QUnit  (Javascript-Framework zum Test-Aufruf der REST-Endpoints aus einer Browser-View) ebenfalls ausführlich beschrieben ist.

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

– 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 einem 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 und einen unterhaltsamen Super Bowl mit seinen legendären Halbzeitauftritten.