Reliable XML Web Service (2)

Source: Internet
Author: User
Tags datetime extend header implement soap stub web services wsdl
The function of Web|xml header
Before we look at the code, we need to look at the SOAP topic, the header. One of the least discussed aspects of the SOAP 1.1 specification is the SOAP header. Headers provide an easy way to extend the message processing architecture. The SOAP 1.1 specification mentions that headers are useful when implementing processing rules that do not have a specific relationship with the message body, such as validation and transaction management. For any type of message, the SOAP header is the perfect solution for encoding the reliability information in an independent manner. Standards and rules for the implementation and processing of these headers are also outlined in the specification.

Let's look at how to implement a SOAP header that contains reliability information. The first is to determine the schema for the header. This is important because it is the actual effect that end users see in the WSDL file of the Web service that supports the header. For this implementation, I map the processing APIs directly to the SOAP headers.

Let me explain. There is a class named Reliabilityinfo in my processing API. When this class is instantiated, it becomes a dynamic object at run time. That is, you can set the properties that determine how outbound messages are handled from a reliability perspective. This object can also be serialized as a SOAP header at run time. The following is a snapshot of the class and its members. For clarity, I removed the specific implementations and private members.

[XmlRootAttribute (Elementname= "Reliableheader", _
Namespace= "http://ericRP/ReliableHeader/2001/", Isnullable=false)]
public class Reliabilityinfo:soapheader
{
public string destination{}
public string conversationid{}
public int messageid{}
Public Messagestatus status{}
Public DateTime senddate{}
Public DateTime expiredate{}
public string ackurl{}
public enum messagestatus{}

[XmlIgnore]
public int maxretry{}
[XmlIgnore]
public string text{}
}

When serialized as a outbound SOAP message, the header looks like this:

<soap:Header>
<reliableheader xmlns= "http://ericRP/ReliableHeader/2001/" >
<ConversationId>b9e029e1-af0f-42cb-83b0-7888f9e3ffc4</ConversationId>
<MessageId>1</MessageId>
<Status> New </Status>
<SendDate>2001-11-06T14:59:02.1021226-08:00</SendDate>
<ExpireDate>2001-11-06T18:59:02.1021226-08:00</ExpireDate>
<AckURL>http://localhost:8082/ericRPAck/POAck.asmx</AckURL>
</ReliableHeader>
</soap:Header>

This is done through two very important classes in the. NET framework. Basic XML serialization blocks are processed using the System.Xml.Serialization namespace class. One of these two classes is the XmlRootAttribute attribute class, which I use to tell the serializer to refer to the root of the document fragment as Reliableheader and associate it with the namespace. Thereafter, all public members are also serialized, unless you tell the serializer to ignore the member. Another important namespace I use is System.Web.Services.Protocols. Specifically, that is, the SoapHeader class. When inheriting from this class, it automatically joins the serialized XML into the SOAP message. This article will discuss how to add headers to the message later.

This is very powerful because I can not only use type-specific, compiled objects as the basis for headers, but also have specific implementations within the members of these classes.

Review
Well, it's just a simple discussion of reliability and a description of my own specifications. Let's take a look at its code below.

Extending the WEB service client proxy
The first step is to reset the existing. NET WEB service client proxy. Remember, this protocol can be implemented in any SOAP processing engine. I chose the. NET framework because it is easy to use, standards-based, and extensible.

Select an existing WEB service client proxy (for example, Purchaseorderproxy), and then add the following code:

The class must be known as a public member of Reliableheader, and its type must be ericrp.reliabilityinfo. This member will be set at run time by calling the client. This member will be used later to provide header information for the outbound message and provide status information for the message that the header was applied to during the trace. For example:
public class Purchaseorderproxy:
System.Web.Services.Protocols.SoapHttpClientProtocol
{
Public Reliabilityinfo Reliableheader;

For clarity, other code is omitted here
}

Methods called in the Web service client proxy must be annotated with the following properties:
[SoapHeader ("Reliableheader", Required=true)]

During serialization, this property adds the appropriate header value to the outbound SOAP message at run time. The Submitmessage method here is marked with the SoapHeader property. Note that Reliableheader is a member that is implemented in step 1 and is required. This means that if you do not set this member at run time, an exception is generated. For example:

[SoapHeader ("Reliableheader", Required=true)]
public void Submitmessage (object message)
{
This. Invoke ("Submitmessage", new object[] {message});
}

The method invoked in the WEB service client proxy must contain the following properties:
[EricRP.Client.RPClientTrace.TraceExtension ()]

This property indicates that the method supports a custom SOAP extension. This SOAP extension is invoked at run time before and after the message is serialized, and before the message is sent to the underlying transport mechanism. I usually do some simple tracking and logging of a message before it is sent out from the client computer. See the implementation of this extension later. For example:

[EricRP.Client.RPClientTrace.TraceExtension ()]
[Soapheaderattribute ("Reliableheader", Required=true)]
public void Submitmessage (object message)
{
This. Invoke ("Submitmessage", new object[] {message});
}

The class must be implemented from EricRP.Client.RPClientTrace.IClientTrace. This interface implementation provides a basic trace function to check whether the caller supports a specific tracking protocol. You can see this code in the following trace feature. For example:
public class Purchaseorderproxy:
System.Web.Services.Protocols.SoapHttpClientProtocol,
EricRP.Client.RPClientTrace.IClientTrace
{
Public Reliabilityinfo Reliableheader;
}

Finally, the class must implement the Iclienttrace.getreliabilityinfo function, which is the only function required by the Iclienttrace interface. This is a simple mechanism that clients can use to send message status information to the tracking service at run time. For example:
public class Purchaseorderproxy:
System.Web.Services.Protocols.SoapHttpClientProtocol,
EricRP.Client.RPClientTrace.IClientTrace
{
Public Reliabilityinfo Reliableheader;

Ericrp.reliabilityinfo EricRP.Client.RPClientTrace.IClientTrace.GetReliabilityInfo ()
{
return reliableheader;
}
}

It may seem like a lot of code, but it's actually simple. In fact, if I had more time, I could create a new class that inherits from SoapHttpClientProtocol and explicitly implement it, but it would be more fun for the server side.

Extending the Web service server stub
Next, we extend the existing Web service server stub. Select an existing. NET Web service class (for example, Processpurchaseorder), and then add the following code:

The class must have a public member Reliableheader of type Ericrp.reliabilityinfo. This member will be used later to provide deserialization header information for the inbound message and provide status information for the message that the header was applied to during the trace. For example:
public class Processpurchaseorder:
System.Web.Services.WebService
{
Public Reliabilityinfo Reliableheader;
}

The method invoked in the Web service stub must be annotated with the following properties:
[SoapHeader ("Reliableheader", Required=true)]

During deserialization, this property deserializes the appropriate header value in the inbound SOAP message at run time. The Submitmessage method here is marked with the SoapHeader property. For example:

[WebMethod]
[SoapHeader ("Reliableheader", Required=true)]
public void Submitmessage (object message)
{
For clarity, some of the code is omitted here
}

The method invoked in the Web service stub must be annotated with the following properties:
[EricRP.Server.RPServerTrace.TraceExtension ()]

This property indicates that the method supports a custom SOAP extension. See the implementation of this extension later.

Note: This extension differs from client extensions.
For example:

[SoapHeader ("Reliableheader", Required=true)]
[EricRP.Server.RPServerTrace.TraceExtension ()]
public void Submitmessage (object message)
{
For clarity, some of the code is omitted here
}

The method invoked in the Web service stub must be annotated with the following properties:
[SoapDocumentMethod (Oneway=true)]

This property indicates that the called function does not return a value. More specifically, once the message is deserialized, this property forces the Web service to return the HTTP 202 response to the client. This is an effective mechanism for the final processing of detached messages, otherwise the client will have to wait for the service to return to the response synchronously. For example:

[WebMethod]
[SoapDocumentMethod (Oneway=true)]
[SoapHeader ("Reliableheader", Required=true)]
[EricRP.Server.RPServerTrace.TraceExtension ()]
public void Submitmessage (object message)
{
For clarity, some of the code is omitted here
}

The class must be implemented from EricRP.Server.RPServerTrace.IServerTrace. This interface implementation provides a basic trace function to check whether the caller supports a specific tracking protocol. You can see this code in the following trace feature. For example:
public class Processpurchaseorder:
System.Web.Services.WebService, EricRP.Server.RPServerTrace.IServerTrace
{
Public Reliabilityinfo Reliableheader;
}

Finally, the class must implement the Iservertrace.getreliabilityinfo function. This is the only function required by the Iservertrace interface. For example:
public class Processpurchaseorder:
System.Web.Services.WebService, EricRP.Server.RPServerTrace.IServerTrace
{
Public Reliabilityinfo Reliableheader;

Ericrp.reliabilityinfo EricRP.Server.RPServerTrace.IServerTrace.GetReliabilityInfo ()
{
return reliableheader;
}
}

OK, the existing WEB service client and server are ready. Now let's look at how SoapExtension works.

View Rpclienttrance and Rpservertrace
To achieve reliability processing, I decided to use SoapExtension. SoapExtension is an inheritable base class used to track the outbound serialization and inbound deserialization of SOAP messages. It is in this trace that the message is logged and the state is checked. Remember earlier, the WEB service client proxy method implementation [EricRP.Client.RPClientTrace.TraceExtension ()]. When this method is invoked, this property invokes the following code when the SOAP message outbound is serialized.

The main function that needs to be noted specifically is processmessage. When an outbound message is sent, ProcessMessage provides all state information before and after the message is serialized. At this point, you will check who is calling and separating class-level members of the Client property from the current message. Then check to see if the message is in AfterSerialize state. If it has been serialized, it can be logged before the message is sent to the server. By using a custom function called Processoutgoingmessagetext, some stream exchanges are first made to avoid damaging the underlying message flow. Then check to see if the client supports the Iclienttrace interface. If the client supports this interface, it indicates that they also support the reliability protocol. With the interface check feature, you can call Getreliabilityinfo to return the current message to the Conversationmanager that can be applied to the message, and then set some properties and invoke LogMessage. LogMessage writes the current message information to the local database, and then sends an event notifying the client that the message has been logged.

public class Rpclienttrace:soapextension
{
public override void ProcessMessage (SoapMessage message)
{
Soapclientmessage tmpmsg = (soapclientmessage) message;
_client = tmpmsg.client;

if (message. Stage = = soapmessagestage.afterserialize)
{
Processoutgoingmessagetext (message);
}
}

public void Processoutgoingmessagetext (SoapMessage message)
{
newstream.position = 0;
TextReader reader = new StreamReader (newstream);
StringBuilder strmessage = new StringBuilder ();
Strmessage.append (reader. ReadToEnd ());
newstream.position = 0;
Copy (Newstream, oldstream);

if (_client is Client.RPClientTrace.IClientTrace)
{
Try
{
Client.RPClientTrace.IClientTrace _ptrclient = _
(Client.RPClientTrace.IClientTrace) _client;
Reliabilityinfo rinfo = _ptrclient.getreliabilityinfo ();
Rinfo.text = Strmessage.tostring ();
rinfo.destination = message. URL;
RInfo.Manager.LogMessage (Rinfo);
}
catch (Exception e)
{
Throw e;
}
}
}
}

The server side is a bit complicated because the server needs to perform additional operations for the inbound message. The invoked Web method is used to implement [EricRP.Server.RPServerTrace.TraceExtension ()]. The following code is invoked before and after the inbound message is deserialized:

public class Rpservertrace:soapextension
{
public override void ProcessMessage (SoapMessage message)
{
Try
{
Switch (message. Stage)
{
Case SoapMessageStage.BeforeDeserialize:
Readincomingmessagetext (message);
Break
Case Soapmessagestage.afterdeserialize:
SoapServerMessage tmpmsg = (soapservermessage) message;
_server = Tmpmsg.server;
if (_server is Server.RPServerTrace.IServerTrace)
{
Server.RPServerTrace.IServerTrace _ptrserver = _
(Server.RPServerTrace.IServerTrace) _server;
Reliabilityinfo rinfo = _ptrserver.getreliabilityinfo ();
Ericrp.reliabilityinfo Tempinfo = (ericrp.reliabilityinfo) message. Headers[0];
Tempinfo.text = _tempmessage;
Server.conversationmanager manager = new Server.conversationmanager ();
Manager. ProcessMessage (Tempinfo);

}
Break
}
}

After a stream exchange and interface check, Processinboundmessage is invoked on the server Dialog manager. Processinboundmessage is used to check the status of core messages. The message restriction program is used here. First check to see if the message expires, then check if it repeats, and finally check if it is ordered. If all three conditions are met, the message is logged and a confirmation is sent to the client, and if either condition is not met, the status of the message is changed and a confirmation is sent to the client.

public void Processinboundmessage (Ericrp.reliabilityinfo rinfo)
{
Try
{
if (isexpired (Rinfo))
{
Rinfo.status = ericRP.ReliabilityInfo.MessageStatus.Expired;
Sendack (Rinfo);
}
else if (isdulplicate (Rinfo))
{
Rinfo.status = ericRP.ReliabilityInfo.MessageStatus.Duplicate;
Sendack (Rinfo);
}
else if (isnotordered (Rinfo))
{
Rinfo.status = ericRP.ReliabilityInfo.MessageStatus.NotOrdered;
Sendack (Rinfo);
}
Else
{
Rinfo.status = ericRP.ReliabilityInfo.MessageStatus.Success;
LogMessage (Rinfo);
Sendack (Rinfo);
}
}
catch (Exception e)
{
Throw e;
}
}
}

A lot of implementation is needed to make this example work in a production environment. More importantly, the API should be based on a public standard that will be released later. The main purpose of this article is to cause readers to think, to understand the main WEB service classes in the. NET framework, I think these two goals have been achieved. If you are looking for a mature, usable implementation of reliable asynchronous messaging, it is recommended that you take a look at Microsoft biztalk™server 2000.

Finally, you can use similar tracing to perform all types of operations, such as encryption, customer allocation, and notification. Remember, this additional functionality adds to the processing infrastructure required by the WEB service.

Prospect
The future of XML Web Service is bright, both in terms of specification and implementation. Microsoft will work in a collaborative, standard-driven manner to ensure that XML Web Service becomes the best architecture for writing loosely coupled, decentralized applications. Reliable message handling and transaction specifications will be released later. Although there is still a lot of implementation to do, you can now start building your framework with SOAP and WSDL. The closer you are to the public specification process, the easier it will be to change the work later. The SOAP specification is a notable example of this concept. Developers around the world can track the development of the SOAP specification, so you can effortlessly adjust your implementation accordingly.

Hopefully I can have a crystal ball for you to accurately depict the infrastructure of future XML WEB services; Hopefully all the common services we currently depend on, such as security, transactions, storage, query, routing, process coordination, and so on, will be able to map directly to the WEB service architecture in the future; and GXA Implementations can permeate core development languages, application frameworks, business process frameworks, and enterprise infrastructures. By then, we will be able to truly seamlessly couple any two services together. I hope ERICRP will not really become the reliability layer behind the service. < smile >





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.