gemfiregeode

Casting to and from pdx in an Apache Geode event listener


In a linked question I asked about a problem with Geode.Net client casting Geode PDX types to objects (domain objects) and this time I've a problem casting objects to Geode PDX types. It seems a region can hold both pdx serialized object types and other types of object and / or internal object types. By working with byte offsets I guess.

Anyway, this link shows a way to check for object types and handle them:

// get checks Object type and handles each appropriately
Object myObject = myRegion.get(myKey);

either as PDX instances or as domain object types:

if (myObject instanceof PdxInstance) {
  // get returned PdxInstance instead of domain object    
  PdxInstance myPdxInstance = (PdxInstance)myObject;

then with GetField for a PDX Instance you can update just 1 field, very nice...

My problem is with domain objects:

else if (myObject instanceof DomainClass) {
// code to handle domain object instance  

When coming from an event listener

public void AfterCreate(EntryEvent<TKey, TVal> ev)

I first of all try to cast ev.NewValue to Pdx or then the domain object and keep getting one of the following:

When the value in the region is a PdxInstance then without the if (myObject instanceof PdxInstance) as above to prevent it the cast IPdxInstance pdx = (IPdxInstance)ev.NewValue gives:

System.InvalidCastException: Unable to cast object of type myObject to type
Apache.Geode.Client.IPdxInstance

Which is to be expected. I seem to have broken the PdxSerialisation of myObject by creating the region <key, value> as <string, Object> even though myObject extends PdxSerializable and writing keys & values to the region is going through the ToData() override.

So then to deal with myObject directly for example myObject = ev.NewValue or myObject.Field1 = ((myObject)(ev.NewValue)).Field1 or like variations is giving:

Cannot implicitly convert type 'TVal' to 'myObject' 
Cannot convert type 'TVal' to 'myObject'

Surely the event ev.NewValue to myObject cast ought to be straightforward so what am I missing? Otherwise I have to use ev.Key (which does cast without any exception) to specifically get the value again from the region in the cache by using:

IRegion<string, Object> r = cache.GetRegion<string, Object>(region);
return r[key];

So when the object is already given in the TVal type NewValue then why I just can't access it there? :-s


Solution

  • Per programming your application to use PDX instances a region can hold either objects or PDX wrapped objects. For the former, casting through object is working. So I needed to write:

    object o = ev.NewValue;
    if (o.GetType().Name.Equals("PdxInstanceImpl")) 
    {
      PdxInstance myPdx = (PdxInstance)o;
      MyObject m = (MyObject)myPdx.GetObject();
    
      string s = m.MyString;
      decimal d = m.MyDecimal;
    }
    else
    {
      MyObject m = (MyObject)o;
    
      string s = m.MyString;
      decimal d = m.MyDecimal;
    }