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)