This is an automated email from the ASF dual-hosted git repository.
timoninmaxim 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 62b38863b7f IGNITE-27865 Use ClassLoader for deserializing users' Pojo
in collections (#12745)
62b38863b7f is described below
commit 62b38863b7f808620aec92a310cf67b25ecd9bfe
Author: Maksim Timonin <[email protected]>
AuthorDate: Wed Feb 18 23:14:52 2026 +0300
IGNITE-27865 Use ClassLoader for deserializing users' Pojo in collections
(#12745)
---
.../processors/cache/CacheObjectUtils.java | 30 +++--
.../p2p/startcache/PojoCollectionComputeTest.java | 127 +++++++++++++++++++++
.../cache/ComputeCacheCollectionsP2PTest.java | 95 +++++++++++++++
.../IgniteCacheWithIndexingTestSuite.java | 2 +
4 files changed, 245 insertions(+), 9 deletions(-)
diff --git
a/modules/binary/api/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectUtils.java
b/modules/binary/api/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectUtils.java
index e33e2c12f53..1020783d950 100644
---
a/modules/binary/api/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectUtils.java
+++
b/modules/binary/api/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectUtils.java
@@ -96,16 +96,22 @@ public class CacheObjectUtils {
* @param col Collection to unwrap.
* @param keepBinary Keep binary flag.
* @param cpy Copy flag.
+ * @param ldr Optional classloader.
* @return Unwrapped collection.
*/
- private static Collection<Object>
unwrapKnownCollection(CacheObjectValueContext ctx, Collection<?> col,
- boolean keepBinary, boolean cpy) {
+ private static Collection<Object> unwrapKnownCollection(
+ CacheObjectValueContext ctx,
+ Collection<?> col,
+ boolean keepBinary,
+ boolean cpy,
+ @Nullable ClassLoader ldr
+ ) {
Collection<Object> col0 = BinaryUtils.newKnownCollection(col);
assert col0 != null;
for (Object obj : col)
- col0.add(unwrapBinary(ctx, obj, keepBinary, cpy, null));
+ col0.add(unwrapBinary(ctx, obj, keepBinary, cpy, ldr));
return (col0 instanceof MutableSingletonList) ?
CommonUtils.convertToSingletonList(col0) : col0;
}
@@ -115,10 +121,16 @@ public class CacheObjectUtils {
*
* @param map Map to unwrap.
* @param keepBinary Keep binary flag.
+ * @param ldr Optional class loader.
* @return Unwrapped collection.
*/
- private static Map<Object, Object>
unwrapBinariesIfNeeded(CacheObjectValueContext ctx, Map<Object, Object> map,
- boolean keepBinary, boolean cpy) {
+ private static Map<Object, Object> unwrapBinariesIfNeeded(
+ CacheObjectValueContext ctx,
+ Map<Object, Object> map,
+ boolean keepBinary,
+ boolean cpy,
+ @Nullable ClassLoader ldr
+ ) {
if (keepBinary)
return map;
@@ -127,8 +139,8 @@ public class CacheObjectUtils {
for (Map.Entry<Object, Object> e : map.entrySet())
// TODO why don't we use keepBinary parameter here?
map0.put(
- unwrapBinary(ctx, e.getKey(), false, cpy, null),
- unwrapBinary(ctx, e.getValue(), false, cpy, null));
+ unwrapBinary(ctx, e.getKey(), false, cpy, ldr),
+ unwrapBinary(ctx, e.getValue(), false, cpy, ldr));
return map0;
}
@@ -204,9 +216,9 @@ public class CacheObjectUtils {
}
if (BinaryUtils.knownCollection(o))
- return unwrapKnownCollection(ctx, (Collection<Object>)o,
keepBinary, cpy);
+ return unwrapKnownCollection(ctx, (Collection<Object>)o,
keepBinary, cpy, ldr);
else if (BinaryUtils.knownMap(o))
- return unwrapBinariesIfNeeded(ctx, (Map<Object, Object>)o,
keepBinary, cpy);
+ return unwrapBinariesIfNeeded(ctx, (Map<Object, Object>)o,
keepBinary, cpy, ldr);
else if (o instanceof Object[] && !BinaryUtils.useBinaryArrays())
return unwrapBinariesInArrayIfNeeded(ctx, (Object[])o, keepBinary,
cpy);
else if (BinaryUtils.isBinaryArray(o) && !keepBinary)
diff --git
a/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/startcache/PojoCollectionComputeTest.java
b/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/startcache/PojoCollectionComputeTest.java
new file mode 100644
index 00000000000..a5b7d8c85de
--- /dev/null
+++
b/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/startcache/PojoCollectionComputeTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.tests.p2p.startcache;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.lang.IgniteRunnable;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.tests.p2p.cache.Person;
+
+import static org.junit.Assert.assertEquals;
+
+/** */
+public class PojoCollectionComputeTest {
+ /** */
+ private void run(String taskName) {
+ IgniteConfiguration cfg = new IgniteConfiguration()
+ .setPeerClassLoadingEnabled(true)
+ .setClientMode(true)
+ .setLocalHost("127.0.0.1")
+ .setDiscoverySpi(new TcpDiscoverySpi()
+ .setIpFinder(new TcpDiscoveryVmIpFinder()
+
.setAddresses(Collections.singletonList("127.0.0.1:47500..47509"))));
+
+ try (Ignite ignite = Ignition.start(cfg)) {
+ IgniteRunnable task;
+
+ if (PojoArrayTask.class.getSimpleName().equals(taskName))
+ task = new PojoArrayTask();
+ else if (PojoListTask.class.getSimpleName().equals(taskName))
+ task = new PojoListTask();
+ else
+ task = new PojoMapTask();
+
+ ignite.compute().run(task);
+ }
+ }
+
+ /** */
+ private static class PojoArrayTask implements IgniteRunnable {
+ /** */
+ @IgniteInstanceResource
+ private transient Ignite ignite;
+
+ /** */
+ @Override public void run() {
+ IgniteCache<Integer, Object[]> cache =
ignite.getOrCreateCache("personArrayCache");
+
+ Object[] objs = new Object[1];
+ objs[0] = new Person("name0");
+
+ cache.put(0, objs);
+
+ Object[] get = cache.get(0);
+ assertEquals(objs[0], get[0]);
+ }
+ }
+
+ /** */
+ private static class PojoListTask implements IgniteRunnable {
+ /** */
+ @IgniteInstanceResource
+ private transient Ignite ignite;
+
+ /** */
+ @Override public void run() {
+ IgniteCache<Integer, List<Person>> personListCache =
ignite.getOrCreateCache("personListCache");
+
+ List<Person> persons = new ArrayList<>();
+ persons.add(new Person("name0"));
+
+ personListCache.put(0, persons);
+
+ List<Person> get = personListCache.get(0);
+ assertEquals(persons.get(0), get.get(0));
+ }
+ }
+
+ /** */
+ private static class PojoMapTask implements IgniteRunnable {
+ /** */
+ @IgniteInstanceResource
+ private transient Ignite ignite;
+
+ /** */
+ @Override public void run() {
+ IgniteCache<Person, Map<Person, Person>> personMapCache =
ignite.getOrCreateCache("personMapCache");
+
+ Map<Person, Person> persons = new HashMap<>();
+ persons.put(new Person("nameValKey"), new Person("nameValVal"));
+
+ personMapCache.put(new Person("nameKey"), persons);
+
+ Map<Person, Person> get = personMapCache.get(new
Person("nameKey"));
+ assertEquals(persons, get);
+ }
+ }
+
+ /** */
+ public static void main(String[] args) {
+ new PojoCollectionComputeTest().run(args[0]);
+ }
+}
diff --git
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/ComputeCacheCollectionsP2PTest.java
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/ComputeCacheCollectionsP2PTest.java
new file mode 100644
index 00000000000..4a8e6cba089
--- /dev/null
+++
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/ComputeCacheCollectionsP2PTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.internal.processors.cache;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.GridJavaProcess;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.junits.WithSystemProperty;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+import static
org.apache.ignite.IgniteCommonsSystemProperties.IGNITE_USE_BINARY_ARRAYS;
+
+/** */
+public class ComputeCacheCollectionsP2PTest extends GridCommonAbstractTest {
+ /** */
+ private static final String CLIENT_CLS_NAME =
+ "org.apache.ignite.tests.p2p.startcache.PojoCollectionComputeTest";
+
+ /** */
+ @Test
+ @WithSystemProperty(key = IGNITE_USE_BINARY_ARRAYS, value = "true")
+ public void testBinaryArray() throws Exception {
+ runTest("PojoArrayTask");
+ }
+
+ /** */
+ @Test
+ public void testArrayList() throws Exception {
+ runTest("PojoListTask");
+ }
+
+ /** */
+ @Test
+ public void testHashMap() throws Exception {
+ runTest("PojoMapTask");
+ }
+
+ /** */
+ private void runTest(String taskName) throws Exception {
+ try (Ignite ignore = Ignition.start(createConfiguration())) {
+ Collection<String> jvmArgs = Arrays.asList("-ea",
"-DIGNITE_QUIET=false");
+ String cp = U.getIgniteHome() +
"/modules/extdata/p2p/target/classes/";
+
+ GridJavaProcess clientNode = GridJavaProcess.exec(
+ CLIENT_CLS_NAME,
+ taskName,
+ log,
+ null,
+ null,
+ null,
+ jvmArgs,
+ cp
+ );
+
+ int exitCode = clientNode.getProcess().waitFor();
+
+ assertEquals("Unexpected exit code", 0, exitCode);
+ }
+ }
+
+ /** */
+ private IgniteConfiguration createConfiguration() {
+ return new IgniteConfiguration()
+ .setPeerClassLoadingEnabled(true)
+ .setLocalHost("127.0.0.1")
+ .setDiscoverySpi(new TcpDiscoverySpi()
+ .setIpFinder(
+ new TcpDiscoveryVmIpFinder()
+
.setAddresses(Collections.singletonList("127.0.0.1:47500..47509"))
+ ));
+ }
+}
diff --git
a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
index 9b8c26ab6b2..2e78be26fda 100644
---
a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
+++
b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
@@ -33,6 +33,7 @@ import
org.apache.ignite.internal.processors.cache.CacheRegisterMetadataLocallyT
import
org.apache.ignite.internal.processors.cache.ClientReconnectAfterClusterRestartTest;
import
org.apache.ignite.internal.processors.cache.ClusterReadOnlyModeDoesNotBreakSqlSelectTest;
import org.apache.ignite.internal.processors.cache.ClusterReadOnlyModeSqlTest;
+import
org.apache.ignite.internal.processors.cache.ComputeCacheCollectionsP2PTest;
import
org.apache.ignite.internal.processors.cache.EnumClassImplementingIndexedInterfaceTest;
import org.apache.ignite.internal.processors.cache.FieldsPrecisionTest;
import org.apache.ignite.internal.processors.cache.GridCacheOffHeapSelfTest;
@@ -105,6 +106,7 @@ import org.junit.runners.Suite;
ClusterReadOnlyModeSqlTest.class,
GridCacheSqlDdlClusterReadOnlyModeTest.class,
+ ComputeCacheCollectionsP2PTest.class,
ClusterReadOnlyModeDoesNotBreakSqlSelectTest.class,