Web Services Quiz: Issue 2 - the Answer Part 1

There are several problems with the described Web Service implementation.

Let’s start with an architectural issue:

DeletePerson represents a oneway operation and therefore, we have no possibility to be sure that the request has been successfully executed. An http message can arrive zero or many times. Within the oneway scenario, the client gets an http OK as soon as the message has been accepted by the service. Since this is the transport level, it doesn’t mean that the message has been successfully processed. Look at the following code:

           

[WebMethod]

[SoapDocumentMethod(OneWay=true, ParameterStyle=SoapParameterStyle.Bare)]

public void DeletePerson(int i)

{

   throw new Exception("oops");

   // Just do something

}

Although the message is successfully delivered, there is no way for the client to notice that an error has been occurred during message processing. Solving this problem requires us to handle it at the application level. The easiest way is by changing the operation into a request/response pattern. This enables the client to get a response whenever a message has been successfully processed. But since there is no reliable messaging in place, messages can magically disappear. If a message gets lost, the client just resends the message. This is fine as long as it is the request message, but what happens if the response message gets lost? In this case, the message is already processed. If the client resends its request, the message gets processed the second time. There two different message types: Messages that can be sent several times without leading to inconsistent data (e.g. AccountStatementRequest) and messages that require to be processed exactly once (e.g. AccountTransferRequest). To achieve this type of consistency, the service must be able to uniquely identify request messages. Once it detects a message that arrived more than once it can check whether the message already has been processed or not. If yes, a persisted response message will be fetched without processing the message a second time. Check out the following code:

 

public class DeletePersonRequest

{

   public System.Guid messageId;

   public string name;

   public string firstname;

   [XmlAnyElement]

   public XmlElement[] AnyElem;

}

public class DeletePersonResponse

{

   public int errorCode;

}

[WebMethod]

[SoapDocumentMethod(OneWay=true, ParameterStyle=SoapParameterStyle.Wrapped)]

public DeletePersonResponse DeletePerson(DeletePersonRequest dpr)

{

   DeletePersonResponse resp;

   resp = MsgManager.LookupMsg(dpr.messageId);

   if (resp == null)

  {

     try

      {

         // Just do something

resp = new DeletePersonResponse();

resp.errorCode=0;

        MsgManager.AddMsg(dpr.messageId, resp);

      }

      catch(Exception exp)

      {

         resp.errorCode = -1;

      }

   }

   return resp;

}

My comments on some implementation issues will follow in separate post…