Ok, trying to use simple lazy collection here and have something borked up. The exception I'm getting is:
org.exolab.castor.jdo.PersistenceException: Identities can't be null! at org.exolab.castor.persist.RelationCollection$IteratorImp.lazyLoad(RelationCollection.java:290) at org.exolab.castor.persist.RelationCollection$IteratorImp.next(RelationCollection.java:265) at org.moss.tapn.database.impl.TopicManager.getAllReplies(TopicManager.java:218) at $Interceptor_10187854476_28.getAllReplies($Interceptor_10187854476_28.java) at $SingletonProxy_10187853dc9_22.getAllReplies($SingletonProxy_10187853dc9_22.java) at test.TopicManagerTest.testGetAllTopics(TopicManagerTest.java:124) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) Attaching the mapping file with the uneeded parts chopped out. along with the test case I'm running. This is happening with a self-referential object (can hold many of its own type). The object loads fine, and the intial Collection is set up fine as I get the right size() and stuff back from it. Anyone know whats wrong? If not I'll file a bug with all the info and write a test case for it. The offending block of code is: public Object next() { if ( changestamp != parent._changecount ) throw new ConcurrentModificationException("Concurrent Modification is not allowed!"); // only needed if application did not call hasNext(), will skip deleted ids if ( !hasNext() ) throw new NoSuchElementException("Read after the end of iterator!"); Object id; Object o; if ( cursor < _added.size() ) { id = _added.get( cursor++ ); o = _loaded.get( id ); if ( o != null ) return o; return lazyLoad( id ); } else { // the deleted ids were skipped by hasNext(), get is safe id = _ids.get(cursor++ - _added.size()); // RETURNS NULL!!! o = _loaded.get( id ); if ( o != null ) return o; return lazyLoad( id ); } } in RelationCollection. There is nothing in _added or _ids doing the step through with the debugger so something isn't getting in there correctly. =\ -Nick p.s. Using HSQLDB and the latest CVS CO for castor compiled under jdk1.5.0_01
/* * Created on Jan 17, 2005 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package org.moss.tapn.database.impl; import java.util.Collection; import java.util.Iterator; import java.util.Vector; import org.apache.log4j.Logger; import org.exolab.castor.jdo.Database; import org.exolab.castor.jdo.OQLQuery; import org.exolab.castor.jdo.PersistenceException; import org.exolab.castor.jdo.QueryResults; import org.moss.tapn.beans.Category; import org.moss.tapn.beans.Topic; import org.moss.tapn.beans.User; import org.moss.tapn.database.ITopicManager; import org.moss.tapn.utils.MyBeanUtils; /** * @author nstuart * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class TopicManager extends DefaultConnectionImp implements ITopicManager { private Logger log = Logger.getLogger(TopicManager.class); /** Error happens in these two methods, when accessing the Lazy objects **/ public void deleteTopic(Topic topic) { Database db = getConnection(); try{ db.begin(); topic = (Topic)db.load(Topic.class, new Integer(topic.getId())); db.remove(topic); db.commit(); }catch(PersistenceException pe){ if(log.isDebugEnabled()){ log.debug("Could not delete the topic.", pe); } }finally{ closeConnection(db); } } public Vector getAllReplies(Topic parent){ Topic dbTopic = null; Database db = getConnection(); Vector replies = new Vector(); try{ db.begin(); dbTopic = (Topic)db.load(Topic.class, new Integer(parent.getId())); Iterator it = dbTopic.getReply().iterator(); while(it.hasNext()){ replies.add(it.next()); } }catch(PersistenceException pe){ if(log.isDebugEnabled()){ log.debug("Could not get the full list of replies.", pe); } }finally{ closeConnection(db); } return replies; } }
/* * Created on Jan 17, 2005 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package test; import java.util.Vector; import junit.framework.TestCase; import org.apache.log4j.Logger; import org.moss.tapn.beans.Category; import org.moss.tapn.beans.Forum; import org.moss.tapn.beans.Topic; import org.moss.tapn.beans.User; import org.moss.tapn.database.ICategoryManager; import org.moss.tapn.database.IForumManager; import org.moss.tapn.database.ITopicManager; import org.moss.tapn.database.IUserManager; import org.moss.tapn.database.ServiceLocator; /** * @author nstuart * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class TopicManagerTest extends TestCase { private Logger log = Logger.getLogger(TopicManagerTest.class); private ICategoryManager cManager; private IForumManager fManager; private ITopicManager manager; private IUserManager uManager; private static int topicId; private static int replyId; public void setUp(){ cManager = (ICategoryManager)ServiceLocator.getService(ICategoryManager.class); fManager = (IForumManager)ServiceLocator.getService(IForumManager.class); uManager = (IUserManager)ServiceLocator.getService(IUserManager.class); manager = (ITopicManager)ServiceLocator.getService(ITopicManager.class); } public void testCreateTopic() { Forum forum = new Forum(); forum.setTitle("My Test Topic Forum"); fManager.createForum(forum); assertTrue(forum.getId() != 0); Category cat = new Category(); cat.setTitle("My Test Topic Category"); cat.setForum(forum); cManager.createCategory(cat); assertTrue(cat.getId() != 0); User user = new User(); user.setEmailAddress("test@test.com"); user.setUserName("topicUser"); user.setPassword("blah"); uManager.createUser(user); assertTrue(user.getId() != 0); Topic topic = new Topic(); topic.setPoster(user); topic.setCategory(cat); topic.setSubject("My test topic"); topic.setMessage("Blah!"); manager.createTopic(topic); assertTrue(topic.getId() != 0); topicId = topic.getId(); } public void testLoadTopic() { Topic topic = null; topic = manager.loadTopic(topicId); assertNotNull(topic); assertNotNull(topic.getCategory()); assertNotNull(topic.getPoster()); } public void testSaveTopic() { Topic topic = manager.loadTopic(topicId); assertNotNull(topic); String newMsg = topic.getMessage() + " (EDITED)"; topic.setMessage(newMsg); manager.saveTopic(topic); topic = null; topic = manager.loadTopic(topicId); assertEquals(newMsg, topic.getMessage()); } public void testCreateReply() { Topic reply = new Topic(); Topic parent = manager.loadTopic(topicId); assertNotNull(parent); reply.setSubject("RE:" + parent.getSubject()); reply.setMessage("My reply!"); reply.setPoster(parent.getPoster()); manager.createReply(parent, reply); assertTrue(reply.getId() != 0); replyId = reply.getId(); reply = null; parent = null; parent = manager.loadTopic(topicId); assertNotNull(parent); assertTrue(parent.getReply().size() == 1); reply = manager.loadTopic(replyId); assertNotNull(reply); assertNotNull(reply.getParent()); assertEquals(1, reply.getReplyNumber()); } public void testGetAllTopics(){ Topic topic = manager.loadTopic(topicId); assertNotNull(topic); Vector replies = manager.getAllReplies(topic); // <-- error starts here assertNotNull(replies); assertTrue(replies.size() > 0); assertEquals(replyId, ((Topic)replies.get(0)).getId()); } public void testDeleteTopic() { Topic topic = manager.loadTopic(topicId); assertNotNull(topic); manager.deleteTopic(topic); // <-- Error also happens here, exact same as above. topic = manager.loadTopic(topicId); assertNull(topic); topic = manager.loadTopic(replyId); assertNull(topic); } public void testMoveTopic() { fail(); } }
<mapping> <key-generator name="IDENTITY"> </key-generator> ... <class name="org.moss.tapn.beans.Topic" identity="id" key-generator="IDENTITY"> <map-to table="topics"/> <field name="id" type="integer"> <sql name="id"/> </field> <field name="reply" type="org.moss.tapn.beans.Topic" collection="collection" lazy="true"> <sql many-key="parentId"/> </field> <field name="replyNumber" type="integer"> <sql name="replyNumber"/> </field> <field name="subject" type="string"> <sql name="subject"/> </field> <field name="message" type="string"> <sql name="message"/> </field> <field name="postDate" type="date"> <sql name="postDate"/> </field> <field name="editDate" type="date"> <sql name="editDate"/> </field> <field name="edited" type="boolean"> <sql name="edited" type="char[01]"/> </field> <field name="locked" type="boolean"> <sql name="locked" type="char[01]"/> </field> <field name="deleted" type="boolean"> <sql name="deleted" type="char[01]"/> </field> <field name="moved" type="boolean"> <sql name="moved" type="char[01]"/> </field> </class> ... </mapping>
----------------------------------------------------------- If you wish to unsubscribe from this mailing, send mail to [EMAIL PROTECTED] with a subject of: unsubscribe castor-dev