The directory structure of the hosting site has changed due to circumstances beyond our
control. This causes the AirfareAgent to fail because it cannot find the perl script that
generates the airfare information. To correct the problem, change the following line in
the process() method in AirfareAgent.java from:
url = new URL("http://www.bigusbooks.com/cgi-local/airfare.pl");
to:
url = new URL("http://www.bigusbooks.com/cgi-bin/airfare.pl");
In some cases, the code does not run with the latest release of Java from Sun.
The code was written and tested with JDK 1.3, and the corresponding JRE was
shipped on the CD-ROM. If you are having trouble running the code, please try
running it with the earlier release of Java.
One problem we have found seems to be an Introspection bug in the Sun JDK 1.4.1 getTargetEventInfo() method. The CIAgent void
addAgent(CIAgent agent) method is erroneously being processed as a possible addXXXEventListener method.
A workaround is to change the return type from void to something else. A simple fix is to return the
child CIAgent, thus working around the bug in the Sun logic.
/**
* Adds a CIAgent to this agent and sets its parent member to point to
* this agent.
*
* @param child the CIAgent object to be added to this object as a child
*
* @return The CIAgent just added
* NOTE: This change is a workaround for a JDK 1.4.1 Introspection bug
*/
public CIAgent addAgent(CIAgent child) {
children.addElement(child) ;
child.setParent(this) ;
return child;
}
The bug seems to be in the Sun JDK 1.4.x Introspector getTargetEventInfo() method.
String name = method.getName();
Class argTypes[] = method.getParameterTypes();
Class resultType = method.getReturnType();
if (name.startsWith(ADD_PREFIX) && argTypes.length == 1 &&
resultType == Void.TYPE &&
Introspector.isSubclass(argTypes[0], eventListenerType)) {
String listenerName = name.substring(3);
if (listenerName.length() > 0 &&
argTypes[0].getName().endsWith(listenerName)) {
adds.put(listenerName, method);
}
This adds void getAgent(CIAgent agent); to the list. Later on in this method, decapitalize() fails,
because the listenerName = "Agent". It gets an index out of bounds exception from substring()
because they are subtracting 8 from the length.
// Now look for matching addFooListener+removeFooListener pairs.
// Bonus if there is a matching getFooListeners method as well.
Iterator keys = adds.keySet().iterator();
String beanClassName = beanClass.getName();
while (keys.hasNext()) {
String listenerName = (String) keys.next();
// Skip any "add" which doesn't have a matching "remove".
if (removes.get(listenerName) == null) {
continue;
}
String eventName = decapitalize(listenerName.substring(0, listenerName.length()-8));
Method addMethod = (Method)adds.get(listenerName);
Method removeMethod = (Method)removes.get(listenerName);
Method getListenerMethod = (Method)gets.get(listenerName);
Class argType = addMethod.getParameterTypes()[0];