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 649e7742d2771..4c5c1226f8af8 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 PlatformBinaryProcessor(PlatformContext platformCtx) { 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 0000000000000..39390e859492d --- /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 0000000000000..a1aa9b77f237e --- /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 0000000000000..03d99a6e6ad32 --- /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 0000000000000..26c578709bd0c --- /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 c781be8a1fdc0..4e04131fb212f 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.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.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. @@ -414,6 +418,82 @@ public BinaryObject testBinaryObject(BinaryObject o) { return o.toBuilder().setField("field", 15).build(); } + /** */ + 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 iter = deps.iterator(); + + assertEquals("HR", iter.next().getName()); + assertEquals("IT", iter.next().getName()); + + Collection 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 { 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 0000000000000..09502918251b7 --- /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 b28268d01a47c..19dcc801658d0 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 @@ + + @@ -397,6 +399,7 @@ + @@ -617,4 +620,4 @@ --> - \ No newline at end of file + 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 98c69f607d20a..e152c6b94c5c3 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 @@ public void PutBinaryTypes(ICollection types) } /** */ - 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 ccceaf7937bb4..8c9e6b6755b3e 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; /// /// Java service proxy interface. @@ -163,6 +165,18 @@ public interface IJavaService /** */ IBinaryObject testBinaryObject(IBinaryObject x); + /** */ + Address testAddress(Address addr); + + /** */ + Employee[] testEmployees(Employee[] emps); + + /** */ + ICollection testDepartments(ICollection deps); + + /** */ + IDictionary testMap(IDictionary 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 0000000000000..3276b838500ba --- /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; + + /// + /// Explicit service proxy over dynamic variable. + /// + public class JavaServiceDynamicProxy : IJavaService + { + /** */ + private readonly dynamic _svc; + + /** */ + public JavaServiceDynamicProxy(dynamic svc) + { + _svc = svc; + } + + /** */ + public bool isCancelled() + { + return _svc.isCancelled(); + } + + /** */ + public bool isInitialized() + { + return _svc.isInitialized(); + } + + /** */ + public bool isExecuted() + { + return _svc.isExecuted(); + } + + /** */ + public byte test(byte x) + { + return _svc.test(x); + } + + /** */ + public short test(short x) + { + return _svc.test(x); + } + + /** */ + public int test(int x) + { + return _svc.test(x); + } + + /** */ + public long test(long x) + { + return _svc.test(x); + } + + /** */ + public float test(float x) + { + return _svc.test(x); + } + + /** */ + public double test(double x) + { + return _svc.test(x); + } + + /** */ + public char test(char x) + { + return _svc.test(x); + } + + /** */ + public string test(string x) + { + return _svc.test(x); + } + + /** */ + public bool test(bool x) + { + return _svc.test(x); + } + + /** */ + public DateTime test(DateTime x) + { + return _svc.test(x); + } + + /** */ + public Guid test(Guid x) + { + return _svc.test(x); + } + + /** */ + public byte? testWrapper(byte? x) + { + return _svc.testWrapper(x); + } + + /** */ + public short? testWrapper(short? x) + { + return _svc.testWrapper(x); + } + + /** */ + public int? testWrapper(int? x) + { + return _svc.testWrapper(x); + } + + /** */ + public long? testWrapper(long? x) + { + return _svc.testWrapper(x); + } + + /** */ + public float? testWrapper(float? x) + { + return _svc.testWrapper(x); + } + + /** */ + public double? testWrapper(double? x) + { + return _svc.testWrapper(x); + } + + /** */ + public char? testWrapper(char? x) + { + return _svc.testWrapper(x); + } + + /** */ + public bool? testWrapper(bool? x) + { + return _svc.testWrapper(x); + } + + /** */ + public byte[] testArray(byte[] x) + { + return _svc.testArray(x); + } + + /** */ + public short[] testArray(short[] x) + { + return _svc.testArray(x); + } + + /** */ + public int[] testArray(int[] x) + { + return _svc.testArray(x); + } + + /** */ + public long[] testArray(long[] x) + { + return _svc.testArray(x); + } + + /** */ + public float[] testArray(float[] x) + { + return _svc.testArray(x); + } + + /** */ + public double[] testArray(double[] x) + { + return _svc.testArray(x); + } + + /** */ + public char[] testArray(char[] x) + { + return _svc.testArray(x); + } + + /** */ + public string[] testArray(string[] x) + { + return _svc.testArray(x); + } + + /** */ + public bool[] testArray(bool[] x) + { + return _svc.testArray(x); + } + + /** */ + public DateTime?[] testArray(DateTime?[] x) + { + return _svc.testArray(x); + } + + /** */ + public Guid?[] testArray(Guid?[] x) + { + return _svc.testArray(x); + } + + /** */ + public int test(int x, string y) + { + return _svc.test(x, y); + } + + /** */ + public int test(string x, int y) + { + return _svc.test(x, y); + } + + /** */ + public int? testNull(int? x) + { + return _svc.testNull(x); + } + + /** */ + public DateTime? testNullTimestamp(DateTime? x) + { + return _svc.testNullTimestamp(x); + } + + /** */ + public Guid? testNullUUID(Guid? x) + { + return _svc.testNullUUID(x); + } + + /** */ + public int testParams(params object[] args) + { + return _svc.testParams(args); + } + + /** */ + public ServicesTest.PlatformComputeBinarizable testBinarizable(ServicesTest.PlatformComputeBinarizable x) + { + return _svc.testBinarizable(x); + } + + /** */ + public object[] testBinarizableArrayOfObjects(object[] x) + { + return _svc.testBinarizableArrayOfObjects(x); + } + + /** */ + public IBinaryObject[] testBinaryObjectArray(IBinaryObject[] x) + { + return _svc.testBinaryObjectArray(x); + } + + /** */ + public ServicesTest.PlatformComputeBinarizable[] testBinarizableArray(ServicesTest.PlatformComputeBinarizable[] x) + { + return _svc.testBinarizableArray(x); + } + + /** */ + public ICollection testBinarizableCollection(ICollection x) + { + return _svc.testBinarizableCollection(x); + } + + /** */ + public IBinaryObject testBinaryObject(IBinaryObject x) + { + return _svc.testBinaryObject(x); + } + + /** */ + public Address testAddress(Address addr) + { + return _svc.testAddress(addr); + } + + /** */ + public Employee[] testEmployees(Employee[] emps) + { + return _svc.testEmployees(emps); + } + + /** */ + public ICollection testDepartments(ICollection deps) + { + return _svc.testDepartments(deps); + } + + /** */ + public IDictionary testMap(IDictionary dict) + { + return _svc.testMap(dict); + } + + /** */ + 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 0000000000000..584511cd06528 --- /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 +{ + /// + /// A class is a clone of Java class Address with the same namespace. + /// + public class Address + { + /** */ + public string Zip { get; set; } + + /** */ + public string Addr { get; set; } + } + + /// + /// A class is a clone of Java class Department with the same namespace. + /// + public class Department + { + /** */ + public string Name { get; set; } + } + + /// + /// A class is a clone of Java class Employee with the same namespace. + /// + public class Employee + { + /** */ + public string Fio { get; set; } + + /** */ + public long Salary { get; set; } + } + + /// + /// A class is a clone of Java class Employee with the same namespace. + /// + 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(); + } + } + + /// + /// A class is a clone of Java class Employee with the same namespace. + /// + 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 0000000000000..c99a19870604b --- /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; + + /// + /// Tests checks ability to execute service method without explicit registration of parameter type. + /// + public class ServicesTypeAutoResolveTest + { + /** */ + private IIgnite _grid1; + + [TestFixtureTearDown] + public void FixtureTearDown() + { + StopGrids(); + } + + /// + /// Executes before each test. + /// + [SetUp] + public void SetUp() + { + StartGrids(); + } + + /// + /// Executes after each test. + /// + [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 + } + } + + /// + /// Tests Java service invocation with dynamic proxy. + /// Types should be resolved implicitly. + /// + [Test] + public void TestCallJavaServiceDynamicProxy() + { + // Deploy Java service + var javaSvcName = TestUtils.DeployJavaService(_grid1); + var svc = _grid1.GetServices().GetDynamicServiceProxy(javaSvcName, true); + + doTestService(new JavaServiceDynamicProxy(svc)); + } + + /// + /// Tests Java service invocation. + /// Types should be resolved implicitly. + /// + [Test] + public void TestCallJavaService() + { + // Deploy Java service + var javaSvcName = TestUtils.DeployJavaService(_grid1); + + var svc = _grid1.GetServices().GetServiceProxy(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().Select(d => d.Name).ToArray()[0]); + + _grid1.GetServices().Cancel(javaSvcName); + } + + /// + /// Tests java service instance. + /// + 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(); + + 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); + } + + /// + /// Starts the grids. + /// + private void StartGrids() + { + if (_grid1 != null) + return; + + var path = Path.Combine("Config", "Compute", "compute-grid"); + _grid1 = Ignition.Start(GetConfiguration(path + "1.xml")); + } + + /// + /// Stops the grids. + /// + private void StopGrids() + { + _grid1 = null; + + Ignition.StopAll(true); + } + + /// + /// Gets the Ignite configuration. + /// + 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 b62977a53a02a..66380d67ccf2a 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 @@ public void PutBinaryTypes(ICollection types) /// /// The identifier. /// The type name. + /// True if should register type both for dotnet and java platforms. /// True if registration succeeded; otherwise, false. - 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 @@ public bool RegisterType(int id, string typeName) { 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 8ef84c1fe82f3..a45f95f66dc9e 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 /// 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 @@ public void PutBinaryTypes(ICollection types) } /** */ - 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; } /** */ 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 fed78c3f4eb9f..6dfefb1354b95 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 @@ internal interface IBinaryProcessor /// /// The identifier. /// The type name. + /// True if should register type both for dotnet and java platforms. /// True if registration succeeded; otherwise, false. - bool RegisterType(int id, string typeName); + bool RegisterType(int id, string typeName, bool registerSameJavaType); /// /// 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 523a3fb246fb9..4a61cf5eda8d5 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 /// internal class Marshaller { + /** Register same java type flag. */ + public static readonly ThreadLocal RegisterSameJavaType = new ThreadLocal(() => false); + /** Binary configuration. */ private readonly BinaryConfiguration _cfg; @@ -562,7 +566,7 @@ private BinaryFullTypeDescriptor RegisterType(Type type, BinaryFullTypeDescripto 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 37453705d145f..66998cbb114fa 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 @@ public static void WriteProxyMethod(BinaryWriter writer, string methodName, Meth { 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); } /// @@ -265,6 +275,9 @@ private static Action GetPlatformArgWriter(Type paramType, 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);