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