Infinite loops with TreeCacheAOP
twundke Nov 9, 2004 3:44 AMHi all,
I have a bit of a show-stopper of a problem here. Code will follow, but I'll explain it quickly first.
I have a ValueObject, which contains an IdObject that is a unique ID. Both objects implement toString(), equals() and hashCode(), as any good object should. Both objects are also advisable.
I have a HashMap that will contain ValueObjects, keyed by their respective IdObject. The HashMap is put into the cache using putObject().
This results in an infinite loop. Very basically, the problem is that IdObject is part of the FQN (as it's the key in the HashMap) and IdObject implements hashCode() (and toString()), which references an advisable field (id).
I would include a stack trace, but I've totally run out of time. The following should all be compilable, so you can see exactly what's happening.
Here's the code.
public class IdObject{ private String id; public IdObject() { } // IdObject public IdObject(String aId) { id = aId; } // IdObject public String toString() { return id; } // toString public boolean equals(Object aObject) { boolean result = false; if ((aObject != null) && (aObject.getClass().getName().equals( this.getClass().getName()))) { if (id.equals(((IdObject)aObject).id)) { result = true; } // if } // if return result; } // equals public int hashCode() { return id.hashCode(); } // hashCode } // class IdObject
public class ValueObject { private IdObject idObj; private float value; public ValueObject() { } // ValueObject public ValueObject(IdObject aIdObj, float aValue) { idObj = aIdObj; value = aValue; } // ValueObject public IdObject getIdObj() { return idObj; } public float getValue() { return value; } public String toString() { return idObj + ": " + value; } // toString public boolean equals(Object aObject) { boolean result = false; if ((aObject != null) && (aObject.getClass().getName().equals( this.getClass().getName()))) { result = idObj.equals(((ValueObject)aObject).idObj); } // if return result; } // equals public int hashCode() { return idObj.hashCode(); } // hashCode } // class ValueObject
import org.jboss.cache.*; import org.jboss.cache.aop.*; import java.util.*; public class TestRunner { private static final String CONFIG_FILENAME = "data/cacheConfig.xml"; private TreeCacheAop treeCache; private Map cachedMap; public TestRunner() { initCache(); IdObject idObj1 = new IdObject("1"); ValueObject obj1 = new ValueObject(idObj1, 3343.23f); cachedMap.put(idObj1, obj1); // <---- Infinite loop here } // TestRunner private void initCache() { try { treeCache = new TreeCacheAop(); PropertyConfigurator cacheConfig = new PropertyConfigurator(); cacheConfig.configure(treeCache, CONFIG_FILENAME); treeCache.startService(); treeCache.putObject("test", new HashMap()); cachedMap = (Map)treeCache.getObject("test"); } // try catch ( Exception x ) { x.printStackTrace(); System.exit( 1 ); } // catch } // initCache public static void main( String[] aArgs ) { new TestRunner(); } // main } // class TestRunner
Cache Config:
<?xml version="1.0" encoding="UTF-8"?> <server> <classpath codebase="C:/Java/jboss-cache/lib" archives="jboss-cache.jar, jgroups.jar"/> <mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache"> <attribute name="CacheMode">LOCAL</attribute> </mbean> </server>
AOP file:
<?xml version="1.0" encoding="UTF-8"?> <aop> <prepare expr="field(* $instanceof{ValueObject}->*)" /> <prepare expr="field(* $instanceof{IdObject}->*)" /> </aop>