Sign In/My Account | View Cart  
advertisement


Listen Print Discuss

Web Services Integration Patterns, Part 2
by Massimiliano Bigatti | Pages: 1, 2, 3, 4, 5

State Logger

It stores the state of a transaction to restart in a sequent call from that point.

As an evolution of the Flow Logger, the State Logger not only tracks the operation flow, but uses that information to perform only the calls not correctly done in previous invocations.

Think, for example, of a process that involves numerous service calls, like the one outlined in the previous pattern, but that is safe to remain in an inconsisent state between several calls.

The typical scenario is that the user has a function that calls a coordinator, whose logic comprises several services. In the middle of the process, a service raises an exception, maybe due to network errors. The error message is returned to the user, who can eventually take some action, like checking the configuration properties or call the IT support.

Subsequently, the user retry calling that function, that will skip the calls already done, resuming the work from the point where interrupted before.

The State Logger manages the access to the table used to track the operation flow. The Service Coordinator organizes the services in a process, eventually calling only the services not successfully terminated before.

Every time a service returns correctly, with a complete response or a fault, the State Logger write a record in the log table. The Service Coordinator that implement checks before any call that that call wasn't performed before, using the data contained in the logs.

Sample code

The StateLogger interface specifies a track() method that is used to store the current state in the database. The implementation will create a row for each call to this method. The wasDone() method identifies if a specific state was previously done, looking it up in the database. For each method there is an integer key that distinguishes different calls to the same process, maybe executed by different users on different data:


public interface FlowLogger {
  public int track( int key, State currentState );
  public boolean wasDone( int key, State whatState );
}

The AccountCreateCoordinator class models the process shown in the table afterward. Each single call is wrapped inside a method, that checks using the FlowLogger object that the specific call wasn't done before, for this session. Each method could raise a ServiceException, breaking the process in the middle and returning the control to the caller.


public class AccountCreateCoordinator {
  State CREATE = new State("CREATE");
  State INIT = new State("INIT");
  State ADD_A = new State("ADD_A");
  State ADD_B = new State("ADD_B");
  State ADD_C = new State("ADD_C");
  State MODIFY_B = new State("MODIFY_B");
  State MODIFY_C = new State("MODIFY_C");
  State CLOSE = new State("CLOSE");
  
  ...
  
  FlowLogger flowLogger;
  int accountId;
  
  public void createAccount( AccountData data ) throws ServiceException {
    this.data = data;
    
    create();
    init();
    addA();
    ...
    close();
  }
  
  public void create() throws ServiceException {
    if( !flowLogger.wasDone( data.key, CREATE ) ) {
      CreateService createService = new CreateService();
      
      createService.setKey( data.key );
      createService.setType( data.type );
      createService.setName( data.name );
      createService.setSurname( data.surname );
      
      create.call();
      
      accountId = createService.getAccountId();
      flowLogger.track( data.key, CREATE );
    }
  }
  
  ...
}

Pages: 1, 2, 3, 4, 5

Next Pagearrow