A service’s operations are defined by specifying the logical messages that are exchanged when an operation is invoked. These logical messages define the data that is passed over a network as an XML document. They contain all of the parameters that are a part of a method invocation.
Logical messages are defined using the message
element in your contracts. Each
logical message consists of one or more parts, defined in part
elements.
Tip | |
---|---|
While your messages can list each parameter as a separate part, the recommended practice is to use only a single part that encapsulates the data needed for the operation. |
Each operation exposed by a service can have only one input message and one output message. The input message defines all of the information the service receives when the operation is invoked. The output message defines all of the data that the service returns when the operation is completed. Fault messages define the data that the service returns when an error occurs.
In addition, each operation can have any number of fault messages. The fault messages define the data that is returned when the service encounters an error. These messages usually have only one part that provides enough information for the consumer to understand the error.
If you are defining an existing application as a service, you must ensure that each parameter used by the method implementing the operation is represented in a message. You must also ensure that the return value is included in the operation’s output message.
One approach to defining your messages is RPC style. When using RPC style, you define the messages using one part for each parameter in the method’s parameter list. Each message part is based on a type defined in the types
element of the contract. Your input message contains one part for each input parameter in the method. Your output message contains one part for each output parameter, plus a part to represent the return value, if needed. If a parameter is both an input and an output parameter, it is listed as a part for both the input message and the output message.
RPC style message definition is useful when service enabling legacy systems that use transports such as Tibco or CORBA. These systems are designed around procedures and methods. As such, they are easiest to model using messages that resemble the parameter lists for the operation being invoked. RPC style also makes a cleaner mapping between the service and the application it is exposing.
While RPC style is useful for modeling existing systems, the service’s community strongly favors the wrapped document style. In wrapped document style, each message has a single part. The message’s part references a wrapper element defined in the types
element of the contract. The wrapper element has the following characteristics:
It is a complex type containing a sequence of elements. For more information see Defining complex data types.
If it is a wrapper for an input message:
It has one element for each of the method’s input parameters.
Its name is the same as the name of the operation with which it is associated.
If it is a wrapper for an output message:
It has one element for each of the method’s output parameters and one element for each of the method’s inout parameters.
Its first element represents the method’s return parameter.
Its name would be generated by appending
Response
to the name of the operation with which the wrapper is associated.
Each message in a contract must have a unique name within its namespace. It is recommended that you use the following naming conventions:
Messages should only be used by a single operation.
Input message names are formed by appending
Request
to the name of the operation.Output message names are formed by appending
Response
to the name of the operation.Fault message names should represent the reason for the fault.
Message parts are the formal data units of the logical message. Each part is defined using a part
element, and is identified by a name
attribute and either a type
attribute or an element
attribute that specifies its data type. The data type attributes are listed in Table 3.1.
Messages are allowed to reuse part names. For instance, if a method has a parameter, foo
, that is passed by reference or is an in/out, it can be a part in both the request message and the response message, as shown in Example 3.1.
Example 3.1. Reused part
<message name="fooRequest"> <part name="foo" type="xsd:int"/> <message> <message name="fooReply"> <part name="foo" type="xsd:int"/> <message>
For example, imagine you had a server that stored personal information and provided a method that returned an employee’s data based on the employee's ID number. The method signature for looking up the data is similar to Example 3.2.
This method signature can be mapped to the RPC style WSDL fragment shown in Example 3.3.
Example 3.3. RPC WSDL message definitions
<message name="personalLookupRequest"> <part name="empId" type="xsd:int"/> <message/> <message name="personalLookupResponse> <part name="return" element="xsd1:personalInfo"/> <message/>
It can also be mapped to the wrapped document style WSDL fragment shown in Example 3.4.
Example 3.4. Wrapped document WSDL message definitions
<types> <schema ... > ... <element name="personalLookup"> <complexType> <sequence> <element name="empID" type="xsd:int" /> </sequence> </complexType> </element> <element name="personalLookupResponse"> <complexType> <sequence> <element name="return" type="personalInfo" /> </sequence> </complexType> </element> </schema> </types> <message name="personalLookupRequest"> <part name="empId" element="xsd1:personalLookup"/> <message/> <message name="personalLookupResponse"> <part name="return" element="xsd1:personalLookupResponse"/> <message/>