2. Kapitel - JBoss Seam - Die Web-Beans
Transcrição
2. Kapitel - JBoss Seam - Die Web-Beans
JBoss Seam Kapitel 2: Seam als modernes Komponenten-Framework Max Mustermann Uni Musterhausen Fachbereich Informatik Wintersemester 2008/09 Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 1 / 41 Grundlage der Folien Bernd Müller JBoss Seam Die Web-Beans-Implementierung Hanser ISBN 978-3-446-41190-6 34,90 Euro Bei Amazon kaufen Home-Page: www.webbeans.eu Überblick I Java-EE 5 I I I I I I als Reaktion auf Kritik an J2EE 1.4 (und früher) I I I I Servlets 2.5 (JSR 154) JSP 2.1 (JSR 254) JSF 1.2 (JSR 252) EJB 3.0 / JPA 1.0 (JSR 220) und einige mehr verwendet POJO Annotationen, weniger XML, insgesamt weniger aufwändig verwendet Dependency-Injection Seam geht weiter I I integriert EJB und JSF in einheitlichem Komponentenmodell und vereinfacht die Verwendung von Java-EE 5 (EJBs, JPA und JSF) Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 3 / 41 2.1 JSF und Facelets JSF und Facelets Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 4 / 41 2.1 JSF und Facelets Facelets I JSF ist renderunabhängig, Default HTML auf Basis von JSPs I Facelets einfacher und mächtiger als JSPs (und mit JSF 2.0 Standard) I hervorzuheben: Template-Mechanismus für Seiten I Tags: <ui:component>, <ui:composition>, <ui:debug>, <ui:decorate>, <ui:define>, <ui:fragment>, <ui:include>, <ui:insert>, <ui:param>, <ui:remove>, <ui:repeat> Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 5 / 41 2.2 EJBs und JPA EJBs und JPA Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 6 / 41 2.2 EJBs und JPA Enterprise JavaBeans (EJB) I Session-Beans I I Stateless (@Stateless) Stateful (@Stateful) I Entity-Beans (@Entity) I Message-Driven-Beans (@MessageDriven) verwenden wir nicht I alle im Package javax.ejb Literatur: I I I Bill Burke, Richard Monson-Haefel. Enterprise JavaBeans 3.0. O’Reilly, 2006. Bernd Müller, Harald Wehr. Java-Persistence-API mit Hibernate. Addison-Wesley, 2007. Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 7 / 41 2.2 EJBs und JPA Enterprise JavaBeans II I I I I I I Session-Beans definieren Schnittstelle zur Client-Anwendung und realisieren Anwendungsfälle und Geschäftsprozesse z.B. neues Konto (Entity) anlegen, Überweisung durchführen zustandslose Session-Beans besitzen keinen für den Client sichtbaren Zustand, der Container kann sie daher beliebigen Clients zuweisen (Pool!) zustandsbehaftete Session-Beans besitzen einen solchen Zustand in Java-EE typischerweise an HTTP-Session gebunden, Seam kennt weitere Kontexte eine Session-Bean kann I I I ein remote Interface implementieren ein lokales Interface implementieren (@Local) Namenskonventionen: I I I Java-EE-Tutorial Bean“ ” Seam-Doku/Beispiele Action“ ” wir Handler“und HandlerLocal“ ” ” Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 8 / 41 2.2 EJBs und JPA Enterprise JavaBeans III I Entity-Beans: I I I persistente Business-Objekte über JPA-Annotationen auf Datenbank abgebildet @Entity und @Id für einfache Fälle bereits ausreichend Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 9 / 41 2.3 Seam-Komponenten Seam-Komponenten Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 10 / 41 2.3 Seam-Komponenten Ziele I Verwendung von POJOs anstatt Interfaces implementieren oder von Oberklassen erben zu müssen I Minimierung von XML-Konfigurationen (XML-Hölle) I JSF ist ein Komponenten-Framework, EJB ist ein Komponenten-Framework, Seam verbindet beide (plus vieles mehr) I Komponenten werden von Seam verwaltet I Abhängigkeiten werden durch Dependency-Injection bzw. Bijection aufgelöst Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 11 / 41 2.3 Seam-Komponenten Neue Kontexte I Stateless Komponenten dieses Kontextes können keinen Zustand verwalten. I Event Komponenten dieses Kontextes halten ihren Zustand während der Bearbeitung einer einzelnen JSF-Anfrage. I Page Komponenten dieses Kontextes halten ihren Zustand bzgl. einer gerenderten JSF-Seite. I Conversation Komponenten dieses Kontextes halten ihren Zustand über eine Konversation, d.h. eine Reihe von JSF-Anfragen. I Session Komponenten dieses Kontextes halten ihren Zustand in der entsprechenden HTTP-Session. Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 12 / 41 2.3 Seam-Komponenten Neue Kontexte II I Business-Process Komponenten dieses Kontextes halten ihren Zustand über einen länger andauernden Geschäftsprozess. I Application Komponenten dieses Kontextes sind statisch und entsprechend global. Besonders hervorzuheben: I Konversationen (kleiner als Session) I Geschäftsprozesse (mehrere involvierte Benutzer, überleben Ein-/Ausloggen und Server-Neustart) Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 13 / 41 2.4 Das Anwendungsbeispiel Das Anwendungsbeispiel Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 14 / 41 2.4 Das Anwendungsbeispiel Anwendungsbeispiel I zur Einführung ein kleines Beispiel I Online-Banking I einfache Anwendungsfälle I einfache Daten I jedem bekannt Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 15 / 41 2.4 Das Anwendungsbeispiel Die Daten (Entities) Attributes Attributes Attributes Operations Operations Operations Attributes Attributes Attributes Operations Operations Operations Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 16 / 41 Stammdaten < h:form id = " stammdaten " > < s:validateAll > < f:facet name = " afterInvalidField " > < s:div styleClass = " errors " > < h:graphicImage url = " / images / error_small . png " / > < s:message / > </ s:div > </ f:facet > < div class = " usrFormEntry " > < h:outputLabel for = " nachname " styleClass = " usrFormLabel " > Anrede: </ h:outputLabel > < h:selectOneMenu id = " anrede " value = " #{ kunde . geschlecht } " styleClass = " usrFormValue " > < f:selectItem itemLabel = " Frau " itemValue = " w " / > < f:selectItem itemLabel = " Herr " itemValue = " m " / > </ h:selectOneMenu > </ div > ... Stammdaten II ... < div class = " usrFormEntry " > < h:outputLabel for = " nachname " styleClass = " usrFormLabel " > Vorname: </ h:outputLabel > < s:decorate > < h:inputText id = " vorname " value = " #{ kunde . vorname } " required = " true " styleClass = " usrFormValue " </ s:decorate > </ div > ... </ s:validateAll > < h:commandButton action = " #{ stammdatenHandler . speichern } " value = " Speichern " styleClass = " usrFormSubmit " </ h:form > 2.4 Das Anwendungsbeispiel Analyse I ganz normale JSF-Seite mit Ausnahmen: I I <s:validateAll> <s:decorate> I <s:validateAll> validiert alle Eingabekomponenten anhand der Validierungsbedingungen der Modell-Properties (z.B. @Length, siehe Entity ) I <s:decorate> dekoriert bei einem Validierungsfehler die Eingabekomponente (Abbildung folgt) Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 19 / 41 Seite mit Menü- und Fußzeileneinbindung <! 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:ui = " http: // java . sun . com / jsf / facelets " xmlns:h = " http: // java . sun . com / jsf / html " xmlns:f = " http: // java . sun . com / jsf / core " xmlns:s = " http: // jboss . com / products / seam / taglib " > < head > < title > Stammdaten </ title > </ head > < body > < ui:include src = " menu . xhtml " / > < div id = " cTitle " > Stammdaten </ div > < div id = " ... " > < h:form id = " stammdaten " > ... </ h:form > </ div > < ui:include src = " footer . xhtml " / > </ body > </ html > 2.4 Das Anwendungsbeispiel Darstellung Stammdaten Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 21 / 41 2.4 Das Anwendungsbeispiel Darstellung Stammdaten mit Fehlermeldung Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 22 / 41 Entity Kunde @Entity @Scope ( SESSION ) @Name ( " kunde " ) public class Kunde implements Serializable { private private private private private private private private Integer id ; String vorname ; String nachname ; Date geburtsdatum ; Character geschlecht ; String kundennummer ; String passwort ; Set < Konto > konten = new HashSet < Konto >(); public Kunde () { super (); } ... 2.4 Das Anwendungsbeispiel Analyse I @Entity: JPA-Annotation für Persistenz I Convention over Configuration oder Configuration by Exception: sinnvolle Default-Annahmen für Persistenz: I I I Klassen- gleich Tabellenname alle Properties persistent, selber Spaltenname (nicht persistent: @Transient) einfaches Typ-Mapping I @Scope: Seam-Kontext I @Name: Name der Seam-Komponente Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 24 / 41 Entity Kunde II ... @Id @GeneratedValue ( strategy = GenerationType . IDENTITY ) public Integer getId () { return this . id ; } public void setId ( Integer id ) { this . id = id ; } @Column ( nullable = false ) @Length ( min = 3 , max = 30 , message = " Vorname muss zwischen 3 und 30 Zeichen lang sein " ) public String getVorname () { return this . vorname ; } public void setVorname ( String vorname ) { this . vorname = vorname ; } 2.4 Das Anwendungsbeispiel Analyse I @Id: Primärschlüssel in Datenbanktabelle I wenn Getter/Setter annotiert, erfolgt für alle Propertes Zugriff über Getter/Setter I @GeneratedValue: Primärschlüssel soll generiert und nicht durch Anwendung vergeben werden. Verschiedene Generierungsarten möglich. I @Column: JPA-Annotation, hier: nicht null I @Length: Hibernate-Validator-Annotation mit offensichtlicher Semantik Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 26 / 41 Entity Kunde III ... @Column ( nullable = false ) @Temporal ( TemporalType . DATE ) public Date getGeburtsdatum () { return this . geburtsdatum ; } public void setGeburtsdatum ( Date geburtsdatum ) { this . geburtsdatum = geburtsdatum ; } @Column ( nullable = false , unique = true ) public String getKundennummer () { return kundennummer ; } public void setKundennummer ( String kundennummer ) { this . kundennummer = kundennummer ; } ... 2.4 Das Anwendungsbeispiel Analyse I @Temporal: java.util.Date Zeitstempel mit Millisekunden, muss auf verschiedene SQL-Datentypen abgebildet werden I möglich sind DATE, TIME, TIMESTAMP I @Column(..., unique = true): Constraint Spalte hat keine Duplikate Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 28 / 41 Entity Kunde IV ... @OneToMany ( mappedBy = " kunde " , cascade = CascadeType . ALL ) public Set < Konto > getKonten () { return this . konten ; } public void setKonten ( Set < Konto > konten ) { this . konten = konten ; } ... 2.4 Das Anwendungsbeispiel Analyse I @OneToMany: 1:n-Beziehung zur Klasse Konto I mappedBy: Property für Beziehung (in DB Fremdschlüsselspalte) I cascade: welche Persistenzoperationen sollen automatisch weitergegeben werden? Hier: alle Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 30 / 41 2.4 Das Anwendungsbeispiel Erleichterungen für Entwicklung und Deployment I Generierung des DB-Schemas beim Deployment, falls erwünscht. Hier für HSQLDB: create table Kunde ( id integer generated by default as identity ( start with 1) , vorname varchar (30) not null , nachname varchar (30) not null , geburtsdatum date not null , geschlecht char (1) not null , kundennummer varchar (255) not null , passwort varchar (255) not null , primary key ( id ) , unique ( kundennummer ) ) I Hibernate (im JBoss-AS) lädt beim Deployment Datei import.sql, falls vorhanden. Testdaten!!! Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 31 / 41 2.4 Das Anwendungsbeispiel Wie finden GUI und Persistenz zueinander? I Seam verwalten Netz von Abhängigkeiten zwischen Komponenten I existiert eine Komponente noch nicht, wird sie erzeugt I es können auch anwendungserzeugte Komponenten an Seam zurückgegeben werden I Abhängigkeiten werden also in beide Richtungen aufgelöst I neue Wortschöpfung: Dependency-Bijection, kurz Bijection I analog zu Injection: Outjection I die JSF-Seite zur Stammdatenverwaltung verwendet "#{kunde.vorname}", also direkt ein Entity (@Name("kunde")) I dies werden wir jetzt beim Anmelden erzeugen und outjecten“ ” Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 32 / 41 Die Anmeldeseite < h:form id = " anmeldung " > < div class = " usrFormEntry " > < h:outputLabel for = " kundennummer " styleClass = " usrFormLabel " Kundennummer: </ h:outputLabel > < h:inputText id = " kundennummer " value = " #{ loginHandler . kundennummer } " required = " true " styleClass = " usrFormValue " / > </ div > < div class = " usrFormEntry " > < h:outputLabel for = " passwort " styleClass = " usrFormLabel " > Passwort: </ h:outputLabel > < h:inputSecret id = " passwort " value = " #{ loginHandler . passwort required = " true " styleClass = " usrFormValue " / > </ div > < div class = " usrFormEntry " > < h:commandButton action = " #{ loginHandler . login } " value = " Anmelden " styleClass = " usrFormSubmit " / > </ div > </ h:form > 2.4 Das Anwendungsbeispiel Analyse I nichts bsonderes I es muss alles im loginHandler geschehen Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 34 / 41 2.4 Das Anwendungsbeispiel Die Komponente loginHandler @Stateless @Scope ( SESSION ) @Name ( " loginHandler " ) public class LoginHandler implements Lo ginHan dlerLo cal { @Pers is t e nc e C o nt e x t private EntityManager em ; @Out private Kunde kunde = new Kunde (); private String kundennummer ; private String passwort ; ... Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 35 / 41 2.4 Das Anwendungsbeispiel Analyse I Stateless Session-Bean I bekommt vom Container den Entity-Manager injiziert (ist EJB 3.0, nicht Seam) I gibt Seam die Komponente kunde zurück (Name der Komponente ist Variablenname) I kundennummer und passwort aus GUI I wie wird kunde erzeugt? Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 36 / 41 2.4 Das Anwendungsbeispiel Die Komponente loginHandler II public String login () { Query query = em . createQuery ( " select k from Kunde k " + " where k . kundennummer = : kundennummer " + " and k . passwort = : passwort " ); List l = query . setParameter ( " kundennummer " , kundennumme . setParameter ( " passwort " , passwort ) . getResultList (); if ( l . size () == 1) { kunde = ( Kunde ) l . get (0); return " / stammdaten . xhtml " ; } else { FacesMessages . instance () . add ( " Falsche Kundennummer / Passwort - Kombination " return null ; } } Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 37 / 41 2.4 Das Anwendungsbeispiel Analyse I JPA-Query (einfach zu verstehen) I wird mit Parametern aus GUI versehen I return "/stammdaten.xhtml": Seam erlaubt auch direkte Navigation ohne Navigationsregeln in faces-config.xml I einfaches Erzeugen von JSF-Messages Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 38 / 41 2.4 Das Anwendungsbeispiel Die Stammdatenverwaltung I war einfache JSF-Seite ( I mit direkter Verwendung von Entity-Properties I und mit Action-Methode speichern() in der Komponente stammdatenHandler (nächste Seite) stammdaten.xhtml ) Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 39 / 41 Komponente stammdatenHandler @Stateful @Scope ( SESSION ) @Name ( " stammd atenHa ndler " ) public class Sta mmdatenHandler implements S t am mda te nH an dle rL oc al { @Persis t e nc e C on t ext ( type = EXTENDED ) private EntityManager em ; @In @Out private Kunde kunde ; public String speichern () { em . merge ( kunde ); return null ; } @Destroy @Remove public void destroy () {} } 2.4 Das Anwendungsbeispiel Analyse I I @In, @Out: Bijection (beide Richtungen) speichern()-Methode sehr einfach I I I merge() vereinigt den Zustand des Entities mit dem aktuellen Persistenzkontext alle Methoden laufen in Java-EE default-mäßig in einer Transaktion, daher kein manueller Transaktions-Code @Destroy und @Remove sind die Seam- und Java-EE-Annotationen fürs Aufräumen“. Müssen bei zustandsbehafteter Session-Bean ” vorhanden sein. Max Mustermann (FBI, Uni Musterhausen) JBoss Seam Kapitel 2: Komponenten-Framework WS 2008/09 41 / 41