-->
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.  [ 1 post ] 
Author Message
 Post subject: saveOrUpdateCopy throws NPE if persister.isUnsaved is wrong
PostPosted: Tue Sep 14, 2004 1:56 pm 
Newbie

Joined: Wed Jan 21, 2004 5:51 pm
Posts: 14
Location: San Francisco, CA
This isn't really a bug, but perhaps Hibernate should recover more gracefully. Here's how to reproduce it: Write some code that (1) saves an object, (2) sleeps for 30 seconds. Sneak behind hibernate's back and delete the object from the database. (3) call saveOrUpdateCopy on a copy of the object. Hibernate throws a NullPointerException.

The problem occurs in the doCopy code in SessionImpl:

At line 3807, persister.isUnsaved returns false because the object already has an identifier value...
Code:
if ( id==null && persister.isUnsaved(object) ) {
   saveWithGeneratedIdentifier(object, Cascades.ACTION_COPY, copiedAlready);
   return object; //TODO: handle its proxy (reassociate it, I suppose)
}
else {

... Then at line 3814, the code tries to get the object, gets back nothing. Seeng that 'result' is null, the code realizes the session was lying about the object being unsaved, and saves a new instance. 'result' is still null ...
Code:
   Object result = get(clazz, id);
   if (result==null) {
      saveWithGeneratedIdentifier(object, Cascades.ACTION_COPY, copiedAlready);
   }
   else if ( Hibernate.getClass(result)!=clazz ) {
      throw new WrongClassException("class of the given object did not match class of persistent copy", id, clazz);
   }

   //cascade first, so that all unsaved objects get saved before we actually copy
   Cascades.cascade(this, persister, object, Cascades.ACTION_COPY, Cascades.CASCADE_ON_COPY, copiedAlready);

... Here's the problem. 'result' is still null when the code tries to unproxy it and get its property values. Things fall apart with a NullPointerException. Is the call to TypeFactory.copy still necessary after the previous call to saveWithGeneratedIdentifier?
Code:
   Object target = unproxy(result);
   //no need to handle the version differently
   Object[] copiedValues = TypeFactory.copy(
      persister.getPropertyValues(object),
      persister.getPropertyValues(target),
      persister.getPropertyTypes(),
      this,
      target
   );



While I'm sifting through this code, I have another question. Shouldn't 'saveOrUpdateCopy' call interceptor.isUnsaved instead of persister.isUnsaved the same way that 'save' and 'update' do?

It's not hard to imagine a real (albeit stupid or implausible) situation where something like this behind-the-back delete would occur. I discovered this exception when I was doing some testing of another component.


Hibernate Version: 2.1.1

Name and version of the database you are using: Microsoft SQL Server 2000

Full stack trace of any exception that occurs:
Code:
Thread [ExecuteThread: '14' for queue: 'weblogic.kernel.Default'] (Suspended (exception NullPointerException))
   GeneratedMethodAccessor110.invoke(Object, Object[]) line: not available
   DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
   Method.invoke(Object, Object[]) line: 324
   BasicPropertyAccessor$BasicGetter.get(Object) line: 96
   ConstrainedEntityPersister(AbstractEntityPersister).getPropertyValues(Object) line: 249
   SessionImpl.doCopy(Object, Serializable, Map) line: 3826
   SessionImpl.saveOrUpdateCopy(Object) line: 3780
   HibernatePersistenceManagerSLBean_2p157t_Impl(HibernatePersistenceManager).doSave(Persistable, boolean, boolean) line: 566
   HibernatePersistenceManagerSLBean_2p157t_Impl(AbstractPersistenceManager).save(Persistable, String, boolean, boolean) line: 547
   HibernatePersistenceManagerSLBean_2p157t_Impl(AbstractPersistenceManager).save(Persistable) line: 258
   HibernatePersistenceManagerSLBean_2p157t_ELOImpl.save(Persistable) line: 349
   DataObjectService_jfvdg7_Impl(DataObjectServiceSLBean).save(IDataObject) line: 152
   DataObjectService_jfvdg7_EOImpl.save(IDataObject) line: 388
   DataObjectServiceDelegate.save(IDataObject) line: 139
   RepositoryDataService_3wn7w7_Impl(RepositoryDataServiceImpl).saveMetadataStorage(IMetadataStorage) line: 88
   RepositoryDataService_3wn7w7_EOImpl.saveMetadataStorage(IMetadataStorage) line: 496
   RepositoryDataServiceDelegate.saveMetadataStorage(IMetadataStorage) line: 96
   RepositoryManager_vlvjzr_Impl(RepositoryManagerSLBean).addOrReplaceMetadata(Metadata) line: 390
   RepositoryManager_vlvjzr_EOImpl.addOrReplaceMetadata(Metadata) line: 376
   RepositoryManager_vlvjzr_EOImpl_WLSkel.invoke(int, InboundRequest, OutboundResponse, Object) line: not available
   ClusterableServerRef(BasicServerRef).invoke(RuntimeMethodDescriptor, InboundRequest, OutboundResponse) line: 466
   ClusterableServerRef(ReplicaAwareServerRef).invoke(RuntimeMethodDescriptor, InboundRequest, OutboundResponse) line: 108
   BasicServerRef$1.run() line: 409
   AuthenticatedSubject.doAs(AbstractSubject, PrivilegedExceptionAction) line: 353
   SecurityManager.runAs(AuthenticatedSubject, AuthenticatedSubject, PrivilegedExceptionAction) line: 144
   ClusterableServerRef(BasicServerRef).handleRequest(InboundRequest) line: 404
   BasicExecuteRequest.execute(ExecuteThread) line: 30
   ExecuteThread.execute(ExecuteRequest) line: 197
   ExecuteThread.run() line: 170


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

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.