-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: 2.1 Final IllegalArgumentException and onDelete
PostPosted: Fri Dec 12, 2003 6:43 pm 
Newbie

Joined: Sun Nov 30, 2003 4:11 pm
Posts: 11
Hi!

I've just upgraded to 2.1 final (from 2.0.3??) and I'm facing a strange exception when rerunning my unit tests.

I'm getting this exception

Code:
java.lang.IllegalArgumentException: fromIndex(1) > toIndex(0)

when I try to delete an object.
This object has an onDelete in which it tries to delete some related objects (not tied via hibernate because of legacy model defects).

The exception is thrown in the session.delete method, not in the onDelete, though if I comment out the onDelete code, it makes the parent deletion correctly...and throws NO exception!

What has changed in Hibernate since 2.0.3 that could cause such a change in behaviour? Do you have any tip? Do you know where could this exception come from?

Lots of thanks,

_
Jorge


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 12, 2003 10:06 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
stack trace???


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 12, 2003 10:07 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
http://www.hibernate.org/ForumMailingli ... AskForHelp


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 13, 2003 8:25 am 
Newbie

Joined: Sun Nov 30, 2003 4:11 pm
Posts: 11
Hi,

More info, of course, excuse me.

Please, note that this is a unit test... I think there could be a case in which, in the same session, children would be deleted and then the parent (of course, more things would happen between those two delete() calls)

My code is something like, in lines 38-39 of TestAgenteAislarFallo.java:

Code:
    mgr2.delete(ag2);
    mgr2.delete(ag2.getNIFPassword());


Being that NIFPassword cascade-deletes manually (in its onDelete) the related object, ag2... this is a case of "first I will delete the children. then I will delete the parent", and the parent will anyway try to delete it's associated children (though they've been already deleted).

mgr2.delete() is just a wrapper to Session.delete()

The NIFPassword object onDelete will not even try to delete anything really, because it shares the session, and it's only child has already been deleted (in the previous line).

this is the stack trace I get:

Code:
1) testCGMB(com.previsora.tests.data.TestAgenteAislarFallo)java.lang.IllegalArgumentException: fromIndex(1) > toIndex(0)
   at java.util.SubList.<init>(AbstractList.java:706)
   at java.util.RandomAccessSubList.<init>(AbstractList.java:860)
   at java.util.AbstractList.subList(AbstractList.java:569)
   at net.sf.hibernate.impl.SessionImpl.doDelete(SessionImpl.java:1155)
   at net.sf.hibernate.impl.SessionImpl.delete(SessionImpl.java:1114)
   at com.previsora.data.hibernate.HibernateManager.delete(HibernateManager.java:377)
   at com.previsora.tests.data.TestAgenteAislarFallo.testCGMB(TestAgenteAislarFallo.java:39)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at com.intellij.rt.execution.junit.TextTestRunner.main(TextTestRunner.java:12)


I'm tracking Hibernate's source in order to try to understand what I'm doing wrong. In line 1155 of SessionImpl:

Code:
deletionsByOnSave = deletions.subList( oldDeletions.size(), deletions.size() );


The size of deletion is 0, and oldDeletion's is 1, so subList it will throw the IllegalArgumentException.

This is in the context of:

Code:
         if ( persister.implementsLifecycle() ) {
            HashSet oldNullifiables = (HashSet) nullifiables.clone();
            ArrayList oldDeletions = (ArrayList) deletions.clone();
            log.debug("calling onDelete()");
            if ( ( (Lifecycle) object ).onDelete(this) ) {
               //rollback deletion
               entry.status = LOADED;
               entry.deletedState = null;
               log.debug("deletion vetoed by onDelete()");
               return; //don't let it cascade
            }
            deletionsByOnSave = deletions.subList( oldDeletions.size(), deletions.size() );
            deletions = oldDeletions;
            nullifiablesByOnSave = nullifiables;
            nullifiables = oldNullifiables;
         }


Trying to understand the code (excuse me if I throw bizarre assumptions here :-() while debugging:

* deletions holds scheduled deletions in the session, in my case there is one before calling onDelete.
* oldDeletions is a clone of the previous state of deletions (and so also has a size of 1)
* after the call to onDelete, deletions will contain NO elements?? Why? I haven't deleted anything, and I haven't made neither flush() nor close()... can't understand this.

So I track again the onDelete, and get that I run a session.find() in there, in order to get the amount of related objects I will delete... and seems like this session.find() would reset the "deletions" list...

Then, I will track session.find() and get that if AutoFlush == true, and dontFlushFromFind is 0, it will flush my collections, and so my 'deletions' will be 0, leading to my Exception...

I've checked what that dontFlushFromFind is, and seems like it's a control to avoid flushing too early when a find is recursively called... should that be of application to my code? Is this control needed in the delete too??

I still don't get why should this code have worked without problem in the previous version...
* Am I allowed to run a find inside an onDelete? If so... should I try to avoid this in some way?? (maybe changing the AutoFlush property?)
* Is this the correct behaviour, or was it correct in the previous Hibernate version?

Thank you very much!

_
Jorge


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 13, 2003 8:34 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Quote:
Am I allowed to run a find inside an onDelete? If so... should I try to avoid this in some way?? (maybe changing the AutoFlush property?)


Its probably not advisable.


You might be able to make your exception go away by doing session.setFlushMode(FlushMode.COMMIT) .... but really, I don't think its very safe to run queries from onDelete().


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 13, 2003 8:34 am 
Newbie

Joined: Sun Nov 30, 2003 4:11 pm
Posts: 11
Hi, just one more thing...

I've changed my flushmode when doing the onDelete call:

Code:
  public boolean onDelete(Session session) throws CallbackException {
    boolean bError = false;
    FlushMode prevFlushMode = session.getFlushMode();
    session.setFlushMode(FlushMode.NEVER);
    List agentes = this.getAgentes();             // THIS WILL RUN A session.find() !!!
    Iterator it = agentes.iterator();
    IAgente ag = null;
    while (it.hasNext()) {
      try {
        ag = (IAgente)it.next();
        _sesion.delete(ag);
      } catch (HibernateException he) {
        _log.error("onDelete: No se pudo borrar en cascada: " + ag + ": " + he);
        bError = true;
      } catch (Exception e) {
        System.out.println(e);
      }
    }
    session.setFlushMode(prevFlushMode);
    return bError;
  }


The change is that now I preserve my previous FlushMode, and change it to NEVER while the onDelete code runs... this seems to make it run again, but I still wonder... is this really the solution?

Anyway, thank you very much, I guess I'm now more in the way of understanding Hibernate... (not too much in the way, though)


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 13, 2003 8:41 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Here is the change that is responsible:


http://cvs.sourceforge.net/viewcvs.py/h ... =v21branch


As you can see, it makes the code significantly cleaner...


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.