Mega Code Archive

 
Categories / Delphi / XML
 

SOAP the World of Services

Title: SOAP the World of Services Question: Web services understanding and creating. Answer: The current development of the web seems to be radical. That is because the web will soon migrate to business to business exchange model. Fortunately, this migration is really cool and with the current tools, for a programmer, all that is a piece of cake. We will speak in this article about SOAP, one the coolest technologies in creating multiplatphorm application. In fact SOAP means Simple Object Access Protocol and it was developed by DevelopMentor and Microsoft. SOAP is defined as a lightweight protocol for exchanging information in a descentralized, distributed environment. In fact, SOAP is a RPC (Remote Procedure Calling) protocol that uses the XML over a HTTP connexion. Using XML is the best part of this specification, because XML is an open standard. Anyway, text protocols are very popular in Internet world (sendmail, POP3, IMAP, ftp are text protocols and they work fine). The good part for a Delphi programmer is that in the current version (6), the SOAP protocol is entirelly supported in Borland maneer: easiest to deploy in a high productivity environment. And you will be surprised to know that you can deploy SOAP applications without knowing anything about SOAP! But, for a good programmer, knowing the basic stone of this protocol is a need. That is because SOAP is development process and it is possible to change in the near future. In figure 1, you can see a schematic representation of the SOAP protocol. As you can oberve there are 4 steps: one preliminar (the step 0) and other 3 steps. Lets understand! - In the preliminar step the client requests from the server a special file (named WSDL) that describes the service. In many cases, this happens in the development time of the application; - Then, the client sends to the server a request. This request is a remote procedure calling. In fact, the client requests to the server to execute a procedure or a function; - In the Step 2 the server tries to execute the client requested function/procedure; - Finally, the server sends the response to the client. This can be the procedure/function result or an error. As I have said, the SOAP protocol is based on exchanging messages between the client and the server (usually over a HTTP connection). The client sends a request that is a function or a procedure to call and the server responses with the result. All of this message exchange is based on well formed XML documents. Lets see! In figure 2 you have a client request and a server response messages. The CLIENT REQUEST TheParameter The SERVER RESPONSE 34.5 Figure 2 For easilly understanding, you have to know that a SOAP document has a standard structure and it is divided in 3 parts: the SOAP Envelope, the Body, and optionally the Header. If it is present, the Header element will be the first child of the Envelope. Bellow you have a short description about each part of a SOAP document. The SOAP Envelope is the root element. The first parameter is a namespace declaration, it points to http://schemas.xmlsoap.org/soap/envelope and it is a required parameter. The second parameter is optional and it declares the encoding style. In fact, it lists additional URIs that describe how data types will be used in the SOAP document; The Header element is optional but if it is present in the document it must be the first child of the SOAP Envelope. Generally, the Header element is used for authentification. It also can be used to extend the message. The Body represents the interesting part of a SOAP document because inside it are the messages (requests or responses). As you can see in Figure 2, in the Client Request document we have the procedure we want to call and in the Response we have the result(s). In fact that is all about SOAP documents. But, in order to deliver a Web Service, we will need another element named the WSDL file. WSDL means Web Service Description Languge and describes the interface of the SOAP Service. It contains the definitions for all procedures/functions and data types. You can see a WDSL example file bellow. It is the file corresponding to a service that we will implement in this article. Looking inside this file you will observe that you have to deal with the following elements: Message, Operation, Port Type, Binding, Port and Service. There is another element that is not presented here named DataType. Because there is a little documentation related to these elements, I will present here a little description for each element. DataType is a container for describing the data types used by the service. If the service deals with simple data types (string, float etc.) this section is not necessary (as above); Message contains the description about data being communicated. Above, we have defined the request(SumRequest) that consists in 2 integer parameters(i1 and i2) and the response (SumResponse) that consists in an integer; Operation consists in a description of the action suported by the services. In our case Sum; PortType is a set of operations supported by the service; Binding contains the protocol and data specifications for a PortType; Port is a endpoint defined as a combination of a binding and a network address; Service is a collection of endpoints (Port). With all of these elements presented, a web service is described in a simple and clear maneer. As you can see all of these elements are put together for easy representation of any web service. Its now time to speak a little about SOAP data types. SOAP defines simple datatypes like integer, float, string and provides a standard for constructing complex data types as enumeration, array or object. In fact you can represent using SOAP anything you want. Because this subject is really waste, I recomend you to visit sites listed in the resources section. There, you will be able to read some good documents that treat almost any aspect related to SOAP. Now is Delphi time. For all of you that have Entreprise Edition of Delphi 6 I have good news. You will be able to create easy and fast SOAP servers and clients. For others (also for Delphi 5 users) I will provide another way to work with SOAP. Lets build a SOAP client! But, before starting our client, we need to know what service we will use. In the present days there are many sites that list available web services. One of the best is xMethods (http://www.xmethods.org). Here you will find detailed informations about a plethora of web services. Also, this site has an available SOAP Service that can be used to obtain informations about listed services. We will create now a client for this service. First create a new project and then File|New|Other... and from WebServices select the WebServicesImporter and the WebServicesImporter dialog will be shown (as in Figure 3). In the editbox insert the path to the WSDL file. In our case this is http://www.xmethods.net/sd/2001/XMethodsListingsService.wsdl. Then press the Generate button. Be carefull, you have to be online in order to import a web service. After few seconds the Delphi will generate for you 2 units: one for data types declarations and one for interface declaration. This is not a rule. If the service does not deal with complex data types, just a single unit with interface declaration will be generated. Looking inside the declaration unit (unit2.pas) you will observe something like bellow. type SOAPService = class;{ ArrayOfSOAPService } ArrayOfSOAPService = array of SOAPService;{ SOAPService } SOAPService = class(TRemotable) private............................ published............................end; The TRemotable class was specially introduced in Delphi 6 (into the InvokeRegistry unit) for working with SOAP and it is the base class for all classes that can be passed as parameters in Web Service applications. Moving now to the next unit you will observe the interface declaration: type XmethodsListingsPortType = interface(IInvokable) ['{8E844E84-4886-487D-8C11-76AEC9727219}'] function getAllSOAPServices: ArrayOfSOAPService; stdcall; end; Here you will find all available procedures/functions for the selected Web Service. As you can see for Xmethods Service (XmethodsListingsPortType) we have just a single function available getAllSOAPService that has no parameters and returns an array of SoapService type. Now we have all we need for building our client. Lets move on the form and start to create the interface. For that put the following components on the form: a Listbox, a Memo, a Button and, from the WebService tab a THTTPRio component. The listbox will be filled with the names of the services and in the memo we will put the other details about a selected service. THTTPRio component is able to call remote interfaced object via HTTP. It is a descendant on the TRio that is a base class for components that generate calls to remote interfaced objects. In order to work with THTTPRio component you have to set some properties. First, you have to fill the WSDLLocation property. This can be a file (local) or a URI (also, be carefull to be online if you insert here a URI!). Then you have to fill the Service and Port properties. For that, just select from the combobox the implicit values. And now, you are (in the final!) ready to write something! Now, in order to receive all services from Xmethods service, all we have to do is to declare a variable of ArrayOfSOAPService type and then to write something like bellow: var services:ArrayOfSOAPService;beginservices:=(Httprio1 as XmethodsListingsPortType).getAllSOAPService;......................... ... and thats all. Now you have in the services variable an array of SoapService type. Accessing each service properties is easy: services[i].name will contain the name, services[i].id contains the id etc. In fact that was all about constructing a SOAP client. In the attachment you have the complete source for this project. Its time now for developping a SOAP server. It is good to have installed on your computer a web server that is able to handle cgis requests. I have on my computer Apache and Pws and this example work fine on both servers. For better understanding all concepts, I will create a simple service that returns a two numbers sum. Close all your opened projects and start with New|Other| and here click on the WebServices tab. Select the SoapServerApplication. From the dialog select StandAloneCGI (you can use any option that appers there but, for our purposes, this selection is good). Delphi will generate a SOAP server scheleton. It consists in a SoapDispatcher, a HTTPSOAPPascalInvoker and a WSDLHTMLPublish. The SoapDispatcher is responsable to respond to SOAP messages. It guides messages to the HTTPSOAPPascalInvoker, which is responsable to interpret received messages and execute the requested procedure. The WSDLHTMLPublish component publishes WSDL documents coresponding to actual registered services. As you can see, all the hard work is handled by these 3 components. Now, for developping our service we will work with interfaces. This is a requirement! From File menu, select New|Unit. It is time now to declare our interface. Lets see: Type IAddition=interface(IInvokable) ['{2F331D45-0BAE-4ECE-8F6C-047E9FCBC864}'] function Sum(i1:integer;i2:integer):integer; stdcall;end; The only new concept you saw there is that the IAddition (our interface) is an IInvokable descendant. In the sysutils unit, this interface is declared with {$M} option enable that means the RTTI is available on run-time. Also, the Sum function is declared using stdcall. Now, in the initialization section of the unit add the following declaration: Initialization InvRegistry.RegisterInterface(TypeInfo(IAddition)); InvRegistry is a global function declared in the InvokeRegistry unit. It returns a catalog of all registered Invokable interfaces. Also, when an interface is registered with InvRegistry, a namespace is automatically generated for it. Its time now to create the code that implements our interface. Borland recommends to put the code in other unit, so start a new unit and write the code. type Taddition=class(TInvokableClass,IAddition) protected function Sum(i1:integer;i2:integer):integer;stdcall;end;implementationfunction Taddition.Sum(i1:integer;i2:integer):integer;stdcall;beginResult:=i1+i2;end;initialization InvRegistry.RegisterInvokableClass (TAddition);end. As you can see, this implementation is a normal one, without any tricks. All is clean and easy. The same, initialization section has to be present. And, this is the finish. Save your project in a directory and compile it. Move now the executable file on your web server. Dont forget to put it into a directory with execute permission (i.e. /cgi-bin for Apache). Now, lets see the WSDL for our SOAP service. Point your browser to the location where your exe file is followed by /wsdl (i.e. on my apache server the location will be http://localhost/cgi-bin/test.exe/wsdl and for PWS/IIS something like http://localhost/your_directory/test.exe/wsdl). If all works, you will see a table with URIs for WSDL for our first SOAP service. As a test you can create a client for this service. Anyway, all sources are attached to this article. Now we will concentrate on how creating SOAP applications without the help of Delphi 6 Entreprise Edition. Microsoft has delivered a cool toolset for working with SOAP named Soap Toolkit. The actual version is ServicePack 2 and contains all you need to create easy end fast SOAP servers or clients. You can download the SOAP Toolkit from http://msdn.microsoft.com/download. In the package you will have: some COM components (SOAPServer and SOAPClient are the most important for us), a WSDL/WSML generator (it works just on NT or 2000) and a very good help file. Creating a client with Microsoft SOAP Toolkit is really easilly. We will create now the client for our already created service. Here you will encounter a problem. If the service is created with Delphi, you will have to download the WSDL file and make a little modification. In the definition, for a Borland generated web service you will have: xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap" All you have to do is to put the final slash. So, your WSDL file will contain now something like that: xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" **********Making generated WSDL compatible with MSSoap********** **********For Advanced Users Only!********** If you want to repair this WSDL generation routine, all you have to do is to modify the Wsdlintf.pas unit. You can find it in: \Source\Internet\At line 71 modify from:Soapns = Wsdlns +'soap';to:Soapns = Wsdlns +'soap\'; And then recompile your server project and all related units. But before this operation make a backup copy of your actual \Lib directory.Its a good idea to make this modification because, in this case, your service will generate a MSSoap compatible WSDL file. Anyway, if you dont want to modify you have another option that does not need modifications in delphi libraries. You can manually modify your WSDL file and then indicate to your service users the modificated WSDL as source. ************************************************************************* Ok! Its coding time now. In order to work with MSSoap you have to do 2 steps. First, you have to create an instance of MSSoap.Client class using CreateOLEObject and then to initialize it using mssoapinit method. As parameter for this method you will put the path to our modified WSDL file. Bellow you have all the code. var service:OLEVariant;response:variant;beginservice:=CreateOLEObject('MSSOAP.SoapClient');service.mssoapinit('c:\IAddition.xml');response:=service.Sum(12,22);showmessage(response);end; And now you have your SOAP client almost complete. As you can see there are a few lines of code. This situation is the same for many other web services. The single problem regarding SOAP clients is about long time response. Your application is blocked for a long time (it is waiting for response from server) and this is a bad problem in a commercial application. My recomandation is to place all SOAP related code in a separate thread. At this point, our crash course to SOAP is complete. There are many other aspects to cover but I think this was a good start for you. Web Resources: 1. http://www.w3.org/TR/SOAP Soap specifications. This document covers all aspects about SOAP. 2. http://www.w3.org/TR/wsdl WSDL file specifications. All you need to understand WSDL. 3. http://msdn.microsoft.com/soap A very good source for SOAP related materials. Also, here you can read about MS Soap Toolkit. 4. http://www.xmethods.com, http://www.salcentral.com SOAP services repositories. If you want to find services these sites represents best sources. 5. http://xml.coverpages.org/soap.html Huge collection of SOAP related articles and links.