You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@ignite.apache.org by Artem Schitow <ar...@gmail.com> on 2017/01/10 15:15:09 UTC

Re: Using object as key with BinaryMarshaller

Hi, Alisher!

I guess, it’s expected behaviour. The documentation <http://apacheignite.gridgain.org/docs/binary-marshaller> says, that “By default when an object is serialized into the binary format, Ignite captures it's hash code and stores it alongside with the binary object fields. This way a proper and consistent hash code can be provided on all nodes in a cluster for any object. For the equals comparison, Ignite by default relies on binary representation of the serialized object comparing the fields sub-array byte-by-byte.”

Look at this from the following perspective: BinaryObjects are class-independent representations, that may be accessed and modified by different Ignite clients, including Java clients without object’s real class on the classpath, or even .NET and C++ clients. If we have a .NET client, that retrieves the UserObject as a BinaryObject and modifies some field, the .NET client has no knowledge on your custom hashCode() and equals() implementation, thus the client has no way to compute the hash your way. Thus the contract states, that for BinaryObjects the “normal” Java hashCode() and equals() logic is omitted in favour of implementation-independent logic, that use binary representation only.

You may override this behaviour with one you desire by writing a bit of custom code for your Ignite installation and deploying this customisation onto your cluster (“If the default approach is not suitable, then you can customize it by implementing BinaryIdentityResolver or using alternate BinaryFieldIdentityResolver implementation.”).

The other way for Ignite could be automatic P2P Deployment of entity classes to the servers and utilising their hashCode() and equals() methods, but that would probably have a lot of caveats (say, dependencies) and would degrade performance significantly due to additional server-side deserialisation and serialisation required to apply Java methods on entities instances.

> On 10 Jan 2017, at 16:30, Alisher Alimov <al...@gmail.com> wrote:
> 
> Hello!
> 
> I have a little problem when try to use object as key with BinaryMarshaller. Bug occurred only with BinaryMarshaller, on JdkMarshaller all is working fine as expected.
> 
> Here is example:
> 
> UserObject class used as key that override hashCode and equals methods but seems that BinaryMarshaller using all fields from key object for building hashCode
> 
> private static class UserObject implements Serializable {
>     private final Integer id;
>     private final Integer notIdField;
> 
>     UserObject(Integer id, Integer notIdField) {
>         this.id = id;
>         this.notIdField = notIdField;
>     }
> 
>     public Integer getId() {
>         return id;
>     }
> 
>     public Integer getNotIdField() {
>         return notIdField;
>     }
> 
>     @Override
>     public int hashCode() {
>         return Objects.hash(id);
>     }
> 
>     @Override
>     public boolean equals(Object obj) {
>         if (obj instanceof UserObject) {
>             return Objects.equals(((UserObject) obj).getId(), getId());
>         }
> 
>         return false;
>     }
> }
> 
> 
> public void testObjectKey() throws Exception {
>     IgniteCache<UserObject, Integer> cache = ignite.getOrCreateCache("test");
> 
> 
>     for (int i = 0; i < 10; i++) {
>         cache.put(new UserObject(0, i), i);
> 
>         Assert.assertEquals(1, cache.size(CachePeekMode.PRIMARY));
>     }
> 
>  }
> 
> Is it expected behaviour or bug?
> 
> With best regards
> Alisher Alimov
> alimovalisher@gmail.com <ma...@gmail.com>
> 
> 
> 
>