Pages

Showing posts with label Java Code Sample. Show all posts
Showing posts with label Java Code Sample. 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 2, 2014

How To Implement Session Expired Alert using JSF, PrimeFaces and Java Script

You have to handle this issue at client side, because any solution that uses server side scripts initiates session time again. We can use java script for solving this issue.

Basically the solution has four steps.
1. After user logs into the system, a timer equals to the session time is set and count down is started.
2. Each server request the server side session time is restarted, so count down is restarted.
3. When the count down is close to 0, system shows additional time dialog to the user.
4. At the end of the count down, user is redirected to the exit page.

The implementation and demo is below. Java script code is placed in .xhtml document at this implementation but if you use a .js file you can paste the code in it.


Important code lines and explanations.

1.
if (document.getElementById('loggedInUserId') == null) {
  return;
}

With this code line we check the logged user info in rendered xhtml. So we sure that user logged in and ready for count down.
2.
<p:ajaxStatus onstart="statusDialog.show();" 
    onsuccess="statusDialog.hide();countDownInit();" />
With this code line we restart count down again with any ajax request. Because in each server request the server side session time is restarted.
3.
if (0 > minute) {
  exit();
  return;
}

At the end of the count down, we redirect current page to the exit page.
4.
<p:commandButton value="Yes" process="@this" 
    update="@none" oncomplete="additionalTimeDialog.hide();" />
<p:commandButton value="No" type="button" onclick="exit();" />

If the user clicks yes button to get extra time we send an ajax request using command button and close the additional time dialog. So with this request server side session time will be restarted.

If the use clikcs no button, we simply redirect user to the exit page.

index.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://java.sun.com/jsf/core">
  <h:head>
    <title>Facelet Title2</title>
  <script type="text/javascript">
    var countDownTime; //in miliseconds
    var sessionTime = 61000; //in miliseconds
    var whenToShowAdditionalTimeDialog = 60000; //in miliseconds 
    var isAdditionalTimeDialogShowed = false;
    var countDownStarted = false;
    var minute;
    var second;
    function countDownInit() {
      countDownTime = (new Date()).getTime();
      minute = 1;
      second = 00;
      countDownStarted = false;
    }
    function checkCountDown() {
      if (document.getElementById('loggedInUserId') == null) {
        return;
      }
      var now = (new Date()).getTime();
      if (now - countDownTime > (sessionTime - whenToShowAdditionalTimeDialog)) {
        additionalTimeDialog.show();
        countDownStarted = true;
      }
      if (countDownStarted) {
        second = second - 1;
        if (0 > second) {
          second = 59;
          minute = minute - 1;
        }
        if (0 > minute) {
          exit();
          return;
        }
        document.getElementById('additionalTimeDialog:minuteOutput').innerHTML = minute;
        document.getElementById('additionalTimeDialog:secondOutput').innerHTML = second;
      }
    } 
    function exit() {
      document.location.href = '/projectname/eng/loggedout.xhtml';
    }
    window.setInterval(checkCountDown, 1000);
    </script>
  </h:head>

  <h:body>
    <p:ajaxStatus onstart="statusDialog.show();" 
        onsuccess="statusDialog.hide();countDownInit();" />
    <p:dialog modal="true" widgetVar="statusDialog" header="Status" 
        draggable="false" closable="false">
      <p:graphicImage value="/image/ajaxloadingbar.gif" />
    </p:dialog>
    <p:dialog modal="true" widgetVar="additionalTimeDialog" header="Alert" 
         draggable="false" closable="false">
      <h:form id="additionalTimeDialog"> Your session time will be expired in 
        <h:outputText id="minuteOutput" /> : <h:outputText id="secondOutput" /> . 
            Do you want extra time ?
        <p:commandButton value="Yes" process="@this" update="@none" 
            oncomplete="additionalTimeDialog.hide();" />
        <p:commandButton value="No" type="button" onclick="exit();" />
      </h:form>
    </p:dialog>
    <h:form id="form" prependId="false">
      <p:remoteCommand name="sendRequest" update="@none" process="@this" />
      <h:panelGrid id="userform">
        <p:panelGrid columns="2" rendered="#{not testManagedBean.userLogged}">
          <h:outputLabel value="Name" />
          <p:inputText value="#{testManagedBean.name}" />
          <h:outputLabel value="Password" />
          <p:inputText value="#{testManagedBean.passWord}" />
          <p:separator />
          <p:commandButton value="Log in" action="#{testManagedBean.login}" 
                process=":form:userform" update=":form:userform" />
        </p:panelGrid>
        <p:panelGrid columns="2" rendered="#{testManagedBean.userLogged}">
          <h:outputLabel value="Name" />
          <h:outputText id="loggedInUserId" value="#{testManagedBean.name}" />
        </p:panelGrid>
        </h:panelGrid>
      </h:form>
  </h:body>
</html>
loggedout.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://java.sun.com/jsf/core">
  <h:head>
    <title>LoggedOut.xhtml</title>
  </h:head>
  <h:body>
    Logged out.
  </h:body>
</html>

Test.java
package controlleryonetici;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean(name = "testManagedBean")
@ViewScoped
public class Test {
  private String name;
  private String passWord;
  private boolean userLogged = false;
  public String getPassWord() {
    return this.passWord;
  }
  public void setPassWord(final String passWord) {
    this.passWord = passWord;
  }
  public String getName() {
    return this.name;
  }
  public void setName(final String name) {
    this.name = name;
  }
  public void login() {
    if ("admin".equals(this.name) && "admin".equals(this.passWord))
      this.userLogged = true;
    }
    public boolean getUserLogged() {
      return this.userLogged;
    }
    public void setUserLogged(final boolean isUserLogged) {
      this.userLogged = isUserLogged;
  }
}
Demo

1. log in



2. alert



3. log out