Temat Stworzenie systemu składającego się z prostej usługi sieciowej (ang. web service) oraz komunikującej się z nią aplikacji klienckiej umożliwiającej dostęp do usługi przez przeglądarkę internetową. Cele 1. Zapoznanie się z podstawowymi elementami składającymi się na kompletny system usługi sieciowej dostępnej dla użytkowników przez przeglądarkę internetową; przeprowadzenie przy użyciu środowiska Oracle9i JDeveloper procesu implementacji kodu takiej aplikacji obejmującego kolejne etapy: - konfiguracja środowiska programistycznego oraz serwerowego, - opublikowanie usługi sieciowej (przygotowanej uprzednio w postaci gotowego kodu źródłowego), - implementacja aplikacji klienckiej działającej w środowisku tworzenia aplikacji (za pośrednictwem modułu typu web service stub) lub dostępnej zdalnie przy użyciu przeglądarki internetowej. 2. Zapoznanie się z funkcjonalnościami środowiska wspomagającego tworzenie aplikacji usług sieciowych. Zadania 1. Uruchomić i skonfigurować środowisko tworzenia aplikacji i serwer aplikacji. 1.1. Uruchomić serwer aplikacji Oracle9iAS Containers for J2EE (zmienić aktualny katalog na \jdev903\j2ee\home, a następnie uruchomić serwer w środowisku maszyny wirtualnej Java poleceniem ..\..\jdk\bin\java –jar oc4j.jar). 1.2. Uruchomić środowisko tworzenia aplikacji Oracle9i JDeveloper. 1.3. Utworzyć i przetestować połączenie pomiędzy środowiskiem Oracle9i JDeveloper a serwerem Oracle9iAS Containers for J2EE. 1.3.1. Utworzyć nowe połączenie typu “Oracle9iAS-StandAlone” (Connections->Application Server->New Connection->Oracle9iAS-StandAlone). 1.3.2. Ustawić identyfikator użytkownika (Username) jako "admin", a hasło jako "welcome" jednocześnie zaznaczając opcję "Deploy Password”. 1.3.3. Ustawić lokalizację URL jako “ormi://127.0.0.1/”. 1 1.3.4. Ustawić opcję Target Web Site jako “http-web-site’. 1.3.5. Jako wartość pola “Local Directory Where admin.jar for Oracle9iAS is installed" wskazać lokalizację pliku admin.jar (zwykle w katalogu \j2ee\home). 1.3.6. Przetestować utworzone połączenie. 2. Uruchomić (opublikować) i przetestować prostą aplikację sieciową 2.1. Otworzyć plik przestrzeni roboczej zawierającej gotowy kod źródłowy prostej usługi sieciowej (\statelessnew\WorkspaceStatelessJava.jws) 2.2. Zlokalizować i zapoznać się z zawartością pliku zawierającego kod źródłowy klasy, której metoda udostępniana jest jako implementowana w ramach ćwiczenia usługa sieciowej; opisać przewidywane działanie usługi sieciowej 2.3. Utorzyć postać wykonywalną (Make) zlokalizowanej klasy. 2.4. Do struktury projektu (ProjectStateless.Java.jpr) dodać usługę sieciową wraz z definicjami potrzebnymi do jej opublikowania (General->Web Service->Java Web Service) przy użyciu wizualnego komponentu środowiska JDeveloper Web Service Publishing Wizard. 2.4.1. W pierwszym kroku procedury Web Service Publishing Wizard zlokalizować klasę HelloImpl jako wartość pola “Select the class that you want to publish as a Web service”. 2.4.2. W drugim kroku procedury Web Service Publishing Wizard wybrać metodę sayHello jako udostępnianą usługę sieciową. 2.4.3. W trzecim kroku procedury Web Service Publishing Wizard zaakceptować domyślne lokalizacje generowanego pliku WSDL, generowanego pliku definiującego proces publikacji usługi sieciowej (web.xml) i punktu końcowego usługi sieciowej (ang. web service endpoint) oraz domyślną konfigurację portu serwera WWW oraz wybór konfiguracji połączenia z serwerem aplikacji (Oracle9iAS-StandAlone). 2.5. Zapoznać się z zawartością i określić działanie wygenerowanych przez Web Service Publishing Wizard plików: HelloImpl.wsdl i web.xml 2.6. Opublikować stworzoną usługę sieciową (tj. serwlet komunikacji SOAP wraz z klasą Java HelloImpl) zgodnie z informacjami zawartymi w profilu WebServices.deploy wybierając opcję Oracle9iAS_Standalone. 3. Uruchomić i przetestować aplikację kliencką usługi sieciowej 3.1. Do struktury projektu (ProjectStateless.Java.jpr) dodać aplikację kliencką utworzonej usługi sieciowej (New->General->Web Service-> Web Service Stub/Skeleton) 2 3.1.1. Użyć procedury Web Service Stub/Skeleton Wizard (automatyczne generowanie kodu). Skorzystać z automatycznego generowania metody głównej. Zaobserwować wynik analizy pliku WSDL prezentowany przez środowisko Oracle9i JDeveloper w postaci listy metod udostępnianych przez usługę sieciową. 3.1.2. Kontynuować procedurę automatycznego generowania kodu przez wybranie odpowiedniej metody. 3.1.3. Zapoznać się z wygenerowanym kodem - klasami, ich wzajemnymi zależnościami i głównym przeznaczeniem (ze szczególnym uwzględnieniem komunikacji przy użyciu protokołu SOAP). 3.1.4. W odpowiednim miejscu kodu klasy HelloImplStub.java dodać następującą linię: System.out.println(stub.sayHello("Test")); 3.2. Uruchomić klasę HelloImplStub.java i zaobserwować wynik jej działania (w oknie typu log). 3.3. Użyć narzędzia Tools->TCP Packet Monitor w celu śledzenia komunikatów języka SOAP wymienianych pomiędzy serwerem a klientem w procesie korzystania z usługi sieciowej. 3.3.1. Zainicjować tryb śledzenia komunikacji (Start TCP Packet Monitor |>). 3.3.2. Ponownie uruchomić klasę HelloImplStub.java. 3.3.3. Zapoznać się z zapisem przepływu komunikatów przedstawionym na zakładce History oraz z zawartością poszczególnych komunikatów przedstawioną na zakładce Data; porównać ją z przykładami z załącznika. 3.4. Przetestować działanie aplikacji przy użyciu przeglądarki internetowej. 3.4.1. Wywołać okno edycji właściwości usługi sieciowej (Edit), a następnie po wybraniu zakładki File Locations (w obrębie Web Service Publishing Wizard) zaznaczyć i skopiować zawartość pola określającego adres punktu końcowego usługi sieciowej (ang. web service endpoint). 3.4.2. Uruchomić przeglądarkę internetową i korzystając z uprzednio skopiowanej wartości uzyskać dostęp do punktu końcowego usługi sieciowej. 3.4.3. Zapoznać się z działaniem uruchomionej aplikacji klienckiej wykorzystując dostęp lokalny jak i zdalny (przy pomocy innego komputera znajdującego się w sieci lokalnej). Załącznik Przykładowa postać dokumentu WSDL (HelloImpl.wsdl) opisującego implementowaną usługę sieciową (w przypadku różnych implementacji wartość pola soap:address location jest zmienna): 3 <?xml version = '1.0' encoding = 'UTF-8'?> <!--Generated by the Oracle9i JDeveloper Web Services WSDL Generator-> <!--Date Created: Sat Nov 01 13:21:36 CET 2003--> <definitions name="HelloImpl" targetNamespace="http://HelloImpl.wsdl" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://HelloImpl.wsdl" xmlns:ns1="http://IHelloImpl.xsd"> <types> <schema targetNamespace="http://IHelloImpl.xsd" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"/> </types> <message name="sayHello0Request"> <part name="param" type="xsd:string"/> </message> <message name="sayHello0Response"> <part name="return" type="xsd:string"/> </message> <portType name="HelloImplPortType"> <operation name="sayHello"> <input name="sayHello0Request" message="tns:sayHello0Request"/> <output name="sayHello0Response" message="tns:sayHello0Response"/> </operation> </portType> 4 <binding name="HelloImplBinding" type="tns:HelloImplPortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="sayHello"> <soap:operation soapAction="" style="rpc"/> <input name="sayHello0Request"> <soap:body use="encoded" namespace="HelloImpl" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output name="sayHello0Response"> <soap:body use="encoded" namespace="HelloImpl" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> </binding> <service name="HelloImpl"> <port name="HelloImplPort" binding="tns:HelloImplBinding"> <soap:address location="http://127.0.0.1:8888/WorkspaceStatelessJavaProjectStatelessJava-context-root/HelloImpl"/> </port> </service> </definitions> Przykładowa postać dokumentu IHelloImpl.java opisującego interfejs implementowanej usługi sieciowej poprzez odwołania metod publicznych klasy wskazanej przez programistę podczas wspomaganego przez środowisko Oracle9i JDeveloper procesu tworzenia usługi: IHelloImpl.java /** * Generated by the Oracle9i JDeveloper Web Services Interface Generator * Date Created: Sat Nov 01 13:21:37 CET 2003 5 * * This interface lists the subset of public methods that you * selected for inclusion in your web service's public interface. * It is referenced in the web.xml deployment descriptor for this service. * * This file should not be edited. */ public interface IHelloImpl { public String sayHello(String param); } Przykładowa postać dokumentu HelloImpl.java zawierającego klasę o metodzie publicznej sayHello udostępnianej implementowanej w ramach ćwiczenia usłudze sieciowej: public class HelloImpl { public HelloImpl() { } public String sayHello(String param) { return "Hello " + param + "! The current time is " + new java.util.Date(); } } Przykładowa postać dokumentu HelloImplStub.java zawierającego kod klienta protokołu SOAP wchodzącego w skład aplikacji klienckiej komunikujacej się z implementowaną w ramach ćwiczenia usługą sieciową (w zależności od różnych lokalizacji, w których usługa sieciowa może być zaimplementowana (opublikowana) zmienna jest wartość pola endpoint): import oracle.soap.transport.http.OracleSOAPHTTPConnection; 6 import org.apache.soap.encoding.soapenc.BeanSerializer; import org.apache.soap.encoding.SOAPMappingRegistry; import org.apache.soap.util.xml.QName; import java.net.URL; import org.apache.soap.Constants; import org.apache.soap.Fault; import org.apache.soap.SOAPException; import org.apache.soap.rpc.Call; import org.apache.soap.rpc.Parameter; import org.apache.soap.rpc.Response; import java.util.Vector; import java.util.Properties; /** * Generated by the Oracle9i JDeveloper Web Services Stub/Skeleton Generator. * Date Created: Sat Nov 01 13:29:37 CET 2003 * WSDL URL: file:/C:/PP/webservices/cwiczenie_2/statelessnew/Project/src/HelloImp l.wsdl */ public class HelloImplStub { public HelloImplStub() { m_httpConnection = new OracleSOAPHTTPConnection(); m_smr = new SOAPMappingRegistry(); } public static void main(String[] args) { try 7 { HelloImplStub stub = new HelloImplStub(); // Add your own code here. System.out.println(stub.sayHello("Test")); } catch(Exception ex) { ex.printStackTrace(); } } public String endpoint = "http://127.0.0.1:8888/WorkspaceStatelessJava-ProjectStatelessJavacontext-root/HelloImpl"; private OracleSOAPHTTPConnection m_httpConnection = null; private SOAPMappingRegistry m_smr = null; public String sayHello(String param) throws Exception { String returnVal = null; URL endpointURL = new URL(endpoint); Call call = new Call(); call.setSOAPTransport(m_httpConnection); call.setTargetObjectURI("HelloImpl"); call.setMethodName("sayHello"); call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC); Vector params = new Vector(); 8 params.addElement(new Parameter("param", java.lang.String.class, param, null)); call.setParams(params); call.setSOAPMappingRegistry(m_smr); Response response = call.invoke(endpointURL, ""); if (!response.generatedFault()) { Parameter result = response.getReturnValue(); returnVal = (String)result.getValue(); } else { Fault fault = response.getFault(); throw new SOAPException(fault.getFaultCode(), fault.getFaultString()); } return returnVal; } public void setMaintainSession(boolean maintainSession) { m_httpConnection.setMaintainSession(maintainSession); } public boolean getMaintainSession() { return m_httpConnection.getMaintainSession(); 9 } public void setTransportProperties(Properties props) { m_httpConnection.setProperties(props); } public Properties getTransportProperties() { return m_httpConnection.getProperties(); } } Przykładowa postać dokumentu web.xml stanowiącego specyfikację sposobu implementacji usługi sieciowej, tj. zawierającego kod konfigurujacy predefiniowaną klasę serwletu oracle.j2ee.ws.StatelessJavaRpcWebService, który służy przetwarzaniu komunikatów SOAP i komunikacji z “wyżej położoną” instancją klasy HelloImpl: <?xml version = '1.0' encoding = 'windows-1250'?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <description>Generated by the Oracle9i JDeveloper Web Services WebXML Generator</description> <servlet> <servlet-name>HelloImpl</servlet-name> <servletclass>oracle.j2ee.ws.StatelessJavaRpcWebService</servlet-class> <init-param> <param-name>class-name</param-name> <param-value>HelloImpl</param-value> </init-param> 10 <init-param> <param-name>interface-name</param-name> <param-value>IHelloImpl</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>HelloImpl</servlet-name> <url-pattern>/HelloImpl</url-pattern> </servlet-mapping> </web-app> Przykładowa treść komunikatu SOAP typu Request: <?xml version = '1.0' encoding = 'UTF-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <ns1:sayHello xmlns:ns1="HelloImpl" SOAPENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <param xsi:type="xsd:string">Mike</param> </ns1:sayHello> ENV:Body></SOAP-ENV:Envelope> </SOAP- Przykładowa treść komunikatu SOAP typu Response: <?xml version = '1.0' encoding = 'UTF-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <ns1:sayHelloResponse xmlns:ns1="HelloImpl" SOAPENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <return xsi:type="xsd:string"> Hello Mike! The current time is Sun Jun 23 23:41:27 PDT 2002 </return> </ns1:sayHelloResponse> </SOAP-ENV:Body></SOAP-ENV:Envelope> 11