You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ni...@apache.org on 2020/12/08 17:08:00 UTC

[ignite] branch master updated: IGNITE-10075 .NET Avoid binary configurations of Ignite Java service params (#8509)

This is an automated email from the ASF dual-hosted git repository.

nizhikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 35f551c  IGNITE-10075 .NET Avoid binary configurations of Ignite Java service params (#8509)
35f551c is described below

commit 35f551c023a12b3570d65c803d10c89480f7d5e4
Author: Nikolay <ni...@apache.org>
AuthorDate: Tue Dec 8 20:07:31 2020 +0300

    IGNITE-10075 .NET Avoid binary configurations of Ignite Java service params (#8509)
---
 .../platform/binary/PlatformBinaryProcessor.java   |  11 +-
 .../java/org/apache/ignite/platform/Address.java   |  47 +++
 .../org/apache/ignite/platform/Department.java     |  34 +++
 .../java/org/apache/ignite/platform/Employee.java  |  47 +++
 .../test/java/org/apache/ignite/platform/Key.java  |  51 ++++
 .../ignite/platform/PlatformDeployServiceTask.java |  80 +++++
 .../java/org/apache/ignite/platform/Value.java     |  51 ++++
 .../Apache.Ignite.Core.Tests.csproj                |   5 +-
 .../Client/Cache/CacheTestNoMeta.cs                |   2 +-
 .../Services/IJavaService.cs                       |  14 +
 .../Services/JavaServiceDynamicProxy.cs            | 340 +++++++++++++++++++++
 .../Apache.Ignite.Core.Tests/Services/Model.cs     |  86 ++++++
 .../Services/ServiceTypeAutoResolveTest.cs         | 193 ++++++++++++
 .../Impl/Binary/BinaryProcessor.cs                 |   4 +-
 .../Impl/Binary/BinaryProcessorClient.cs           |  19 +-
 .../Impl/Binary/IBinaryProcessor.cs                |   3 +-
 .../Apache.Ignite.Core/Impl/Binary/Marshaller.cs   |   6 +-
 .../Impl/Services/ServiceProxySerializer.cs        |  51 ++--
 18 files changed, 1017 insertions(+), 27 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
index 649e774..4c5c122 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
@@ -76,10 +76,19 @@ public class PlatformBinaryProcessor extends PlatformAbstractTarget {
             case OP_REGISTER_TYPE: {
                 int typeId = reader.readInt();
                 String typeName = reader.readString();
+                boolean registerSameJavaType = reader.readBoolean();
 
-                return platformContext().kernalContext().marshallerContext()
+                int res = platformContext().kernalContext().marshallerContext()
                     .registerClassName(MarshallerPlatformIds.DOTNET_ID, typeId, typeName, false)
                     ? TRUE : FALSE;
+
+                if (registerSameJavaType && res == TRUE) {
+                    res = platformContext().kernalContext().marshallerContext()
+                        .registerClassName(MarshallerPlatformIds.JAVA_ID, typeId, typeName, false)
+                        ? TRUE : FALSE;
+                }
+
+                return res;
             }
         }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/Address.java b/modules/core/src/test/java/org/apache/ignite/platform/Address.java
new file mode 100644
index 0000000..39390e8
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/platform/Address.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.platform;
+
+/** Test value object. */
+public class Address {
+    /** */
+    private String zip;
+
+    /** */
+    private String addr;
+
+    /** */
+    public String getZip() {
+        return zip;
+    }
+
+    /** */
+    public void setZip(String zip) {
+        this.zip = zip;
+    }
+
+    /** */
+    public String getAddr() {
+        return addr;
+    }
+
+    /** */
+    public void setAddr(String addr) {
+        this.addr = addr;
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/Department.java b/modules/core/src/test/java/org/apache/ignite/platform/Department.java
new file mode 100644
index 0000000..a1aa9b7
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/platform/Department.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.platform;
+
+/** Test value object. */
+public class Department {
+    /** */
+    private String name;
+
+    /** */
+    public String getName() {
+        return name;
+    }
+
+    /** */
+    public void setName(String name) {
+        this.name = name;
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/Employee.java b/modules/core/src/test/java/org/apache/ignite/platform/Employee.java
new file mode 100644
index 0000000..03d99a6
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/platform/Employee.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.platform;
+
+/** Test value object. */
+public class Employee {
+    /** */
+    private String fio;
+
+    /** */
+    private long salary;
+
+    /** */
+    public String getFio() {
+        return fio;
+    }
+
+    /** */
+    public void setFio(String fio) {
+        this.fio = fio;
+    }
+
+    /** */
+    public long getSalary() {
+        return salary;
+    }
+
+    /** */
+    public void setSalary(long salary) {
+        this.salary = salary;
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/Key.java b/modules/core/src/test/java/org/apache/ignite/platform/Key.java
new file mode 100644
index 0000000..26c5787
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/platform/Key.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.platform;
+
+import java.util.Objects;
+
+/** Test key object. */
+public class Key {
+    /** */
+    private long id;
+
+    /** */
+    public Key(long id) {
+        this.id = id;
+    }
+
+    /** */
+    public long getId() {
+        return id;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+        Key key = (Key)o;
+        return id == key.id;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        return Objects.hash(id);
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/PlatformDeployServiceTask.java b/modules/core/src/test/java/org/apache/ignite/platform/PlatformDeployServiceTask.java
index c781be8..4e04131 100644
--- a/modules/core/src/test/java/org/apache/ignite/platform/PlatformDeployServiceTask.java
+++ b/modules/core/src/test/java/org/apache/ignite/platform/PlatformDeployServiceTask.java
@@ -21,6 +21,8 @@ import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -41,6 +43,8 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import static java.util.Calendar.JANUARY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Task that deploys a Java service.
@@ -415,6 +419,82 @@ public class PlatformDeployServiceTask extends ComputeTaskAdapter<String, Object
         }
 
         /** */
+        public Address testAddress(Address addr) {
+            if (addr == null)
+                return null;
+
+            assertEquals("000", addr.getZip());
+            assertEquals("Moscow", addr.getAddr());
+
+            addr.setZip("127000");
+            addr.setAddr("Moscow Akademika Koroleva 12");
+
+            return addr;
+        }
+
+        /** */
+        public Employee[] testEmployees(Employee[] emps) {
+            if (emps == null)
+                return null;
+
+            assertEquals(2, emps.length);
+
+            assertEquals("Sarah Connor", emps[0].getFio());
+            assertEquals(1, emps[0].getSalary());
+
+            assertEquals("John Connor", emps[1].getFio());
+            assertEquals(2, emps[1].getSalary());
+
+            Employee kyle = new Employee();
+
+            kyle.setFio("Kyle Reese");
+            kyle.setSalary(3);
+
+            return new Employee[] { kyle };
+        }
+
+        /** */
+        public Collection testDepartments(Collection deps) {
+            if (deps == null)
+                return null;
+
+            assertEquals(2, deps.size());
+
+            Iterator<Department> iter = deps.iterator();
+
+            assertEquals("HR", iter.next().getName());
+            assertEquals("IT", iter.next().getName());
+
+            Collection<Department> res = new ArrayList<>();
+
+            Department d = new Department();
+
+            d.setName("Executive");
+
+            res.add(d);
+
+            return res;
+        }
+
+        /** */
+        public Map testMap(Map map) {
+            if (map == null)
+                return null;
+
+            assertTrue(map.containsKey(new Key(1)));
+            assertTrue(map.containsKey(new Key(2)));
+
+            assertEquals("value1", ((Value)map.get(new Key(1))).getVal());
+            assertEquals("value2", ((Value)map.get(new Key(2))).getVal());
+
+            Map m = new HashMap();
+
+            m.put(new Key(3), new Value("value3"));
+
+            return m;
+        }
+
+        /** */
         public void sleep(long delayMs) {
             try {
                 U.sleep(delayMs);
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/Value.java b/modules/core/src/test/java/org/apache/ignite/platform/Value.java
new file mode 100644
index 0000000..0950291
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/platform/Value.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.platform;
+
+import java.util.Objects;
+
+/** Test value object. */
+public class Value {
+    /** */
+    private String val;
+
+    /** */
+    public Value(String val) {
+        this.val = val;
+    }
+
+    /** */
+    public String getVal() {
+        return val;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+        Value value = (Value)o;
+        return Objects.equals(val, value.val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        return Objects.hash(val);
+    }
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index b28268d..19dcc80 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -285,7 +285,9 @@
     <Compile Include="Plugin\TestIgnitePluginConfiguration.cs" />
     <Compile Include="Plugin\TestIgnitePluginException.cs" />
     <Compile Include="Plugin\TestIgnitePluginProvider.cs" />
+    <Compile Include="Services\Model.cs" />
     <Compile Include="Services\IJavaService.cs" />
+    <Compile Include="Services\JavaServiceDynamicProxy.cs" />
     <Compile Include="Ssl\SslConfigurationTest.cs" />
     <Compile Include="TaskExtensions.cs" />
     <Compile Include="TestAppConfig.cs" />
@@ -397,6 +399,7 @@
     <Compile Include="Services\ServicesTestAsync.cs" />
     <Compile Include="Services\ServiceProxyTest.cs" />
     <Compile Include="Services\ServicesAsyncWrapper.cs" />
+    <Compile Include="Services\ServiceTypeAutoResolveTest.cs" />
     <Compile Include="TestRunner.cs" />
     <Compile Include="TestUtils.cs" />
     <Compile Include="TestUtilsJni.cs" />
@@ -617,4 +620,4 @@
   <Target Name="AfterBuild">
   </Target>
   -->
-</Project>
\ No newline at end of file
+</Project>
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs
index 98c69f6..e152c6b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs
@@ -104,7 +104,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
             }
 
             /** <inheritdoc /> */
-            public bool RegisterType(int id, string typeName)
+            public bool RegisterType(int id, string typeName, bool registerSameJavaType)
             {
                 return false;
             }
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/IJavaService.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/IJavaService.cs
index ccceaf7..8c9e6b6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/IJavaService.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/IJavaService.cs
@@ -19,8 +19,10 @@ namespace Apache.Ignite.Core.Tests.Services
 {
     using System;
     using System.Collections;
+    using System.Collections.Generic;
     using System.Diagnostics.CodeAnalysis;
     using Apache.Ignite.Core.Binary;
+    using org.apache.ignite.platform;
 
     /// <summary>
     /// Java service proxy interface.
@@ -164,6 +166,18 @@ namespace Apache.Ignite.Core.Tests.Services
         IBinaryObject testBinaryObject(IBinaryObject x);
 
         /** */
+        Address testAddress(Address addr);
+
+        /** */
+        Employee[] testEmployees(Employee[] emps);
+
+        /** */
+        ICollection testDepartments(ICollection deps);
+
+        /** */
+        IDictionary testMap(IDictionary<Key, Value> dict);
+        
+        /** */
         void sleep(long delayMs);
     }
 }
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/JavaServiceDynamicProxy.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/JavaServiceDynamicProxy.cs
new file mode 100644
index 0000000..3276b83
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/JavaServiceDynamicProxy.cs
@@ -0,0 +1,340 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Tests.Services
+{
+    using System;
+    using System.Collections;
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Binary;
+    using org.apache.ignite.platform;
+
+    /// <summary>
+    /// Explicit service proxy over dynamic variable.
+    /// </summary>
+    public class JavaServiceDynamicProxy : IJavaService
+    {
+        /** */
+        private readonly dynamic _svc;
+
+        /** */
+        public JavaServiceDynamicProxy(dynamic svc)
+        {
+            _svc = svc;
+        } 
+
+        /** <inheritDoc /> */
+        public bool isCancelled()
+        {
+            return _svc.isCancelled();
+        }
+
+        /** <inheritDoc /> */
+        public bool isInitialized()
+        {
+            return _svc.isInitialized();
+        }
+
+        /** <inheritDoc /> */
+        public bool isExecuted()
+        {
+            return _svc.isExecuted();
+        }
+
+        /** <inheritDoc /> */
+        public byte test(byte x)
+        {
+            return _svc.test(x);
+        }
+
+        /** <inheritDoc /> */
+        public short test(short x)
+        {
+            return _svc.test(x);
+        }
+
+        /** <inheritDoc /> */
+        public int test(int x)
+        {
+            return _svc.test(x);
+        }
+
+        /** <inheritDoc /> */
+        public long test(long x)
+        {
+            return _svc.test(x);
+        }
+
+        /** <inheritDoc /> */
+        public float test(float x)
+        {
+            return _svc.test(x);
+        }
+
+        /** <inheritDoc /> */
+        public double test(double x)
+        {
+            return _svc.test(x);
+        }
+
+        /** <inheritDoc /> */
+        public char test(char x)
+        {
+            return _svc.test(x);
+        }
+
+        /** <inheritDoc /> */
+        public string test(string x)
+        {
+            return _svc.test(x);
+        }
+
+        /** <inheritDoc /> */
+        public bool test(bool x)
+        {
+            return _svc.test(x);
+        }
+
+        /** <inheritDoc /> */
+        public DateTime test(DateTime x)
+        {
+            return _svc.test(x);
+        }
+
+        /** <inheritDoc /> */
+        public Guid test(Guid x)
+        {
+            return _svc.test(x);
+        }
+
+        /** <inheritDoc /> */
+        public byte? testWrapper(byte? x)
+        {
+            return _svc.testWrapper(x);
+        }
+
+        /** <inheritDoc /> */
+        public short? testWrapper(short? x)
+        {
+            return _svc.testWrapper(x);
+        }
+
+        /** <inheritDoc /> */
+        public int? testWrapper(int? x)
+        {
+            return _svc.testWrapper(x);
+        }
+
+        /** <inheritDoc /> */
+        public long? testWrapper(long? x)
+        {
+            return _svc.testWrapper(x);
+        }
+
+        /** <inheritDoc /> */
+        public float? testWrapper(float? x)
+        {
+            return _svc.testWrapper(x);
+        }
+
+        /** <inheritDoc /> */
+        public double? testWrapper(double? x)
+        {
+            return _svc.testWrapper(x);
+        }
+
+        /** <inheritDoc /> */
+        public char? testWrapper(char? x)
+        {
+            return _svc.testWrapper(x);
+        }
+
+        /** <inheritDoc /> */
+        public bool? testWrapper(bool? x)
+        {
+            return _svc.testWrapper(x);
+        }
+
+        /** <inheritDoc /> */
+        public byte[] testArray(byte[] x)
+        {
+            return _svc.testArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public short[] testArray(short[] x)
+        {
+            return _svc.testArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public int[] testArray(int[] x)
+        {
+            return _svc.testArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public long[] testArray(long[] x)
+        {
+            return _svc.testArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public float[] testArray(float[] x)
+        {
+            return _svc.testArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public double[] testArray(double[] x)
+        {
+            return _svc.testArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public char[] testArray(char[] x)
+        {
+            return _svc.testArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public string[] testArray(string[] x)
+        {
+            return _svc.testArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public bool[] testArray(bool[] x)
+        {
+            return _svc.testArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public DateTime?[] testArray(DateTime?[] x)
+        {
+            return _svc.testArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public Guid?[] testArray(Guid?[] x)
+        {
+            return _svc.testArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public int test(int x, string y)
+        {
+            return _svc.test(x, y);
+        }
+
+        /** <inheritDoc /> */
+        public int test(string x, int y)
+        {
+            return _svc.test(x, y);
+        }
+
+        /** <inheritDoc /> */
+        public int? testNull(int? x)
+        {
+            return _svc.testNull(x);
+        }
+
+        /** <inheritDoc /> */
+        public DateTime? testNullTimestamp(DateTime? x)
+        {
+            return _svc.testNullTimestamp(x);
+        }
+
+        /** <inheritDoc /> */
+        public Guid? testNullUUID(Guid? x)
+        {
+            return _svc.testNullUUID(x);
+        }
+
+        /** <inheritDoc /> */
+        public int testParams(params object[] args)
+        {
+            return _svc.testParams(args);
+        }
+
+        /** <inheritDoc /> */
+        public ServicesTest.PlatformComputeBinarizable testBinarizable(ServicesTest.PlatformComputeBinarizable x)
+        {
+            return _svc.testBinarizable(x);
+        }
+
+        /** <inheritDoc /> */
+        public object[] testBinarizableArrayOfObjects(object[] x)
+        {
+            return _svc.testBinarizableArrayOfObjects(x);
+        }
+
+        /** <inheritDoc /> */
+        public IBinaryObject[] testBinaryObjectArray(IBinaryObject[] x)
+        {
+            return _svc.testBinaryObjectArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public ServicesTest.PlatformComputeBinarizable[] testBinarizableArray(ServicesTest.PlatformComputeBinarizable[] x)
+        {
+            return _svc.testBinarizableArray(x);
+        }
+
+        /** <inheritDoc /> */
+        public ICollection testBinarizableCollection(ICollection x)
+        {
+            return _svc.testBinarizableCollection(x);
+        }
+
+        /** <inheritDoc /> */
+        public IBinaryObject testBinaryObject(IBinaryObject x)
+        {
+            return _svc.testBinaryObject(x);
+        }
+
+        /** <inheritDoc /> */
+        public Address testAddress(Address addr)
+        {
+            return _svc.testAddress(addr);
+        }
+
+        /** <inheritDoc /> */
+        public Employee[] testEmployees(Employee[] emps)
+        {
+            return _svc.testEmployees(emps);
+        }
+
+        /** <inheritDoc /> */
+        public ICollection testDepartments(ICollection deps)
+        {
+            return _svc.testDepartments(deps);
+        }
+
+        /** <inheritDoc /> */
+        public IDictionary testMap(IDictionary<Key, Value> dict)
+        {
+            return _svc.testMap(dict);
+        }
+
+        /** <inheritDoc /> */
+        public void sleep(long delayMs)
+        {
+            _svc.sleep(delayMs);
+        }
+    }
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/Model.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/Model.cs
new file mode 100644
index 0000000..584511c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/Model.cs
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace org.apache.ignite.platform
+{
+    /// <summary>
+    /// A class is a clone of Java class Address with the same namespace.
+    /// </summary>
+    public class Address
+    {
+        /** */
+        public string Zip { get; set; }
+
+        /** */
+        public string Addr { get; set; }
+    }
+    
+    /// <summary>
+    /// A class is a clone of Java class Department with the same namespace.
+    /// </summary>
+    public class Department
+    {
+        /** */
+        public string Name { get; set; }
+    }
+    
+    /// <summary>
+    /// A class is a clone of Java class Employee with the same namespace.
+    /// </summary>
+    public class Employee
+    {
+        /** */
+        public string Fio { get; set; }
+
+        /** */
+        public long Salary { get; set; }
+    }
+
+    /// <summary>
+    /// A class is a clone of Java class Employee with the same namespace.
+    /// </summary>
+    public class Key
+    {
+        public long Id { get; set; }
+
+        protected bool Equals(Key other)
+        {
+            return Id == other.Id;
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != this.GetType()) return false;
+            return Equals((Key) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return Id.GetHashCode();
+        }
+    }
+
+    /// <summary>
+    /// A class is a clone of Java class Employee with the same namespace.
+    /// </summary>
+    public class Value
+    {
+        public string Val { get; set; }
+    }
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceTypeAutoResolveTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceTypeAutoResolveTest.cs
new file mode 100644
index 0000000..c99a198
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceTypeAutoResolveTest.cs
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Tests.Services
+{
+    using System;
+    using System.Collections;
+    using System.Collections.Generic;
+    using System.IO;
+    using System.Linq;
+    using NUnit.Framework;
+    using org.apache.ignite.platform;
+
+    /// <summary>
+    /// Tests checks ability to execute service method without explicit registration of parameter type.
+    /// </summary>
+    public class ServicesTypeAutoResolveTest
+    {
+        /** */
+        private IIgnite _grid1;
+
+        [TestFixtureTearDown]
+        public void FixtureTearDown()
+        {
+            StopGrids();
+        }
+
+        /// <summary>
+        /// Executes before each test.
+        /// </summary>
+        [SetUp]
+        public void SetUp()
+        {
+            StartGrids();
+        }
+
+        /// <summary>
+        /// Executes after each test.
+        /// </summary>
+        [TearDown]
+        public void TearDown()
+        {
+            try
+            {
+                _grid1.GetServices();
+
+                TestUtils.AssertHandleRegistryIsEmpty(1000, _grid1);
+            }
+            catch (Exception)
+            {
+                // Restart grids to cleanup
+                StopGrids();
+
+                throw;
+            }
+            finally
+            {
+                if (TestContext.CurrentContext.Test.Name.StartsWith("TestEventTypes"))
+                    StopGrids(); // clean events for other tests
+            }
+        }
+
+        /// <summary>
+        /// Tests Java service invocation with dynamic proxy.
+        /// Types should be resolved implicitly.
+        /// </summary>
+        [Test]
+        public void TestCallJavaServiceDynamicProxy() 
+        {
+            // Deploy Java service
+            var javaSvcName = TestUtils.DeployJavaService(_grid1);
+            var svc = _grid1.GetServices().GetDynamicServiceProxy(javaSvcName, true);
+
+            doTestService(new JavaServiceDynamicProxy(svc));
+        }
+
+        /// <summary>
+        /// Tests Java service invocation.
+        /// Types should be resolved implicitly.
+        /// </summary>
+        [Test]
+        public void TestCallJavaService()
+        {
+            // Deploy Java service
+            var javaSvcName = TestUtils.DeployJavaService(_grid1);
+            
+            var svc = _grid1.GetServices().GetServiceProxy<IJavaService>(javaSvcName, false);
+
+            doTestService(svc);
+            
+            Assert.IsNull(svc.testDepartments(null));
+
+            var arr  = new[] {"HR", "IT"}.Select(x => new Department() {Name = x}).ToArray();
+
+            ICollection deps = svc.testDepartments(arr);
+
+            Assert.NotNull(deps);
+            Assert.AreEqual(1, deps.Count);
+            Assert.AreEqual("Executive", deps.OfType<Department>().Select(d => d.Name).ToArray()[0]);
+
+            _grid1.GetServices().Cancel(javaSvcName);
+        }
+
+        /// <summary>
+        /// Tests java service instance.
+        /// </summary>
+        private void doTestService(IJavaService svc)
+        {
+            Assert.IsNull(svc.testAddress(null));
+
+            Address addr = svc.testAddress(new Address {Zip = "000", Addr = "Moscow"});
+
+            Assert.AreEqual("127000", addr.Zip);
+            Assert.AreEqual("Moscow Akademika Koroleva 12", addr.Addr);
+
+            Assert.IsNull(svc.testEmployees(null));
+
+            Employee[] emps = svc.testEmployees(new[]
+            {
+                new Employee { Fio = "Sarah Connor", Salary = 1 }, 
+                new Employee { Fio = "John Connor", Salary = 2 }
+            });
+
+            Assert.NotNull(emps);
+            Assert.AreEqual(1, emps.Length);
+
+            Assert.AreEqual("Kyle Reese", emps[0].Fio);
+            Assert.AreEqual(3, emps[0].Salary);
+
+            Assert.IsNull(svc.testMap(null));
+
+            var map = new Dictionary<Key, Value>();
+
+            map.Add(new Key() {Id = 1}, new Value() {Val = "value1"});
+            map.Add(new Key() {Id = 2}, new Value() {Val = "value2"});
+
+            var res = svc.testMap(map);
+
+            Assert.NotNull(res);
+            Assert.AreEqual(1, res.Count);
+            Assert.AreEqual("value3", ((Value)res[new Key() {Id = 3}]).Val);
+        }
+
+        /// <summary>
+        /// Starts the grids.
+        /// </summary>
+        private void StartGrids()
+        {
+            if (_grid1 != null)
+                return;
+
+            var path = Path.Combine("Config", "Compute", "compute-grid");
+            _grid1 = Ignition.Start(GetConfiguration(path + "1.xml"));
+        }
+
+        /// <summary>
+        /// Stops the grids.
+        /// </summary>
+        private void StopGrids()
+        {
+            _grid1 = null;
+
+            Ignition.StopAll(true);
+        }
+
+        /// <summary>
+        /// Gets the Ignite configuration.
+        /// </summary>
+        private IgniteConfiguration GetConfiguration(string springConfigUrl)
+        {
+            springConfigUrl = Compute.ComputeApiTestFullFooter.ReplaceFooterSetting(springConfigUrl);
+
+            return new IgniteConfiguration(TestUtils.GetTestConfiguration())
+            {
+                SpringConfigUrl = springConfigUrl
+            };
+        }
+    }
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
index b62977a..66380d6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
@@ -103,8 +103,9 @@ namespace Apache.Ignite.Core.Impl.Binary
         /// </summary>
         /// <param name="id">The identifier.</param>
         /// <param name="typeName">The type name.</param>
+        /// <param name="registerSameJavaType">True if should register type both for dotnet and java platforms.</param>	
         /// <returns>True if registration succeeded; otherwise, false.</returns>
-        public bool RegisterType(int id, string typeName)
+        public bool RegisterType(int id, string typeName, bool registerSameJavaType)
         {
             Debug.Assert(typeName != null);
             Debug.Assert(id != BinaryTypeId.Unregistered);
@@ -113,6 +114,7 @@ namespace Apache.Ignite.Core.Impl.Binary
             {
                 w.WriteInt(id);
                 w.WriteString(typeName);
+                w.WriteBoolean(registerSameJavaType);
             }) == True;
         }
 
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs
index 8ef84c1..a45f95f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs
@@ -28,6 +28,9 @@ namespace Apache.Ignite.Core.Impl.Binary
     /// </summary>
     internal class BinaryProcessorClient : IBinaryProcessor
     {
+        /** Java platform id. See org.apache.ignite.internal.MarshallerPlatformIds in Java. */
+        private const byte JavaPlatformId = 0;
+
         /** Type registry platform id. See org.apache.ignite.internal.MarshallerPlatformIds in Java. */
         private const byte DotNetPlatformId = 1;
 
@@ -73,14 +76,26 @@ namespace Apache.Ignite.Core.Impl.Binary
         }
 
         /** <inheritdoc /> */
-        public bool RegisterType(int id, string typeName)
+        public bool RegisterType(int id, string typeName, bool registerSameJavaType)
         {
-            return _socket.DoOutInOp(ClientOp.BinaryTypeNamePut, ctx =>
+            var res = _socket.DoOutInOp(ClientOp.BinaryTypeNamePut, ctx =>
             {
                 ctx.Stream.WriteByte(DotNetPlatformId);
                 ctx.Stream.WriteInt(id);
                 ctx.Writer.WriteString(typeName);
             }, ctx => ctx.Stream.ReadBool());
+
+            if (registerSameJavaType && res)
+            {
+                res = _socket.DoOutInOp(ClientOp.BinaryTypeNamePut, ctx =>
+                {
+                    ctx.Stream.WriteByte(JavaPlatformId);
+                    ctx.Stream.WriteInt(id);
+                    ctx.Writer.WriteString(typeName);
+                }, ctx => ctx.Stream.ReadBool());
+            }
+
+            return res;
         }
 
         /** <inheritdoc /> */
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryProcessor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryProcessor.cs
index fed78c3..6dfefb1 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryProcessor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryProcessor.cs
@@ -47,8 +47,9 @@ namespace Apache.Ignite.Core.Impl.Binary
         /// </summary>
         /// <param name="id">The identifier.</param>
         /// <param name="typeName">The type name.</param>
+        /// <param name="registerSameJavaType">True if should register type both for dotnet and java platforms.</param>	
         /// <returns>True if registration succeeded; otherwise, false.</returns>
-        bool RegisterType(int id, string typeName);
+        bool RegisterType(int id, string typeName, bool registerSameJavaType);
 
         /// <summary>
         /// Registers the enum.
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
index 523a3fb..4a61cf5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
@@ -22,6 +22,7 @@ namespace Apache.Ignite.Core.Impl.Binary
     using System.Diagnostics;
     using System.Linq;
     using System.Runtime.Serialization;
+    using System.Threading;
     using Apache.Ignite.Core.Binary;
     using Apache.Ignite.Core.Cache.Affinity;
     using Apache.Ignite.Core.Common;
@@ -42,6 +43,9 @@ namespace Apache.Ignite.Core.Impl.Binary
     /// </summary>
     internal class Marshaller
     {
+        /** Register same java type flag. */
+        public static readonly ThreadLocal<Boolean> RegisterSameJavaType = new ThreadLocal<Boolean>(() => false);
+
         /** Binary configuration. */
         private readonly BinaryConfiguration _cfg;
 
@@ -562,7 +566,7 @@ namespace Apache.Ignite.Core.Impl.Binary
             var typeName = GetTypeName(type);
             var typeId = GetTypeId(typeName, _cfg.IdMapper);
 
-            var registered = _ignite != null && _ignite.BinaryProcessor.RegisterType(typeId, typeName);
+            var registered = _ignite != null && _ignite.BinaryProcessor.RegisterType(typeId, typeName, RegisterSameJavaType.Value);
 
             return AddUserType(type, typeId, typeName, registered, desc);
         }
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs
index 3745370..66998cb 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs
@@ -46,35 +46,45 @@ namespace Apache.Ignite.Core.Impl.Services
         {
             Debug.Assert(writer != null);
 
-            writer.WriteString(methodName);
+            Marshaller.RegisterSameJavaType.Value = true;
 
-            if (arguments != null)
+            try
             {
-                writer.WriteBoolean(true);
-                writer.WriteInt(arguments.Length);
+                writer.WriteString(methodName);
 
-                if (platformType == PlatformType.DotNet)
+                if (arguments != null)
                 {
-                    // Write as is for .NET.
-                    foreach (var arg in arguments)
+                    writer.WriteBoolean(true);
+                    writer.WriteInt(arguments.Length);
+
+                    if (platformType == PlatformType.DotNet)
                     {
-                        writer.WriteObjectDetached(arg);
+                        // Write as is for .NET.
+                        foreach (var arg in arguments)
+                        {
+                            writer.WriteObjectDetached(arg);
+                        }
                     }
-                }
-                else
-                {
-                    // Other platforms do not support Serializable, need to convert arrays and collections
-                    var mParams = method != null ? method.GetParameters() : null;
-                    Debug.Assert(mParams == null || mParams.Length == arguments.Length);
-
-                    for (var i = 0; i < arguments.Length; i++)
+                    else
                     {
-                        WriteArgForPlatforms(writer, mParams != null ? mParams[i].ParameterType : null, arguments[i]);
+                        // Other platforms do not support Serializable, need to convert arrays and collections
+                        var mParams = method != null ? method.GetParameters() : null;
+                        Debug.Assert(mParams == null || mParams.Length == arguments.Length);
+
+                        for (var i = 0; i < arguments.Length; i++)
+                        {
+                            WriteArgForPlatforms(writer, mParams != null ? mParams[i].ParameterType : null,
+                                arguments[i]);
+                        }
                     }
                 }
+                else
+                    writer.WriteBoolean(false);
+            }
+            finally
+            {
+                Marshaller.RegisterSameJavaType.Value = false;
             }
-            else
-                writer.WriteBoolean(false);
         }
 
         /// <summary>
@@ -265,6 +275,9 @@ namespace Apache.Ignite.Core.Impl.Services
             if (type.IsArray)
                 return (writer, o) => writer.WriteArrayInternal((Array) o);
 
+            if (arg is IDictionary)
+                return (writer, o) => writer.WriteDictionary((IDictionary) o);
+
             if (arg is ICollection)
                 return (writer, o) => writer.WriteCollection((ICollection) o);