• Simple Object Access Protocol (SOAP) - general description. SOAP protocol. Basic concepts. SOAP Message Structure

    What is SOAP?

    SOAP stands for Simple Object Access Protocol (Simple Object Access Protocol). I hope after reading the article you will only be left wondering: “What is this strange name?”

    SOAP in its current form is a remote procedure call (RPC) method over a network. (Yes, it is also used to transfer documents as XML, but we'll leave that out for now.)

    Let's figure it out. Imagine that you have a service that returns a stock quote for a given ticker (stock symbol). It sends the data to the Nasdaq site and generates it based on the returned HTML desired result. Next, to allow other developers to use it inside their applications, you make a component out of this service that finds information about quotes via the Internet. It works great until one day Nasdaq changes the layout of its pages. You have to reconsider the entire logic of the component and send updates to all developers using it. And they, in turn, need to send updates to all their users. If this happens on a more or less constant basis, you can make a lot of enemies among your fellow developers. And programmers, as you know, are not to be trifled with. You don't want to take out a photo of your favorite cat from the office shredder tomorrow, do you?

    What to do? Let's see... all you need is to provide one function that will take as input a ticker symbol (type string) and return a stock quote (type float or double). So wouldn't it be easier to just let your developers call this function over the Internet somehow? Great! This is also news to me, there are COM and Corba and Java that have been doing this for years... what is true is true, but these methods are not without flaws. Remote COM setup not trivial. In addition, you need to open so many ports in the firewall that you can't get enough beer from a system administrator. Yes, and you will have to forget about users of all operating systems except Windows. But Linux users are also sometimes interested in the exchange.

    Although it looks like all is not lost for Linux users if they use DCOM, more here: http://www.idevresource.com/com/library/res/articles/comonlinux.asp.

    I can’t say much about Corba and Java, so as an exercise I invite readers to find the cons in these approaches.

    SOAP is a standard that allows you to describe such a remote call and the form in which the result will be returned. So you need to host your function in an application accessible over the network and receive calls as SOAP packets. You then validate the input, run your function, and return the result in a new SOAP packet. The entire process can run over HTTP, so you don't have to open a bunch of ports on your firewall. Is it really simple?

    What is this article about?

    This is the first in a series of articles we are writing about SOAP at Agni Software. In this article I will try to give you an idea of ​​what SOAP is and how to write an application that communicates with a SOAP server.

    Soap and XML

    If SOAP still seems simple to you, let's add XML. Now, instead of the function name and parameters, we get a rather complex XML envelope, as if designed to confuse you. But don’t rush to get scared. There's more to it than that, and you need to see the whole picture to appreciate the complexity of SOAP.
    If you don't know what XML is, first read my article on XML here: http://www.agnisoft.com/white_papers/xml_delphi.asp.

    All SOAP packages are in XML format. What does it mean? Let's see. Take a look at this function (Pascal):
    function GetStockQuote(Symbol: string) : double; It looks great, but the problem is that it's Pascal. What is the use of this simple definition for a Java developer? Or for someone who works with VB? We need something that will be understandable to everyone, even VB programmers. So give them XML containing the same information (parameters, stock quote values, etc.). You create a SOAP package, which is essentially a call to your function, wrapped in XML so that any application on any platform can understand it. Now let's see what our SOAP call looks like:
    xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/1999/XMLSchema">


    IBM


    Informative, right? SOAP is becoming easier before our eyes. Okay, jokes aside. Now I will try to explain to you how to understand this SOAP call.

    Tag decoding

    The first tag that catches your eye is . This tag is the outer wrapper of a SOAP package, containing several namespace declarations that we are not particularly interested in, but are very important for any programming language or parser. Namespaces are defined to ensure that subsequent prefixes such as "SOAP-ENV:" or "xsd:" are understood by the parser.

    Next tag – . (We've missed a tag not shown here - . It's not in this particular example, but if you want to read more about it, check out the SOAP specification here: http://www.w3.org/TR/SOAP/). Tag actually contains a SOAP call.

    The next tag in the list is . The tag name, GetStockQuote, is the function being called. In SOAP terminology, this is called an operation. So GetStockQuote is the operation that needs to be performed. ns1 is the namespace pointing to urn:xmethods-quotes in our case.

    A note on namespaces: A namespace makes it possible to qualify an XML tag. You cannot, for example, have two variables with the same name in one procedure, but if they are in two different procedures, there is no problem. Thus, a procedure is a namespace, since all names in it are unique. Likewise, XML tags have their scope within namespaces, so given a namespace and a tag name, you can uniquely identify it. We'll define the namespace as a URI to differentiate our NS1 from copycats. In the example above, NS1 is an alias pointing to urn:xmethods-quotes.

    Also pay attention to the encodingStyle attribute - this attribute determines how the SOAP call is serialized.

    Inside a tag contains parameters. In our simplest case, we have only one parameter - tag . Notice this line next to the tag:
    xsi:type="xsd:string"
    This is roughly how types are defined in XML. (Notice how cleverly I used the word "approximately" when making a generalization about technology that may change once the article is published.) What exactly does this mean: a type defined in the xsi namespace, which you'll notice is defined in the tag – xsd:string. And this, in turn, is string, defined in the xsd namespace, again, defined earlier. (I’m sure lawyers would just be thrilled by all this).

    Inside a tag "IBM" is indicated. This is the value of the symbol parameter of the GetStockQuote function.

    Well, in the end, like decent people, we closed all the tags.

    So we figured out the SOAP packet that defines the call to the SOAP server. And the SOAP server, using XML parsers, the red button and the MIR space station, decodes this call and determines that you need a stock quote. He immediately finds the right quote and returns it to you in this form:
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>


    34.5


    After unwrapping the SOAP envelope, tearing off the ribbons and rustling the wrapper, we learn that the IBM share price is 34.5.

    Most commercial servers would return much more information, such as in what currency and at what price the last stock was purchased. And the share price, perhaps, would have been more accurate.

    This way we know what the SOAP server expects and what it will return. So HOW do you send this information? You can use any transport. The most covered is HTTP. I won't go into detail about HTTP, for those who don't know, it's what your browser uses to communicate with the sites you visit.

    The required HTTP request will look something like this:
    POST /StockQuote HTTP/1.1
    Host: www.stockquoteserver.com

    Content-Length: nnnn
    SOAPAction: "Some-URI"

    The soap request packet here... The only other thing worth noting is the SOAPAction header. This header indicates the purpose of the request and is required. Each SOAP server can have an unlimited number of functions and can use the SOAPAction header to determine which function is called. Firewalls and multiplexers can also filter content based on this header.

    SOAP response from HTTP servers will look like this:
    HTTP/1.1 200 OK
    Content-Type: text/xml; charset="utf-8"
    Content-Length: nnnn

    Soap Response packet here... Why HTTP? First, network administrators won't have to open a ton of separate ports for SOAP calls... the web server can handle the calls with ease, because Port 80 is usually open to everyone to receive incoming requests. Another advantage is the extensibility of web servers using CGI, ISAPI and other native modules. This extensibility allows you to write a module that processes SOAP requests without affecting other web content.

    That's it

    I hope this article helped shed some light on SOAP. If you're still here and want to read more on this topic, visit the authors' website: http://www.agnisoft.com/soap

    History of creation

    With the advent personal computers There was also a need to unite them. At first there were simple cable connections, then network protocols appeared that united computers running on the same OS; with the development of technology, the need to have one OS on all computers disappeared and it became possible to combine computers running different OSes. The Internet has changed the speed of movement along the path of unification.

    But even today, not all integration problems have been solved; unfortunately, there was no single protocol for communication between Internet applications and services. To solve this problem, companies such as Microsoft, DevelopMentor, UserLand Software, IBM and Lotus Development teamed up and as a result of their joint activities, the Simple Object Access Protocol was created - a simple object access protocol that describes a standard for remote procedure calls based on the XML language (Extensible Markup Language - extensible markup language). SOAP is designed to greatly simplify the development of cross-language applications and business integration tools. The beginning was made with SOAP 1.0, which required the HTTP protocol to operate.

    After the appearance of the initial version of SOAP, created, as already noted, by the joint efforts of Microsoft, DevelopMentor and UserLand, IBM and Lotus joined in the development of the product. As a result, the specification has undergone a significant overhaul to better suit the integration of heterogeneous environments. The main difference between the next version of SOAP 1.1 and the initial version was the transition from Microsoft's XML-Data to XML Schema. In addition, in the new version the specification no longer depends on transport protocols. For SOAP 1.0 to work, the HTTP protocol was required, while for SOAP 1.1 the type of transport does not matter: you can use by email or pointers to message queues (massage queving links). Companies that had already adopted SOAP 1.0 found themselves tied to Microsoft's non-standard technology. However, a number of promising products from this corporation, including BizTalk Server and SQL Server 7.0, also rely on XML-Data. With the advent of version 1.1, the circle of supporters of the SOAP protocol is expanding

    Initial version of SOAP 1.1 submitted to the Task Force technical support Internet IETF, was based on the XML-Data technology proposed by Microsoft in January 1998. However, in the process of considering standards in the W3C consortium basic structure has been replaced by XML Schema. The World Wide Web Consortium was asked to consider SOAP 1.1 as a potential standard.

    The latest version of the Simple Object Access Protocol (SOAP) specification is available on the web server serving MSDN™ Developer Program members (http://msdn.microsoft.com/). SOAP is an open, standards-based protocol that defines, based on XML (Extensible Markup Language), a common format for communication between any Internet applications and services. This version extends SOAP's capabilities for asynchronous communications to include support not only for HTTP, but also for Internet protocols such as SMTP, FTP, and TCP/IP. The latest version of the SOAP specification has received widespread support from companies such as ActiveState Tool Corp., Ariba Inc., BORN Information Services Inc., Commerce One Inc., Compaq Computer Corp., DevelopMentor Inc., Extensibility Inc., IBM, IONA Technologies PLC, Intel Corp., Lotus Development Corp., ObjectSpace Inc., Rogue Wave Software Inc., Scriptics Corp., Secret Labs AB, UserLand Software and Zveno Pty. Ltd. The SOAP specification provides a common mechanism for integrating services across the Internet and/or intranets, regardless of the operating system, object model, or programming language used. Based on the Internet standards XML and HTTP, SOAP allows any new or existing applications. Web sites that support SOAP can become Web services that are accessible purely programmatically and do not require human intervention. A single infrastructure that enables direct interaction between Internet-facing applications opens up new opportunities for integrating services and devices—no matter where they are on the Internet.

    Web Services and SOAP

    Web services and SOAP are designed to solve the problems of cross-platform application communication. This article will help you gain insight into these new promising technologies.

    What is SOAP

    Currently used technologies for remote method calling (DCOM, CORBA/IIOP and RMI) are quite difficult to configure and organize interaction. This entails problems in the operation and functioning of distributed systems (security problems, transport through firewalls, etc.). The existing problems were successfully solved by the creation of SOAP (Simple Object Access Protocol), a simple XML-based protocol for exchanging messages in distributed environments (WWW). It is designed for creating web services and calling methods remotely. SOAP can be used with different transport protocols, including HTTP, SMTP, etc.

    What are web services

    Web services are functionality and data exposed for use by external applications that interact with the services through standard protocols and data formats. Web services are completely independent of the implementation language and platform. Web services technology is the cornerstone program model Microsoft .NET. To demonstrate the capabilities of SOAP, I used the recently released implementation of SOAP Toolkit version 2.0 from Microsoft. It should be noted that current version Toolkit is noticeably different from the previous one (Microsoft SOAP Toolkit for Visual Studio 6.0) and from the beta version of SOAP Toolkit 2.0.

    Mechanism of interaction between client and server

    1. The client application instantiates the SOAPClient object
    2. SOAPClient reads web service method description files (WSDL and Web Services Meta Language - WSML). These files can also be stored on the client.
    3. The client application, using the late binding capabilities of the SOAPClient object, calls the service method. SOAPClient generates a request packet (SOAP Envelope) and sends it to the server. It is possible to use any transport protocol, but usually HTTP is used.
    4. The packet takes a Listener server application (can be an ISAPI application or an ASP page), creates a SOAPServer object and passes the request packet to it
    5. SOAPServer reads the web service description, loads the description and request packet into XML DOM trees
    6. SOAPServer calls a method of the object/application implementing the service
    7. The results of the method execution or error description are converted by the SOAPServer object into a response packet and sent to the client
    8. The SOAPClient object parses the received packet and returns client application results of the service or a description of the error that occurred.

    A WSDL file is an XML document that describes the methods provided by a web service. Also parameters of methods, their types, names and location of the service Listener. The SOAP Toolkit wizard automatically generates this document.

    SOAP Envelope (Package) - an XML document that contains a request/response for executing a method. It is most convenient to consider it as a postal envelope in which information is enclosed. The Envelope tag must be the root element of the package. The Header element is optional, but the Body element must be present and be a direct child of the Envelope element. If a method execution error occurs, the server generates a packet containing a Fault element in the Body tag, which contains a detailed description of the error. If you use the high-level interfaces SOAPClient, SOAPServer, then you do not have to go into the intricacies of the package format, but, if desired, you can use low-level interfaces or even create a package by hand.

    The SOAP Toolkit object model makes it possible to work with low-level API objects:

    • SoapConnector - Provides work with the transport protocol for exchanging SOAP packets
    • SoapConnectorFactory - Provides a method for creating a connector for the transport protocol specified in the WSDL file (tag)
    • SoapReader - Reads SOAP messages and builds XML DOM trees
    • SoapSerializer - Contains methods for creating a SOAP message
    • IsoapTypeMapper, SoapTypeMapperFactory - Interfaces that allow you to work with complex data types

    Using high-level API objects, you can only transfer data of simple types (int, srting, float ...), but the SOAP 1.1 specification allows you to work with more complex data types, such as arrays, structures, lists and their combinations. To work with such types, you have to use the IsoapTypeMapper and SoapTypeMapperFactory interfaces.

    • Tutorial

    Hi all!
    It so happened that in lately I started developing web services. But today the topic is not about me, but about how we can write our own XML Web Service based on the SOAP 1.2 protocol.

    I hope that after reading the topic you will be able to:

    • write your own server implementation of a web application;
    • write your own client implementation of a web application;
    • write your own web service description (WSDL);
    • send the client arrays of the same type of data to the server.
    As you might have guessed, all the magic will happen with using PHP and the built-in SoapClient and SoapServer classes. Our rabbit will be a service for sending SMS messages.

    1 Problem statement

    1.1 Boundaries

    At the beginning, I propose to deal with the result that we will achieve at the end of the topic. As announced above, we will write a service for sending SMS messages, and more precisely, we will receive messages from different sources via the SOAP protocol. After which, we will consider in what form they come to the server. The process of queuing messages for further sending to the provider, unfortunately, is beyond the scope of this post for many reasons.

    1.2 What data will we change?

    Great, we have decided on the boundaries! The next step that needs to be taken is to decide what data we will exchange between the server and the client. On this topic, I suggest not to split hairs for too long and immediately answer the main questions for yourself:
    • What minimum data must be sent to the server in order to send an SMS message to a subscriber?
    • What minimum data must be sent from the server to satisfy the client's needs?
    Something tells me that for this you need to send the following:
    • mobile phone number and
    • text of the SMS message.
    In principle, these two characteristics are enough for sending, but I immediately imagine the case of an SMS with birthday greetings coming to you at 3 o’clock in the morning, or 4! At this moment, I will be very grateful to everyone for not forgetting about me! Therefore, we will also send to the server and
    • date of sending the SMS message.
    The next thing I would like to send to the server is:
    • Message type.
    This parameter is not mandatory, but it can be very useful to us if we quickly need to tell the boss how many of our clients we have “delighted” with our news, and also draw some beautiful statistics on this matter.

    And yet, I forgot something! If we reflect a little more, it is worth noting that the client can send either one SMS message or a number of them to the server at a time. In other words, one data packet can contain from one to infinity messages.

    As a result, we get that to send an SMS message we need the following data:

    • mobile phone number,
    • SMS message text,
    • time of sending the SMS message to the subscriber,
    • message type.

    We have answered the first question, now we need to answer the second question. And perhaps I’ll allow myself to mess around a little. Therefore, from the server we will send only Boolean data, the meaning of which has the following meaning:

    • TRUE – the packet successfully reached the server, passed authentication and queued for sending to the SMS provider
    • FALSE – in all other cases

    This concludes the description of the problem statement! And finally, let's get down to the fun part - let's figure out what kind of strange beast this SOAP is!

    2 What is SOAP?

    In general, initially I did not plan to write anything about what SOAP is and wanted to limit myself to links to the w3.org website with the necessary specifications, as well as links to Wikipedia. But at the very end I decided to write a short note about this protocol.

    And I will begin my story with the fact that this data exchange protocol belongs to a subset of protocols based on the so-called RPC (Remote Procedure Call) paradigm, the antipode of which is REST (Representational State Transfer). You can read more about this on Wikipedia; links to articles are at the very end of the topic. From these articles we need to understand the following: “The RPC approach allows the use of a small number of network resources with a large number of methods and a complex protocol. With the REST approach, the number of methods and protocol complexity are strictly limited, which means the number of individual resources can be large.” That is, in relation to us, this means that in the case of the RPC approach on the site there will always be one input (link) to the service and what procedure to call to process incoming data we transfer along with the data, while with the REST approach in our The site has many inputs (links), each of which accepts and processes only certain data. If anyone reading knows how to explain the difference in these approaches even more simply, be sure to write in the comments!

    The next thing we need to know about SOAP is that this protocol uses the same XML as a transport, which on the one hand is very good, because immediately our arsenal receives the full power of a stack of technologies based on given language markup, namely XML-Schema - a language for describing the structure of an XML document (thanks Wikipedia!), which allows automatic validation of data received by the server from clients.

    And so, now we know that SOAP is a protocol used to implement remote procedure calls and it uses XML as a transport! If you read the article on Wikipedia, you can also learn from there that it can be used over any application-level protocol, and not just in combination with HTTP (unfortunately, in this topic we will only consider SOAP over HTTP). And you know what I like most about all this? If there are no guesses, then I will give a hint - SOAP!... Still no guesses?... Are you sure you read the article on Wikipedia?... In general, I won’t torture you further. Therefore, I’ll go straight to the answer: “SOAP (from the English Simple Object Access Protocol - simple protocol access to objects; up to specification 1.2)". The most remarkable thing about this line is in italics! I don’t know what conclusions you drew from all this, but I see the following - since this protocol cannot in any way be called “simple” (and apparently even w3 agrees with this), then from version 1.2 it stopped being decrypted somehow! And it became known as SOAP, just SOAP, period.

    Well, okay, please excuse me, I got a little sidetracked. As I wrote earlier, XML is used as transport, and the packets that travel between the client and server are called SOAP envelopes. If you consider the general structure of the envelope, it will seem very familiar to you, because... resembles the structure of an HTML page. It has a main section - Envelop, which includes sections Header And Body, or Fault. IN Body data is transmitted and it is a mandatory section of the envelope, while Header is optional. IN Header authorization or any other data that is not directly related to the input data of the web service procedures may be transmitted. About Fault there is nothing special to tell, except that it comes to the client from the server in case of any errors.

    This is where my review story about the SOAP protocol ends (we will look at the envelopes themselves and their structure in more detail when our client and server finally learn to run them at each other) and a new one begins - about the SOAP companion called WSDL(Web Services Description Language). Yes, yes, this is the very thing that scares most of us away from even trying to implement our API on this protocol. As a result, we usually reinvent our wheel with JSON as transport. So what is WSDL? WSDL is a language for describing web services and accessing them, based on the XML language (c) Wikipedia. If this definition does not make clear to you the entire sacred meaning of this technology, then I will try to describe it in my own words!

    WSDL is designed to allow our clients to communicate normally with the server. To do this, the file with the extension “*.wsdl” describes the following information:

    • What namespaces were used?
    • What data schemas were used?
    • What types of messages does the web service expect from clients?
    • Which data belongs to which web service procedures,
    • What procedures does the web service contain?
    • How should the client call the web service procedures,
    • To which address should customer calls be sent?
    As you can see, this file is the entire web service. By specifying the address of the WSDL file in the client, we will know everything about any web service! As a result, we do not need to know absolutely nothing about where the web service itself is located. All you need to know is the location of its WSDL file! We will soon find out that SOAP is not as scary as Russian proverbs make it out to be.

    3 Introduction to XML-Schema

    Now we know a lot about what SOAP is, what is inside it, and have an overview of the technology stack that surrounds it. Since, first of all, SOAP is a method of interaction between a client and a server, and XML markup language is used as a transport for it, in this section we will understand a little about how automatic data validation occurs using XML schemas.

    The main purpose of the diagram is to describe the structure of the data that we are going to process. All data in XML schemas is divided into simple(scalar) and complex(structures) types. Simple types include the following types:

    • line,
    • number,
    • boolean value,
    • date.
    Something very simple that has no extensions inside. Their antipode is complex complex types. The simplest example of a complex type that comes to everyone’s mind is objects. For example, a book. The book consists of properties: author, Name, price, ISBN number etc. And these properties, in turn, can be either simple types or complex ones. And the task of the XML schema is to describe this.

    I suggest not going far and writing an XML schema for our SMS message! Below is the xml description of the SMS message:

    71239876543 Test message 2013-07-20T12:00:00 12
    Our complex type diagram will look like this:


    This entry reads as follows: We have a variable " message" type " Message" and there is a complex type called " Message", which consists of a sequential set of elements " phone" type string, « text" type string, « date" type dateTime, « type" type decimal. These types are simple and are already defined in the schema description. Congratulations! We just wrote our first XML Schema!

    I think that the meaning of the elements " element" And " complexType"Everything has become more or less clear to you, so we won’t focus on them any more and let’s switch straight to the composer element" sequence" When we use the composer element " sequence“We inform you that the elements included in it must always be located in the sequence specified in the diagram, and all of them are mandatory. But don't despair! There are two more composer elements in XML schemas: " choice" And " all" Composer " choice" announces that there must be one of the elements listed in it, and the composer " all» – any combination of the listed elements.

    As you remember, in the first section of the topic we agreed that from one to infinity SMS messages can be transmitted in a package. Therefore, I propose to understand how such data is declared in the XML schema. General structure The package might look like this:

    71239876543 Test message 1 2013-07-20T12:00:00 12 71239876543 Test message N 2013-07-20T12:00:00 12
    The diagram for such a complex type will look like this:


    The first block contains the familiar declaration of the complex type “ Message" If you noticed, then in each simple type included in " Message", new clarifying attributes have been added " minOccurs" And " maxOccurs" As you might guess from the name, the first ( minOccurs) indicates that this sequence must contain at least one element of type “ phone», « text», « date" And " type", while the next one ( maxOccurs) attribute declares to us that there is at most one such element in our sequence. As a result, when we write our own schemas for any data, we are given the widest choice in how to configure them!

    The second block of the diagram declares the element " messageList" type " MessageList" It is clear that " MessageList" is a complex type that contains at least one element " message", but the maximum number of such elements is not limited!

    4 Write your WSDL

    Do you remember that WSDL is our web service? I hope you remember! As we write it, our little web service will run on it. Therefore, I suggest not to mess around.

    In general, in order for everything to work correctly for us, we need to transfer the WSDL file with the correct MIME type to the client. To do this, you need to configure your web server accordingly, namely, set the MIME type for files with the “*.wsdl” extension to the following line:

    Application/wsdl+xml
    But in practice, I usually sent the HTTP header via PHP " text/xml»:

    Header("Content-Type: text/xml; charset=utf-8");
    and everything worked great!

    I want to warn you right away that our simple web service will have a rather impressive description, so don’t be alarmed, because... Most of the text is obligatory water and, having written it once, you can constantly copy it from one web service to another!

    Since WSDL is XML, you need to write about this directly in the very first line. The root element of the file should always be named " definitions»:


    Typically, WSDL consists of 4-5 main blocks. The very first block is the definition of a web service or, in other words, the entry point.


    It says here that we have a service called “ SmsService" In principle, all the names in the WSDL file can be changed by you to whatever you want, because they play absolutely no role.

    After this we announce that in our web service " SmsService" there is an entry point ("port") called " SmsServicePort" It is to this entry point that all requests from clients to the server will be sent. And indicate in the element “ address» link to the handler file that will accept requests.

    Once we have defined the web service and specified the entry point for it, we need to bind supported procedures to it:


    To do this, it lists which operations and in what form they will be called. Those. for port " SmsServicePort" a binding is defined under the name " SmsServiceBinding", which has a call type " rpc"and HTTP is used as the transfer protocol. Thus, we indicated here that we will make an RPC call over HTTP. After this we describe which procedures ( operation) are supported in the web service. We will support only one procedure – “ sendSms" Through this procedure our wonderful messages will be sent to the server! After the procedure has been declared, it is necessary to indicate in what form the data will be transmitted. In this case, it is indicated that standard SOAP envelopes will be used.

    After that, we need to bind the procedure to messages:


    To do this, we specify that our binding is of type " SmsServicePortType" and in the element " portType"with the name of the same type, we indicate the binding of procedures to messages. So, incoming message(from client to server) will be called " sendSmsRequest", and outgoing (from server to client) " sendSmsResponse" Like all names in WSDL, the names of incoming and outgoing messages are arbitrary.

    Now we need to describe the messages themselves, i.e. incoming and outgoing:


    To do this we add the elements " message" with names " sendSmsRequest" And " sendSmsResponse" respectively. In them we indicate that the input should be an envelope whose structure corresponds to the data type " Request" After which an envelope is returned from the server containing the data type - “ Response».

    Now we need to do just a little - add a description of these types to our WSDL file! And how do you think the WSDL describes incoming and outgoing data? I think that you have already understood everything a long time ago and told yourself that using XML schemas! And you will be absolutely right!


    You can congratulate us! Our first WSDL has been written! And we are one step closer to achieving our goal.
    Next, we'll look at what PHP provides us with for developing our own distributed applications.

    5 Our first SOAP server

    Earlier I wrote that to create a SOAP server in PHP we will use the built-in SoapServer class. In order for everything further actions happened the same way as mine, you will need to tweak your PHP a little. To be even more precise, you need to make sure that you have the “php-soap” extension installed. It is best to read how to install it on your web server on the official PHP website (see the list of references).

    After everything has been installed and configured, we will need to create a file in the root folder of your hosting “ smsservice.php» with the following content:

    setClass("SoapSmsGateWay"); //Start the server $server->handle();
    I hope there is no need to explain what is above the line with the “ini_set” function. Because there it is determined which HTTP headers we will send from the server to the client and the environment is configured. In the line with “ini_set” we disable caching of the WSDL file so that our changes in it immediately take effect on the client.

    Now we come to the server! As you can see, the entire SOAP server takes only three lines! On the first line, we create a new instance of the SoapServer object and pass the address of our WSDL description of the web service to its constructor. Now we know that it will be located in the root of the hosting in a file with the self-explanatory name “ smsservice.wsdl.php" In the second line, we tell the SOAP server which class needs to be pulled in order to process the envelope received from the client and return the envelope with the response. As you might have guessed, it is in this class that our only method will be described sendSms. On the third line we start the server! That's it, our server is ready! With which I congratulate us all!

    Now we need to create the WSDL file. To do this, you can either simply copy its contents from the previous section, or take liberties and “template” it a little:

    "; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http:// schemas.xmlsoap.org/wsdl/http/" name="SmsWsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> /"> /smsservice.php" />
    At this stage, we should be completely satisfied with the resulting server, because We can log the envelopes coming to it and then calmly analyze the incoming data. In order for us to receive anything on the server, we need a client. So let's get to it!

    6 SOAP client on the way

    First of all, we need to create a file in which we will write the client. As usual, we will create it in the root of the host and call it " client.php", and inside we will write the following:

    messageList = new MessageList(); $req->messageList->message = new Message(); $req->messageList->message->phone = "79871234567"; $req->messageList->message->text = "Test message 1"; $req->messageList->message->date = "2013-07-21T15:00:00.26"; $req->messageList->message->type = 15; $client = new SoapClient("http://($_SERVER["HTTP_HOST"])/smsservice.wsdl.php", array("soap_version" => SOAP_1_2)); var_dump($client->sendSms($req));
    Let's describe our objects. When we wrote the WSDL, it described three entities for the envelope incoming to the server: Request, MessageList And Message. Accordingly classes Request, MessageList And Message are reflections of these entities in our PHP script.

    Once we have defined the objects, we need to create an object ( $req), which we will send to the server. After which come the two most cherished lines for us! Our SOAP client! Believe it or not, this is enough for our server to start receiving messages from the client, as well as for our server to successfully receive and process them! In the first of them, we create an instance of the SoapClient class and pass the address of the location of the WSDL file to its constructor, and in the parameters we explicitly indicate that we will work using the SOAP protocol version 1.2. On the next line we call the method sendSms object $client and immediately display the result in the browser.
    Let's run it and see what we finally got!

    The following object was returned to me from the server:

    Object(stdClass) public "status" => boolean true
    And this is great, because... Now we know for sure that our server is working and not only works, but can also return some values ​​to the client!

    Now let's look at the log that we prudently keep on the server side! In its first part we see the raw data that arrived at the server:

    79871234567 Test message 1 2013-07-21T15:00:00.26 15
    This is the envelope. Now you know what it looks like! But it’s unlikely that we’ll be interested in looking at it all the time, so let’s deserialize the object from the log file and see if everything is fine:

    Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 1 " (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length=2)
    As you can see, the object was deserialized correctly, for which I want to congratulate us all! Something more interesting awaits us next! Namely, we will send the client to the server not just one SMS message, but a whole pack (to be more precise, three)!

    7 Sending complex objects

    Let's think about how we can transfer a whole bunch of messages to the server in one packet? Probably the easiest way would be to organize an array inside the messageList element! Let's do this:

    // create an object to send to the server $req = new Request(); $req->messageList = new MessageList(); $msg1 = new Message(); $msg1->phone = "79871234567"; $msg1->text = "Test message 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = new Message(); $msg2->phone = "79871234567"; $msg2->text = "Test message 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = new Message(); $msg3->phone = "79871234567"; $msg3->text = "Test message 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->type = 17; $req->messageList->message = $msg1; $req->messageList->message = $msg2; $req->messageList->message = $msg3;
    Our logs indicate that the following packet was received from the client:

    79871234567 Test message 1 2013-07-21T15:00:00.26 15 79871234567 Test message 2 2014-08-22T16:01:10 16 79871234567 Test message 3 2014-08-22T16:01:10 17
    What nonsense, you say? And you will be right in a sense, because... As soon as we learned that an object left the client, it came to our server in exactly the same form in the form of an envelope. True, SMS messages were not serialized in XML the way we needed - they had to be wrapped in elements message, not in Struct. Now let's see in what form such an object comes to the method sendSms:

    Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "Struct" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public " type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 2" (length= 37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone " => string "79871234567" (length=11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length= 19) public "type" => string "17" (length=2)
    What does this knowledge give us? Only that the path we chose is not correct and we did not receive an answer to the question - “How can we get the correct data structure on the server?” But I suggest not to despair and try to convert our array to the type object:

    $req->messageList->message = (object)$req->messageList->message;
    In this case, we will receive another envelope:

    79871234567 Test message 1 2013-07-21T15:00:00.26 15 79871234567 Test message 2 2014-08-22T16:01:10 16 79871234567 Test message 3 2014-08-22T16:01:10 17
    Came into the method sendSms the object has the following structure:

    Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public " type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 2" (length= 37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone " => string "79871234567" (length=11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length= 19) public "type" => string "17" (length=2)
    As for me, “the sum does not change from changing the places of the terms” (c). What BOGUS, What Struct– we have not yet achieved our goal! And to achieve it, we need to make sure that instead of these incomprehensible names our native one is displayed message. But the author does not yet know how to achieve this. Therefore, the only thing we can do is get rid of the extra container. In other words, we will now make sure that instead of message became BOGUS! To do this, change the object as follows:

    // create an object to send to the server $req = new Request(); $msg1 = new Message(); $msg1->phone = "79871234567"; $msg1->text = "Test message 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = new Message(); $msg2->phone = "79871234567"; $msg2->text = "Test message 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = new Message(); $msg3->phone = "79871234567"; $msg3->text = "Test message 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->type = 17; $req->messageList = $msg1; $req->messageList = $msg2; $req->messageList = $msg3; $req->messageList = (object)$req->messageList;
    What if we get lucky and the correct name comes up from the diagram? To do this, let's look at the envelope that arrived:

    79871234567 Test message 1 2013-07-21T15:00:00.26 15 79871234567 Test message 2 2014-08-22T16:01:10 16 79871234567 Test message 3 2014-08-22T16:01:10 17
    Yes, a miracle did not happen! BOGUS– we won’t win! Came to sendSms the object in this case will look like this:

    Object(stdClass) public "messageList" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public " text" => string "Test message 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length =2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 2" (length=37) public "date" => string " 2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone" => string "79871234567" (length= 11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string " 17" (length=2)
    As they say – “Almost”! On this (slightly sad) note, I propose to slowly wrap things up and draw some conclusions for ourselves.

    8 Conclusion

    Finally we got here! Let's figure out what you can do now:
    • you can write the WSDL file necessary for your web service;
    • you can easily write your own client that can communicate with the server via SOAP;
    • you can write your own own server communicating with the outside world via SOAP;
    • you can send arrays of the same type of objects to the server from your client (with some restrictions).
    We also made some discoveries during our little research:
    • the native SoapClient class does not correctly serialize data structures of the same type in XML;
    • when serializing an array to XML it creates extra element with name Struct;
    • when serializing an object to XML it creates an extra element called BOGUS;
    • BOGUS less evil than Struct due to the fact that the envelope is more compact (extra namespaces are not added to the XML header of the envelope);
    • Unfortunately, the SoapServer class does not automatically validate the envelope data with our XML schema (perhaps other servers do not do this either).

    The topic title is really a question, because... I myself don’t know what it is and for the first time I will try to work with it within the framework of this article. The only thing I can guarantee is that the code presented below will work, but my phrases will only be assumptions and guesses about how I myself understand all this. So, let's go...

    Introduction

    We need to start with why the concept of web services was created. By the time this concept appeared in the world, technologies already existed that allowed applications to interact at a distance, where one program could call some method in another program, which could be launched on a computer located in another city or even country. All this is abbreviated as RPC (Remote Procedure Calling). Examples include CORBA technologies, and for Java - RMI (Remote Method Invoking). And everything seems to be good in them, especially in CORBA, because... You can work with it in any programming language, but something was still missing. I believe that the disadvantage of CORBA is that it works through some of its own network protocols instead of simple HTTP, which will fit through any firewall. The idea of ​​the web service was to create an RPC that would be inserted into HTTP packets. Thus began the development of the standard. What are the basic concepts of this standard:
    1. SOAP. Before calling a remote procedure, you need to describe this call in an XML file in SOAP format. SOAP is just one of many XML markup, which is used in web services. Everything we want to send somewhere via HTTP is first turned into XML description SOAP, then stuffed into an HTTP packet and sent to another computer on the network via TCP/IP.
    2. WSDL. There is a web service, i.e. a program whose methods can be called remotely. But the standard requires that this program be accompanied by a description that says that “yes, you’re right – this is really a web service and you can call such and such methods from it.” This description is represented by another XML file, which has a different format, namely WSDL. Those. WSDL is just an XML file describing a web service and nothing more.
    Why so briefly you ask? Can't you be more specific? It’s probably possible, but to do this you’ll have to turn to books such as T. Mashnin, “Java Web Services.” There, over the first 200 pages, there is a detailed description of each tag of the SOAP and WSDL standards. Is it worth doing? In my opinion, no, because... all this is created automatically in Java, and you only need to write the contents of the methods that are supposed to be called remotely. So, an API such as JAX-RPC appeared in Java. If anyone doesn't know, when they say that Java has such and such an API, it means that there is a package with a set of classes that encapsulate the technology in question. JAX-RPC evolved over time from version to version and eventually became JAX-WS. WS obviously stands for WebService and you might think that this is simply a renaming of RPC as a popular buzzword these days. This is not true, because Now web services have moved away from the original idea and allow you not only to call remote methods, but also to simply send document messages in SOAP format. I don’t know why this is needed yet; it’s unlikely that the answer here will be “just in case it’s needed.” I myself would like to learn from more experienced comrades. And lastly, then JAX-RS appeared for so-called RESTful web services, but this is the topic of a separate article. The introduction can end here, because... Next we will learn to work with JAX-WS.

    General approach

    In web services there is always a client and a server. The server is our web service and is sometimes called the endpoint (as in, the end point where SOAP messages from the client reach). We need to do the following:
    1. Describe the interface of our web service
    2. Implement this interface
    3. Launch our web service
    4. Write a client and remotely call the desired web service method
    You can launch a web service in different ways: either describe a class with the main method and launch the web service directly as a server, or deploy it to a server like Tomcat or any other. In the second case, we do not launch ourselves new server and we don’t open another port on the computer, but simply tell the Tomcat servlet container that “we have written web service classes here, please publish them so that everyone who contacts you can use our web service.” Regardless of the method of launching the web service, we will have the same client.

    Server

    Let's launch IDEA and create a new project Create New Project. Let's indicate the name HelloWebService and press the button Next, then button Finish. In a folder src let's create a package ru.javarush.ws. In this package we will create the HelloWebService interface: package ru. javarush. ws; // these are annotations, i.e. a way to mark our classes and methods, // as related to web service technology import javax. jws. WebMethod; import javax. jws. WebService; import javax. jws. soap. SOAPBinding; // we say that our interface will work as a web service@WebService // we say that the web service will be used to call methods@SOAPBinding (style = SOAPBinding. Style. RPC) public interface HelloWebService ( // we say that this method can be called remotely@WebMethod public String getHelloString(String name) ; ) In this code, the WebService and WebMethod classes are so-called annotations and do nothing except mark our interface and its method as a web service. The same applies to the SOAPBinding class. The only difference is that SOAPBinding is an annotation with parameters. In this case, the style parameter is used with a value indicating that the web service will work not through document messages, but as a classic RPC, i.e. to call a method. Let's implement our interface logic and create a HelloWebServiceImpl class in our package. By the way, I note that ending a class with Impl is a convention in Java, according to which the implementation of interfaces is so designated (Impl - from the word implementation, i.e. implementation). This is not a requirement and you are free to name the class whatever you want, but good manners require it: package ru. javarush. ws; // the same annotation as when describing the interface, import javax. jws. WebService; // but here it is used with the endpointInterface parameter, // indicating full name interface class of our web service@WebService(endpointInterface= "ru.javarush.ws.HelloWebService") public class HelloWebServiceImpl implements HelloWebService ( @Override public String getHelloString (String name) ( // just return the greeting return "Hello, " + name + "!" ; ) ) Let's launch our web service as standalone server, i.e. without the participation of any Tomcat and application servers (this is a topic for a separate discussion). To do this, in the project structure in the folder src Let's create a package ru.javarush.endpoint, and in it we will create a class HelloWebServicePublisher with a method main: package ru. javarush. endpoint; // class for running a web server with web services import javax. xml. ws. Endpoint; // class of our web service import ru. javarush. ws. HelloWebServiceImpl; public class HelloWebServicePublisher ( public static void main (String... args) ( // start the web server on port 1986 // and to the address specified in the first argument, // start the web service passed in the second argument Endpoint. publish( "http://localhost:1986/wss/hello", new HelloWebServiceImpl () ) ; ) ) Now let's run this class by clicking Shift+F10. Nothing will appear in the console, but the server is running. You can verify this by typing the line http://localhost:1986/wss/hello?wsdl in your browser. The page that opens, on the one hand, proves that we have a web server (http://) running on port 1986 on our computer (localhost), and, on the other hand, shows a WSDL description of our web service. If you stop the application, the description will become unavailable, as will the web service itself, so we won’t do this, but move on to writing the client.

    Client

    In the project folder src Let's create a package ru.javarush.client , and in it the HelloWebServiceClient class with the main method: package ru. javarush. client; // needed to get wsdl description and through it // reach the web service itself import java. net. URL; // this exception will occur when working with a URL object import java. net. MalformedURLException; // classes to parse xml with wsdl description // and reach the service tag in it import javax. xml. namespace. QName; import javax. xml. ws. Service; // interface of our web service (we need more) import ru. javarush. ws. HelloWebService; public class HelloWebServiceClient ( public static void main (String args) throws MalformedURLException ( // create a link to wsdl description URL url = new URL ( "http://localhost:1986/wss/hello?wsdl") ; // We look at the parameters of the next constructor in the very first tag of the WSDL description - definitions // look at the 1st argument in the targetNamespace attribute // look at the 2nd argument in the name attribute QName qname = new QName ("http://ws.site/" , "HelloWebServiceImplService" ) ; // Now we can reach the service tag in the wsdl description, Service service= Service. create (url, qname) ; // and then up to the port tag nested in it, so that // get a link to a web service object remote from us HelloWebService hello = service. getPort(HelloWebService.class); // Hooray! Now you can call remote method System. out. println (hello. getHelloString ( "JavaRush" ) ) ; ) ) I gave maximum comments on the code in the listing. I have nothing to add, so let’s run (Shift+F10). We should see the text in the console: Hello, JavaRush! If you didn’t see it, then you probably forgot to start the web service.

    Conclusion

    This topic provided a brief excursion into web services. Once again, I will say that much of what I wrote is my guess as to how it works, and therefore you should not trust me too much. I would be grateful if knowledgeable people correct me, because then I will learn something. UPD.

    SOAP-a text protocol that uses XML to exchange structured messages in a distributed computing environment. SOAP was originally intended primarily to implement remote call procedures (RPC), and the name was an abbreviation: Simple Object Access Protocol - a simple protocol for accessing objects. The protocol is now used to exchange arbitrary messages in XML format, and not just to call procedures. Official Specification latest version 1.2 of the protocol does not decipher the name SOAP in any way. SOAP is an extension of the XML-RPC protocol. SOAP can be used with any application layer protocol: SMTP, FTP, HTTP, etc. However, its interaction with each of these protocols has its own characteristics that must be defined separately. Most often, SOAP is used over HTTP. SOAP is one of the standards on which web services technologies are based. Communication between web services and their clients is carried out through messages in XML format. SOAP (Simple Object Access Protocol) is a message protocol for selecting web services. We can say that the SOAP format is ideal for RPC (Remote Procedure Call) technology, since the SOAP message contains parameters sent by the client or a return value sent by the service.

    Advantages of using the SOAP format:

    · More flexible data types.

    · Support for headers and extensions:

    Flaws:

    · Using SOAP to transmit messages increases their volume and reduces processing speed. In systems where speed is important, it is more common to send XML documents over HTTP directly, where the request parameters are passed as regular HTTP parameters.

    · Although SOAP is a standard, different programs often generate messages in an incompatible format. For example, a request generated by an AXIS client will not be understood by the WebLogic server.

    Basic concepts of the protocol: The party that sends the SOAP message is called the SOAP sender, and the party that receives is called the SOAP receiver. The path that a SOAP message takes from the original sender to the final recipient is called the message route. The message route contains the original sender, the final recipient, and 0 or more SOAP intermediaries. Objects that process messages according to the rules of specific SOAP protocols are called SOAP nodes. The elementary unit of information that participates in the exchange between SOAP nodes is called a SOAP message - it is XML document with a SOAP wrapper around the root element.