Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Explore the Dynamic Proxy API

Explore the Dynamic Proxy API

Tutorial Details:

Explore the Dynamic Proxy API
Explore the Dynamic Proxy API
By: By Jeremy Blosser
Use dynamic proxies to bring strong typing to abstract data types
ith the introduction of the Dynamic Proxy API in Java 1.3, a huge and often overlooked improvement has been made to the Java platform. The uses for dynamic proxies are sometimes hard concepts to grasp. In this article, I hope to introduce you first to the Proxy design pattern and then to the java.lang.reflect.Proxy class and the java.lang.reflect.InvocationHandler interface, which make up the heart of Dynamic Proxy's functionality.
The functionality discussed here combines the Java 1.3 dynamic proxies with abstract data types to bring strong typing to those types. I will also discuss the power of the dynamic proxy by introducing the concept of views in your Java programming. Lastly, I will introduce a powerful way to add access control to your Java objects with, of course, the use of the dynamic proxy.
Definition of a proxy
A proxy forces object method calls to occur indirectly through the proxy object, which acts as a surrogate or delegate for the underlying object being proxied. Proxy objects are usually declared so that the client objects have no indication that they have a proxy object instance.
Some common proxies are the access proxy, facades, remote proxies, and virtual proxies. An access proxy is used to enforce a security policy on access to a service or data-providing object. A facade is a single interface to multiple underlying objects. The remote proxy is used to mask or shield the client object from the fact that the underlying object is remote. A virtual proxy is used to perform lazy or just-in-time instantiation of the real object.
The proxy is a fundamental design pattern that is used quite often in programming. However, one of its drawbacks is the specificity or tight coupling of the proxy with its underlying object. Looking at the UML for the Proxy design pattern in Figure 1, you see that for the proxy to be useful and transparent, it usually needs to either implement an interface or inherit from a known superclass (with the exception of a facade, perhaps).
Figure 1. UML Diagram of the Proxy Design Pattern
Dynamic proxies
In Java 1.3, Sun introduced the Dynamic Proxy API. For the dynamic proxy to work, you must first have a proxy interface. The proxy interface is the interface that is implemented by the proxy class. Second, you need an instance of the proxy class.
Interestingly, you can have a proxy class that implements multiple interfaces. However, there are a few restrictions on the interfaces you implement. It is important to keep those restrictions in mind when creating your dynamic proxy:
The proxy interface must be an interface. In other words, it cannot be a class (or an abstract class) or a primitive.
The array of interfaces passed to the proxy constructor must not contain duplicates of the same interface. Sun specifies that, and it makes sense that you wouldn't be trying to implement the same interface twice at the same time. For example, an array { IPerson.class, IPerson.class } would be illegal, but the code { IPerson.class, IEmployee.class } would not. The code calling the constructor should check for that case and filter out duplicates.
All the interfaces must be visible to the ClassLoader specified during the construction call. Again, that makes sense. The ClassLoader must be able to load the interfaces for the proxy.
All the nonpublic interfaces must be from the same package. You cannot have a private interface from package com.xyz and the proxy class in package com.abc . If you think about it, it is the same way when programming a regular Java class. You couldn't implement a nonpublic interface from another package with a regular class either.
The proxy interfaces cannot have a conflict of methods. You can't have two methods that take the same parameters but return different types. For example, the methods public void foo() and public String foo() cannot be defined in the same class because they have the same signature, but return different types (see The Java Language Specification ). Again, that is the same for a regular class.
The resulting proxy class cannot exceed the limits of the VM, such as the limitation on the number of interfaces that can be implemented.
To create an actual dynamic proxy class, all you need to do is implement the java.lang.reflect.InvocationHandler interface:
public Class MyDynamicProxyClass implements
java.lang.reflect.InvocationHandler
{
Object obj;
public MyDynamicProxyClass(Object obj)
{ this.obj = obj; }
public Object invoke(Object proxy, Method m, Object[] args) throws
Throwable
{
try {
// do something
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw e;
}
// return something
}
}
That's all there is to it! Really! I'm not lying! Okay, well, you also have to have your actual proxy interface:
public interface MyProxyInterface
{
public Object MyMethod();
}
Then to actually use that dynamic proxy, the code looks like this:
MyProxyInterface foo = (MyProxyInterface)
java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),
Class[] { MyProxyInterface.class },
new MyDynamicProxyClass(obj));
Knowing that the above code is just horribly ugly, I'd like to hide it in some type of factory method. So instead of having that messy code in the client code, I'll add that method to my MyDynamicProxyClass :
static public Object newInstance(Object obj, Class[] interfaces)
{
return
java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),
interfaces,
new
MyDynamicProxyClass(obj));
}
That allows me to use the following client code instead:
MyProxyInterface foo = (MyProxyInterface)
MyDynamicProxyClass.newInstance(obj, new Class[]
{ MyProxyInterface.class });
That is much cleaner code. It might be a good idea in the future to have a factory class that completely hides the entire code from the client, so that the client code looks more like:
MyProxyInterface foo = Builder.newProxyInterface();
Overall, implementing a dynamic proxy is fairly simple. However, behind that simplicity is great power. That great power is derived from the fact that your dynamic proxy can implement any interface or interface group. I'll explore that concept in the next section.
Abstract data
The best example of abstract data is in the Java collection classes such as java.util.ArrayList , java.util.HashMap , or java.util.Vector . Those collection classes are capable of holding any Java object. They are invaluable in their use in Java. The concept of abstract data types is a powerful one, and those classes bring the power of collections to any data type.
Tying the two together
By combining the concept of dynamic proxies with abstract data types, you can gain all the benefits of abstract data types with strong typing. In addition, you can easily use the proxy class to implement access control, virtual proxies, or any other useful proxy type. By masking the actual creation and use of proxies from the client code, you can make changes to the underlying proxy code without affecting the client code.
The concept of a view
When architecting a Java program, it is common to run into design problems in which a class must display multiple, different interfaces to client code. Take Figure 2 for example:
Figure 2. Class Diagram of Person
public class Person {
private String name;
private String address;
private String phoneNumber;
public String getName() { return name; }
public String getAddress() { return address; }
public String getPhoneNumber() { return phoneNumber; }
public void setName(String name) { this.name = name; }
public void setAddress(String address) { this.address = address; }
public void setPhoneNumber(String phoneNumber) { this.phoneNumber =
phoneNumber; }
}
public class Employee extends Person {
private String SSN;
private String department;
private float salary;
public String getSSN() { return ssn; }
public String getDepartment() { return department; }
public float getSalary() { return salary; }
public void setSSN(String ssn) { this.ssn = ssn; }
public void setDepartment(String department) { this.department =
department; }
public void setSalary(float salary) { this.salary = salary; }
}
public class Manager extends Employee {
String title;
String[] departments;
public String getTitle() { return title; }
public String[] getDepartments() { return departments; }
public void setTitle(String title) { this.title = title; }
public void setDepartments(String[] departments) { this.departments =
departments; }
}
In that example, a Person class contains the properties Name , Address , and PhoneNumber . Then, there is the Employee class, which is a Person subclass and contains the additional properties SSN , Department , and Salary . From the Employee class, you have the subclass Manager , which adds the properties Title and one or more Departments for which Manager is responsible.
After you've designed that, you should take a step back and think about how the architecture is to be used. Promotion is one idea that you might want to implement in your design. How would you take a person object and make it an employee object, and how would you take an employee object and make it a manager object? What about the reverse? Also, it might not be necessary to expose a manager object as anything more than a person object to a particular client.
A real-life example might be a car. A car has your typical interface such as a pedal for accelerating, another pedal for braking, a wheel for turning left or right, and so forth. However, another interface is revealed when you think of a mechanic working on your car. He has a completely different interface to the car, such as tuning the engine or changing the oil. In that case, to expect the car's driver to know the car's mechanic interfac


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Explore the Dynamic Proxy API

View Tutorial:
Explore the Dynamic Proxy API

Related Tutorials:

Java Tip 56: How to eliminate debugging problems for RMI-based applications - JavaWorld - July 1998
Java Tip 56: How to eliminate debugging problems for RMI-based applications - JavaWorld - July 1998
 
Java Tip 71: Use dynamic messaging in Java - JavaWorld - April 1999
Java Tip 71: Use dynamic messaging in Java - JavaWorld - April 1999
 
Create automated and distributed management applications with Jiro technology, Part 1 - JavaWorld February
Create automated and distributed management applications with Jiro technology, Part 1 - JavaWorld February 2000
 
Make room for JavaSpaces, Part 3 - JavaWorld March 2000
Make room for JavaSpaces, Part 3 - JavaWorld March 2000
 
Take control of the servlet environment, Part 1 - JavaWorld November 2000
Take control of the servlet environment, Part 1 - JavaWorld November 2000
 
Clean up your wire protocol with SOAP, Part 4 - JavaWorld July 2001
Clean up your wire protocol with SOAP, Part 4 - JavaWorld July 2001
 
Explore the Dynamic Proxy API
Explore the Dynamic Proxy API
 
Implement Design by Contract for Java using dynamic proxies
Implement Design by Contract for Java using dynamic proxies
 
Take control with the Proxy design pattern
Take control with the Proxy design pattern
 
Integrate Java and C++ with Jace
Integrate Java and C++ with Jace
 
Discover and publish Web services with JAXR
Discover and publish Web services with JAXR
 
J2SE 1.4 breathes new life into the CORBA community, Part 1
J2SE 1.4 breathes new life into the CORBA community, Part 1
 
Very interesting
Very interesting
 
Second-generation aspect-oriented programming
Second-generation aspect-oriented programming
 
HA-JDBC: High-Availability JDBC
HA-JDBC: High-Availability JDBC Summary HA-JDBC is a JDBC driver proxy that provides light-weight, transparent clustering capability to any underlying JDBC driver.
 
Java validation with dynamic proxies
Decouple validation processes from your business object implementations.
 
Develop aspect-oriented Java applications with Eclipse and AJDT
AspectJ is an aspect-oriented extension of the Javaâ„¢ language that enables a modular implementation of crosscutting concerns. This crosscutting behavior, which can be static or dynamic, presents an extra challenge to tools that support AspectJ. The AJDT
 
Dynamic Delegation and Its Applications
Dynamic Delegation and Its Applications The Proxy pattern is an important and widely used design pattern in object-oriented programming. Do you ever use Proxy in Java since its introduction in JDK 1.3? A dynamic proxy class is a class that implements a l
 
Java Tech: Acquire Images with TWAIN and SANE, Part 1
Scanners, digital cameras, and other image-acquisition devices are part of the computing landscape. Despite their ubiquity, however, Java does not provide a standard API for interacting with these devices. And yet there certainly is a desire to have a sta
 
Mock Objects in Unit Tests
EasyMock is a well-known mock tool that can create a mock object for a given interface at runtime.
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.