Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Java Tip 71: Use dynamic messaging in Java - JavaWorld - April 1999

Java Tip 71: Use dynamic messaging in Java - JavaWorld - April 1999

Tutorial Details:

Java Tip 71: Use dynamic messaging in Java
Java Tip 71: Use dynamic messaging in Java
By: By Alex Blewitt
Get around Java's inability to trap a request it doesn't know about -- by implementing the 'doesNotUnderstand' method!
rogrammers who have worked in Smalltalk or Objective C are used to the doesNotUnderstand message, which enables an object to trap a request it doesn't know about. This can't happen in Java directly, because all messages are statically type-checked at compile time -- so it's never possible to send a message directly to an object that Java doesn't understand.
However, with the introduction of Java 1.1, Sun released the java.lang.reflect API. It allows an object to inspect itself to find out what methods it supports, and to dynamically invoke them. The API elevates Java from being a dynamic runtime environment to being a truly dynamic language.
This Java Tip shows you how to use the Reflection API, and specifically how to use it to implement a simple system for sending dynamic messages. In our particular case, this simple system is the doesNotUnderstand message.
In order to understand how to implement dynamic messaging, it is necessary to first examine the java.lang.Reflection API.
Reflection
In the world of programming, reflection is a process that allows an object to look at itself (as in a mirror, ergo the term) to see what it can do. Reflection identifies all of the members that are associated with an object (field members and method members) and makes it possible for that object to interact with them.
One question that is asked often is, What's the difference between introspection and reflection? The answer: Reflection allows you to find out which members an object has; and introspection allows you to identify which (JavaBean) properties an object has. That's why the java.lang.reflect lives in a separate package, and the Introspector object is in the java.beans package. Links to these packages on Sun's Java site, as well as further information on JavaBeans, are available in the Resources section below.
The java.lang.reflect package defines wrapper objects for manipulating arrays, methods, and fields. However, you can't create objects like Method , Field , or Constructor directly; you have to invoke a factory method in the Class object ( getMethod , getConstructor , and so on).
Find out what an object can do
To give you an example of reflection at work, this sample piece of code, DisplayMembers.java , takes a Java classname as its argument, and then prints out all the members it contains.
The next piece of code, listed below, takes a fully qualified classname as its argument(s), and for each class listed prints out all of the methods that are declared in that class. For instance, running:
java DisplayMembers DisplayMembers
lists the main and displayClassInfo methods along with their types and exceptions. (I have been purposefully lazy here by declaring that the main method generates an exception; this saves having to type in a try/catch block, but results in ugly code. Don't use this style unless you want to write compact demo code.)
Do what I say, not what I do
Once you've got a list of the methods an object has, you can invoke them dynamically. This allows you to select a method dynamically (based on its name and argument types) and invoke it against a given object. The next example demonstrates how an object can be instantiated and given a method name, and how it can take optional arguments.
This is implemented in the source code DWIS.java . This class can be run as an application, and it takes a class name, method name, and a value. The method is then resolved using getMethodCalled . Once the method has been located, it is invoked using meth.invoke , and the result is displayed on System.out .
When DWIS is run, the output looks like this:
java DWIS java.lang.Integer toHexString 123
> 7b
java DWIS java.lang.Integer toBinaryString 45
> 101101
java DWIS java.awt.Button setLabel "Hello, world!"
> java.awt.Button[button0,0,0,0x0,invalid,label=Hello, world!]
java DWIS java.lang.System getProperties
This piece of code works in four stages;
The class name given is resolved to a java.lang.Class using Class.forName
The first method with the same number of arguments is located using getMethod
The arguments are converted from strings into objects
The method is invoked and displays the result and/or the target
The convertFromString method is used to convert the command-line argument (a string) into an object of the appropriate type.
When the convertFromString method is called, the desired argument type is passed as the class parameter. If a boolean method (such as setEnabled ) has been resolved, then the class parameter will be Boolean.TYPE .
There are some standard types that can be easily converted; boolean, character, and integer values can be parsed from a string, since suitable constructors are available. These types are tested at the top of the method.
If the type is not located, then the convertFromString method tries to instantiate an object of type class with a string constructor.
This convertFromString method can be extended to deal with other argument types, such as Float , Double , and other user-defined types. Creating these extensions is left as an exercise for the reader.
It's time to build the 'doesNotUnderstand' system
Having looked at how reflection can be used to dynamically resolve a method that takes a specific number of arguments, we are now ready to implement our doesNotUnderstand system. We need to implement a message delegator that calls a method with a given name and set of arguments. If this fails (for example, the method isn't present), we can invoke another predefined method.
MessageSender.java essentially is a tidied-up version of the DWIS object, with a few nicer features. For one thing, the method lookup (in getMethod ) carries out some sensible checks to see whether the arguments that are passed are compatible with the given arguments.
Note that in the event multiple methods may be called -- such as a parseFrom (object) and parseFrom (string) -- this getMethod will select the "nearest" method, not necessarily the correct one.
The code above allows us to invoke dynamic methods, based on a method name and a sequence of arguments. Although this is much easier than having to work out the Method objects yourself, it does not achieve the objective: the doesNotUnderstand message.
Fortunately, adding the functionality for the doesNotUnderstand message is relatively simple. All we have to do is detect when a given method cannot be found; that is, we need to catch when a NoSuchMethodException is raised.
We can therefore modify the original code:
Method meth = getMethod(tclass,message,args,target == null);
to become
try {
Method meth = getMethod(tclass,message,args,target == null);
} catch (NoSuchMethodException e) {
// send it to another object
if (message.equals("doesNotUnderstand"))) {
throw e;
} else {
Object newArgs[] = { message, args };
sendMessage(target,"doesNotUnderstand",newArgs);
}
}
and voilą! The code to call the doesNotUnderstand method is implemented. When a method is invoked using sendMessage and it cannot be found (a NoSuchMethodException is thrown), the above code sends the doesNotUnderstand method to the same target.
To use the MessageSender , we need to implement the doesNotUnderstand method in our target:
public class TestObject {
public void doesNotUnderstand(String messageName, Object args[]) {
// this will be called when a message is not understood
System.out.println("Method " + messageName + " is not understood");
}
// other methods go here
}
Now, when we call an unknown method using MessageSender.sendMessage , our special doesNotUnderstand method will be invoked. In this example, this special method only prints out a message, but it could be used to implement a proxy or other such design patterns.
TestObject to = new TestObject();
MessageSender.sendMessage(to,"helloWorld",null);
// prints out "Method helloWorld is not understood"
The applet below demonstrates in action the technique described in this tip. A method name can be typed in the bottom field of the applet, and clicking on Invoke will call that method with no arguments on itself ( FinalMessageApplet ). List methods will generate a list of all the zero-argument methods that the object supports.
If you type a nonexistent method name into the applet field, the doesNotUnderstand method is called, displaying the method name and arguments. Click on the links here for the source to the example applet and the final message sender .
Note: In order to view the applet below, your browser must support JDK 1.1.
alt="Final Message Applet demonstration"> You need a Java 1.1-enabled browser to view this applet.
Conclusion
Using the Reflection API may be cumbersome, but it is a powerful way to implement dynamic messaging in Java. There is a certain amount of bookwork involved in obtaining the necessary Method objects, but creating a sendMessage method is relatively straightforward -- and the best part is that you can let that method do all the hard work for you.
Once the sendMessage has been implemented, changing it to invoke doesNotUnderstand when a method is not recognizable is a simple task. Plus, the MessageSender object can be reused generically to invoke dynamic messages on any object with any argument types.
This page formated for crawlers and browsers that don't support scripts and tables.
Home
EZone


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Java Tip 71: Use dynamic messaging in Java - JavaWorld - April 1999

View Tutorial:
Java Tip 71: Use dynamic messaging in Java - JavaWorld - April 1999

Related Tutorials:

Applet to Applet Communication
Applet to Applet Communication
 
Java Tip 72: Press Escape to close your Swing dialog windows
Java Tip 72: Press Escape to close your Swing dialog windows
 
XML messaging, Part 3
XML messaging, Part 3
 
Trace your steps in Java 1.4
Trace your steps in Java 1.4
 
Jabber away with instant messaging
Jabber away with instant messaging
 
J2SE 1.4 breathes new life into the CORBA community, Part 1
J2SE 1.4 breathes new life into the CORBA community, Part 1
 
Sun boosts
Sun boosts enterprise Java
 
Java Tip 143: Utilize the Database Schema Browser
Java Tip 143: Utilize the Database Schema Browser
 
RMI, Dynamic Proxies, and the Evolution of Deployment
RMI, Dynamic Proxies, and the Evolution of Deployment Dynamic Generation of Stub Classes This release adds support for the dynamic generation of stub classes at runtime, obviating the need to use the Java Remote Method Invocation (Java RMI) stub compi
 
JMS Messaging Online Resource
JMS Messaging Online Resource JMS Tutorials JMS provides a way for Java programs to access an enterprise messaging system, also known as message oriented middleware (MOM). Check out the below tutorials.
 
Java validation with dynamic proxies
Decouple validation processes from your business object implementations.
 
XML Messaging Using JBoss
It\'s common practice to share data using FTP, but an increasingly popular alternative is to use a messaging service. As always, each approach has its own pros and cons, depending on the nature of "what to share," how easy it is to implement the technolog
 
SOFIA 2.3 released with Hibernate and Dynamic HTML components
SOFIA 2.3 released with Hibernate and Dynamic HTML components
 
Distributed Enterprise Messaging with MantaRay
A very important communication standard in Java is Java Messaging Service (JMS). JMS is a set of Java interfaces and associated semantics that define a way for a Java-based client to access a messaging system. JMS provides a rich, yet simple, set of messa
 
Java Server Pages Dynamically Generated Web Content.
JavaServer PagesTM (JSP TM) technology allows Web developers and designers to rapidly develop and easily maintain, information-rich, dynamic Web pages that leverage existing business systems.
 
JSP Tutorial
Adding dynamic content via expressionsAs we saw in the previous section, any HTML file can be turned into a JSP file by changing its extension to .jsp. Of course, what makes JSP useful is the ability to embed Java. Put the following text in a file wit
 
Power Messaging, Maps and more...
BuddySpace is an instant messenger with four novel twists: (1) it allows optional maps for geographical & office-plan visualizations in addition to standard 'buddy lists'; (2) it is built on open source Jabber, which makes it interoperable with ICQ, MSN,
 
Getting Started with Java Message Service (JMS)
The Java Message Service (JMS) is designed to allow Java applications to use enterprise messaging systems. It makes it easy to develop enterprise applications that asynchronously send and receive business data and events. Learn how to implement it for you
 
J2ME Technology Turns 5!
In 2004 the Java 2 Platform, Micro Edition (J2ME) celebrated its fifth anniversary. This article presents where J2ME is today.
 
J2ME Wireless Toolkit 2.2
Now available.This version of the toolkit is fully compatible with the Java Technology for the Wireless Industry (JTWI) specification (JSR 185).
 
Site navigation
 

 

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

Copyright © 2006. All rights reserved.