Pages

Showing posts with label Logging. Show all posts
Showing posts with label Logging. Show all posts

March 15, 2014

How to use Proxy Pattern To Implement Service's Aspects Funcionality such as Logging, Authorization, Transaction.

Proxy pattern is used to add some extra operations, checks, controls before and after wrapped subject's operation. 

  As you can see on figure, client uses Subject interface and Proxy implementation, and when a service method is called, Proxy delegates call to Real Subject. At this point you can add some more operations before and after delegation.









Code sample is below, you can download eclipse project as .rar file from here.

Package Structure

proxy pattern uml diagram
package client;

import proxypattern.IService;
import proxypattern.ServiceProxy;

public class Main {
  public static void main (String[] args) {
    IService service = new ServiceProxy();
    service.method1();
  }
}
package proxypattern.authorization;

import proxypattern.User;

public class AuthorizationService implements IAuthorizationService {
  public boolean isUserAuthorizedToCallServiceMethod (String methodName, User user) {
    System.out.println(user + " has access rights to do " + methodName);
    return true;
  }
}
package proxypattern.authorization;

import proxypattern.User;

public interface IAuthorizationService {
  boolean isUserAuthorizedToCallServiceMethod (String methodName, User user);
}
package proxypattern.log;

public interface ILogService {
  void log (String log);
}
package proxypattern.log;

public class LogService implements ILogService {
  public void log (String log) {
    System.out.println(log);
  }
}
package proxypattern.transaction;

public interface ITransactionService {
  Session getSession ();
}
package proxypattern.transaction;

public class Session {
  public void beginTransaction () {
    System.out.println("transaction started.");
  }
  public void close () {
    System.out.println("session closed.");
  }
  public void commit () {
    System.out.println("transaction committed.");
  }
  public void executeQuery (String query) {
    System.out.println(query + " executed.");
  }
  public void open () {
    System.out.println("session opened.");
  }
  public void rollback () {
    System.out.println("transaction rollbacked.");
  }
}
package proxypattern.transaction;

public class TransactionService implements ITransactionService {
  public Session getSession () {
    return new Session(); // for example you can use hibernate session factory to get a session.
  }
}
package proxypattern;

import proxypattern.authorization.AuthorizationService;
import proxypattern.authorization.IAuthorizationService;
import proxypattern.log.ILogService;
import proxypattern.log.LogService;
import proxypattern.transaction.ITransactionService;
import proxypattern.transaction.Session;
import proxypattern.transaction.TransactionService;

// this class is used for all cross cut concerns such as authorization, log, transaction.
abstract class AbstractServiceMethodCall {
  private ILogService logService = new LogService();
  private IAuthorizationService authorizatiService = new AuthorizationService();
  private ITransactionService transactionService = new TransactionService();
  protected Session session;
  public void afterDelegation (String methodName, User user) {
    this.session.commit();
    this.session.close();
    this.logService.log(methodName + " operation complete successfully");
  }
  public void beforeDelegation (String methodName, User user) throws IllegalAccessException {
    this.logService.log(methodName + " is called by " + user.toString());
    if (!this.authorizatiService.isUserAuthorizedToCallServiceMethod(methodName, user)) {
      throw new IllegalAccessException();
    }
    this.session = this.transactionService.getSession();
    this.session.open();
    this.session.beginTransaction();
  }
  public void executeOperation (String methodName, User user) {
    try {
      this.beforeDelegation("method1", user);
      this.serviceOperation(this.session);
      this.afterDelegation("method1", user);
    }
    catch (IllegalAccessException e) {
      this.operationFailed("method1", user);
    }
  }
  public void operationFailed (String string, User user) {
    this.session.rollback();
    this.session.close();
  }
  public abstract void serviceOperation (Session session);
}
package proxypattern;

class ServiceImp implements IService {
  public void method1 () {
    System.out.println("method1 of " + this.getClass().getSimpleName() + " called.");
  }
}
package proxypattern;

import proxypattern.transaction.Session;

// this class is not thread safe you have to create a new instance before using
public class ServiceProxy implements IService {
  private IService delegated = new ServiceImp();

  public void method1 () {
    new AbstractServiceMethodCall() {
      
@Override
      public void serviceOperation (Session session) {
        ServiceProxy.this.delegated.method1();
      }
    }.executeOperation("method1", new User());
  }
}
package proxypattern;

public class User {
  @Override
  public String toString () {
    return "userId";
  }
}
As you can see in ServiceProxy .java we add log, authorization and transaction operations before and after actual service method call.

Output :
method1 is called by userId //log service
userId has access rights to do method1 //authorization service
session opened. //transaction service
transaction started. //transaction service
method1 of ServiceImp called. //actual service call service
transaction committed. //transaction service
session closed. //transaction service
method1 operation complete successfully //log service

March 14, 2014

Basic Architectural Design of Service for Enterprise Applications with Class Diagram and Sequence Diagram

Basic requirements for a service implementation are transaction, logging, authorization and of course business rules with service operations. When you think deeply you will see that these requirements are cross cut concerns. It means transaction, logging, security and business rule engine can be thought aspects, infrastructural requirements. These are independent from business domain.


Why transactional ?
It is important for the integrity and consistency of data.

Why log ?
It is important to observe performance, security, errors, statistics.

Why authorization ?
It is important to achieve that any client uses service, can call only operations which it has rights to call.

Why business rule engine ?
Any service operation has some business rules and it is important to cover them with a modern approach.

About Class Diagram of Service
  • The service is designed modular, each module can be thought a service or services, when a module is dependent to an other module, interaction between modules must be using service interfaces.These are important for high cohesion.
  • A Service implementation has data access objects to achieve database operations. 
  • Both service, data access objects and of course service client uses entities to do operations.
  • All service operations must be transactional. It means when a service method is called, all operations, all data access object operations must be in same transaction. So if service call succeed all database changes must be applied to the databases, but if it is failed none of them must be applied.
  • Transaction, business rule engine, log and authorization can be implemented as java interceptors or decorators. Because these are all aspects and independent from business domain.
About Sequence Diagram of Service
  • When a service method is called, transaction is started by the transaction manager.
  • Log Service is used to log that operation is called and other logs for example performance considerations.
  • Authorization Service is used for checking that client has access grants to call service method.
  • Business Rule Engine is used to execute domain specific business rules.
*Log Service and Authorization Service can be seperated from business transaction. The order of service call can be changed according to the different approaches.


Service Class Diagram.vsd, Service Sequence Diagram.vsd