Proxy pattern, Java and protection proxy

Proxy pattern is very important in developer world. That can be used in many real scenario. This pattern is useful when we want to have access control to object by creating protection proxy.Now we will see the scenario where we can use proxy pattern and we will use java to implement it.Lets say we have two employee SunA and SunB.Employee has two attributes name and grade. In Manager and employee scenario, one employee can set its own name, but he cant set another employee name,Similarly one employee cant set its own grade ,but He can set another employee grade.
How we are going to achieve this access control ?????


Proxy pattern and java is going to help to resolve this problem.So here we are going to create two proxy objects,one for accessing its own object and second for accessing another object, Because Java creates the proxy class for us,we need a way to tell the proxy class what to do. We cant put the access control code in to the Proxy class,So if can't put the code in Proxy class , where do we put it ?? In InvocationHandler.The job of the InvocationHandler is to respond to any method call on the proxy.
I am going to give a try to explain this by code samples.


First we will create the Employee interface:
Employee.java


package proxypattern;


public interface Employee {
    public String getName();
    public int getGrade();
    public void setName(String aName);
    public void setGrade(int aGrade);


}


Implementation of this :
EmployeeImpl.java


package proxypattern;


public class EmployeeImpl implements Employee{
private String gName;
private int gGrade;
    public EmployeeImpl() {
    }
    public String getName(){
        return gName;
    }
    public int getGrade(){
        return gGrade;
    }
    public void setName(String aName){
        gName = aName;
       
    }
    public void setGrade(int aGrade){
        gGrade = aGrade;
    }


}


Next step is we will create two InvocationHandler. InvocationHandlers implements the behaviour of the proxy. Java takes care of creating the actual proxy class and object,We need to supply handler that know what to do when a method is called on it.


FirstInvocationHandler.java
package proxypattern;


import java.lang.reflect.\*;


public class FirstInvocationHandler implements InvocationHandler {
Employee gEmployee;
    public FirstInvocationHandler(Employee aEmployee) {
        gEmployee = aEmployee;
    }
    public Object invoke(Object aProxy, Method aMethod, Object aArgs[])
                  throws IllegalAccessException {
        try{
            if(aMethod.getName().startsWith("get")){
                return aMethod.invoke(gEmployee, aArgs);
            }
            else if (aMethod.getName().equals("setGrade")){
                throw new IllegalAccessException();
            }
            else if (aMethod.getName().startsWith("set")){
                return aMethod.invoke(gEmployee, aArgs);
            }
        }catch (InvocationTargetException aEx){
            aEx.printStackTrace();
        }
        return null;
    }


}



SecondInvocationHandler.java
package proxypattern;
import java.lang.reflect.\*;


public class SecondInvocationHandler implements InvocationHandler {


  Employee gEmployee;
    public SecondInvocationHandler(Employee aEmployee) {
        gEmployee = aEmployee;
    }
    public Object invoke(Object aProxy, Method aMethod, Object aArgs[])
                  throws IllegalAccessException {
        try{
            if(aMethod.getName().startsWith("get")){
                return aMethod.invoke(gEmployee, aArgs);
            }
            else if (aMethod.getName().equals("setName")){
                throw new IllegalAccessException();
               
            }
            else if (aMethod.getName().startsWith("set")){
                return aMethod.invoke(gEmployee, aArgs);
               
            }
        }catch (InvocationTargetException aEx){
            aEx.printStackTrace();
        }
        return null;
    }


}



So Above we have created two invocation handler to deal with two different proxies.You can see that we need to implement only invoke method of InvocationHandler interface,invoke method has parameter proxy object that will invoke this handler,method object that was invoked and args that is arguments to method.This InvocationHandler makes call on real object as per condition defined.


Next we will see how to get the Proxy objects.


Employee getFirstProxy(Employee aEmployee){
        return (Employee)Proxy.newProxyInstance(
                aEmployee.getClass().getClassLoader(),
                aEmployee.getClass().getInterfaces(),
                new FirstInvocationHandler(aEmployee));
    }



Employee getSecondProxy(Employee bEmployee) {
        return (Employee)Proxy.newProxyInstance(
                bEmployee.getClass().getClassLoader(),
                bEmployee.getClass().getInterfaces(),
                new SecondInvocationHandler(bEmployee));
    }



Above we have two methods that returns proxy objects , for creating proxy object We are calling Proxy's static method newProxyInstance(), that takes as arguments , classloader of real object,interfaces and invocationhandler.We pass the real object into the constructor of InvocationHandler. 
We will create a Class to create employee database,that we will use in sample program.


package proxypattern;


import java.util.\*;


public class EmployeeDB {
HashMap < String, Employee >theEmployeeDB = new HashMap< String, Employee>();
    public EmployeeDB() {
    }
    public void addEmployee(Employee aEmployee){
        theEmployeeDB.put(aEmployee.getName(), aEmployee);
    }
public Employee getEmployee(String aName){
    return theEmployeeDB.get(aName);
}
}


Now we will put everything togather and will test the whole concept we tried to learn.


TestProxyPattern.java


package proxypattern;
import java.lang.reflect.\*;
public class TestProxyPattern {
EmployeeDB gDB = new EmployeeDB();
    /\*\* Creates a new instance of TestProxyPattern \*/
    public TestProxyPattern() {
        Employee aEmp = new EmployeeImpl();
        aEmp.setName("SunA");
        aEmp.setGrade(1);
        Employee bEmp = new EmployeeImpl();
        bEmp.setName("SunB");
        bEmp.setGrade(2);
        gDB.addEmployee(aEmp);
        gDB.addEmployee(bEmp);
       
    }


    /\*\*
     \* @param args the command line arguments
     \*/
    public static void main(String[] args) {
        TestProxyPattern theProxyPattern = new TestProxyPattern ();
        theProxyPattern.runExample();
    }
    public void runExample(){
        Employee aFirstEmp = gDB.getEmployee("SunA");
        Employee aFirstEmpProxy = getFirstProxy(aFirstEmp);
        aFirstEmpProxy.setName("SunAChanged");
        System.out.println("NEW NAME of SunA is ::"+aFirstEmp.getName());
        try{
            aFirstEmpProxy.setGrade(10);
        }catch(Exception theEx){
            System.out.println(aFirstEmp.getName()+", You can't set your grade yourself," +
                    "Your grade is still::"+aFirstEmp.getGrade());
        }
       Employee aSecondEmp = gDB.getEmployee("SunB");
       Employee aSecondEmpProxy = getSecondProxy(aFirstEmp);
       aSecondEmpProxy.setGrade(5);
       System.out.println(aFirstEmp.getName()+", Your grade is changed by :"
               +aSecondEmp.getName()+". Your grade is now :"+aFirstEmp.getGrade());
       try{
           aSecondEmpProxy.setName("SunA_changed_by_SunB");
       } catch(Exception theEx){
           System.out.println("No one can change anyone name So "
                   +"First employee name is still :"+aFirstEmp.getName());
       }
    }
    Employee getFirstProxy(Employee aEmployee){
        return (Employee)Proxy.newProxyInstance(
                aEmployee.getClass().getClassLoader(),
                aEmployee.getClass().getInterfaces(),
                new FirstInvocationHandler(aEmployee));
    }
    Employee getSecondProxy(Employee bEmployee) {
        return (Employee)Proxy.newProxyInstance(
                bEmployee.getClass().getClassLoader(),
                bEmployee.getClass().getInterfaces(),
                new SecondInvocationHandler(bEmployee));
    }


}


If we run the code we see following output :


NEW NAME of SunA is ::SunAChanged
SunAChanged, You can't set your grade yourself,Your grade is still::1
SunAChanged, Your grade is changed by :SunB. Your grade is now :5
No one can change anyone name So First employee name is still :SunAChanged

Comments:

Thank you for the explanation, this is the first time for me to know Proxy in java.lang.reflect

Posted by prosp on July 09, 2007 at 10:06 PM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

sandeeps

Search

Archives
« May 2015
SunMonTueWedThuFriSat
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
      
Today