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.

Kommentare

5 Kommentare zu “WebApps – JSF 2, RichFaces 4, Primefaces 6, REST, JPA 2, EJB 3, JEE7, JBoss WildFly”

  1. Von WebApps – Primefaces 6, FileUploads, JSF 2, JPA 2, EJB 3, JEE7, REST, AngularJS, WildFly : Karriere als Software Entwickler | binaris informatik GmbH am Mittwoch, 22. Februar 2017 21:15

    […] Servers ist ebenfalls leicht durchführbar und wurde bereits in einem Blog-Eintrag in diesem Blog hier […]

  2. Von WebApps – JSF 2, Primefaces, FileDownloads, JPA 2, EJB 3, JEE7, REST, MySQL, WildFly : Karriere als Software Entwickler | binaris informatik GmbH am Sonntag, 26. März 2017 20:01

    […] Servers ist ebenfalls leicht durchführbar und wurde bereits in einem Blog-Eintrag in diesem Blog hier […]

  3. Von WebApps – Primefaces 6, JPA 2, EJB 3, PDFs parsen, iText, MySQL, REST, JEE7, WildFly : Karriere als Software Entwickler | binaris informatik GmbH am Sonntag, 30. April 2017 12:03

    […] von JBoss, welches auf dem WildFly zu konfigurieren ist, was bereits in diesem Blog-Eintrag hier beschrieben […]

  4. Von WebApps – mit Primefaces 6,JSF 2,JPA 2,EJB 3, JEE7, Java 8, REST auf WildFly 9, 10 und 11 : Karriere als Software Entwickler | binaris informatik GmbH am Samstag, 30. September 2017 19:19

    […] 9 und 10 ist ebenfalls leicht durchführbar und wurde bereits in einem Blog-Eintrag in diesem Blog hier […]

  5. Von WebApps – RESTful mit JSF 2, JPA 2, EJB 3, Primefaces 6, JEE7, Java 8 und 9 auf WildFly 9, 10 und 11 : Karriere als Software Entwickler | binaris informatik GmbH am Mittwoch, 1. November 2017 13:02

    […] 9 und 10 ist ebenfalls leicht durchführbar und wurde bereits in einem Blog-Eintrag in diesem Blog hier […]