[ 
https://issues.apache.org/jira/browse/IGNITE-12625?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Aleksey Plekhanov updated IGNITE-12625:
---------------------------------------
    Description: 
For each thin client cache operation marshaling/unmarshaling of objects 
performed twice. For example, cache "put" operation marshal object on the 
client-side, then unmarshal object (with keep binaries) on the server-side and 
marshal it again before putting it to the cache. It causes some undesirable 
effects. For example, references to the same binary object in a collection ( 
{{new ArrayList(Arrays.asList(person, person))}} ) deserialized as different 
objects.

Reproducer:
{code:java}
try (IgniteClient client = startClient()) {
    ClientCache<Integer, Object[]> cache = 
client.getOrCreateCache(DEFAULT_CACHE_NAME);
    Person person = new Person(0, "name");
    cache.put(0, new Object[] {person, person} );
    Object[] res = cache.get(0);
    assertTrue(res[0] == res[1]);
}{code}
Also, we need to unwrap binaries recursively since all objects inside 
collections, arrays and maps become binary objects after 
marshaling/unmarshalling (see IGNITE-12468)

Also, we don't know do we really need to deserialize binary objects. If object 
was originally binary there is no evidence of this after 
marshaling/unmarshaling on server-side. This leads to problems when a binary 
object was created for unknown class.

Reproducer:
{code:java}
cache.put(0, client.binary().builder("TestType").setField("test", 
"val").build())
cache.get(0){code}
Will throw exception:
{noformat}
class org.apache.ignite.binary.BinaryInvalidTypeException: TestType
    at 
org.apache.ignite.internal.binary.BinaryContext.descriptorForTypeId(BinaryContext.java:762)
    at 
org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize0(BinaryReaderExImpl.java:1757)
    at 
org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize(BinaryReaderExImpl.java:1716)
    at 
org.apache.ignite.internal.binary.GridBinaryMarshaller.deserialize(GridBinaryMarshaller.java:319)
    at 
org.apache.ignite.internal.client.thin.ClientBinaryMarshaller.deserialize(ClientBinaryMarshaller.java:74)
    at 
org.apache.ignite.internal.client.thin.ClientUtils.unwrapBinary(ClientUtils.java:558)
    at 
org.apache.ignite.internal.client.thin.ClientUtils.readObject(ClientUtils.java:547){noformat}
To avoid double marshaling we could pass byte array from request content to 
cache directly (for example using {{CacheObject}}), but we don't have object 
size in thin client protocol, so in any case, we need to traverse the objects. 
Also, we don't have the ability to get {{CacheObject}} from the cache now, so 
such an approach will only work in one way, for "put" operations, but not for 
"get" operations.

  was:
For each thin client cache operation marshaling/unmarshaling of objects 
performed twice. For example, cache "put" operation marshal object on the 
client-side, then unmarshal object (with keep binaries) on the server-side and 
marshal it again before putting it to the cache. It causes some undesirable 
effects. For example, references to the same binary object in a collection ( 
{{new ArrayList(Arrays.asList(person, person))}} ) deserialized as different 
objects.

Reproducer:
{code:java}
try (IgniteClient client = startClient()) {
    ClientCache<Integer, Object[]> cache = 
client.getOrCreateCache(DEFAULT_CACHE_NAME);
    Person person = new Person(0, "name");
    cache.put(0, new Object[] {person, person} );
    Object[] res = cache.get(0);
    assertTrue(res[0] == res[1]);
}{code}
Also, we need to unwrap binaries recursively since all objects inside 
collections, arrays and maps become binary objects after 
marshaling/unmarshalling (see IGNITE-12468)

Also, we don't know do we really need to deserialize binary objects. If object 
was originally binary there is no evidence of this after 
marshaling/unmarshaling on server-side. This leads to problems when a binary 
object was created for unknown class.

Reproducer:
{code:java}
cache.put(0, client.binary().builder("TestType").setField("test", 
"val").build())
cache.get(0){code}
Will throw exception:
{noformat}
class org.apache.ignite.binary.BinaryInvalidTypeException: TestTypeclass 
org.apache.ignite.binary.BinaryInvalidTypeException: TestType
    at 
org.apache.ignite.internal.binary.BinaryContext.descriptorForTypeId(BinaryContext.java:762)
    at 
org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize0(BinaryReaderExImpl.java:1757)
    at 
org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize(BinaryReaderExImpl.java:1716)
    at 
org.apache.ignite.internal.binary.GridBinaryMarshaller.deserialize(GridBinaryMarshaller.java:319)
    at 
org.apache.ignite.internal.client.thin.ClientBinaryMarshaller.deserialize(ClientBinaryMarshaller.java:74)
    at 
org.apache.ignite.internal.client.thin.ClientUtils.unwrapBinary(ClientUtils.java:558)
    at 
org.apache.ignite.internal.client.thin.ClientUtils.readObject(ClientUtils.java:547){noformat}
To avoid double marshaling we could pass byte array from request content to 
cache directly (for example using {{CacheObject}}), but we don't have object 
size in thin client protocol, so in any case, we need to traverse the objects. 
Also, we don't have the ability to get {{CacheObject}} from the cache now, so 
such an approach will only work in one way, for "put" operations, but not for 
"get" operations.


> Thin client: Marshaling/unmarshaling of objects performed twice
> ---------------------------------------------------------------
>
>                 Key: IGNITE-12625
>                 URL: https://issues.apache.org/jira/browse/IGNITE-12625
>             Project: Ignite
>          Issue Type: Bug
>          Components: binary, thin client
>            Reporter: Aleksey Plekhanov
>            Assignee: Aleksey Plekhanov
>            Priority: Major
>
> For each thin client cache operation marshaling/unmarshaling of objects 
> performed twice. For example, cache "put" operation marshal object on the 
> client-side, then unmarshal object (with keep binaries) on the server-side 
> and marshal it again before putting it to the cache. It causes some 
> undesirable effects. For example, references to the same binary object in a 
> collection ( {{new ArrayList(Arrays.asList(person, person))}} ) deserialized 
> as different objects.
> Reproducer:
> {code:java}
> try (IgniteClient client = startClient()) {
>     ClientCache<Integer, Object[]> cache = 
> client.getOrCreateCache(DEFAULT_CACHE_NAME);
>     Person person = new Person(0, "name");
>     cache.put(0, new Object[] {person, person} );
>     Object[] res = cache.get(0);
>     assertTrue(res[0] == res[1]);
> }{code}
> Also, we need to unwrap binaries recursively since all objects inside 
> collections, arrays and maps become binary objects after 
> marshaling/unmarshalling (see IGNITE-12468)
> Also, we don't know do we really need to deserialize binary objects. If 
> object was originally binary there is no evidence of this after 
> marshaling/unmarshaling on server-side. This leads to problems when a binary 
> object was created for unknown class.
> Reproducer:
> {code:java}
> cache.put(0, client.binary().builder("TestType").setField("test", 
> "val").build())
> cache.get(0){code}
> Will throw exception:
> {noformat}
> class org.apache.ignite.binary.BinaryInvalidTypeException: TestType
>     at 
> org.apache.ignite.internal.binary.BinaryContext.descriptorForTypeId(BinaryContext.java:762)
>     at 
> org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize0(BinaryReaderExImpl.java:1757)
>     at 
> org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize(BinaryReaderExImpl.java:1716)
>     at 
> org.apache.ignite.internal.binary.GridBinaryMarshaller.deserialize(GridBinaryMarshaller.java:319)
>     at 
> org.apache.ignite.internal.client.thin.ClientBinaryMarshaller.deserialize(ClientBinaryMarshaller.java:74)
>     at 
> org.apache.ignite.internal.client.thin.ClientUtils.unwrapBinary(ClientUtils.java:558)
>     at 
> org.apache.ignite.internal.client.thin.ClientUtils.readObject(ClientUtils.java:547){noformat}
> To avoid double marshaling we could pass byte array from request content to 
> cache directly (for example using {{CacheObject}}), but we don't have object 
> size in thin client protocol, so in any case, we need to traverse the 
> objects. Also, we don't have the ability to get {{CacheObject}} from the 
> cache now, so such an approach will only work in one way, for "put" 
> operations, but not for "get" operations.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to