在Apache Geode事件侦听器

时间:2018-02-02 14:57:43

标签: gemfire geode

a linked question中我询问了将Geode PDX类型转换为对象(域对象)的问题,这次我将对象转换为Geode PDX类型时遇到了问题。区域似乎可以包含pdx序列化对象类型和其他类型的对象和/或内部对象类型。通过使用字节偏移我猜。

无论如何,this link显示了检查对象类型并处理它们的方法:

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

作为PDX实例或作为域对象类型:

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

然后使用GetField获取PDX实例,您只需更新1个字段,非常好......

我的问题在于域对象:

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

来自事件监听器

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

我首先尝试将ev.NewValue转换为Pdx,然后转换为域对象并继续获取以下内容之一:

当区域中的值为PdxInstance时,如果没有上述if (myObject instanceof PdxInstance)以防止投射IPdxInstance pdx = (IPdxInstance)ev.NewValue给出:

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

这是可以预料的。我似乎通过将<key, value>区域设置为<string, Object>来打破myObject的PdxSerialisation,即使myObject扩展了PdxSerializable并写入了密钥&amp;该区域的值正在通过ToData()覆盖。

然后直接处理myObject例如myObject = ev.NewValuemyObject.Field1 = ((myObject)(ev.NewValue)).Field1或类似变体提供:

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

事件ev.NewValuemyObject的事件当然应该是直截了当的,所以我错过了什么?否则,我必须使用ev.Key(没有任何异常进行转换)通过使用以下方式从缓存中的区域再次专门get值:

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

因此,当TVal类型NewValue中已经提供了对象时,为什么我无法在那里访问它? :-s

2 个答案:

答案 0 :(得分:1)

我建议您删除“read-serialized = true”并删除IPdxInstance的类型检查。您仍然可以在您的区域中拥有PDX对象,而不使用read-serialized = true。你真的想要在你的回调而不是PDX实例中反序列化的域对象本身。关闭read-serialized将实现这一点,并在AfterCreate方法中返回反序列化的域对象。

注意:上述建议是基于您使用.NET客户端而.NET正在为您提供编译错误。 Java客户端不会发生这种情况。令人费解的是,为什么.NET交互正在这样做。

FYI众所周知,一个区域可能包含PDX实例或正在使用PDX的区域中的域对象。这是为了提高性能。主节点可以以非PDX形式存储域对象,以避免序列化成本,但是辅助服务器上的PDX版本。这就是客户在操作实例之前总是需要检查类型的原因。

是的,我知道字符串是你的关键,但是你是否使用Native Client是我的关键问题。小写的“s”是一个线索。

答案 1 :(得分:0)

programming your application to use PDX instances个区域可以包含对象或PDX包装的对象。对于前者,通过object进行投射是有效的。所以我可以写:

object o = ev.NewValue;
MyObject m = (MyObject)o;
string s = m.MyString;
decimal d = m.MyDecimal;