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

alexpl 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 c8a6958d49d IGNITE-27938 Java thin: Add ability to configure cache 
partitions count - Fixes #12783.
c8a6958d49d is described below

commit c8a6958d49d18bf8d48d163171ad107a2c06088e
Author: Aleksey Plekhanov <[email protected]>
AuthorDate: Fri Mar 27 10:10:16 2026 +0300

    IGNITE-27938 Java thin: Add ability to configure cache partitions count - 
Fixes #12783.
    
    Signed-off-by: Aleksey Plekhanov <[email protected]>
---
 .../ignite/client/ClientAffinityConfiguration.java |  88 ++++++++++++
 .../ignite/client/ClientCacheConfiguration.java    |  25 ++++
 .../ignite/internal/client/thin/ClientUtils.java   |  29 +++-
 .../client/thin/ProtocolBitmaskFeature.java        |   5 +-
 .../internal/processors/cache/GridCacheUtils.java  |  36 +++--
 .../platform/client/ClientBitmaskFeature.java      |   5 +-
 .../cache/ClientCacheConfigurationSerializer.java  |  21 +++
 .../client/thin/CacheConfigurationTest.java        | 159 +++++++++++++++++++++
 .../internal/client/thin/FunctionalTest.java       |  93 ------------
 .../org/apache/ignite/client/ClientTestSuite.java  |   2 +
 10 files changed, 358 insertions(+), 105 deletions(-)

diff --git 
a/modules/core/src/main/java/org/apache/ignite/client/ClientAffinityConfiguration.java
 
b/modules/core/src/main/java/org/apache/ignite/client/ClientAffinityConfiguration.java
new file mode 100644
index 00000000000..1e5732a293b
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/client/ClientAffinityConfiguration.java
@@ -0,0 +1,88 @@
+/*
+ * 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.client;
+
+import java.io.Serializable;
+import org.apache.ignite.internal.util.typedef.internal.A;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/** Affinity configuration for default (rendezvous) affinity function. */
+public final class ClientAffinityConfiguration implements Serializable {
+    /** Serial version uid. */
+    private static final long serialVersionUID = 0L;
+
+    /** @serial Total number of partitions. */
+    private int partitions = -1;
+
+    /** @serial Flag to exclude same-host-neighbors from being backups of each 
other. */
+    private boolean excludeNeighbors;
+
+    /** Default constructor. */
+    public ClientAffinityConfiguration() {
+        // No-op.
+    }
+
+    /**
+     * Gets total number of partitions.
+     *
+     * @return Total number of partitions.
+     */
+    public int getPartitions() {
+        return partitions;
+    }
+
+    /**
+     * Sets total number of partitions.
+     *
+     * @param partitions Total number of partitions.
+     * @return {@code this} for chaining.
+     */
+    public ClientAffinityConfiguration setPartitions(int partitions) {
+        A.ensure(partitions > 0, "Partitions count must be positive");
+
+        this.partitions = partitions;
+
+        return this;
+    }
+
+    /**
+     * Checks flag to exclude same-host-neighbors from being backups of each 
other (default is {@code false}).
+     *
+     * @return {@code True} if nodes residing on the same host may not act as 
backups of each other.
+     */
+    public boolean isExcludeNeighbors() {
+        return excludeNeighbors;
+    }
+
+    /**
+     * Sets flag to exclude same-host-neighbors from being backups of each 
other (default is {@code false}).
+     *
+     * @param excludeNeighbors {@code True} if nodes residing on the same host 
may not act as backups of each other.
+     * @return {@code this} for chaining.
+     */
+    public ClientAffinityConfiguration setExcludeNeighbors(boolean 
excludeNeighbors) {
+        this.excludeNeighbors = excludeNeighbors;
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(ClientAffinityConfiguration.class, this);
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/client/ClientCacheConfiguration.java
 
b/modules/core/src/main/java/org/apache/ignite/client/ClientCacheConfiguration.java
index 82bc982a322..693832b30ad 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/client/ClientCacheConfiguration.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/client/ClientCacheConfiguration.java
@@ -131,6 +131,9 @@ public final class ClientCacheConfiguration implements 
Serializable {
     /** @serial Expiry policy. */
     private ExpiryPolicy expiryPlc;
 
+    /** @serial Affinity configuration. */
+    private ClientAffinityConfiguration affCfg;
+
     /**
      * Root directories where partition files are stored.
      * @see DataStorageConfiguration#setStoragePath(String)
@@ -193,6 +196,7 @@ public final class ClientCacheConfiguration implements 
Serializable {
         writeSynchronizationMode = ccfg.getWriteSynchronizationMode();
         storagePaths = ccfg.getStoragePaths();
         idxPath = ccfg.getIndexPath();
+        affCfg = ccfg.getAffinityConfiguration();
     }
 
     /**
@@ -793,6 +797,27 @@ public final class ClientCacheConfiguration implements 
Serializable {
         return this;
     }
 
+    /**
+     * Gets affinity configuration.
+     *
+     * @return Affinity configuration.
+     */
+    public ClientAffinityConfiguration getAffinityConfiguration() {
+        return affCfg;
+    }
+
+    /**
+     * Sets affinity configuration.
+     *
+     * @param affCfg Affinity configuration.
+     * @return {@code this} for chaining.
+     */
+    public ClientCacheConfiguration 
setAffinityConfiguration(ClientAffinityConfiguration affCfg) {
+        this.affCfg = affCfg;
+
+        return this;
+    }
+
     /**
      * @return A path to the root directory where the Persistent Store for 
cache group will persist data and indexes.
      */
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientUtils.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientUtils.java
index 34984d755df..ddac9642170 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientUtils.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientUtils.java
@@ -47,6 +47,7 @@ import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.cache.QueryIndexType;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.client.ClientAffinityConfiguration;
 import org.apache.ignite.client.ClientCacheConfiguration;
 import org.apache.ignite.client.ClientFeatureNotSupportedByServerException;
 import org.apache.ignite.internal.binary.BinaryContext;
@@ -62,6 +63,7 @@ import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.T2;
 import org.jetbrains.annotations.Nullable;
 
+import static 
org.apache.ignite.internal.client.thin.ProtocolBitmaskFeature.CACHE_AFFINITY_CFG;
 import static 
org.apache.ignite.internal.client.thin.ProtocolBitmaskFeature.CACHE_STORAGES;
 import static 
org.apache.ignite.internal.client.thin.ProtocolBitmaskFeature.QRY_INITIATOR_ID;
 import static 
org.apache.ignite.internal.client.thin.ProtocolBitmaskFeature.QRY_PARTITIONS_BATCH_SIZE;
@@ -382,6 +384,15 @@ public final class ClientUtils {
             else if (!F.isEmpty(cfg.getStoragePaths()) || 
!F.isEmpty(cfg.getIndexPath()))
                 throw new ClientFeatureNotSupportedByServerException("Cache 
storages are not supported by the server");
 
+            if (protocolCtx.isFeatureSupported(CACHE_AFFINITY_CFG) && 
cfg.getAffinityConfiguration() != null) {
+                itemWriter.accept(CfgItem.AFFINITY_CFG, w -> {
+                    w.writeInt(cfg.getAffinityConfiguration().getPartitions());
+                    
w.writeBoolean(cfg.getAffinityConfiguration().isExcludeNeighbors());
+                });
+            }
+            else if (cfg.getAffinityConfiguration() != null)
+                throw new ClientProtocolError("Affinity configuration by thin 
client is not supported by the server");
+
             writer.writeInt(origPos, out.position() - origPos - 4); // 
configuration length
             writer.writeInt(origPos + 4, propCnt.get()); // properties count
         }
@@ -518,10 +529,21 @@ public final class ClientUtils {
                     : reader.readStringArray())
                 .setIndexPath(!protocolCtx.isFeatureSupported(CACHE_STORAGES)
                     ? null
-                    : reader.readString());
+                    : reader.readString())
+                
.setAffinityConfiguration(!protocolCtx.isFeatureSupported(CACHE_AFFINITY_CFG) ? 
null
+                    : affinityConfiguration(reader));
         }
     }
 
+    /** Deserialize affinity configuration from stream. */
+    private ClientAffinityConfiguration affinityConfiguration(BinaryReaderEx 
reader) {
+        int parts = reader.readInt();
+        boolean exclNeighbors = reader.readBoolean();
+
+        return parts > 0 ? new 
ClientAffinityConfiguration().setPartitions(parts).setExcludeNeighbors(exclNeighbors)
+            : null;
+    }
+
     /** Serialize SQL field query to stream. */
     void write(SqlFieldsQuery qry, BinaryOutputStream out, ProtocolContext 
protocolCtx) {
         writeObject(out, qry.getSchema());
@@ -798,7 +820,10 @@ public final class ClientUtils {
         STORAGE_PATH(408),
 
         /** Index path. */
-        IDX_PATH(409);
+        IDX_PATH(409),
+
+        /** Affinity configuration. */
+        AFFINITY_CFG(410);
 
         /** Code. */
         private final short code;
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolBitmaskFeature.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolBitmaskFeature.java
index 65457cb9cce..6c4a3fa676c 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolBitmaskFeature.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolBitmaskFeature.java
@@ -115,7 +115,10 @@ public enum ProtocolBitmaskFeature {
     DC_AWARE(22),
 
     /** SqlFieldsQuery initiatorId property. */
-    QRY_INITIATOR_ID(23);
+    QRY_INITIATOR_ID(23),
+
+    /** Cache affinity configuration. */
+    CACHE_AFFINITY_CFG(24);
 
     /** */
     private static final EnumSet<ProtocolBitmaskFeature> 
ALL_FEATURES_AS_ENUM_SET =
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
index 67b50a82466..00e0fd0f3ec 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
@@ -52,6 +52,7 @@ import org.apache.ignite.cache.CacheKeyConfiguration;
 import org.apache.ignite.cache.CachePartialUpdateException;
 import org.apache.ignite.cache.CacheServerNotFoundException;
 import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.affinity.AffinityFunction;
 import org.apache.ignite.cache.affinity.AffinityKeyMapped;
 import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
 import org.apache.ignite.cache.store.CacheStoreSessionListener;
@@ -1634,6 +1635,30 @@ public class GridCacheUtils {
         }
     }
 
+    /**
+     * @return Default affinity function.
+     */
+    public static AffinityFunction createDefaultAffinity() {
+        return new RendezvousAffinityFunction();
+    }
+
+    /**
+     * @param parts Total number of partitions.
+     * @return Default affinity function with predefined parameters.
+     */
+    public static AffinityFunction createDefaultAffinity(int parts) {
+        return createDefaultAffinity(false, parts);
+    }
+
+    /**
+     * @param exclNeighbors {@code True} if nodes residing on the same host 
may not act as backups of each other.
+     * @param parts Total number of partitions.
+     * @return Default affinity function with predefined parametrers.
+     */
+    public static AffinityFunction createDefaultAffinity(boolean 
exclNeighbors, int parts) {
+        return new RendezvousAffinityFunction(exclNeighbors, parts);
+    }
+
     /**
      * @param log Logger.
      * @param cfg Initializes cache configuration with proper defaults.
@@ -1650,15 +1675,10 @@ public class GridCacheUtils {
             cfg.setNodeFilter(CacheConfiguration.ALL_NODES);
 
         if (cfg.getAffinity() == null) {
-            if (cfg.getCacheMode() == PARTITIONED) {
-                RendezvousAffinityFunction aff = new 
RendezvousAffinityFunction();
-
-                cfg.setAffinity(aff);
-            }
+            if (cfg.getCacheMode() == PARTITIONED)
+                cfg.setAffinity(createDefaultAffinity());
             else {
-                RendezvousAffinityFunction aff = new 
RendezvousAffinityFunction(false, 512);
-
-                cfg.setAffinity(aff);
+                cfg.setAffinity(createDefaultAffinity(512));
 
                 cfg.setBackups(Integer.MAX_VALUE);
             }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientBitmaskFeature.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientBitmaskFeature.java
index 62eb4e8787e..8562155e347 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientBitmaskFeature.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientBitmaskFeature.java
@@ -112,7 +112,10 @@ public enum ClientBitmaskFeature implements 
ThinProtocolFeature {
     DC_AWARE(22),
 
     /** SqlFieldsQuery initiatorId property. */
-    QRY_INITIATOR_ID(23);
+    QRY_INITIATOR_ID(23),
+
+    /** Cache affinity configuration. */
+    CACHE_AFFINITY_CFG(24);
 
     /** */
     private static final EnumSet<ClientBitmaskFeature> 
ALL_FEATURES_AS_ENUM_SET =
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
index f03610aa15d..10a60b76df7 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
@@ -33,6 +33,8 @@ import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 import org.apache.ignite.cache.PartitionLossPolicy;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.affinity.AffinityFunction;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
 import org.apache.ignite.client.ClientException;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.internal.binary.BinaryWriterEx;
@@ -41,6 +43,7 @@ import 
org.apache.ignite.internal.processors.platform.client.ClientProtocolConte
 import 
org.apache.ignite.internal.processors.platform.client.ClientProtocolVersionFeature;
 import 
org.apache.ignite.internal.processors.platform.utils.PlatformConfigurationUtils;
 import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.CU;
 
 import static java.util.Optional.ofNullable;
 import static 
org.apache.ignite.internal.processors.platform.client.ClientProtocolVersionFeature.QUERY_ENTITY_PRECISION_AND_SCALE;
@@ -148,6 +151,9 @@ public class ClientCacheConfigurationSerializer {
     /** */
     private static final short IDX_PATH = 409;
 
+    /** */
+    private static final short AFFINITY_CFG = 410;
+
     /**
      * Writes the cache configuration.
      * @param writer Writer.
@@ -226,6 +232,13 @@ public class ClientCacheConfigurationSerializer {
             writer.writeString(cfg.getIndexPath());
         }
 
+        if 
(protocolCtx.isFeatureSupported(ClientBitmaskFeature.CACHE_AFFINITY_CFG)) {
+            AffinityFunction aff = cfg.getAffinity();
+            writer.writeInt(aff instanceof RendezvousAffinityFunction ? 
aff.partitions() : -1);
+            writer.writeBoolean(aff instanceof RendezvousAffinityFunction
+                && ((RendezvousAffinityFunction)aff).isExcludeNeighbors());
+        }
+
         // Write length (so that part of the config can be skipped).
         writer.writeInt(pos, writer.out().position() - pos - 4);
     }
@@ -471,6 +484,14 @@ public class ClientCacheConfigurationSerializer {
                 case IDX_PATH:
                     cfg.setIndexPath(reader.readString());
                     break;
+
+                case AFFINITY_CFG:
+                    int parts = reader.readInt();
+                    boolean exclNeighbors = reader.readBoolean();
+
+                    cfg.setAffinity(CU.createDefaultAffinity(exclNeighbors, 
parts));
+
+                    break;
             }
         }
 
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/client/thin/CacheConfigurationTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/CacheConfigurationTest.java
new file mode 100644
index 00000000000..c8793513543
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/CacheConfigurationTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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.client.thin;
+
+import java.util.AbstractMap;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheKeyConfiguration;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CacheRebalanceMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.cache.PartitionLossPolicy;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
+import org.apache.ignite.client.ClientAffinityConfiguration;
+import org.apache.ignite.client.ClientCache;
+import org.apache.ignite.client.ClientCacheConfiguration;
+import org.apache.ignite.client.Comparers;
+import org.apache.ignite.client.IgniteClient;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import 
org.apache.ignite.internal.processors.platform.cache.expiry.PlatformExpiryPolicy;
+import org.junit.Test;
+
+/**
+ * Thin client cache configuration tests.
+ */
+public class CacheConfigurationTest extends AbstractThinClientTest {
+    /**
+     * Tested API:
+     * <ul>
+     * <li>{@link ClientCache#getName()}</li>
+     * <li>{@link ClientCache#getConfiguration()}</li>
+     * </ul>
+     */
+    @Test
+    public void testCacheConfiguration() throws Exception {
+        final String dataRegionName = "functional-test-data-region";
+
+        IgniteConfiguration cfg = getConfiguration()
+            .setDataStorageConfiguration(new DataStorageConfiguration()
+                .setDefaultDataRegionConfiguration(new 
DataRegionConfiguration()
+                    .setName(dataRegionName)));
+
+        try (Ignite ignite = startGrid(cfg); IgniteClient client = 
startClient(ignite)) {
+            final String CACHE_NAME = "testCacheConfiguration";
+
+            ClientCacheConfiguration cacheCfgTemplate = new 
ClientCacheConfiguration().setName(CACHE_NAME)
+                .setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL)
+                .setBackups(3)
+                .setCacheMode(CacheMode.PARTITIONED)
+                
.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC)
+                .setEagerTtl(false)
+                .setGroupName("FunctionalTest")
+                .setDefaultLockTimeout(12345)
+                .setPartitionLossPolicy(PartitionLossPolicy.READ_WRITE_SAFE)
+                .setReadFromBackup(true)
+                .setRebalanceBatchSize(67890)
+                .setRebalanceBatchesPrefetchCount(102938)
+                .setRebalanceDelay(54321)
+                .setRebalanceMode(CacheRebalanceMode.SYNC)
+                .setRebalanceOrder(2)
+                .setRebalanceThrottle(564738)
+                .setRebalanceTimeout(142536)
+                .setKeyConfiguration(new CacheKeyConfiguration("Employee", 
"orgId"))
+                .setQueryEntities(new QueryEntity(int.class.getName(), 
"Employee")
+                    .setTableName("EMPLOYEE")
+                    .setFields(
+                        Stream.of(
+                            new AbstractMap.SimpleEntry<>("id", 
Integer.class.getName()),
+                            new AbstractMap.SimpleEntry<>("orgId", 
Integer.class.getName())
+                        ).collect(Collectors.toMap(
+                            AbstractMap.SimpleEntry::getKey, 
AbstractMap.SimpleEntry::getValue, (a, b) -> a, LinkedHashMap::new
+                        ))
+                    )
+                    // During query normalization null keyFields become empty 
set.
+                    // Set empty collection for comparator.
+                    .setKeyFields(Collections.emptySet())
+                    .setKeyFieldName("id")
+                    .setNotNullFields(Collections.singleton("id"))
+                    .setDefaultFieldValues(Collections.singletonMap("id", 0))
+                    .setIndexes(Collections.singletonList(new QueryIndex("id", 
true, "IDX_EMPLOYEE_ID")))
+                    .setAliases(Stream.of("id", 
"orgId").collect(Collectors.toMap(f -> f, String::toUpperCase)))
+                )
+                .setExpiryPolicy(new PlatformExpiryPolicy(10, 20, 30))
+                .setCopyOnRead(!CacheConfiguration.DFLT_COPY_ON_READ)
+                .setDataRegionName(dataRegionName)
+                .setMaxConcurrentAsyncOperations(4)
+                .setMaxQueryIteratorsCount(4)
+                .setOnheapCacheEnabled(true)
+                .setQueryDetailMetricsSize(1024)
+                .setQueryParallelism(4)
+                .setSqlEscapeAll(true)
+                .setSqlIndexMaxInlineSize(1024)
+                .setSqlSchema("functional-test-schema")
+                .setStatisticsEnabled(true);
+
+            ClientCacheConfiguration cacheCfg = new 
ClientCacheConfiguration(cacheCfgTemplate);
+
+            ClientCache<Object, Object> cache = client.createCache(cacheCfg);
+
+            assertEquals(CACHE_NAME, cache.getName());
+
+            assertTrue(Comparers.equal(cacheCfgTemplate, 
cache.getConfiguration()));
+        }
+    }
+
+    /** Tests cache partitions configuration. */
+    @Test
+    public void testCachePartitionsConfiguration() throws Exception {
+        try (Ignite ignite = startGrid(0); IgniteClient client = 
startClient(ignite)) {
+            // Explicit partitions count test.
+            String cacheName = "test";
+
+            // Client to server propagation.
+            client.createCache(new 
ClientCacheConfiguration().setName(cacheName).setAffinityConfiguration(
+                new 
ClientAffinityConfiguration().setPartitions(100).setExcludeNeighbors(true)));
+
+            assertEquals(100, ignite.cache(cacheName)
+                
.getConfiguration(CacheConfiguration.class).getAffinity().partitions());
+
+            assertEquals(true, 
((RendezvousAffinityFunction)ignite.cache(cacheName)
+                
.getConfiguration(CacheConfiguration.class).getAffinity()).isExcludeNeighbors());
+
+            // Server to client propagation.
+            assertEquals(100, 
client.cache(cacheName).getConfiguration().getAffinityConfiguration().getPartitions());
+
+            // Implicit partitions count test.
+            cacheName = "test2";
+
+            client.createCache(new 
ClientCacheConfiguration().setName(cacheName));
+
+            
assertEquals(ignite.cache(cacheName).getConfiguration(CacheConfiguration.class).getAffinity().partitions(),
+                
client.cache(cacheName).getConfiguration().getAffinityConfiguration().getPartitions());
+        }
+    }
+}
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/client/thin/FunctionalTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/FunctionalTest.java
index d434d966108..4153ea56a82 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/client/thin/FunctionalTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/FunctionalTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.client.thin;
 
-import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -25,7 +24,6 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -38,7 +36,6 @@ import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
-import java.util.stream.Stream;
 import javax.cache.expiry.AccessedExpiryPolicy;
 import javax.cache.expiry.CreatedExpiryPolicy;
 import javax.cache.expiry.Duration;
@@ -49,20 +46,14 @@ import org.apache.ignite.IgniteCache;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.cache.CacheAtomicityMode;
-import org.apache.ignite.cache.CacheKeyConfiguration;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.CachePeekMode;
-import org.apache.ignite.cache.CacheRebalanceMode;
 import org.apache.ignite.cache.CacheWriteSynchronizationMode;
-import org.apache.ignite.cache.PartitionLossPolicy;
-import org.apache.ignite.cache.QueryEntity;
-import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.client.ClientCache;
 import org.apache.ignite.client.ClientCacheConfiguration;
 import org.apache.ignite.client.ClientConnectionException;
 import org.apache.ignite.client.ClientException;
 import org.apache.ignite.client.ClientTransaction;
-import org.apache.ignite.client.Comparers;
 import org.apache.ignite.client.Config;
 import org.apache.ignite.client.IgniteClient;
 import org.apache.ignite.client.LocalIgniteCluster;
@@ -70,14 +61,11 @@ import org.apache.ignite.client.Person;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.ClientConfiguration;
 import org.apache.ignite.configuration.ClientConnectorConfiguration;
-import org.apache.ignite.configuration.DataRegionConfiguration;
-import org.apache.ignite.configuration.DataStorageConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.binary.AbstractBinaryArraysTest;
 import 
org.apache.ignite.internal.processors.cache.CacheEnumOperationsAbstractTest.TestEnum;
-import 
org.apache.ignite.internal.processors.platform.cache.expiry.PlatformExpiryPolicy;
 import org.apache.ignite.internal.processors.platform.client.ClientStatus;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.T2;
@@ -183,87 +171,6 @@ public class FunctionalTest extends 
AbstractBinaryArraysTest {
         }
     }
 
-    /**
-     * Tested API:
-     * <ul>
-     * <li>{@link ClientCache#getName()}</li>
-     * <li>{@link ClientCache#getConfiguration()}</li>
-     * </ul>
-     */
-    @Test
-    public void testCacheConfiguration() throws Exception {
-        final String dataRegionName = "functional-test-data-region";
-
-        IgniteConfiguration cfg = Config.getServerConfiguration()
-            .setDataStorageConfiguration(new DataStorageConfiguration()
-                .setDefaultDataRegionConfiguration(new 
DataRegionConfiguration()
-                    .setName(dataRegionName)));
-
-        try (Ignite ignored = Ignition.start(cfg);
-             IgniteClient client = 
Ignition.startClient(getClientConfiguration())
-        ) {
-            final String CACHE_NAME = "testCacheConfiguration";
-
-            ClientCacheConfiguration cacheCfgTemplate = new 
ClientCacheConfiguration().setName(CACHE_NAME)
-                .setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL)
-                .setBackups(3)
-                .setCacheMode(CacheMode.PARTITIONED)
-                
.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC)
-                .setEagerTtl(false)
-                .setGroupName("FunctionalTest")
-                .setDefaultLockTimeout(12345)
-                .setPartitionLossPolicy(PartitionLossPolicy.READ_WRITE_SAFE)
-                .setReadFromBackup(true)
-                .setRebalanceBatchSize(67890)
-                .setRebalanceBatchesPrefetchCount(102938)
-                .setRebalanceDelay(54321)
-                .setRebalanceMode(CacheRebalanceMode.SYNC)
-                .setRebalanceOrder(2)
-                .setRebalanceThrottle(564738)
-                .setRebalanceTimeout(142536)
-                .setKeyConfiguration(new CacheKeyConfiguration("Employee", 
"orgId"))
-                .setQueryEntities(new QueryEntity(int.class.getName(), 
"Employee")
-                    .setTableName("EMPLOYEE")
-                    .setFields(
-                        Stream.of(
-                            new SimpleEntry<>("id", Integer.class.getName()),
-                            new SimpleEntry<>("orgId", Integer.class.getName())
-                        ).collect(Collectors.toMap(
-                            SimpleEntry::getKey, SimpleEntry::getValue, (a, b) 
-> a, LinkedHashMap::new
-                        ))
-                    )
-                    // During query normalization null keyFields become empty 
set.
-                    // Set empty collection for comparator.
-                    .setKeyFields(Collections.emptySet())
-                    .setKeyFieldName("id")
-                    .setNotNullFields(Collections.singleton("id"))
-                    .setDefaultFieldValues(Collections.singletonMap("id", 0))
-                    .setIndexes(Collections.singletonList(new QueryIndex("id", 
true, "IDX_EMPLOYEE_ID")))
-                    .setAliases(Stream.of("id", 
"orgId").collect(Collectors.toMap(f -> f, String::toUpperCase)))
-                )
-                .setExpiryPolicy(new PlatformExpiryPolicy(10, 20, 30))
-                .setCopyOnRead(!CacheConfiguration.DFLT_COPY_ON_READ)
-                .setDataRegionName(dataRegionName)
-                .setMaxConcurrentAsyncOperations(4)
-                .setMaxQueryIteratorsCount(4)
-                .setOnheapCacheEnabled(true)
-                .setQueryDetailMetricsSize(1024)
-                .setQueryParallelism(4)
-                .setSqlEscapeAll(true)
-                .setSqlIndexMaxInlineSize(1024)
-                .setSqlSchema("functional-test-schema")
-                .setStatisticsEnabled(true);
-
-            ClientCacheConfiguration cacheCfg = new 
ClientCacheConfiguration(cacheCfgTemplate);
-
-            ClientCache<Object, Object> cache = client.createCache(cacheCfg);
-
-            assertEquals(CACHE_NAME, cache.getName());
-
-            assertTrue(Comparers.equal(cacheCfgTemplate, 
cache.getConfiguration()));
-        }
-    }
-
     /**
      * Tested API:
      * <ul>
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/client/ClientTestSuite.java 
b/modules/indexing/src/test/java/org/apache/ignite/client/ClientTestSuite.java
index ea9e99b1f24..7e36b9ae6ba 100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/client/ClientTestSuite.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/client/ClientTestSuite.java
@@ -22,6 +22,7 @@ import 
org.apache.ignite.internal.client.thin.AffinityMetricsTest;
 import org.apache.ignite.internal.client.thin.AtomicLongTest;
 import org.apache.ignite.internal.client.thin.BlockingTxOpsTest;
 import org.apache.ignite.internal.client.thin.CacheAsyncTest;
+import org.apache.ignite.internal.client.thin.CacheConfigurationTest;
 import org.apache.ignite.internal.client.thin.CacheEntryListenersTest;
 import org.apache.ignite.internal.client.thin.CacheExceptionsTest;
 import org.apache.ignite.internal.client.thin.ClusterApiTest;
@@ -111,6 +112,7 @@ import org.junit.runners.Suite;
     RecoveryModeTest.class,
     ReliableChannelDuplicationTest.class,
     CacheExceptionsTest.class,
+    CacheConfigurationTest.class,
 })
 public class ClientTestSuite {
     // No-op.

Reply via email to