Enterprise Java Beans - Teil 3

Werbung
Enterprise Java Beans - Teil 3
■ Transaktionenssteuerung in EJB
■ Message-Driven Beans (MDB) und Java Message Service
■ EJB3: Interceptors
■ Web Services
Transaktionen
School of Engineering
© K. Rege, ZHAW
2 von 74
Transaktionen
■ Transaktionen sind essentiell, wenn es um die Datenkonsistenz geht
■
Änderungen in der einen Tabelle können andere implizieren
■ Standard Beispiel: Überweisung
■
KontoA = KontoA - Betrag
■
KontoB = KontoB + Betrag
■ Es darf weder der Betrag verloren gehen noch darf der Betrag zweimal
gutgeschrieben werden
■ Lösung: Beide Operationen werden innerhalb einer Transaktion durchgeführt
■ Dabei gilt das ACID Prinzip für Transaktionen
■
■
■
■
Atomicity: Jede Transaktion wird ganz oder gar nicht ausgeführt.
Consistency: Transaktionen hinterlassen die Datenbank in einem konsistenten Zustand (wenn sie
vorher konsistent war).
Isolation: Transaktionen erscheinen, als wenn sie hintereinander (sequentiell) ausgeführt würden.
Durability: Wenn eine Transaktion erfolgreich beendet ist, sind ihre Änderungen an Daten persistent.
■ Der EJB Container soll das Entwickeln von Komponenten mit ACID
Transaktionen unterstützen und erleichtern
School of Engineering
© K. Rege, ZHAW
3 von 74
Einfache Transaktionen
■ Pseudocode für transaktionale Logik (TX-Logik)
Beginn Transaction
KontoA = KontoA - Betrag
KontoB = KontoB + Betrag
Connection c = …
try {
c.autoCommit(false)
…
c.commit() }
catch () {
c.rollback(); }
Wenn kein Fehler
Commit Transaction
Sonst
Rollback Transaction
■ Transaktionen wird von JDBC unterstützt
■
über Connection Object
■
Transaktion wird bei der ersten Operation gestartet
autoCommit muss aber auf false gesetzt werden
■
■ Problem bei dieser Lösung
■
Es können mehrere Datenbanken (Ressourcen) an einer Transaktion beteiligt sein
■
Bei allen involvierten Transaktionsteilnehmern muss die entsprechende Aktion (z.B. Commit)
ausgeführt werden
School of Engineering
© K. Rege, ZHAW
4 von 74
Bean Managed Transaction Demarcation
(BMTD/JTA)
■ Steuerung über das Java Transaction API (JTA)
■
■
Ermöglicht das Setzen der Transaktionsgrenzen (Transaction Demarcation) unabhängig von
eigentlichen Ressourcen (z.B. DB Connections)
Der EJB Container übernimmt die Koordination (Transaction Manager) und "kennt" alle
involvierten Ressourcen (z.B. JDBC Connections, EntityManger, etc.) und ruft diese entsprechend
auf
■ Der Aufruf über das javax.transaction.UserTransaction Objekt
■
■
wird vom SessionContext Objekt zur Verfügung gestellt
um BMTD zu verwenden muss die oder Klasse (oder Methode) mit
@TransactionManagement(BEAN) annotiert sein
import javax.ejb.*;
@TransactionManagement(TransactionManagementType.BEAN)
@Stateless
public class BankService {
@Resource SessionContext ctx;
@PersistenceContext EntityManager em;
public void transfer(int accA,int accB, double amount){
try {
UserTransaction utx = ctx.getUserTransaction()
utx.begin();
em.find(Account.class, accId).withdraw(amount);
em.find(Account.class, accId).deposit(amount);
utx.commit();
} catch (Exception e) {
utx.rollback();
}
School of Engineering
© K. Rege, ZHAW
5 von 74
Vom Klienten gesteuerte Transaktion
■ Klient ist anderes EJB oder "echter" Klient (JSF)
■ Auch "echter" Klient kann Transaktion steuern
■
■
eher zurückhalten verwenden
nie über unsicheres/instabiles Netzwerk (Internet)
begin
Client
Methoden Aufruf
commit
"java:comp/UserTransaction"
"java:comp/UserTransaction"oder
oder
annotieren
mit
@Ressource
annotieren mit @Ressource
InitialContext ctx = new InitialContext();
UserTransaction utx = (UserTransaction)ctx.lookup("java:comp/UserTransaction");
try {
utx.begin();
BankService bank = ctx.lookup("sample/BankService");
bank.transfer(12323,134343,10.0);
utx.commit();
}
catch (Exception e) {
try {
logger.error("rolling back transaction");
utx.rollback(); throw new AppException (e);
}
catch (Exception e2)
{logger.fatal("error rolling back transaction");
throw e2);
}
}
}
School of Engineering
© K. Rege, ZHAW
6 von 74
Problemfälle mit BMTD
■ Problem1: "Nested Transaction": EJB kann weiters EJB aufrufen, das ebenfalls
eine Transaktionsklammer (begin,commit) gesetzt hat.
■ Dieses kann sich sogar auf einer anderen Maschine befinden
■ EJB Einschränkung: Transaktionen können nicht geschachtelt werden
begin
…
commit
begin
…
commit
begin
…
commit
EJB Container
EJB Container
■ Problem 2: Transaktion auf Klientenmaschine gestartet; Klient kann Verbindung
verlieren oder abstürzen ->DB Locks bleiben gesetzt
begin
…
commit
->->BMTD
BMTDnur
nurininAusnahmefällen
Ausnahmefällen
verwenden
(Anfänger
verwenden (Anfängeram
ambesten
besten
gar
nicht)
gar nicht)
…
EJB Container
School of Engineering
© K. Rege, ZHAW
7 von 74
Container Managed Transactions Demarcation
(CMTD)
■ Container übernimmt Steuerung der Transaktion
begin
■
■
■
Startet eine Transaktion "bei Bedarf"
Stellt das korrekte Verhalten der Transaktion
auch im Fehlerfall sicher, z.B. Rollback
Insbesondere Fehlerbehandlung in verteilter Umgebung ist
komplex
Methoden Aufruf
EJB
commit
EJB Container
■ Zuerst müssen vom EJB Container alle Ressourcen, die an Transaktion beteiligt
sind bestimmt werden →Transaction Scope
■
kein Problem, wenn alle Ressourcen über Container angefordert wurden
■ Beispiel Funktionsweise:
■
■
■
Beim ersten Aufruf einer TX-Ressource wird die Transaktion vom Container gestartet
Allen TX-Ressourcen wird nach Operation im Transaction Scope entweder ein Commit oder
Rollback ausgelöst
Im Falle einer Exception wird automatisch ein Rollback ausgelöst
■ Konsequenz -> CMTD
■
Bean selber darf die Transaktion nicht mehr selber steuern (z.B. ein Commit veranlassen)
School of Engineering
© K. Rege, ZHAW
8 von 74
Deklarative Transaktionssteuerung
■ EJB gibt Hinweis, wie der Container mit Transaktionen umgehen soll
■ Container übernimmt die eigentliche Steuerung
■ @TransactionManagement(CONTAINER):Die Transaktionsgrenzen
(Transaktion Demarcation) wird vom Container bestimmt (ist der Default)
■ @TransactionAttribute(REQUIRED): EJB soll innerhalb einer Transaktion
ablaufen
■
■
falls noch keine gestartet wurde, wird eine gestartet -> begin
wenn der Aufruf beendet ist, wird die Transaktion abgeschlossen -> commit
■ 5 weitere Transaktionsattribute definiert
@TransactionManagement(CONTAINER)
@TransactionAttribute(REQUIRED)
begin
Client
Methoden Aufruf
Methoden Aufruf
commit
EJB
EJB Container
School of Engineering
© K. Rege, ZHAW
9 von 74
Hello CMTD
■ Typischerweise werden die Transaktionen in Session Bean gestartet
■ Session Bean Fassade: SLSB, das ausschliesslich von Klient aufgerufen wird
■ Klient ruft EJB einfach auf (ohne Setzen von Transaktionsklammern)
@TransactionManagement(TransactionManagementType.CONTAINER) // optional, default
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
@Stateless
Transaktions-Attribut
Transaktions-Attribut
public class BankService {
für
fürKlasse.
Klasse.i.e.
i.e.alle
alleMethoden
Methoden
@Resource SessionContect ctx;
@PersistenceContext EntityManager em;
Transaktions-Attribut
Transaktions-Attribut
für
füreinzelne
einzelneMethode
Methode
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void transfer(int accA,int accB, double amount){
em.find(Account.class, accId).withdraw(amount);
em.find(Account.class, accId).deposit(amount);
}
■ Können aber auch im Deployment
Descriptors (DD) des Beans
spezifiziert werden (nachträglich)
School of Engineering
ejb-jar.xml
Alle Methoden einfach
Alle Methoden einfach
"*" verwenden
"*" verwenden
<ejb-jar>
<ejb-jar>
<assembly-descriptor>
<assembly-descriptor>
<container-transaction>
<container-transaction>
<method>
<method>
<ejb-name>BankService</ejb-name>
<ejb-name>BankService</ejb-name>
<method-name>transfer</method-name>
<method-name>transfer</method-name>
</method>
</method>
<trans-attribute>Required</trans-attribute>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</container-transaction>
</assembly-descriptor>
</assembly-descriptor>
</ejb-jar>
</ejb-jar>
© K. Rege, ZHAW
10 von 74
TX-Attribut: REQUIRED
■ Eine EJB mit diesem TX-Attribut wird immer in einem TX-Kontext ausgeführt.
Wird ein TX-Kontext vom Clienten mitgegeben, wird dieser genutzt. Andernfalls
wird ein TX-Kontext durch den EJB-Container erzeugt.
EJB Container
begin
Client
Methoden Aufruf
commit
Methoden Aufruf
EJB
EJB Container
begin
Client
Methoden Aufruf
Methoden Aufruf
commit
EJB
EJB Container
School of Engineering
© K. Rege, ZHAW
11 von 74
TX-Attribut: SUPPORTS
■ Ist dieses TX-Attribut gesetzt, kann ein EJB wahlweise mit oder ohne TX
ausgeführt werden. Wird ein TX-Kontext mitgegeben, so wird die gerufene
Methode in diesm Kontext ausgeführt. Der Entwickler ist dafür zuständig, den
Code in der EJB entsprechend für eine Ausführung mit oder ohne TX zu
implementieren
begin
Client
Methoden Aufruf
commit
Methoden Aufruf
EJB
EJB
EJB Container
Container
Client
Methoden Aufruf
Methoden Aufruf
EJB
EJB Container
School of Engineering
© K. Rege, ZHAW
12 von 74
TX-Attribut: NOTSUPPORTED
■ Bei Aufruf des EJB in einem Transaktionskontext wird die TX suspendiert, bis
die im EJB gerufene Methode ausgeführt wurde.
begin
Client
Methoden Aufruf
commit
Methoden Aufruf
EJB
EJB
EJB Container
Container
Client
Methoden Aufruf
Methoden Aufruf
EJB
EJB Container
School of Engineering
© K. Rege, ZHAW
13 von 74
TX-Attribut: REQUIRES_NEW
■ Es wird eine neue TX durch den EJB-Container erzeugt, in der die gerufene
Methode ausgeführt wird. Eine ggf. mitgegeben TX wird für die Ausführung der
gerufenen Methode suspendiert und nach der Ausführung wieder aktiviert.
Tx1
begin
Client
Methoden Aufruf
commit
Tx2
begin
Methoden Aufruf
commit
EJB
EJB
EJB Container
Container
begin
Client
Methoden Aufruf
Methoden Aufruf
commit
EJB
EJB Container
School of Engineering
© K. Rege, ZHAW
14 von 74
TX-Attribut: MANDATORY
Ein EJB mit diesem TX-Attribut muss zwingend in einer bestehenden TX
aufgerufen werden. Beim Aufruf ohne mitgegebenem TX-Kontext wird vom
EJB-Container eine TransactionRequiredException geworfen.
begin
Client
Methoden Aufruf
commit
Methoden Aufruf
EJB
EJB
EJB Container
Container
Client
Methoden Aufruf
TransactionRequired
Exception
EJB
EJB
EJBContainer
Container
School of Engineering
© K. Rege, ZHAW
15 von 74
TX-Attribut: NEVER
■ Es ist nicht zulässig, eine Methode einer mit diesem TX-Attribut versehenes EJB
mit einem TX-Kontext aufzurufen. Geschieht dies doch, wird vom EJB-Container
eine RemoteException beim entfernten oder eine EJBException beim lokalen
Zugriff geworfen.
begin
Client
Methoden Aufruf
commit
Remote/EJB
Exception
EJB
EJB
EJB Container
Container
Client
Methoden Aufruf
Methoden Aufruf
EJB
EJB Container
School of Engineering
© K. Rege, ZHAW
16 von 74
Fehlerbehandlung
■ Falls eine Bedingung in der Anwendungslogik verletzt wird, kann mit
setRollbackOnly ein Rollback der gesamten Transaktion erzwungen werden.
public class BankService {
@Resource SessionContect ctx;
public void transfer(int accA,int accB, double amount){
if (em.find(Account.class, accA).saldo() < amount) {
ctx.setRollbackOnly();
}
else {
em.find(Account.class, accA).withdraw(amount);
em.find(Account.class, accB).deposit(amount);
}
}
■ Oftmals soll auch eine Exception geworfen werden. Wenn eine Exception von
einer Klasse die mit @ApplicationException(rollback = true) annotiert wurde,
geworfen wird, dann kann ebenfalls nur noch Rollback ausgeführt werden.
@ApplicationException(rollback=true)
AppException extends Exception {}
...
public void transfer(int accA,int accB, double amount){
if (em.find(Account.class, accA).saldo() < amount) {
throw new AppException();
}
School of Engineering
© K. Rege, ZHAW
17 von 74
Kontext, verteilte Transaktionen
School of Engineering
© K. Rege, ZHAW
18 von 74
Verteilte Transaktionen
■ Transaktionen können mehrere EJB
betreffen: Beim Aufruf von Bean A wird
die Transaktion gestartet,dieses ruft
seinerseits Bean B auf
■ 2PC Protokoll über mehrere
Datenbanken
■ Transaktionen können über mehrere
Maschinen verteilt
sein. Bean B befindet sich in einem
anderen EJB Container
■ Transaktion übers Netzwerk: muss vom
Protokoll unterstützt sein (z.Z. nur IIOP)
■
OTS mit JTS (Java Schnittstelle für OTS)
■ Optimierung möglich wenn TX nur
innerhalb Container: Local Transaktion
School of Engineering
© K. Rege, ZHAW
19 von 74
Verteilte Transaktionen
■ Aufgabe wird aufgeteilt auf
■
Transaktions Manager: koordiniert die verschiedenen Ressourcen; steuert das 2PC Protokoll
zwischen den verschiedenen Ressourcen
■
Ressource Manager: steuert die Ressource
■
Ressource: macht die eigentliche Arbeit
■ Ein Kontext wird bei jedem Aufruf übergeben (bei IIOP);
■
jeder EJB Bean Typ hat eigenen Context Typ:SessionContext, EntityContext,
MessageDrivenContext Oberklasse: EJBContext
School of Engineering
© K. Rege, ZHAW
20 von 74
Session Context
■ Im Session Context sind Informationen gespeichert über
■
■
Benutzer: z.B. Name des aufrufenden Benutzer: getCallerPrincipal()
Transaktionszustand : z.B. Abbruch der laufenden Transaktion: setRollbackOnly()
■ Der Session Context wird bei Aufrufen automatisch mit übertragen
■ Für Zugriff auf der Server-Seite einfach mittels Injection definieren
@Resource
@Resource
public
publicSessionContext
SessionContextsc;
sc;
Identität
Identität
SessionContext {
// Obtain the java.security.Principal that
// identifies the caller.
java.security.Principal getCallerPrincipal();
// Test if the caller has a given security role.
boolean isCallerInRole(java.lang.String roleName)
// Test if the transaction has been marked for
// rollback only.
boolean getRollbackOnly()
// Obtain the transaction demarcation interface.
UserTransaction getUserTransaction()
// Mark the current transaction for rollback.
void setRollbackOnly()
}
Transaktionskontext
Transaktionskontext
School of Engineering
© K. Rege, ZHAW
21 von 74
Message Driven Beans
School of Engineering
© K. Rege, ZHAW
22 von 74
Asynchrones Messaging
■ Zur zeitliche Entkopplung von Sender und Empfänger
■
■
aber keine inhaltliche Entkopplung: Sender und Empfänger müssen beide das Meldungsformat
verstehen
Fälle, in denen Empfänger die Daten sofort braucht (z.B. Read => 95%), ist A.M. ungeeignet
■ Reliable Messaging (üblicherweise von EJB Container übernommen)
■
■
Sicherstellen, dass Meldung auch abgeliefert wird
heisst aber nicht, dass sie erfolgreich verarbeitet wurde
■ Asynchrones Messaging ist für den Entwickler wesentlich komplexer in der
Handhabung als einfaches RPC Modell, insbesondere im Fehlerfall.
■ Sollte nur bei Bedarf eingesetzt werden.
■ Einsatz von asynchronem Messaging
1) Um Spitzen beim Anfallen von Meldungen kontinuierlich zu verarbeiten
■ Meldungssystem als Puffer verwendet
■ 2) Wenn Empfänger der Nachricht nicht dauern on-line ist
■ 3) Um bei lange andauernden Berechnungen den Klienten nicht zu blockieren
■ Klient kann auch ein EJB sein
■ 4) Um Daten zwischen 2 Systemen im Hintergrund abzugleichen (wenn keine andere Lösung
möglich)
School of Engineering
© K. Rege, ZHAW
23 von 74
■
Aufrufmodelle
■ Publish-and-Subscribe
■
Ein Klient senden (publizieren) Meldung an einen Topic-Kanal
■
Alle Empfänger die sich bei diesem Topic-Kanal angemeldet haben (subscribe) bekommen die
Meldung zugeschickt
■
Jeder Empfänger bekommt Kopie der Nachricht
■ Queue (Point-to-Point)
■
Ein Klient sendet eine Meldung an eine Queue.
■
Auf der Empfängerseite kann mittels polling oder call-back der Empfänger die Meldung empfangen
■
Empfänger können die Meldungen nach gewissen Kriterien filtern
■
Jede Meldung wird durch einen Empfänger verarbeitet
School of Engineering
© K. Rege, ZHAW
24 von 74
Java Messaging API
Connection Factory: ist ein Objekt um
Connections zu erzeugen. Es kapselt die
entsprechenden Verbindungsparameter
@Resource(mappedName="jms/HelloFactory")
@Resource(mappedName="jms/HelloFactory")
private
private static
static QueueConnectionFactory
QueueConnectionFactory connectionFactory;
connectionFactory;
Queue: ist der Kanal über den die Meldungen
versendet werden.
@Resource(mappedName="jms/Hello")
@Resource(mappedName="jms/Hello")
private
private Queue
Queue queue;
queue;
Eine Connection kapselt eine Verbindung z.B.
als TCP/IP Socket. Sessions werden darüber
erstellt.
Connection connection = connectionFactory.createConnection();
Connection connection = connectionFactory.createConnection();
Durch Schliessen der Verbindung werden auch alle Sessions geschlossen
connection.close();
connection.close();
School of Engineering
© K. Rege, ZHAW
25 von 74
Session
■ Eine Session wird für die Erstellung und das Konsumieren von Meldungen
verwendet. Eine Session selber wird via die Connection erstellt.
Session
Session session
session == connection.createSession(false,
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Session.AUTO_ACKNOWLEDGE);
■ Folgende Objekte werden via Session erstellt
■
Message Producer
■
Message Consumer
■
Messages
■ Schliessen der Session blockiert bis alle Meldungen
abgeschickt sind.
session.close()
session.close()
School of Engineering
© K. Rege, ZHAW
26 von 74
Producer & Consumer
■ Message Producers ist ein Objekt, das für das Versenden von Meldungen
verwendet wird.
MessageProducer
MessageProducer producer
producer == session.createProducer(queue);
session.createProducer(queue);
■ Nach der Erzeugung des Producers, kann dieser verwendet werden um
Meldungen zu senden.
producer.send(message);
producer.send(message);
■ Message Consumers ist ein Objekt, das für das Empfangen von Meldungen
verwendet wird. Es implementiert das MessageConsumer Interface
MessageConsumer consumer = session.createConsumer(queue);
MessageConsumer consumer = session.createConsumer(queue);
■ Empfang von Meldungen via polling
Message
Message mm == consumer.receive();
consumer.receive();
■ Oder via Call-back in dem ein Message Listener als aynchroner Event Handler
für Meldungen angemeldet wurde.
Listener
Listener myListener
myListener == new
new Listener();
Listener();
consumer.setMessageListener(myListener);
consumer.setMessageListener(myListener);
School of Engineering
© K. Rege, ZHAW
27 von 74
Message
■ Der Message Header enthält eine Reihe von vordefinierten Feldern zur
Identifikation und dem Routing der Meldung.
■
z.B. JMSTimestamp, JMSType, ...
■ Der Message Body enthält die Daten der JMS Meldung entsprechen den 5 in
JMS definierten Meldungstypen.
TextMessage
TextMessage message
message == session.createTextMessage();
session.createTextMessage();
message.setText(msg_text);
//
message.setText(msg_text);
// msg_text
msg_text is
is aa String
String
producer.send(message);
producer.send(message);
Message
Message mm == consumer.receive();
consumer.receive();
if
(m
instanceof
if (m instanceof TextMessage)
TextMessage) {{
TextMessage
TextMessage message
message == (TextMessage)
(TextMessage) m;
m;
System.out.println("Reading
message:
System.out.println("Reading message: "" ++ message.getText());
message.getText());
}} else
else {{
//
// Handle
Handle error
error
}}
School of Engineering
© K. Rege, ZHAW
28 von 74
Typen von Meldungen
■ Oft einfache TextMessages
■
Inhalt kann beliebiger String sein, z.B. XML Dokument
■ MapMessage: wenn Key/Value Paare, etc
TextMessage
MapMessage
Übermittelt einzelnen Text-String.
Übermittelt (mehrere) Attribute als Key/Value-Paare.
Dabei können die Values nicht nur Strings sein,
sondern auch viele andere Java-Typen.
ObjectMessage Übermittelt ein Java-Object (welches 'Serializable'
implementieren muss).
StreamMessage Übermittelt Streams ähnlich wie 'DataOutputStream'.
Anders als 'BytesMessage' übergibt 'StreamMessage' auch
Datentypen.
BytesMessage Übermittelt Streams ähnlich wie 'DataOutputStream'.
Anders als 'StreamMessage' übergibt 'BytesMessage' nicht
interpretierte Rohdaten.
School of Engineering
© K. Rege, ZHAW
29 von 74
Message Driven Beans (MDB)
■ Implementiert das javax.jms.MessageListener
Interface
■ Die Klasse muss mit @MessageDriven Annotation versehen sein
■ Mit mappedName wird der JNDI Eintrag bestimmt unter der das MDB
Meldungen konsumiert;
■ Wenn eine neue Nachricht ankommt, wird die onMessage Methode aufgerufen
Definition
Definitionder
derQueue
Queuevia
via
Annotation
Annotation
import javax.ejb.*; import javax.jms.*;
import javax.ejb.*; import javax.jms.*;
@MessageDriven(mappedName = "jms/Hello", activationConfig = {
@MessageDriven(mappedName = "jms/Hello", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
})
public class HelloMessageBean implements MessageListener {
public class HelloMessageBean implements MessageListener {
@Resource private MessageDrivenContext mdc;
@Resource private MessageDrivenContext mdc;
}
public void onMessage(Message inMessage) {
public void onMessage(Message inMessage) {
if (inMessage instanceof TextMessage) {
if (inMessage instanceof TextMessage) {
TextMessage msg = (TextMessage)inMessage;
TextMessage msg = (TextMessage)inMessage;
logger.info("Hallo "+ msg.getText());
logger.info("Hallo "+ msg.getText());
}
}
}
}
}
School of Engineering
© K. Rege, ZHAW
30 von 74
Zustände von MDBs
■ Ebenfalls in einem Pool verwaltet
■ Während der Verarbeitung eines Aufrufs (onMessage) bleibt die Instanz für
andere gesperrt, d.h. innerhalb des Beans "single threaded"
@PreDestroy
School of Engineering
@PostCostruct
© K. Rege, ZHAW
31 von 74
JMS Klient
■ Der Klient kann das MDB über das Standard JMS API ansprechen
import javax.jms.*;
import javax.jms.*;
import javax.ejb.*;
import javax.ejb.*;
import javax.annotation.Resource;
import javax.annotation.Resource;
...
...
@Resource(mappedName="jms/HelloFactory")
@Resource(mappedName="jms/HelloFactory")
private QueueConnectionFactory factory;
private QueueConnectionFactory factory;
@Resource(mappedName="jms/Hello")
@Resource(mappedName="jms/Hello")
private Queue queue;
private Queue queue;
public void insert() {
public void insert() {
try {
try {
Connection connection = factory.createQueueConnection();
Connection connection = factory.createQueueConnection();
Session session = connection.createSession(false, QueueSession.AUTO_ACKNOWLEDGE);
Session session = connection.createSession(false, QueueSession.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(queue);
MessageProducer producer = session.createProducer(queue);
TextMessage tm = session.createTextMessage();
TextMessage tm = session.createTextMessage();
tm.setText("hugo");
tm.setText("hugo");
producer.send(tm);
producer.send(tm);
producer.close();
producer.close();
session.close();
session.close();
}
}
catch (Exception ex) {
catch (Exception ex) {
logger.error(ex.toString());
logger.error(ex.toString());
}
}
}
}
School of Engineering
© K. Rege, ZHAW
32 von 74
Zusammenfassung
■ Asynchrones Messaging
■
■
Erlaubt eine zeitliche Entkopplung von Verarbeitungsteilen
verschiedene Anwendungsszenarien
■ In der konkreter Anwendung oft komplex
■
Ob und wann die Meldung erfolgreich verarbeitet wurde, muss von Anwendung sichergestellt
werden
■
Ev. zweite Queue für Rückmeldungen nötig
■
In Kombination mit synchronem Messaging kann es zu unerwarteten Effekten kommen z.B. wenn
Update asynchron(verzögert) und Read synchron
■ Message Driven Beans
■
Empfänger von asynchronen Meldungen
School of Engineering
© K. Rege, ZHAW
33 von 74
Custom Interceptors
School of Engineering
© K. Rege, ZHAW
34 von 74
Custom Interceptors
■ Aspektorientierte Programmierung
■
■
Infrastruktur-Aufgaben (System Level Concerns) werden vom eigentlichen Anwendungs-Code
getrennt.
In EJB für Transaktionssteuerung, Sicherheit, etc. verwendet.
■ Eigene Aspekte um zusätzliche allgemeine technische Funktionalität transparent
einzubauen
■
z.B. Logging, Auditing, zusätzliche Sicherheit, etc.
■ Die Verarbeitung wird durch Interceptor übernommen
■ Custom Interceptors
■
eigener Interceptoren, der vor- und nach dem EJB Aufruf angestossen wird
School of Engineering
© K. Rege, ZHAW
35 von 74
Interceptor
■ Aufruf des Interceptors
School of Engineering
© K. Rege, ZHAW
36 von 74
Interceptor Definition
■ Klasse mit einer Methode mit @AroundInvoke Annotation
■
InvocationContext enthält Information über abgefangene Klasse ctx.proceed() um
abgefangene Methode auszuführen
■ Ist Teil des Methodenaufrufs:
■
■
■
teilt Transaktionskontext
kann dieselben Exceptions wie "ihre" Methode werfen
kann selber JNDI, JDBC, JMS, EJBs, Entity Manager verwenden
import javax.ejb.*; import javax.interceptor.*;
import javax.ejb.*; import javax.interceptor.*;
public class Tracer {
public class Tracer {
static Logger logger = Logger.getLogger(Tracer.class);
static Logger logger = Logger.getLogger(Tracer.class);
@AroundInvoke
@AroundInvoke
public Object log (InvocationContext ctx) throws Exception {
public Object log (InvocationContext ctx) throws Exception {
String className = ctx.getTarget().getClass().getName();
String className = ctx.getTarget().getClass().getName();
String methodName = ctx.getMethod().getName();
String methodName = ctx.getMethod().getName();
String target = className + "." + methodName + "()";
String target = className + "." + methodName + "()";
long start = System.currentTimeMillis();
long start = System.currentTimeMillis();
logger.info ("Invoking " + target);
logger.info ("Invoking " + target);
try {
try {
return ctx.proceed();
return ctx.proceed();
} catch(Exception e) {throw e;}
} catch(Exception e) {throw e;}
finally {
finally {
System.out.println("Exiting " + target);
System.out.println("Exiting " + target);
long time = System.currentTimeMillis() - start;
long time = System.currentTimeMillis() - start;
logger.info("This method takes " + time + "ms to execute");
logger.info("This method takes " + time + "ms to execute");
}
}
}
}
School of Engineering
© K. Rege, ZHAW
sollte
sollteininanderem
anderem
Package
Packageals
alsEJB
EJB
Klasse
Klassesein.
sein.
37 von 74
Interceptor Verwendung
Aufrufreihenfolge entspricht Definitionsreihenfolge
import
import javax.interceptor.*;
javax.interceptor.*; import
import javax.ejb.*;
javax.ejb.*;
@Stateless
@Stateless
@Interceptors
@Interceptors (Tracer.class)
(Tracer.class)
public
public class
class HelloBean
HelloBean {{
...
...
}}
Interceptor via Konfiguration
■ wird im ejb-jar.xml definiert
* *->->für
füralle
alleBeans
Beans
ejb-jar.xml
<assembly-descriptor>
<assembly-descriptor>
<interceptor-binding>
<interceptor-binding>
<ejb-name>*</ejb-name>
<ejb-name>*</ejb-name>
<interceptor-class>Tracer</interceptor-class>
<interceptor-class>Tracer</interceptor-class>
</interceptor-binding>
</interceptor-binding>
...
...
</assembly-descriptor>
</assembly-descriptor>
School of Engineering
© K. Rege, ZHAW
38 von 74
Web Services
School of Engineering
© K. Rege, ZHAW
39 von 74
Web Services - SOAP
■ SOAP: Simple Object Access Protocol
■
Definiert ein Standard-Format für den Transport von XML Daten, via HTTP, SMTP und FTP für
den Zugriff auf Web Services
■ WSDL: Web Service Description Language
■
Beschreibt die Schnittstelle eines Web Service (Ein-/Ausgabe Parameter, Protokoll Bindung,
etc.)
■ UDDI: Universal Description, Discovery, and Integration
■
(Weltweites) Verzeichnis von Web Services in dem nach verschiedenen Kriterien gesucht
werden kann
Fi
nd
e
UDDI
UDDI
Verzeichnis
Verzeichnis
Pu
bli
z
ier
e
Service Verzeichnis
Service Konsument
HTTP-Request
SOAP
SOAP
Klient
Klient
SOAP
SOAP
Fassade
Fassade
HTTP-Response
WSDL
WSDL
School of Engineering
GeschäftsGeschäftsLogik
Logik
© K. Rege, ZHAW
Service Anbieter
40 von 74
WebService
(Soap)
(Soap)
Web
Web
Service
Service
SOAP-Request
SOAP-Response
(RPC)
■
■
■
■
plattformunabhängig
sprachunabhängig
offene Spezifikation (W3C)
basiert auf XML (Datentyp-Definitionen und Datentransport)
Anwendung
Anwendung
Anwendung
Anwendung
Anwendung
Anwendung
66
SOAP/XML
SOAP/XML
66
SOAP/XML
SOAP/XML
66
SOAP/XML
SOAP/XML
55
HTTP
HTTP
5
5
SMTP/MIME
SMTP/MIME
5
5
Messaging
Messaging
44
TCP(+SSL)
TCP(+SSL)
4
4
TCP(+SSL)
TCP(+SSL)
4
4
TCP(+SSL)
TCP(+SSL)
School of Engineering
© K. Rege, ZHAW
41 von 74
Erweiterter Web Service Stack
■ In konkreten Anwendungsfall von Web Services sind Erweiterungen notwendig
für Sicherheit, Transaktionssteuerung, etc.
■ Werden angeboten
■
■
vom Anbieter des WS Infrastruktur ( Microsoft, IBM, Open Source)
Standards z.T. noch nicht verabschiedet -> proprietäre, z.T. nicht interoperable Lösungen
Anwendung
Anwendung
Workflow,
Workflow,
Network
NetworkTransport
TransportLayer
Layer
TCP/IP
TCP/IP
School of Engineering
WS-Attachement
BinäreAnhänge
Anhänge
Binäre
WS-Attachement
WS Adressing
Addressierung
Addressierung
WS Adressing
Zuverlässigkeit
Zuverlässigkeit
WS Reliable Messaging
WS Reliable Messaging
WS Transactions
Transaktionen
Transaktionen
WS Transactions
WS Security
.
© K. Rege, ZHAW
Sicherheit
Sicherheit
WS Security
SOAP
SMTP, FTP
HTTP, SMTP, FTP
SOAPTransport
TransportHTTP,
UDDI
XML
XMLMessaging
MessagingSOAP
SOAP
ServiceVerzeichnis
Verzeichnis
Service
UDDI
.
.NET, JAX-WS
.NET, JAX-WS
WSDL
XML
XMLMessaging
MessagingAPI
API
ServiceBeschreibung
Beschreibung
Service
WSDL
BPEL, XLANG(MS)
BPEL, XLANG(MS)
42 von 74
WS-* (W3C/OASIS)
Step 2 – Workshops & Community Dev
Step 2 – Workshops & Community Dev
Stand der Implementierung (Anfang 2016)
Step 3 – Standardization
Step 3 – Standardization
Step 4 – Approved Standard
Step 4 – Approved Standard
WS-Federation
WS-Federation
WS-Management
WS-Management
Devices
Devices
Profile
Profile
WS-Security
WS-Security
Policy
Policy
WS-Business
WS-Business
Activity
Activity
WS-Trust
WS-Trust
WS-Atomic
WS-Atomic
Transaction
Transaction
WS-Security
WS-Security
WS-Reliable
WS-Reliable
Messaging
Messaging
WS-Coordination
WS-Coordination
WS-Transfer
WS-Transfer
WS-Enumeration
WS-Enumeration
WS-Eventing
WS-Eventing
SOAP
SOAP
WS-Addressing
WS-Addressing
MTOM
MTOM
Infrastructure
Infrastructure
and Profiles
and Profiles
Assurances
Assurances
WS-Discovery
WS-Discovery
UDDI
UDDI
WS-Policy
WS-Policy
Messaging
Messaging
School of Engineering
SOAP
SOAP/ /UDP
UDP
XML
XML
Namespaces
Namespaces
MIME
MIME
WSDL
WSDL
XML Schema
XML Schema
XML
XMLInfoset
Infoset
XML
XML1.0
1.0
Metadata
Metadata
WS-Metadata
WS-Metadata
Exchange
Exchange
Foundation
Foundation
SOAP / HTTP
SOAP / HTTP
© K. Rege, ZHAW
43 von 74
Aufbau einer SOAP Meldung
POST/objectURI HTTP/1.1
Objekt Endpunkt
Informationen für den
Transport der Nachricht
SOAPAction
Objekt Identifikation
soapenv:Envelope
soapenv:Header
Header 1
Methoden Identifikation
Erweiterungskopfteil
Header 2
Meldungsdaten Daten
soapenv:Body
Informationen für
den/die Empfänger der
Nachricht
Informationen über die
Daten der Nachricht,
Unterschrift, etc.
Logische Aufteilung
Daten der Nachricht
Daten
SOAP Nachricht
School of Engineering
© K. Rege, ZHAW
44 von 74
Beispiel: Aufbau einer SOAP Meldung
HTTP
HTTPHeader
Header(def:
(def:HTTP)
HTTP)
POST /Accounts HTTP/1.1
Host: www.webservicebank
.com
www.webservicebank.com
Content-Length: nnnn
Content-Type: text/xml
; charset="
utf-8"
-8"
text/xml;
charset="utf
SOAPAction:
SOAPAction: "Some-URI"
<?xml version="1.0" encoding="UTF-8"?>
SOAP
SOAPEnvelope
Envelope
<SOAP:Envelope xmlns:SOAP="http://schemas.
xmlsoap.org/soap/envelope/"
.org/soap/envelope/"
xmlns:SOAP="http://schemas.xmlsoap
(def:
SOAP)
(def: SOAP)
SOAP:encodingStyle
="http://schemas.xmlsoap
xmlsoap.org/soap/encoding/">
.org/soap/encoding/">
SOAP:encodingStyle="http://schemas.
<SOAP:Header>
SOAP
SOAPHeader
Header
<t:Signature xmlns:t="some-URI"
="1">
xmlns:t="some-URI" SOAP:mustUnderstand
SOAP:mustUnderstand="1">
(def:
SOAP,opt)
(def: SOAP,opt)
5984928340298340238475272938420348
</t:Signature>
Header
Header Entry
Entry
</SOAP:Header>
(def:Applikation)
(def:Applikation)
<SOAP:Body>
<m:Deposit xmlns:m="Some-URI">
xmlns:m="Some-URI">
SOAP Body
<acctNumber>1234567890</
acctNumber>
>
acctNumber>1234567890</acctNumber
SOAP Body
(def:SOAP)
<amount>200</amount>
(def:SOAP)
Body
BodyEntry
Entry
</m:Deposit>
(def:Applikation)
(def:Applikation)
</SOAP:Body>
</SOAP:Envelope>
School of Engineering
© K. Rege, ZHAW
45 von 74
Servicebeschreibung mit WSDL
School of Engineering
© K. Rege, ZHAW
46 von 74
Service Schnittstellen Beschreibung
■ Funktionen einer Schnittstellen Beschreibungssprache (IDL)
■
von Menschen lesbar und erstellbar
■ Definition der Schnittstelle (gutes SW Engineering ⇒ zuerst)
■ Dokumentation
■
von Maschine lesbar
■ zur Laufzeit: überprüfen ob Daten mit Schnittstelle konform(Validierung)
■ zur Entwicklungszeit: Generierung von Hilfsklassen
■ Implementierungsrumpf für Web Services
■ Proxy für den Aufruf
■ Web Service Definition Language WSDL
■
■
■
die Schnittstellen Beschreibungssprache für Web Services
Version 1.2: W3C Recommendation seit 24. Juni 2003
Version 2.0: W3C Recommendation seit 26. Juni 2007 aber D.O.A.
School of Engineering
© K. Rege, ZHAW
47 von 74
Aufbau eines WSDL Dokuments
z:B. HTTP+SOAP
z:B. HTTP+SOAP
Verwendung
Verwendungvon
von
XML-Schema
XML-Schema
Port
(Endpunkt)
Operation
Type/
Element
Service
Port
(Endpunkt)
Binding
(Interface)
Port Type
(abstrakte
Interface)
Operation
Message
Type/
Element
Type/
Type/
Element
Element
Port
(Endpunkt)
Operation
Operationen
Web Service
School of Engineering
Protokoll
abstraktes
Interface
© K. Rege, ZHAW
Typen &
Elemente
48 von 74
<wsdl:service
<wsdl:service name="CalculatorService">
name="CalculatorService">
<wsdl:port
binding="impl:CalculatorSoapBinding"
<wsdl:port binding="impl:CalculatorSoapBinding" name="Calculator">
name="Calculator">
</wsdl:port>
</wsdl:port>
Service
</wsdl:service>
Servicemit
mit
</wsdl:service>
Ports
</wsdl:definitions>
Ports
</wsdl:definitions>
School of Engineering
© K. Rege, ZHAW
Protokoll
Bindung hinzu
Bindung hinzu
Web Service
<wsdl:definitions
<wsdl:definitions name="Calculator"
name="Calculator"
targetNamespace="http://localhost:8080/Calculator"
targetNamespace="http://localhost:8080/Calculator" Namesspaces
Namesspaces
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
Import
xmlns:impl="http://localhost:8080/Calculator"
…… >>anderer
Import
andererSchemas
Schemas
xmlns:impl="http://localhost:8080/Calculator" ……
<wsdl:import>
namespace="…"
location
=
"…"
/>
<wsdl:import> namespace="…" location = "…" />
<wsdl:types>
<wsdl:types> <xsd:schema>
<xsd:schema> ...
... </xsd:schema>
</xsd:schema> <wsdl:types>
<wsdl:types>
<wsdl:message
name="addResponse">
<wsdl:message name="addResponse">
</wsdl:message>
</wsdl:message>
Binding
Bindingdefiniert
definiert
<wsdl:message
name="addRequest">
Port
<wsdl:message name="addRequest">
PortTyp:
Typ:abstr.
abstr.Interface
Interface
</wsdl:message>
</wsdl:message>
<wsdl:portType
<wsdl:portType name="Calculator">
name="Calculator">
...
...
... ...
</wsdl:portType>
</wsdl:portType>
<wsdl:binding
<wsdl:binding name="CalculatorSoapBinding"
name="CalculatorSoapBinding" type="impl:Calculator">
type="impl:Calculator">
...
...
Port fügt prot. abh.
... ...
Port fügt prot. abh.
</wsdl:binding>
</wsdl:binding>
abstraktes Interface
Aufbau eines WSDL Dokuments - Struktur
49 von 74
abstraktes Interface - Typen & Elemente
■ Die Typen und Elemente werden mittels XML Schemas beschrieben
■ Deklaration der Typen, die in Aufruf verwendet werden
■
double add(double a, double b)
<wsdl:types>
<wsdl:types>
<xsd:schema
<xsd:schema targetNamespace='http://localhost:8080/CalcMessage/'
targetNamespace='http://localhost:8080/CalcMessage/'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:typens='http://localhost:8080/CalcMessage/'>
xmlns:typens='http://localhost:8080/CalcMessage/'>
<xsd:element
<xsd:element name="op1"
name="op1" type="xsd:double"
type="xsd:double" />
/>
<xsd:element
name="op2"
type="xsd:double"
/>
<xsd:element name="op2" type="xsd:double" />
<xsd:element
<xsd:element name="result"
name="result" type="xsd:double"
type="xsd:double" />
/>
</xsd:schema>
</xsd:schema>
</wsdl:types>
</wsdl:types>
School of Engineering
<soapenv:Body>
<soapenv:Body>
<ns1:add xmlns:ns1="http://localhost:8080/Calculator">
<ns1:add xmlns:ns1="http://localhost:8080/Calculator">
<arg0 xsi:type="xsd:double">20.0</arg0>
<arg0 xsi:type="xsd:double">20.0</arg0>
<arg1 xsi:type="xsd:double">22.0</arg1>
<arg1 xsi:type="xsd:double">22.0</arg1>
</ns1:add>
</ns1:add>
</soapenv:Body>
</soapenv:Body>
</soapenv:Envelope>
</soapenv:Envelope>
© K. Rege, ZHAW
50 von 74
Interface - Typen & Elemente Komplexe Typen
■ Es können eigene Typen definiert werden
■ Grundsätzlich voller XSD Umfang,
■
aber meist nicht vollständig implementiert
■ Eigener Typ für Arrays (nicht behandelt)
<wsdl:types>
<wsdl:types>
<xsd:schema
<xsd:schema targetNamespace='http://localhost:8080/CalcMessage/'
targetNamespace='http://localhost:8080/CalcMessage/'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:typens='http://localhost:8080/CalcMessage/'>
xmlns:typens='http://localhost:8080/CalcMessage/'>
<xsd:simpleType
<xsd:simpleType name="op1Type">
name="op1Type">
<xsd:restriction
<xsd:restriction base="xsd:double"
base="xsd:double" />
/>
</xsd:simpleType>
</xsd:simpleType>
<xsd:element
<xsd:element name="op1"
name="op1" type="typens:op1Type"
type="typens:op1Type" />
/>
</wsdl:types>
</wsdl:types>
School of Engineering
© K. Rege, ZHAW
51 von 74
abstraktes Interface - message und part
■ Definition wie die Typen verwendet werden:
■
■
fasst definierte Typen zu Meldungen zusammen
entspricht in Java der Liste der formalen Parameter in Methode:
■
■
[double] add([double a, double b])
es können auch direkt XSD Typen verwendet werden:
element="xsd:double"
<wsdl:types>
<wsdl:types>
<xsd:schema … … >
<xsd:schema … … >
<xsd:element name="op1" type="xsd:double" />
<xsd:element name="op1" type="xsd:double" />
<xsd:element name="op2" type="xsd:double" />
<xsd:element name="op2" type="xsd:double" />
<xsd:element name="result" type="xsd:double" />
<xsd:element name="result" type="xsd:double" />
</xsd:schema>
</xsd:schema>
</wsdl:types>
</wsdl:types>
Types
Name
Namedes
desMeldungstyp
Meldungstyp
<wsdl:message
<wsdl:message name='addRequestMsg'>
name='addRequestMsg'>
<wsdl:part
name='a'
<wsdl:part name='a' element='typens:op1'/>
element='typens:op1'/>
<wsdl:part
name='b'
element='typens:op2'/>
<wsdl:part name='b' element='typens:op2'/>
</wsdl:message>
</wsdl:message>
Mehrere
Mehrereparts
partsmöglich
möglich
->->Parameter
Liste
Parameter Liste
Typ
Typdes
desMeldungsteils
Meldungsteils(part)
(part)
Namen des Meldungsteils
Namen des Meldungsteils
<wsdl:message
<wsdl:message name='addResponseMsg'>
name='addResponseMsg'>
<wsdl:part
<wsdl:part name='Response'
name='Response' element='typens:result'/>
element='typens:result'/>
</wsdl:message>
</wsdl:message>
School of Engineering
© K. Rege, ZHAW
52 von 74
abstraktes Interface - portType
■ portType definiert ein abstraktes Interface
■ enthält eine oder mehrere operations
■
interface
interface Calculator
Calculator {{
double
double add(double
add(double a,
a, double
double b);
b);
}}
entspricht in Java dem Interface
■ Definiert Eingabe und Ausgabe-Meldung
■
■
wsdl:input = request
wsdl:output = response
Name des Porttyp
Name des Porttyp
Message
<wsdl:message name='addRequestMsg'>
<wsdl:message name='addRequestMsg'>
<wsdl:part name='a' … … />
<wsdl:part name='a' … … />
<wsdl:part name='b' … … />
<wsdl:part name='b' … … />
</wsdl:message>
</wsdl:message>
Namen
Namender
der Operation(en)
Operation(en)
Reihenfolge
Reihenfolgeder
der
Parameter
(opt.)
Parameter (opt.)
<wsdl:message name='addResponseMsg'>
<wsdl:message name='addResponseMsg'>
<wsdl:part name='Response' … … />
<wsdl:part name='Response' … … />
</wsdl:message>
</wsdl:message>
<wsdl:portType
<wsdl:portType name="Calculator">
name="Calculator">
<wsdl:operation
<wsdl:operation name="add"
name="add" parameterOrder="a
parameterOrder="a b">
b">
<wsdl:input
name="addRequestOp"
message="impl:addRequestMsg"
<wsdl:input name="addRequestOp" message="impl:addRequestMsg" />
/>
<wsdl:output
name="addResponseOp"
message="impl:addResponseMsg"
<wsdl:output name="addResponseOp" message="impl:addResponseMsg" />
/>
</wsdl:operation>
</wsdl:operation>
</wsdl:portType>
</wsdl:portType>
Meldungen
Meldungenfür
fürrequest
requestund
undresponse
response
School of Engineering
© K. Rege, ZHAW
53 von 74
Protokoll - binding
portType
■ binding: bindet Interface an Protokoll
■ enthält eine oder mehrere operations
■
entspricht Aufbau von portType
<wsdl:portType name="Calculator">
<wsdl:portType name="Calculator">
<wsdl:operation name="add" … >
<wsdl:operation name="add" … >
<wsdl:input name="addRequestOp" … />
<wsdl:input name="addRequestOp" … />
<wsdl:output name="addResponseOp" … />
<wsdl:output name="addResponseOp" … />
</wsdl:operation>
</wsdl:operation>
</wsdl:portType>
</wsdl:portType>
<wsdl:binding
<wsdl:binding name="CalculatorSoapBinding"
name="CalculatorSoapBinding" type="impl:Calculator">
type="impl:Calculator"> Name des
Name des
<wsdlsoap:binding
style="rpc"
Port Types
<wsdlsoap:binding style="rpc"
Port Types
transport="http://schemas.xmlsoap.org/soap/http"/>
transport="http://schemas.xmlsoap.org/soap/http"/>
verwende
<wsdl:operation
verwendeHTTP
HTTP
<wsdl:operation name="add">
name="add">
Name
der
für
Transport
<wsdlsoap:operation
soapAction=""/>
Name
der
für Transport
<wsdlsoap:operation soapAction=""/>
Alle
Operation
Alle
Operation
<wsdl:input
name="addRequestOp">
Operationen
<wsdl:input name="addRequestOp">
Operationen
<wsdlsoap:body
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://localhost:8080/Calculator"
namespace="http://localhost:8080/Calculator"
use="encoded"/>
use="encoded"/>
</wsdl:input>
</wsdl:input>
Namen
Namender
der
<wsdl:output
name="addResponseOp">
<wsdl:output name="addResponseOp"> Operationsteile
Operationsteile
…… ……
</wsdl:output>
</wsdl:output>
</wsdl:operation>
</wsdl:operation>
</wsdl:binding>
</wsdl:binding>
School of Engineering
© K. Rege, ZHAW
54 von 74
konkretes Interface: Port und Service
■ Service definiert
■
port: protokollabhängiges, konkretes Interface
■ mehrere Ports, für verschiedene Protokolle möglich
■
wsdlsoap:address : Adress-Element des Ports
■ location Attribut: URI des Ports
Implementiertes
ImplementiertesInterface
Interface
Namen
Namendes
desService
Service
Namen
Namendes
desPorts
Ports
<wsdl:binding name="CalculatorSoapBinding"
<wsdl:binding name="CalculatorSoapBinding"
...>
...>
<wsdlsoap:binding style="rpc" .../>
<wsdlsoap:binding style="rpc" .../>
<wsdl:operation name="add">
<wsdl:operation name="add">
...
...
</wsdl:operation>
</wsdl:operation>
</wsdl:binding>
</wsdl:binding>
<wsdl:service
<wsdl:service name="CalculatorService">
name="CalculatorService">
<wsdl:port
name="Calculator"
<wsdl:port name="Calculator" binding="impl:CalculatorSoapBinding"
binding="impl:CalculatorSoapBinding" >>
<wsdlsoap:address
<wsdlsoap:address
location="http://localhost:8080/calc/Calculator"/>
location="http://localhost:8080/calc/Calculator"/>
</wsdl:port>
</wsdl:port>
</wsdl:service>
</wsdl:service>
URI
URIdes
desWeb
WebServices
Services
School of Engineering
© K. Rege, ZHAW
55 von 74
Schnittstellenbeschreibung mit WSDL
■ Schreiben einer WSDL
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0"
encoding="UTF-8"?>
<definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://calculator/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://calculator/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://calculator/"
xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://calculator/"
name="CalculatorImplService">
name="CalculatorImplService">
<types/>
<types/>name="addRequest">
<message
<message
name="addRequest">
<part name="a"
type="xsd:double"/>
<partname="b"
name="a"type="xsd:double"/>
type="xsd:double"/>
<part
<part name="b" type="xsd:double"/>
</message>
</message>
<message
name="addResponse">
<message
name="addResponse">
<part name="addResult"
type="xsd:double"/>
<part
name="addResult"
type="xsd:double"/>
</message>
</message>
<portType
name="Calculator">
<portType
<operationname="Calculator">
name="add" parameterOrder="a b">
<operation
name="add" parameterOrder="a b">
<input
message="tns:addRequest"/>
<input message="tns:addResponse"/>
message="tns:addRequest"/>
<output
<output message="tns:addResponse"/>
</operation>
</operation>
</portType>
</portType>
<binding
name="CalculatorImplPortBinding" type="tns:Calculator">
<binding
name="CalculatorImplPortBinding"
type="tns:Calculator">style="rpc"/>
<soap:binding
transport="http://schemas.xmlsoap.org/soap/http"
<soap:binding
transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>
<operation
name="add">
<operation
name="add">
<soap:operation
soapAction=""/>
<soap:operation soapAction=""/>
<input>
<input>
<soap:body use="literal" namespace="http://calculator/"/>
<soap:body use="literal" namespace="http://calculator/"/>
</input>
</input>
<output>
<output>
<soap:body use="literal" namespace="http://calculator/"/>
<soap:body use="literal" namespace="http://calculator/"/>
</output>
</output>
</operation>
</operation>
</binding>
</binding>
<service
name="CalculatorImplService">
<service
name="CalculatorImplService">
<port name="CalculatorImplPort"
binding="tns:CalculatorImplPortBinding">
<port
name="CalculatorImplPort"
binding="tns:CalculatorImplPortBinding">
<soap:address
location="http://localhost:8081/calc/Calculator"/>
<soap:address location="http://localhost:8081/calc/Calculator"/>
</port>
</port>
</service>
</service>
</definitions>
</definitions>
School of Engineering
© K. Rege, ZHAW
56 von 74
Schnittstellenbeschreibung Java mit JSR 181
■ Schreiben eines Java Interface mit JSR 181 Annotationen
package calculator;
package calculator;
import javax.jws.*;
import javax.jws.*;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding.Style;
SOAPBinding(style = Style.DOCUMENT,
SOAPBinding(style = Style.DOCUMENT,
use=Use.LITERAL,
use=Use.LITERAL,
parameterStyle=SOAPBinding.ParameterStyle.BARE)
parameterStyle=SOAPBinding.ParameterStyle.BARE)
@WebService
@WebService
@SOAPBinding(style = Style.RPC)
@SOAPBinding(style = Style.RPC)
public interface Calculator{
public interface Calculator{
@WebMethod
@WebMethod
@WebResult(name = "addResult")
@WebResult(name = "addResult")
double add( @WebParam(name="a") double a, @WebParam(name="b") double b);
double add( @WebParam(name="a") double a, @WebParam(name="b") double b);
}
}
■ Schreiben der Implementation
package calculator;
package calculator;
import javax.jws.WebService;
import javax.jws.WebService;
@Stateless
@Stateless
@WebService(endpointInterface = "calculator.Calculator")
@WebService(endpointInterface = "calculator.Calculator")
public class CalculatorImpl implements Calculator{
public class CalculatorImpl implements Calculator{
@Override
@Override
public double add(double a, double b) {
public double add(double a, double b) {
return a+b;
return a+b;
}
}
}
}
School of Engineering
© K. Rege, ZHAW
57 von 74
Server
School of Engineering
© K. Rege, ZHAW
58 von 74
SOAP Aufrufe in Java
■ Definition eines Java APIs for XML-based Web Services (JAX-WS)
■ Sun liefert Referenz-Implementation: Teil von JEE 5
JSR181
JSR181
WSGen
Annotated
Annotated
Interface
Interface
WSDL
WSDL
WSImport
Client
Client
Generierte
Generierte
Proxy
Proxy
JAX-WS
JAX-WS
Runtime
Runtime
HTTP
HTTP
Config
Config
Implemention
Implemention
Server
Server
JAX-WS
JAX-WS
Runtime
Runtime
HTTP
HTTP
Web
WebServer
Server
School of Engineering
© K. Rege, ZHAW
59 von 74
Self Hosted Web Server
■ Ab JDK 1.6 ist auch ein Mini-WebServer integriert
■ Mittels Endpoint.publish wird der Service bekannt gemacht
package calculator;
package calculator;
import javax.swing.JOptionPane;
import javax.swing.JOptionPane;
import javax.xml.ws.Endpoint;
import javax.xml.ws.Endpoint;
class CalcStarter {
class CalcStarter {
}
public static void main(String[] args) {
public static void main(String[] args) {
String endpointUrl = "http://localhost:8081/calc/Calculator";;
String endpointUrl = "http://localhost:8081/calc/Calculator";;
Object service = new CalculatorImpl();
Object service = new CalculatorImpl();
Endpoint endpoint = Endpoint.publish(endpointUrl,service);
Endpoint endpoint = Endpoint.publish(endpointUrl,service);
JOptionPane.showMessageDialog( null, service.getClass().getSimpleName()
JOptionPane.showMessageDialog( null, service.getClass().getSimpleName()
+" started on "+ endpointUrl+"\nStop Service?");
+" started on "+ endpointUrl+"\nStop Service?");
endpoint.stop();
endpoint.stop();
}
}
}
School of Engineering
© K. Rege, ZHAW
60 von 74
… Self Hosted Web Server
■ Test und Anzeige der WSDL via Browser
School of Engineering
© K. Rege, ZHAW
61 von 74
Web Server hosted
■ Erzeugen eines web.xml deployment descriptor: WSServletContextListener des
Listener Servlets.
■ File : web.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems,Inc.//DTD Web Application
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems,Inc.//DTD Web Application
2.3//EN"
2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
"http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
<web-app>
<web-app>
<listener>
<listener>
<listener-class>
<listener-class>
com.sun.xml.ws.transport.http.servlet.WSServletContextListener
com.sun.xml.ws.transport.http.servlet.WSServletContextListener
</listener-class>
</listener-class>
</listener>
</listener>
<servlet>
<servlet>
<servlet-name>calc</servlet-name>
<servlet-name>calc</servlet-name>
<servlet-class>
<servlet-class>
com.sun.xml.ws.transport.http.servlet.WSServlet
com.sun.xml.ws.transport.http.servlet.WSServlet
</servlet-class>
</servlet-class>
<load-on-startup>1</load-on-startup>
<load-on-startup>1</load-on-startup>
</servlet>
</servlet>
<servlet-mapping>
<servlet-mapping>
<servlet-name>calc</servlet-name>
<servlet-name>calc</servlet-name>
<url-pattern>/calc</url-pattern>
<url-pattern>/calc</url-pattern>
</servlet-mapping>
</servlet-mapping>
<session-config>
<session-config>
<session-timeout>120</session-timeout>
<session-timeout>120</session-timeout>
</session-config>
</session-config>
</web-app>
</web-app>
School of Engineering
© K. Rege, ZHAW
62 von 74
… Web Server hosted
■ Schreiben der WS Deployment Descriptor, auch als JAX-WS RI deployment
descriptor – sun-jaxws.xml bezeichnet
■ File : sun-jaxws.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<endpoints
<endpoints
xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
version="2.0">
version="2.0">
<endpoint
<endpoint
name="Calculator"
name="Calculator"
implementation="calculator.CalculatorImpl"
implementation="calculator.CalculatorImpl"
url-pattern="/calc"/>
url-pattern="/calc"/>
</endpoints>
</endpoints>
School of Engineering
© K. Rege, ZHAW
63 von 74
… Web Server hosted
■ Erstellen eines WAR Files mit folgendem Inhalt
WEB-INF/classes/calculator/Calculator.class
WEB-INF/classes/calculator/Calculator.class
WEB-INF/classes/calculator/CalculatorImpl.class
WEB-INF/classes/calculator/CalculatorImpl.class
WEB-INF/web.xml
WEB-INF/web.xml
WEB-INF/sun-jaxws.xml
WEB-INF/sun-jaxws.xml
■ File : build.xml
<property name="build" location="classes"/>
<property name="build" location="classes"/>
<property name="dist" location="dist"/>
<property name="dist" location="dist"/>
<property name="webcontent" location="WebContent"/>
<property name="webcontent" location="WebContent"/>
...
...
<target name="war" depends="compile"
<target name="war" depends="compile"
description="generate the distribution war" >
description="generate the distribution war" >
<!-- Create the war distribution directory -->
<!-- Create the war distribution directory -->
<mkdir dir="${dist}/war"/>
<mkdir dir="${dist}/war"/>
<!-- Follow standard WAR structure -->
<!-- Follow standard WAR structure -->
<copydir dest="${dist}/war/build/WEB-INF/" src="${webcontent}/WEB-INF/" />
<copydir dest="${dist}/war/build/WEB-INF/" src="${webcontent}/WEB-INF/" />
<copydir dest="${dist}/war/build/WEB-INF/classes/" src="${build}" />
<copydir dest="${dist}/war/build/WEB-INF/classes/" src="${build}" />
<jar jarfile="${dist}/war/${ant.project.name}.war" basedir="${dist}/war/build/"/>
<jar jarfile="${dist}/war/${ant.project.name}.war" basedir="${dist}/war/build/"/>
</target>
</target>
School of Engineering
© K. Rege, ZHAW
64 von 74
… Web Server hosted
■ Dependencies: Tomcat braucht noch zusätzliche jars für die JAX-WS
Dependencies
■ Diese müssen von Hand hinzugefügt werden
■
■
■
1. Seite mit Dependencies http://jax-ws.java.net/.
2. Lade JAX-WS RI herunter.
3. Unzip und folgende JAX-WS Dependencies in den Tomcat Folder “{$TOMCAT}/lib“ kopieren
■
■
■
■
■
■
■
■
jaxb-impl.jar
jaxws-api.jar
jaxws-rt.jar
gmbal-api-only.jar
management-api.jar
stax-ex.jar
streambuffer.jar
policy.jar
School of Engineering
© K. Rege, ZHAW
65 von 74
… Web Server hosted
■ Deployment: Das WAR File in den {$TOMCAT}/webapps/ Folder kopieren und
den Server starten (Catalina start).
■ Zu Testzwecken kann URL : http://localhost:8080/Calculator/calc aufgerufen
werden: folgende Seite zeigt, dass es geklappt hat.
School of Engineering
© K. Rege, ZHAW
66 von 74
Client
School of Engineering
© K. Rege, ZHAW
67 von 74
Der Klient
■ Statische Bindung an Service
■ WSDL Service ⇒ Service Interface: Port
Service Class (Factory: getXXXPort())
■ Aufruf einfach
■
■
■
1) Instanziere Service
2) hole Port Interface
3) rufe EndPoint Interface bzw. die implementierende Klasse
CalculatorImpService service = new CalculatorImpService();
CalculatorImpService service = new CalculatorImpService();
Calculator calc = service.getCalculatorImplPort();
Calculator calc = service.getCalculatorImplPort();
double d = calc.add(4,5);
double d = calc.add(4,5);
Client
Client
Generierte
Generierte
Proxy
Proxy
JAX-WS
JAX-WS
Runtime
Runtime
HTTP
HTTP
School of Engineering
wsimport
WSDL
WSDL
public interface Calculator {
public interface Calculator {
public double add(double a, double b) ;
public double add(double a, double b) ;
...
...
}
}
public class CalculatorImpService{
public class CalculatorImpService{
public Calculator getCalculatorImplPort() {
public Calculator getCalculatorImplPort() {
...
...
}
}
}
}
© K. Rege, ZHAW
68 von 74
Generierung des statischen Proxy
■ Java Proxy Klassen können mittels Kommandozeilen-Werkzeug erzeugt werden
directory
directory
wsimport -d gen
package der
package der
generierten
generierten
-p calculator.ws
Klassen
Klassen
-keep
http://localhost:8081/Calculator/calc?wsdl
JSR181
JSR181
Java
Java
School of Engineering
© K. Rege, ZHAW
69 von 74
…. statische Proxy
■ Instanzierung und Aufruf des Proxy
package calculator;
package calculator;
import java.net.URL;
import java.net.URL;
import javax.xml.namespace.*;
import javax.xml.namespace.*;
import javax.xml.ws.*;
import javax.xml.ws.*;
import calculator.ws.*;
import calculator.ws.*;
URL
URLder
derWSDL
WSDL
public class CalculatorClient1{
public class CalculatorClient1{
public static void main(String[] args) throws Exception {
public static void main(String[] args) throws Exception {
}
}
CalculatorImplService service = new CalculatorImplService();
CalculatorImplService service = new CalculatorImplService();
calculator.ws.Calculator calc = service.getCalculatorImplPort();
calculator.ws.Calculator calc = service.getCalculatorImplPort();
System.out.println("result="+calc.add(32,23));
System.out.println("result="+calc.add(32,23));
}
}
School of Engineering
© K. Rege, ZHAW
70 von 74
Anpassung der Web Service URL
■ Nötig falls z.B. via Proxy zugegriffen
package calculator;
package calculator;
import java.net.URL;
import java.net.URL;
import javax.xml.namespace.*;
import javax.xml.namespace.*;
import javax.xml.ws.*;
import javax.xml.ws.*;
import calculator.ws.*;
import calculator.ws.*;
Entfällt
Entfälltfalls
fallsProxy
Proxy
Generierung
Generierungvia
vialokale
lokale
WSDL
und
WSDL
WSDL und WSDL
mitverteilt
mitverteilt
public class CalculatorClient1{
public class CalculatorClient1{
public static void main(String[] args) throws Exception {
public static void main(String[] args) throws Exception {
// define location of WSDL
// define location of WSDL
URL url = new URL("http://localhost:8081/Calculator/calc?wsdl");
URL url = new URL("http://localhost:8081/Calculator/calc?wsdl");
QName qname = new QName("http://calculator/", "CalculatorImplService");
QName qname = new QName("http://calculator/", "CalculatorImplService");
CalculatorImplService service = new CalculatorImplService(url,qname);
CalculatorImplService service = new CalculatorImplService(url,qname);
calculator.ws.Calculator calc = service.getCalculatorImplPort();
calculator.ws.Calculator calc = service.getCalculatorImplPort();
// define location of URL
// define location of URL
String endpointURL = "http://localhost:8081/Calculator/calc";
String endpointURL = "http://localhost:8081/Calculator/calc";
BindingProvider bp = (BindingProvider)calc;
BindingProvider bp = (BindingProvider)calc;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
}
}
System.out.println("result="+calc.add(32,23));
System.out.println("result="+calc.add(32,23));
}
}
School of Engineering
© K. Rege, ZHAW
71 von 74
Dynamische Proxy
■ Einfacher: Proxy wird dynamisch anhand WSDL generiert
package calculator;
package calculator;
import java.net.URL;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.Service;
public class CalculatorClient2{
public class CalculatorClient2{
public static void main(String[] args) throws Exception {
public static void main(String[] args) throws Exception {
URL url = new URL("http://localhost:8081/Calculator/calc?wsdl");
URL url = new URL("http://localhost:8081/Calculator/calc?wsdl");
QName qname = new QName("http://calculator/", "CalculatorImplService");
QName qname = new QName("http://calculator/", "CalculatorImplService");
Service service = Service.create(url, qname);
Service service = Service.create(url, qname);
Calculator calc = service.getPort(Calculator.class);
Calculator calc = service.getPort(Calculator.class);
System.out.println("result="+calc.add(32,23));
System.out.println("result="+calc.add(32,23));
}
}
}
}
School of Engineering
© K. Rege, ZHAW
72 von 74
Zusammenfassung
■ Transaktionen
■
■
■
■
■
EJB unterstützt CMTD (Container Managed Transaction Demarcation)
BMTD zwar unterstützt, aber Verwendung nicht empfohlen
Durch CMTD Vereinfachung der Entwicklung von TX-Komponenten
Transaktion kann mehrere Beans, Ressourcen und EJB Container überspannen
Dürfen aber nicht geschachtelt sein
■ Message Driven Beans
■
einfache Implementation eines JMS Listeners
■ Interceptor
■
Neue Aspekte mittels eigenen Klassen
■ Web Services
■
Aufrufe via HTTP
School of Engineering
© K. Rege, ZHAW
73 von 74
Anhang JSR181 Web Service Metadata
■ Definition der Web Service Schnittstelle einer annotierten Java Klasse
■ Folgende Annotation in javax.ws und javax.ws.soap definiert
■
@WebService. Jede Web-Service-Implementierung muss diese Klassen-Annotation besitzen.
Optionale Elemente sind zum Beispiel name (bestimmt den <wsdl:Interface>, Standard ist der
unqualifizierte Name der Klasse bzw. Schnittstelle), targetNamespace, serviceName oder
EndPointName.
■
@SOAPBinding. Setzt den Stil der Nachrichten auf Dokument oder RPC.
■
@WebMethod. Die Annotation macht eine Methode zur Web-Service-Operation. Der StandardName unter <wsdl:operation> ist der Name der Methode; er lässt sich mit dem Element
operationName ändern.
optional
■
@WebParam. Beschreibt die Parameter genauer. Das Element name überschreibt den
Parameternamen, der sonst »argX« heißen würde, für das WSDL-Element <wsdl:part>.
■
@WebResult. Definiert die Rückgabe einer Web-Service-Methode genauer.
■
@OneWay. Für asynchrone Aufrufe.
Aus "Java ist auch eine Insel",
Galileo Computing
School of Engineering
© K. Rege, ZHAW
74 von 74
Herunterladen