I'm trying to implement history interceptor based on the implementation provided on the wiki page. I'm using hibernate 2.1.x.
My HistoryInterceptor's OnFlushDirty method when called has the oldValues set to NULL.
Here's my HibernateInterceptor's OnflushDirty method impl.
Code:
public boolean onFlushDirty(Object obj, Serializable id, Object[] newValues, Object[] oldValues, String[] properties, Type[] types) throws CallbackException {
if (!(obj instanceof Historizable)) {
return false;
}
Historizable h = (Historizable) obj;
// get the copy from the map
Set entries = (Set) histories.get(obj);
for (int i = 0; i < properties.length; i++) {
// Skip the historyEntries
if (properties[i].equals("historyEntries") == true) {
continue;
}
Object oldOne = oldValues[i];
Object newOne = newValues[i];
// Check for changes
if (oldOne == null && newOne == null) {
continue;
}
if (newOne instanceof PersistentCollection) {
// Collections must be compared against the snapshot
PersistentCollection collection = (PersistentCollection) newValues[i];
if (collection.isDirectlyAccessible() == false) {
continue;
}
// retrieve Snapshot
oldOne = collection.getCollectionSnapshot().getSnapshot();
if (oldOne instanceof Map && newOne instanceof Set) {
// a Set is internally stored as Map
oldOne = ((Map) oldOne).values();
}
}
if (oldOne != null && oldOne.equals(newOne) == true) {
continue;
}
// Generate a new entry
HistoryEntry entry = new HistoryEntry();
entry.setWho(getUser());
entry.setTimestamp(new Timestamp(new Date().getTime()));
entry.setWhat("update");
entry.setProperty(properties[i]);
entry.setOldValue(format(oldOne));
entry.setNewValue(format(newOne));
if (log.isDebugEnabled()) {
log.debug("Changed " + properties[i] + " from " + oldOne + " to " + newOne);
}
// and store it.
entries.add(entry);
}
return false;
}
Here's my JUnit test case for HistoryInterceptor:
Code:
public void testHistoryInterceptor() throws Exception {
Project project = new Project();
project.setName("Espresso-New");
project.setStatus("New");
dao.saveProject(project);
assertTrue("primary key assigned", project.getId() != null);
log.info(project);
assertEquals(1, project.getHistoryEntries().size());
project = dao.loadProject(project.getId());
Set hist = project.getHistoryEntries();
assertEquals(1, hist.size());
project.setStatus("New-1");
dao.saveProject(project);
assertEquals(2, project.getHistoryEntries().size());
/*
project = dao.getProject(project.getId());
hist = project.getHistoryEntries();
log.debug("hist=" + hist);
// Contains the creation and the modification
assertEquals(2, hist.size());
dao.removeProject(project.getId());
*/
}
The first saveProject goes fine. When i do the update, i'm getting following NULL Pointer Exception as oldValues argument to OnFlushDirty is NULL.
Code:
[junit] Testcase: testHistoryInterceptor(com.apple.ermt.persistence.audit.interceptor.HistoryInterceptorTest): Caused an ERROR
[junit] null
[junit] java.lang.NullPointerException
[junit] at com.apple.ermt.persistence.audit.interceptor.HistoryInterceptor.onFlushDirty(HistoryInterceptor.java:113)
[junit] at net.sf.hibernate.impl.SessionImpl.flushEntity(SessionImpl.java:2535)
[junit] at net.sf.hibernate.impl.SessionImpl.flushEntities(SessionImpl.java:2454)
[junit] at net.sf.hibernate.impl.SessionImpl.flushEverything(SessionImpl.java:2256)
[junit] at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2235)
[junit] at org.springframework.orm.hibernate.HibernateAccessor.flushIfNecessary(HibernateAccessor.java:214)
[junit] at org.springframework.orm.hibernate.HibernateTemplate.execute(HibernateTemplate.java:201)
[junit] at org.springframework.orm.hibernate.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:341)
[junit] at com.apple.ermt.dao.hibernate.HibernateProjectDAO.saveProject(HibernateProjectDAO.java:47)
[junit] at com.apple.ermt.persistence.audit.interceptor.HistoryInterceptorTest.testHistoryInterceptor(HistoryInterceptorTest.java:36)
[junit] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[junit] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
[junit] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
Could someone please let me know why the oldValues is NULL for OnFlushDirty method?
Thanks!