Java EE - Department of Information Systems
Transcription
Java EE - Department of Information Systems
1 3.0 Java Platform, Enterprise Edition (Java EE) • Java Servlets und JSP-Seiten in Webzugangsschicht • Enterprise JavaBeans 3.0 zur Realisierung der Geschäftslogik 2 3.1 Java-Servlets • werden von Java-Laufzeitumgebung interpretiert, die in den Webserver (z.B. Apache) integriert wird • erlauben die dynamische Generierung von HTML-Seiten • zur Bearbeitung einer Anfrage: neuer Thread in JVM Webserver HTML Client Internet DB API response request JVM Servlet 3 Java-Servlets (Fortsetzung) • Servlets werden z.B. in speziellem Verzeichnis gesammelt • Server wird so konfiguriert, dass bei Zugriff hierauf das jeweilige Servlet ausgeführt wird • Anfrage an ein Servlet über HTTP, z.B.: http://servername/servlets/Welcome?name=Ute+Mai • Parameterübergabe und Ergebnis nicht über Umgebungsvariablen bzw. Standardein-/ausgabe (wie bei CGI) sondern komfortabler über vorgegebene Anfrage- und Antwort-Objekte (Argumente von doGet) 4 Beispiel: Java-Servlet import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class Welcome extends HttpServlet{ public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{ String name = req.getParameter("name"); if ((name==null) || (name.length()==0)) name = "Unbekannter"; res.setContentType("text/html"); PrintWriter out =res.getWriter(); out.println("<HTML> \n <HEAD> \n <TITLE>Hallo </TITLE> \n </HEAD>"); out.println("<BODY> \n <H1>Hallo "+name+".</H1>"); out.println("</BODY> \n </HTML>"); out.close();} } 5 Vorteile von Servlets • • • • effizienter als herkömmliche CGI-Skripte (Thread statt Prozess) Servlets ggf. über mehrere Anfragen hinweg im Hauptspeicher Code ggf. gemeinsam genutzt Servlet und Applet können kontinuierlich über beliebiges Protokoll (auch verschlüsselt) kommunizieren • Kommunikation von Servlets untereinander über gemeinsame Variablen/Objekte synchronisiert durch Java-“Monitore” • Servlets bieten komfortable Methoden zur Aufrechterhaltung einer Sitzung (session tracking; intern basierend auf Low-Level-Techniken wie Cookies) • (lange) Datenbanktransaktionen können hiermit leicht realisiert werden • Datenbankverbindungen (ggf. auch Connection-Pools) bleiben geöffnet 6 3.2 Java Server Pages (JSP) • Nachteil von Servlets: wenn Webseiten aus viel vorgefertigtem Text mit wenig Logik generiert werden, besteht das Servlet fast nur aus Ausgabe-Anweisungen • dann übersichtlicher: Logik (Java) in HTML-Seite integrieren • hierzu: JSP • JSP-Code wird intern in Servlets transformiert • eigene Tag-Libraries erlauben Trennung von Webdesign und Logik 7 JSP-Beispiel 1: Hallo <HTML> <HEAD><TITLE>Hallo</TITLE> <BODY> <H2>JSP-Beispiel</H2> <% if (request.getParameter("name") == null) out.println("Hallo!"); else out.println("Hallo "+request.getParameter("name")+"!"); %> <it>Herzlich willkommen!</it> </BODY></HTML> 8 JSP-Beispiel 2: Quadrat <HTML> <HEAD><TITLE>Quadrat</TITLE> <BODY> <%@ include file = "/kopf.html" %> <H2>JSP-Beispiel</H2> <%@ page session="false" %> <%@ page errorpage = "/error.jsp" %> <% String vorname = request.getParameter("vorname"); String nachname = request.getParameter("nachname"); int z = Integer.parseInt(request.getParameter("zahl")); if ((vorname == null) || (nachname == null)) throw new Exception("Bitte geben Sie Ihren Namen an!"); else out.println("Hallo "+vorname+" "+nachname+"!"); %> Das Quadrat der von Ihnen eingegebenen Zahl <%= z %> ist <font color=red><%= quadrat(z) %></font>. <%@ include file = "/fuss.html" %> </BODY></HTML> <%! private int quadrat(int x){return x*x;} %> 9 Vordefinierte Variablen • verwendbar im Java-Code innerhalb einer JSP-Seite • HttpServletRequest request • HttpServletResponse response • javax.servlet.jsp.JspWriter out • HttpSession session • ServletContext application • javax.servlet.jsp.PageContext pageContext 10 JSP-Features <% c %> Java-Code c wird ausgeführt <%= e %> Java-Ausdruck e wird ausgewertet und das Ergebnis als String eingefügt <%! d %> Java-Deklaration d wird vor der Hauptservlet-Methode (doGet) in das generierte Servlet eingefügt <%@ d %> Direktive d wird zur Transformationszeit ausgeführt z.B. Cookies abschalten, Fehlerbehandlungsseite festlegen, Datei einfügen <jsp:useBean . . . > </jsp:useBean> <jsp:include page =”/my.jsp” > </jsp:include> <jsp:forward page=”login.jsp”> </jsp:foward> JavaBean (6= EJB) einfügen Datei zur Zugriffszeit einfügen Zugriff umlenken 11 Frameworks für Benutzerschnittstellen von Webapplikationen • Struts basiert auf Entwurfsmuster Model-View-Controller (MVC) • (z.B.) Servlets für Controller, EJBs für Model, JSP für View • insbesondere geeignet für konplexe Systeme von dynamischen Webseiten • Weiterentwicklung: JavaServer Faces 12 3.3 Enterprise JavaBeans • Java-basierte Middleware für verteilte OO-Anwendungen • Komponenten (Beans) werden in EJB-Container (in Server) bereitgestellt • EJB Container: z.B. BEA WebLogic, IBM WebSphere, Sun J2EE, JBoss . . . • Dienste des Containers: (u.a.) ? ? ? ? ? ? Verwaltung und Suche von Beans (Namensdienst basierend auf JNDI) Transaktionen (basierend auf JTS und JTA) Persistenz Zugriff auf entfernte Objekte (basierend auf RMI/IIOP bzw. JMS) Ressourcenverwaltung (Instance Pooling, Ein-/Auslagerung von Beans) Autorisierung und Authentifizierung (basierend auf JAAS) • Vorteil: Basisdienste bei Anwendungsentwicklung “geschenkt” • Nachteil: Overhead; keine BS-Aufrufe (wegen Transaktionen) 13 Enterprise JavaBeans (Fortsetzung) • typische 4-Schichten-Architektur: ? ? ? ? Client Tier (HTML) Web Tier (JSP,Servlets) Business Tier (EJB) EIS Tier (DB) 14 Arten von Beans • Entity-Bean: ? kapselt persistente Daten ? Zugriff über Session-Bean (oder anderes Entity-Bean) • Session-Bean: ? ? ? ? realisiert Geschäftslogik (z.B. Use-Case) nicht persistent Zugriff von Servlet oder Java-Client aus basierend auf RMI Variante 1: zustandslos ∗ effizient gemeinsam nutzbar durch mehrere Clients ∗ lokale Variablen möglich ∗ jede Anfrage einer Sitzung wird i.d.R. von einem anderen Bean bearbeitet ? Variante 2: zustandsbehaftet ∗ exklusiv für einen Client ∗ Zustand über eine Sitzung (mit mehreren Anfragen) hinweg mitgeführt ∗ Zustand bei Absturz verloren • Message-driven Bean: reagiert auf Ereignis (typischerweise asynchron) 15 Aufbau eines Enterprise JavaBeans • Remote Interface (bzw. Local Interface bei ausschließlich lokalem Zugriff) für “Business”-Methoden (nur bei Session-Beans) • Verwaltungsoperationen (bis EJB 2.X in Home Interface) nun transparent (z.B. Erzeugen, Löschen, Aktivieren, Passivieren) • Bean-Klasse: ? Implementierung der Business-Methoden ? ab EJB 3.0 “POJO” (normales Java-Objekt) • optionaler Deployment Descriptor: ? XML-Dokument zur Konfiguration eines Beans u.a. bzgl. Persistenz, Assoziationen (“Relationen”), Transaktionen und Primärschlüssel ? ab EJB 3.0 i.d.R. ersetzt durch Annotationen in Bean-Klasse • alles zusammengefasst in .jar-Archiv (Packaging) 16 EJB 3.0-Programmiermodell EJB−Container JVM Remote Local Client Client Middleware−Dienste: − Lebenszyklus−Management − Persistenz −Zugriffsschutz Business Container−erzeugte Interface Wrapper−Klasse EJB−Klasse −Transaktionen ... 17 Deployment • Bean wird gemäß Annotationen bzw. Deployment Descriptor konfiguriert und im Container bereitgestellt • hierbei werden Hilfsklassen zur Einbindung der Bean-Klasse in den Container automatisch erstellt und compiliert • wahlweise komfortable Container-verwaltete Persistenz oder flexiblere Bean-verwaltete Persistenz (mit expliziten JDBC-Aufrufen) • wahlweise Container- oder Bean-verwaltete Transaktionen 18 Beispielanwendung: Bibliothek Ausleihe Exemplar 0..1 datum 1 inventarnr Medium * 1 bezeichnung * 1 Benutzer Buch CD name autor interpret adresse isbn asin 19 Entity-Bean: Klasse Benutzer package bibliothek; import java.util.ArrayList; @Entity public class protected protected protected protected import java.util.Collection; import javax.persistence.*; Benutzer implements java.io.Serializable { int bid; /** Primärschlüssel */ String name; String adresse; Collection<Ausleihe> ausleihen = new ArrayList<Ausleihe>(); @Id @GeneratedValue(strategy=GenerationType.AUTO) public int getBid(){return bid;} public void setBid(int id){bid = id;} public String getName(){return name;} public void setName(String name){this.name = name;} public String getAdresse(){return adresse;} public void setAdresse(String adresse){this.adresse = adresse;} @OneToMany(cascade = CascadeType.ALL, mappedBy="benutzer") public Collection<Ausleihe> getAusleihen(){return ausleihen;} public void setAusleihen(Collection<Ausleihe> coll){ausleihen = coll;} public void addAusleihe(Ausleihe vorgang){ausleihen.add(vorgang);} public void removeAusleihe(Ausleihe vorgang){ausleihen.remove(vorgang);} } 20 Entity-Bean: Klasse Ausleihe ... @Entity public class protected protected protected protected Ausleihe implements java.io.Serializable { int id; Date datum; Benutzer benutzer; Exemplar exemplar; @Id @GeneratedValue(strategy=GenerationType.AUTO) public int getId(){return id;} public void setId(int id){this.id = id;} public Date getDatum(){return datum;} public void setDatum(Date d){datum = d;} @ManyToOne @JoinColumn(name = "benutzer") public Benutzer getBenutzer(){return benutzer;} public void setBenutzer(Benutzer b){ benutzer = b; b.addAusleihe(this);} @OneToOne @JoinColumn(name= "exemplar") public Exemplar getExemplar(){return exemplar;} public void setExemplar(Exemplar e){ exemplar = e; e.setAusleihe(this);} } 21 Entity-Bean: Klasse Exemplar ... @Entity public class Exemplar implements java.io.Serializable{ protected int inventarnr; protected Medium medium; protected Ausleihe ausleihe; @Id @GeneratedValue(strategy=GenerationType.AUTO) public int getInventarnr(){return inventarnr;} public void setInventarnr(int nr){inventarnr = nr;} @ManyToOne @JoinColumn(name = "medium") public Medium getMedium(){return medium;} public void setMedium(Medium m){medium = m; m.addExemplar(this);} @OneToOne(cascade = CascadeType.ALL, mappedBy="exemplar") public Ausleihe getAusleihe(){return ausleihe;} public void setAusleihe(Ausleihe a){ausleihe = a;} } 22 Entity-Bean: Klasse Medium ... @Entity @Inheritance(strategy=InheritanceType.SINGLE TABLE) public abstract class Medium implements java.io.Serializable{ protected int id; protected String bezeichnung; protected Collection<Exemplar> exemplare; @Id @GeneratedValue(strategy=GenerationType.AUTO) public int getId(){return id;} public void setId(int id){this.id = id;} public String getBezeichnung(){return bezeichnung;} public void setBezeichnung(String b){bezeichnung = b;} @OneToMany(cascade = CascadeType.ALL, mappedBy="medium") public Collection<Exemplar> getExemplare(){return exemplare;} public void setExemplare(Collection<Exemplar> coll){exemplare = coll;} public void addExemplar(Exemplar e){exemplare.add(e);} public void removeExemplar(Exemplar e){exemplare.remove(e);} } 23 Entity-Bean: Klasse Buch ... @Entity public class Buch extends Medium implements java.io.Serializable{ protected String isbn; protected String autor; public String getISBN(){return isbn;} public void setISBN(String nr){isbn = nr;} public String getAutor(){return autor;} public void setAutor(String a){autor = a;} } Klasse CD analog 24 Beispiel: Session-Bean ... @Remote public interface BenutzerFassade { public void benutzerAnlegen(String name, String adresse) throws Exception; } ... @PermitAll @Stateless public class Benutzerverwaltung implements BenutzerFassade{ @PersistenceContext private EntityManager em; @TransactionAttribute(TransactionAttributeType.REQUIRED) public void benutzerAnlegen(String name, String adresse) throws Exception{ Query q = em.createQuery("SELECT COUNT(*) FROM Benutzer b WHERE b.name = :n"); q.setParameter("n",name); if (((Long) q.getSingleResult()).intValue() == 0){ Benutzer benutzer = new Benutzer(); benutzer.setName(name); benutzer.setAdresse(adresse); em.persist(benutzer);} else throw new Exception("Name bereits verwendet"); } } 25 Erläuterungen zum Beispiel • Annotationen bestimmen, ob es sich um eine Entity-Bean (@Entity) oder Session-Bean (@Stateless,@Stateful) handelt Einstellungen von Entity-Beans: • den Primärschlüssel eines Entity-Beans legt die Annotation (@Id) fest • bei Vererbungshierachien lässt sich durch die Annotation @Inheritance die Abbildungsstrategie auf eine relationale DB festlegen (SINGLE TABLE, TABLE PER CLASS, JOINED) (Details später!) 26 Erläuterungen zum Beispiel (Fortsetzung) Einstellungen von Session-Beans: • Annotationen regeln die Zugriffsrechte auf Klassen und Methoden (@PermitAll, @DenyAll (nur bei Methoden), @RolesAllowed(“Rolle”), @RunAs(“Rolle”)) • die Annotation @TransactionManagement(BEAN) stellt von der voreingestellten Container-verwalteten Transaktionsverwaltung auf Bean-verwaltete um • durch die Annotation @TransactionAttribute lässt sich einstellen, wie eine Methode in eine Transaktion eingebunden werden soll (MANDATORY, NOT SUPPORTED, REQUIRED (default!), REQUIRES NEW, SUPPORTS) 27 Beziehungen von Entity-Beans • bei ?:1-Beziehungen erhält die Klasse ein Attribut vom Typ der Nachbarklasse (und entsprechende getter und setter) • bei ?:N-Beziehungen erhält die Klasse ein Attribut vom Typ Collection<Nachbarklasse> (z.B. ArrayList) • die Multiplizität (@OneToOne, @OneToMany, @ManyToOne, @ManyToMany) wird vor dem zugehörigen getter oder dem Attribut annotiert • bei bidirektionalen Assoziationen ist eine Seite für die Konsistenz verantwortlich • bei ?:N-Beziehungen sollte die/eine “N-Seite” hierfür verantwortlich sein • die verantwortliche Seite verwendet friend-Methoden der Gegenseite zur Konsistenzerhaltung 28 Parameter von Multiplizitätsannotationen • der Parameter cascade gibt an, ob die Nachbarobjekte mit dem Objekt aktualisiert, (persistent) geändert und/oder gelöscht werden sollen (@ALL, @MERGE, @REMOVE, @PERSIST, @REFRESH) • bei @ManyToMany wird intern eine Mappingtabelle in der DB verwendet • die Annotation @JoinTable erlaubt, Details der Mappingtabelle festzulegen • der Parameter fetch gibt an, ob die Nachbarobjekte mit dem Objekt gemeinsam aus der DB geladen werden sollen (default ?:1: EAGER, default ?:N: LAZY) • der Parameter optional gibt an, ob Nullwerte für Nachbarobjekte erlaubt sind • die nicht verantwortliche Seite verwendet den Parameter mappedBy zur Festlegung des Fremdschlüssels der Gegenseite 29 Besonderheiten von Entity-Beans • Container-verwaltete Entity-Beans sind nicht direkt “von außen” (aus anderer JVM) zugreifbar • sie können aber als Ergebnis an Clients geliefert werden • hierdurch werden sie “detached”, d.h. der Container verwaltet sie nicht mehr • spezielle Ergebnisübermittlungsklassen (Data Transfer Objects) sind daher ab EJB 3.0 nicht mehr erforderlich • Entity-Beans müssen (u.a.) zur Übermittlung serialisierbar sein • bei der Übermittlung verlieren Entity-Beans ggf. ihre Verbindung zu “lazy” geladenen Nachbarobjekten • Entity-Beans und ihre Attribute dürfen nicht final sein 30 Lebenszyklus von Entity-Beans new() new persist() merge() find() Queries refresh() remove() removed managed persist() flush() merge() clear() close() serialize() commit rollback detached flush() commit 31 Transformation von Klassen in Relationen Person Nr. Name OID Nr Person Vorname Nachname • Abb. von Attributtyp auf SQL-Typ, ggf. über eingebettete Relation create table Person ( OID number(8) not null, Nr number(8) not null, Vorname char(20), Nachname char(20) not null, primary key (Nr) ); create secondary index PersonIndex on Person(Nachname); (@Embeddable,@Embedded) • (ggf.) OID-Spalte hinzufügen • Primärschlüssel festlegen (@Id) • optionale Attribute festlegen • ggfs. Index anlegen 32 Behandlung von Assoziationen (vgl. Vorlesung Datenmanagement) • bei 1 : m-Assoziation/Komposition (m ≥ 1): Fremdschlüssel K1 A1 A2 K2 1 OID1 K1 A1 K2 A2 OID2 A3 A4 OID1 * A3 A4 • bei n : m-Assoziation/Komposition (n, m > 1): Zuordnungstabelle K1 A1 A2 K2 * * A3 A4 OID1 K1 A1 A2 OID2 K2 A3 A4 K1−2 OID1 OID2 33 Alternativen zur Transformation von Vererbung a) eigene Tabelle pro Klasse ? ? ? ? alle Tabellen enthalten Primärschlüssel kleine Schemata, aber aufgespaltene Informationen (1: Effizienzverlust) 3NF JavaEE-Annotation @Inheritance(strategy = InheritanceType.JOINED) Person Person OID Name 27 Mai 42 Noll Name Kunde Umsatz Mitarbeiter Gehalt Kunde OID Umsatz 27 3212 Mitarbeiter OID Gehalt 42 4619 34 Alternativen zur Transformation von Vererbung (2) b) vervollständigte Tabellen OID 27 Kunde Name Umsatz Mai 3212 OID 42 Mitarbeiter Name Gehalt Noll 4619 ? zu jeder konkreten Klasse eigene Tabelle mit allen Attribute (auch geerbten) ? alle Oberklassenattribute in Unterklassentabellen übernehmen ? Effizienzverlust durch Unions bei Zugriff auf Oberklasse ? geeignet, wenn wenige Oberklassenattribute ? 3NF ? JavaEE-Annotation @Inheritance(strategy = InheritanceType.TABLE PER CLASS) 35 Alternativen zur Transformation von Vererbung (3) c) eine Tabelle für gesamte Verbungshierarchie OID 27 42 Name Mai Noll Person Gruppe Umsatz Kunde 3212 Mitarb. NULL Gehalt NULL 4619 ? alle Unterklassenattribute in Oberklassentabelle übernehmen ? geeignet, wenn wenige Unterklassen mit wenigen Attributen ? null-Werte für fehlende Attribute ? verletzt 3NF ? JavaEE-Annotation @Inheritance(strategy = InheritanceType.SINGLE TABLE)