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("[email protected]");
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