Pivotal Knowledge Base

Follow

The getOldValue() method returns null in the listener afterdestroy event

Applies to

GemFire 7 and later

Purpose

In certain scenarios entryEvent.getOldValue() will return null in the afterdestroy() method. The following article describes when this can happen and how to work around this limitation.

Description

In certain scenarios, the old value of an entry may no longer be available, in which case, entryEvent.getOldValue() will return null. This can happen for disk regions when the old value is on disk only. This limitation is documented in getOldValue API documentation.

In this situation, the old value has gone by the time the listener is invoked and is not included to avoid severe performance impacts.

Workaround

To simply avoid a NullPointerException when getOldValue returns null, you can add a null check on the return value. However, to get the old value for an evicted entry, you can add logic in the beforeupdate method of the cacheWriter to get the old value from disk and add it into the event's old value. For example,

public class TestWriter extends CacheWriterAdapter implements Declarable {

private AtomicInteger numberOfEvents = new AtomicInteger();

  public void beforeCreate(EntryEvent event) throws CacheWriterException {
 } 

  public void beforeUpdate(EntryEvent event) throws CacheWriterException {
 EntryEventImpl eei = (EntryEventImpl) event;
 if (eei.getRawOldValue() == NotAvailable.NOT_AVAILABLE) {
 LocalRegion lr = (LocalRegion) event.getRegion();
 Object oldValueFromDisk = lr.getValueOnDiskOrBuffer(event.getKey());
 eei.setOldValue(oldValueFromDisk, true);
 System.out.println(Thread.currentThread().getName() + ": TestWriter received beforeUpdate (" + getNextEvent() + ") with null old value for: " + event.getKey() + "->" + event.getNewValue() + ". Set old value from disk to " + event.getOldValue() + ".");
 }
 }

 public void init(Properties properties) {}

 public void close() {}
   private int getNextEvent() {
     return this.numberOfEvents.incrementAndGet();
 }
}

We used a CacheWriter and the LocalRegion method getValueOnDiskOrBuffer() method to achieve this. Basically, in the CacheWriter, you check for NOT_AVAILABLE in the old value. If so, get the old value from disk and set it on the event's old value. Then, in the listener the old value can be processed normally.

Comments

Powered by Zendesk