Erinnerung: Eine Komponentenarchitektur-Variante Datenbank als zentrale Kommunikationsplattform Ansatz 1: alle Komponenten kennen Entitäten-Modell Ansatz 2: Datenzugriffsschicht kapselt Datenbank Ansatz 1: Alle kennen Entitäten-Modell (1/2) Datenbank als zentrale Kommunikationsplattform Entitäten sind bekannt, jede Komponente kann zugreifen Benötigt Komponente weitere Eigenschaft einer Entität wird keine Spalte sondern Tabelle ergänzt (auch 1:1, 1:C, nutzt Primärschlüssel) Sehr einfache Architektur Sehr gut Komponenten an- und ausschaltbar Keine Benachrichtigung bei Änderungen (sichtbar beim nächsten Lesen) Stark eingeschränkte Wiederverwendbarkeit Keine echte Informationskapselung Wartbarkeit nimmt mit Systemgröße enorm ab 217 218 Ansatz 1: Alle kennen Entitäten-Modell (2/2) Beispiel: Komponenten Produktverwaltung, Bestellsystem (sieht neue Produkte und Änderungen bei nächsten Aufruf) Ansatz 2: Kapselung mit Datenzugriffsschicht (1/2) Kein direkter Zugriff auf Tabellen Ermöglicht auch Benachrichtigungen (Observer) Zerlegung in wiederverwendbare Komponenten Unterschiedliche Varianten von Kommunikationen möglich Nutzung einer zentralen Zugriffskomponente, die DB kapselt und Observer verwaltet Nur Data Access Objects können miteinander reden Komponentenschnittstellen unabhängig von der DB Selbst gemeinsame Datenbank ist optional 219 220
Ansatz 2: Kapselung mit Datenzugriffsschicht (2/2) Überwachungsmethoden (1/3) @Entity public class Mitarbeiter { @Id @GeneratedValue(strategy=GenerationType.AUTO) private int minr; private String name; private void p(string s){system.out.println(s); @PrePersist public void prepersit() {p("prepersist"); @PostPersist public void postpersist() {p("postpersist"); @PreRemove public void preremove() {p("preremove"); @PostRemove public void postremove() {p("postremove"); @PreUpdate public void preupdate() {p("preupdate"); @PostUpdate public void postupdate() {p("postupdate"); @PostLoad public void postload() {p("postload"); // Hinweis: Rollback bei einer Runtime Exception 221... 222 Überwachungsmethoden (2/3) public static void main(string[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("PrePostPU"); EntityManager em = emf.createentitymanager(); Mitarbeiter m = new Mitarbeiter("Olga"); prepersist Mitarbeiter m2 = new Mitarbeiter("Otto"); prepersist EntityTransaction ta = em.gettransaction(); prepersist ta.begin(); postpersist em.persist(m); postpersist em.persist(m2); postpersist em.persist(new Mitarbeiter("Urs")); preupdate ta.commit(); postupdate ta.begin(); Mitarbeiter mm = em.find(mitarbeiter.class, m.getminr()); mm.setname("anna"); em.persist(mm); ta.commit(); Überwachungsmethoden (3/3) ta.begin(); em.remove(m); ta.commit(); em.close(); // notwendig für neuen Kontext em = emf.createentitymanager(); for (Mitarbeiter m3 : em.createquery( "SELECT m FROM Mitarbeiter m", Mitarbeiter.class).getResultList()) System.out.println(m3.getMinr() + ": " + m3.getname()); em.close(); emf.close(); preremove postremove postload postload 2: Otto 3: Urs 223 224
5. JavaServer Faces (JSF) 5.1 Grundlagen 5.2 Einführendes nulltes Beispiel 5.3 Validierung 5.4 JSF mit JPA und JNDI 5.5 Funktionale Erweiterung 5.6 Ausblick: Nutzung CDI und SessionBeans 5.7 Sicherheit 5.8 Weitere JSF-Möglichkeiten 5.9 JSF-Lebenszyklus 5.10 Templates und Komponenten 5.11 Nutzung von Ajax 5.12 JSF-Erweiterungen 225 Literatur D. Geary, C. Horstmann, Core JavaServerFaces, 3. Auflage, Prentice Hall, USA, 2010 E.Burns, C. Schalk, JavaServer Faces 2.0: The Complete Reference, Mc Graw Hill, New York, 2010 M. Marinschek, M. Kurz, G. Müllan, JavaServerFaces2.0, dpunkt, Heidelberg, 2010 (im Wesentlichen auch: http://tutorials.irian.at/jsf/semistatic/introduction.html) K. Ka IokTong, Beginning JSF 2 APIs and JBossSeam, Apress, Berkeley, USA, 2009 Standard: Sun, JSR 314: JavaServerFaces 2.0, http://www.jcp.org/en/jsr/detail?id=314 Sun, JEE6 Tutorial, http://download.oracle.com/javaee/6/tutorial/doc/ Bücher fixieren teilweise auf Eclipse und JBoss; nicht notwendig, funktioniert fast alles mit Netbeans und Glassfish / Apache 226 5.1 Grundlagen Technische Herausforderungen (1/2) verschiedene Ziele von JSF-Applikationen Software, die Web als zusätzlichen Nutzen hat (z. B. Web- Präsenz, Kataloge, Bestellmöglichkeiten) verteilte Softwaresysteme, die Netz als Komponentenverbindung nutzen (z. B. B2B) Arbeitsplatzsoftware, die auch das Web nutzt (nahtlose Integration, Web ist unsichtbar ) letztes Ziel gewinnt immer mehr Bedeutung für andere Ziele Aber: Nicht immer ist Web-fähige Software gewünscht! auf welchem Rechner läuft welche Software zentraler Server oder peer-to-peer Client-Server, wer ist thin, wer ist fat Browser-fähig oder standalone welcher Browser, welche Sicherheitseinstellungen, welche Plugins, welches HTML Wie bekommt Kunde Software zum Laufen, wie funktionieren Updates darf man, muss man offline arbeiten können Usability 227 228
Technische Herausforderungen (2/2) Sicherheit wie Daten sicher verschicken, wem gehört Internet, wer muss zuhören dürfen Performance und Stabilität schnelle Antworten auch bei Last saubere, reproduzierbare Transaktionen was passiert bei Netzausfall Typische splattformen (Ausschnitt).Net / Microsoft ASP.Net (Active Server Pages, gute Abstraktion, zunächst zu wenig Web-Server (IIS)) Silverlight (Browser-PlugIn) für RIA, mittlerweile auch lokal Oberflächen basierend auf WPF (Windows Presentation Forum, vektorbasiert, anfänglich zu langsam) Java Servlets, JSP, JSF [später genauer], angegeben mit steigenden Abstraktionsgrad sehr weit verbreitet verschiedene neue Frameworks (z. B. Apache Wicket) GWT (Google Widget Toolset), SW einmal in Java schreiben, dann individuell für Browser in Javascript übersetzen JavaFX, eigene Sprache nutzt im Browser JRE Meinung: Silverlight und JavaFX gegenüber Flash(- Nachfolger) immer im Nachteil 229 230 Konzept eines Seitenaufrufs Client HTTP-Request HTTP-Response mit HTML-Datei im Body Web- Container EJB- Container Application Server HTML (Hypertext Markup Language) Auszeichnungssprache mit festgelegten tags zum Aufbau der Ausgabe Ebene 3/4 typisch TCP/IP, Session Ebene 5: HHTP, Darstellungsebene 6: HTML, Programmebene 7: JVM HTTP-Ablauf Client: Request get, post, head, put,... URL HTTP1.x Header Info: Accept, Cookie,... Body: Post-Parameter Server: Response Statusmeldung: HTTP1.x 200 OK, oder 404 Error Header Info: Content-type, set-cookie,... Body: Dokument Verbindungsabbau Protokoll ist zustandslos/gedächtnislos; Client wird bei erneutem Request ohne Trick nicht als Bekannter erkannt 231 232
Web-Server mit Container nutzen Servlet: Wortkreation aus den Begriffen Server und Applet, (serverseitiges Applet) Web-Server leitet HTTP- Request an Servlet weiter Servlet kann Antwort (HTML-Code) berechnen Servlet kann Anfrage- Informationen und Serverumgebung nutzen Servlet kann mit anderen Servlets kommunizieren Container Motivation für JSF Die Widerverwendbarkeit von Servlets ist gering Innerhalb jeder JSP bzw. jedes Servlets müssen ähnliche Schritte ausgeführt werden Nur ein Teil der Applikationslogik kann in Tag-Bibliotheken gekapselt werden Workflow ist in der Applikationslogik versteckt, dadurch schwer nachvollzierbar ab JSF 2.0 sehr flexible Gestaltungsmöglichkeiten, u. a. AJAX- Einbettung Hinweis: wir betrachten nur Grundkonzepte (-> mehr evtl. Semesteraufgabe) 233 234 Web-Server mit JSF- (und EJB-) Unterstützung Konzeptübersicht Beispiele: Apache + Tomcat BEA WebLogic Server IBM WebSphere (Apache Geronimo) JBoss Oracle WebLogic Sun Glassfish Enterprise Server (Glassfish) Web-Seite in XHTML Input-Komponente beschrieben in XHTML... Web-Seite in XHTML Output-Komponente beschrieben in XHTML... event leitet auf Folgeseite liest Modell Java-Programm im Container im Server 235 236
XHTML Idee: HTML nicht XML-konform und zu viele Freiheiten XHTML in fast allen Elementen wie HTML XHTML basierend auf XML-Schema leichter zu verarbeiten Unterschiede zu HTML (Ausschnitt) Tags und Attribute müssen klein geschrieben werden Attributwerte immer in Anführungsstrichen boarder="7" korrekte XML-Syntax: <br/> nicht <br> generell saubere Terminierung <input... /> XHTML2 wegen HTML5 zurückgestellt http://www.w3.org/2009/06/xhtml-faq.html Standard: http://www.w3.org/tr/xhtml1/ Literatur: U. Ogbuji, XHTML step-by-step, http://www.ibm.com/developerworks/edu/x-dw-x-xhtml-i.html Web-GUI-Komponenten JSF bietet alle klassischen GUI-Komponenten zur Darstellung und Bearbeitung an Grundidee: Komponenten schicken bei Veränderungen Events Nutzung von MVC2 Komponenten als XHTML eingebettet <h:inputtext id="imname" value="#{modul.name required="true"/> <h:outputtext id="omname" value="#{modul.name"/> Kontakt zum Java-Programm über Methodenaufrufe (lesend und aufrufend, z. B. modul.setname(...), modul.getname() große Komponenten können aus kleineren komponiert werden 237 238 5.2 Nulltes JSF-Beispiel (1/11) Aufgabe: Modul (Name + Nummer) eingeben und auf zweiter Seite wieder ausgeben Beispiel zeigt: Konzept der XHTML-Nutzung erste JSF-Befehle Seitenmanövrierung durch JSF 0. Beispiel zeigt nicht: ordentliche Softwarearchitektur (Controller und Model trennen) Validierungsmöglichkeiten für Eingaben Layoutgestaltung viele coole Dinge Nulltes JSF-Beispiel (2/11) - Start index.xhtml <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>moduleingabe</title> </h:head> <h:body> <h:form> <h:outputtext value="modulname "/> <h:inputtext id="mname" value="#{modul.name" required="true"/><br/> <h:outputtext value="modulnummer "/> <h:inputtext id="mnr" value="#{modul.nr" required="true"/><br/> <h:commandbutton value="abschicken" action="#{modul.uebernehmen"/> </h:form> </h:body> </html> 239 240
Nulltes JSF-Beispiel (3/11) - Analyse der Startseite Einbinden der JSF-Bibliotheken <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f ="http://java.sun.com/jsf/core" > Nutzung von Standard XHTML (vereinfacht, da so als Standardnamensraum gesetzt) enge Verwandtschaft HTML zu XHTML (<h:form>) für value="#{modul.name" offene Fragen: was ist modul? ( -> ManagedBean) warum #? (Trennung von ausführbaren Elementen) was passiert bei modul.name? (set/getabhängig von in/out) Ausblick: action="#{modul.uebernehmen", echtes Event- Handling (Methodenaufruf) Nulltes JSF-Beispiel (4/11) - Ausgabe ausgabe.xhtml <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>modulausgabe</title> </h:head> <h:body> <h:form> <h:outputtext value="modulname: "/> <h:outputtext id="mname" value="#{modul.name"/> <br/> <h:outputtext value="modulnummer: "/> <h:outputtext id="mnr" value="#{modul.nr"/><br/> <h:commandbutton value="zur Eingabe" action="#{modul.eingeben"/> </h:form> </h:body> </html> 241 242 Nulltes JSF-Beispiel (5/11) - Managed Bean [1/3] Nulltes JSF-Beispiel (6/11) - Managed Bean [2/3] package entities; import java.io.serializable; import javax.faces.bean.managedbean; import javax.faces.bean.requestscoped; @ManagedBean(name="modul") @RequestScoped public class Modul implements Serializable { private static final long serialversionuid = 1L; private int nr; private String name; public Modul(){ public Modul(int nr, String name) { this.nr = nr; this.name = name; 243 public String uebernehmen(){ return "./ausgabe.xhtml"; public String eingeben(){ return "./index.xhtml"; public String getname() { return name; public void setname(string name) { this.name = name; public int getnr() { return nr; public void setnr(int nr) { this.nr = nr; //Manövrieren 244
Nulltes JSF-Beispiel (7/11) - Managed Bean [3/3] @Override public boolean equals(object object) { if (object==null!(object instanceof Modul)) return false; Modul other = (Modul) object; if (this.nr!= other.nr!this.name.equals(other.name)) return false; return true; @Override // generieren lassen public int hashcode() { int hash = 5; hash = 47 * hash + this.nr; hash = 47 * hash + (this.name!= null? this.name.hashcode() : 0); return hash; @Override public String tostring() {return name+"("+nr+")"; Nulltes JSF-Beispiel (8/11) - web.xml [1/2] Konfigurationsdatei für Servlets (hier benötigt) sun-web.xml ist Glassfish-spezifische Konfiguratonsdatei <?xml version="1.0" encoding="utf-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <context-param> <param-name>javax.faces.project_stage</param-name> <param-value>development</param-value> </context-param> <servlet> <servlet-name>faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.facesservlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> 245 246 Nulltes JSF-Beispiel (9/11) - web.xml [2/2] Nulltes JSF-Beispiel (10/11) - Projektstruktur <servlet-mapping> <servlet-name>faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <session-config> <session-timeout> 30 </session-timeout> </session-config> <welcome-file-list> <welcome-file>faces/index.xhtml</welcome-file> </welcome-file-list> </web-app> in sun-web.xml steht u. a. <context-root>/jsfspielerei2</context-root> 247 Applikation in Web-Archives (war-files) gepackt (gibt Strukturregeln) 248
Nulltes JSF-Beispiel (11/11) - Ergebnis Basisprinzip der Applikationssteuerung Im Controller: Aufruf einer Methode ohne Parameter vom Rückgabetyp String <h:commandbutton value="abschicken" action="#{modul.uebernehmen"/> Im Modell: public String uebernehmen(){ return "./ausgabe.xhtml"; Methode kann natürlich abhängig von Variablen unterschiedliche Seiten liefern Beachten: Navigation kann in den Tiefen des Codes verschwinden (-> Konstanten nutzen, Architektur) Hinweis: wir werden noch Varianten kennenlernen 249 250 Lebensdauer von Informationen (scope) None Request Session Application nur aktuelle Seite nur für einen Aufruf (auch für Weiterleitung) für eine Nutzer- Sitzung solange Zeit aktuelles Deployment läuft Anmerkung: Obwohl es verlockend ist, viele Informationen in Session oder Application zu legen, ist dies wg Performance verboten (wird gespeichert, evtl. passiviert, hat wilde Referenzen, Zugriff muss ggfls. synchronisiert werden) Scope-Beispiel (1/5) - Bean-Klasse //@ManagedBean(name = "modul") //@RequestScoped Modul als einfache Klasse (wichtig!) public class Modul implements Serializable {...// wie vorher @ManagedBean(name = "moduln") @NoneScoped public class ModulNone extends Modul{ @ManagedBean(name = "modulr") @RequestScoped public class ModulRequest extends Modul{ @ManagedBean(name = "moduls") @SessionScoped public class ModulSession extends Modul{ @ManagedBean(name = "modula") @ApplicationScoped public class ModulApplication extends Modul{ 251 252
Scope-Beispiel (2/5) - Ausschnitt index.xhtml <h:form> <h:panelgrid columns="3" > <h:outputlabel for="mnamen" value="modulname "/> <h:inputtext id="mnamen" value="#{moduln.name"/> <h:message for="mnamen" /> <h:outputlabel for="mnrn" value="modulnummer "/> <h:inputtext id="mnrn" value="#{moduln.nr"/> <h:message for="mnrn" /> <h:outputlabel for="mnamer" value="modulname "/> <h:inputtext id="mnamer" value="#{modulr.name"/> <h:message for="mnamer" /> <h:outputlabel for="mnrr" value="modulnummer "/> <h:inputtext id="mnrr" value="#{modulr.nr"/> <h:message for="mnrr" /> <!-- auch moduls und modula --> <h:commandbutton value="abschicken" action="#{modulr.uebernehmen"/> </h:panelgrid> 253 Scope-Beispiel (3/5) - Ausschnitt ausgabe.xhtml <h:form> <h:messages globalonly="true"/> <h:outputtext value="modulname n: "/> <h:outputtext id="mnamen" value="#{moduln.name"/> <br/> <h:outputtext value="modulnummer n: "/> <h:outputtext id="mnrn" value="#{moduln.nr"/><br/> <h:outputtext value="modulname r: "/> <h:outputtext id="mnamer" value="#{modulr.name"/> <br/> <h:outputtext value="modulnummer r: "/> <h:outputtext id="mnrr" value="#{modulr.nr"/><br/> <h:commandbutton value="zur Eingabe" action="#{modulr.eingeben"/><br/> <!-- auch moduls und modula --> <h:commandbutton value="ausgabe wiederholen" action="#{modulr.uebernehmen"/> </h:form> 254 Scope-Beispiel (4/5) - Ein Nutzer, zwei Klicks Scope-Beispiel (5/5) - Zwei Nutzer Nutzer 2 Nutzer 1 255 Zeit 256
Manövrieren vor JSF 2.0 Grundidee: Automat mit Seiten als Knoten (Zustände), Übergang findet durch String-Konstanten statt String-Konstanten sind Ergebnisse von (Action-) Methoden (oder stehen direkt in action="eingeben") index.xhtml ausgabe.xhtml 257 Manövrieren vor JSF 2.0 - faces-config.xml 1/2 <?xml version='1.0' encoding='utf-8'?> <faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"> <navigation-rule> <from-view-id>/index.xhtml</from-view-id> <navigation-case> <from-outcome>anzeigen</from-outcome> <to-view-id>/ausgabe.xhtml</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <from-view-id>/ausgabe.xhtml</from-view-id> <navigation-case> <from-outcome>eingeben</from-outcome> <to-view-id>/ index.xhtml </to-view-id> </navigation-case> </navigation-rule> 258 Manövrieren vor JSF 2.0 - Managed Bean // statt durch Annotationen können Beans auch in faces- // config.xml angelegt werden public class Modul implements Serializable { private static final long serialversionuid = 1L; private int nr; private String name; // fehlt: get- und set-methoden für Exemplarvariablen public Modul(){ public String uebernehmen(){ //Action-Methode // Zugriff auf Exemplarvariablen möglich return "ANZEIGEN"; public String eingeben(){ // Zugriff auf Exemplarvariablen möglich return "EINGEBEN";... 259 Manövrieren vor JSF 2.0 - faces-config.xml 2/2 <managed-bean> <managed-bean-name>modul</managed-bean-name> <managed-bean-class>entities.modul</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> </faces-config> Vorteil der klassischen Navigation: Es gibt zentrale Stelle, an der es einen Überblick über mögliche Abläufe gibt Nachteile: JSF 2.0 bietet flexiblere Ablaufsteuerung XML ist schwer nachvollziehbar Konfigurationsdatei faces-config.xml bleibt trotzdem wichtig 260
Erinnerung: Konstanten in Programmen schlecht return "ANZEIGEN"; besser: Konstanten getrennt deklarieren public class Modul implements Serializable{ private final static string ANZEIGEN = "ANZEIGEN";... return ANZEIGEN; Alternativ: Klasse mit Konstanten package konstanten; public class Navigation{ public final static string ANZEIGEN = "ANZEIGEN";... return konstanten.navigation.anzeigen; sumgebungen erlauben dann einfache Suche und Änderung (Refactoring) 261 Standardattribut rendered (1/3) JSF-Elemente werden typischerweise ineinander geschachtelt (typische GUI-Idee der Schächtelchen in Schächtelchen) viele (Schachtel-)Elemente haben Attribut rendered; Boolescher Wert, ob Element dargestellt werden soll @ManagedBean(name="mo") @SessionScoped public class Mojo { private boolean jo=true; public Mojo(){ public boolean getjo() {return jo; public void setjo(boolean jo) {this.jo = jo; public String change(){ jo=!jo; return "./index.xhtml"; 262 Standardattribut rendered (2/3) - JSF-Seite <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>klickklack</title> </h:head> <h:body> <h:form id="f1"> <h:panelgrid id="p1" rendered="#{mo.jo"> <h:outputlabel value= HS rocks"/> </h:panelgrid> <h:panelgrid id="p2" rendered="#{!mo.jo"> <h:outputlabel value="os rocks"/> </h:panelgrid> <h:commandbutton action="#{mo.change" value="press"/> </h:form> </h:body> </html> 263 Standardattribut rendered (3/3) <?xml version='1.0' encoding='utf-8'?> oder in <faces-config version="1.2"...> faces-config.xhtml <managed-bean> <managed-bean-name>mo</managed-bean-name> <managed-bean-class>entities.mojo</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> </faces-config> 264
Strukturierung mit panelgrid / Kommentare mit h:panelgridkönnen einzelne Komponenten zu einem Block zusammengefasst und einheitlich behandelt werden (ähnlich zu JPanel in Swing) weiterhin kann durch columns="3" eine Spaltenanzahl angegeben werden Ausgabe erfolgt in Tabellenform Elemente werden zeilenweise ergänzt echte JSF-Kommentare sehen wie folgt aus <%-- Dies liest eh keiner --%> 265