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

amashenkov 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 b3d5516  IGNITE-5795: Binary metadata is registering during start of 
cache. This closes #5795.
b3d5516 is described below

commit b3d551684156e899287d662d8530743b9748df33
Author: Anton Kalashnikov <[email protected]>
AuthorDate: Mon Oct 7 12:26:35 2019 +0300

    IGNITE-5795: Binary metadata is registering during start of cache. This 
closes #5795.
---
 .../org/apache/ignite/internal/IgniteKernal.java   |   6 +-
 .../binary/BinaryCachingMetadataHandler.java       |  27 +-
 .../ignite/internal/binary/BinaryContext.java      |  91 +++++--
 .../internal/binary/BinaryMetadataHandler.java     |  11 +
 .../internal/binary/BinaryNoopMetadataHandler.java |   9 +-
 .../binary/builder/BinaryObjectBuilderImpl.java    |  32 +--
 .../internal/client/thin/TcpIgniteClient.java      |   6 +
 .../processors/cache/GridCacheProcessor.java       |  11 +-
 .../binary/CacheObjectBinaryProcessorImpl.java     |   5 +
 .../processors/query/GridQueryProcessor.java       |  84 +++++-
 .../binary/TestCachingMetadataHandler.java         |   9 +-
 .../cache/CacheRegisterMetadataLocallyTest.java    | 302 +++++++++++++++++++++
 .../cache/index/AbstractSchemaSelfTest.java        |   8 +-
 .../index/H2DynamicIndexAbstractSelfTest.java      |  54 ++--
 .../IgniteCacheWithIndexingTestSuite.java          |   3 +
 15 files changed, 562 insertions(+), 96 deletions(-)

diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java 
b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index 391dd9f..fc9766a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.internal;
 
+import javax.cache.CacheException;
+import javax.management.JMException;
 import java.io.Externalizable;
 import java.io.File;
 import java.io.IOException;
@@ -53,8 +55,6 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
-import javax.cache.CacheException;
-import javax.management.JMException;
 import org.apache.ignite.DataRegionMetrics;
 import org.apache.ignite.DataRegionMetricsAdapter;
 import org.apache.ignite.DataStorageMetrics;
@@ -1193,6 +1193,7 @@ public class IgniteKernal implements IgniteEx, 
IgniteMXBean, Externalizable {
             // be able to start receiving messages once discovery completes.
             try {
                 startProcessor(COMPRESSION.createOptional(ctx));
+                startProcessor(new GridMarshallerMappingProcessor(ctx));
                 startProcessor(new PdsConsistentIdProcessor(ctx));
                 startProcessor(new MvccProcessorImpl(ctx));
                 
startProcessor(createComponent(DiscoveryNodeValidationProcessor.class, ctx));
@@ -1222,7 +1223,6 @@ public class IgniteKernal implements IgniteEx, 
IgniteMXBean, Externalizable {
                 startProcessor(createHadoopComponent());
                 startProcessor(new DataStructuresProcessor(ctx));
                 startProcessor(createComponent(PlatformProcessor.class, ctx));
-                startProcessor(new GridMarshallerMappingProcessor(ctx));
                 startProcessor(new DistributedMetaStorageImpl(ctx));
                 startProcessor(new DistributedConfigurationProcessor(ctx));
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryCachingMetadataHandler.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryCachingMetadataHandler.java
index a0559cb..e15e64a 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryCachingMetadataHandler.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryCachingMetadataHandler.java
@@ -46,24 +46,29 @@ public class BinaryCachingMetadataHandler implements 
BinaryMetadataHandler {
     }
 
     /** {@inheritDoc} */
-    @Override public synchronized void addMeta(int typeId, BinaryType type, 
boolean failIfUnregistered) throws BinaryObjectException {
-        synchronized (this) {
-            BinaryType oldType = metas.put(typeId, type);
+    @Override public synchronized void addMeta(int typeId, BinaryType type, 
boolean failIfUnregistered)
+        throws BinaryObjectException {
+        BinaryType oldType = metas.put(typeId, type);
 
-            if (oldType != null) {
-                BinaryMetadata oldMeta = ((BinaryTypeImpl)oldType).metadata();
-                BinaryMetadata newMeta = ((BinaryTypeImpl)type).metadata();
+        if (oldType != null) {
+            BinaryMetadata oldMeta = ((BinaryTypeImpl)oldType).metadata();
+            BinaryMetadata newMeta = ((BinaryTypeImpl)type).metadata();
 
-                BinaryMetadata mergedMeta = BinaryUtils.mergeMetadata(oldMeta, 
newMeta);
+            BinaryMetadata mergedMeta = BinaryUtils.mergeMetadata(oldMeta, 
newMeta);
 
-                BinaryType mergedType = 
mergedMeta.wrap(((BinaryTypeImpl)oldType).context());
+            BinaryType mergedType = 
mergedMeta.wrap(((BinaryTypeImpl)oldType).context());
 
-                metas.put(typeId, mergedType);
-            }
+            metas.put(typeId, mergedType);
         }
     }
 
     /** {@inheritDoc} */
+    @Override public synchronized void addMetaLocally(int typeId, BinaryType 
meta, boolean failIfUnregistered)
+        throws BinaryObjectException {
+        addMeta(typeId, meta, failIfUnregistered);
+    }
+
+    /** {@inheritDoc} */
     @Override public synchronized BinaryType metadata(int typeId) throws 
BinaryObjectException {
         return metas.get(typeId);
     }
@@ -77,7 +82,7 @@ public class BinaryCachingMetadataHandler implements 
BinaryMetadataHandler {
 
     /** {@inheritDoc} */
     @Override public synchronized BinaryType metadata(int typeId, int 
schemaId) throws BinaryObjectException {
-        BinaryTypeImpl type = (BinaryTypeImpl) metas.get(typeId);
+        BinaryTypeImpl type = (BinaryTypeImpl)metas.get(typeId);
         return type != null && type.metadata().hasSchema(schemaId) ? type : 
null;
     }
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
index c263def..5e05fea 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
@@ -48,10 +48,6 @@ import java.util.jar.JarFile;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
-import org.apache.ignite.internal.UnregisteredBinaryTypeException;
-import org.apache.ignite.internal.UnregisteredClassException;
-import org.apache.ignite.internal.processors.marshaller.MappingExchangeResult;
-import org.apache.ignite.internal.util.IgniteUtils;
 import org.apache.ignite.binary.BinaryBasicIdMapper;
 import org.apache.ignite.binary.BinaryBasicNameMapper;
 import org.apache.ignite.binary.BinaryIdMapper;
@@ -69,6 +65,8 @@ import org.apache.ignite.configuration.BinaryConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.igfs.IgfsPath;
 import org.apache.ignite.internal.DuplicateTypeIdException;
+import org.apache.ignite.internal.UnregisteredBinaryTypeException;
+import org.apache.ignite.internal.UnregisteredClassException;
 import org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller;
 import org.apache.ignite.internal.processors.cache.binary.BinaryMetadataKey;
 import org.apache.ignite.internal.processors.closure.GridClosureProcessor;
@@ -113,6 +111,7 @@ import 
org.apache.ignite.internal.processors.platform.PlatformJavaObjectFactoryP
 import 
org.apache.ignite.internal.processors.platform.websession.PlatformDotNetSessionData;
 import 
org.apache.ignite.internal.processors.platform.websession.PlatformDotNetSessionLockResult;
 import org.apache.ignite.internal.processors.query.QueryUtils;
+import org.apache.ignite.internal.util.IgniteUtils;
 import org.apache.ignite.internal.util.lang.GridMapEntry;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.T2;
@@ -129,7 +128,7 @@ import static 
org.apache.ignite.internal.MarshallerPlatformIds.JAVA_ID;
  * Binary context.
  */
 public class BinaryContext {
-    /** System loader.*/
+    /** System loader. */
     private static final ClassLoader sysLdr = U.gridClassLoader();
 
     /** */
@@ -619,6 +618,22 @@ public class BinaryContext {
      */
     public BinaryClassDescriptor descriptorForClass(Class<?> cls, boolean 
deserialize, boolean failIfUnregistered)
         throws BinaryObjectException {
+        return descriptorForClass(cls, deserialize, failIfUnregistered, false);
+    }
+
+    /**
+     * @param cls Class.
+     * @param failIfUnregistered Throw exception if class isn't registered.
+     * @param onlyLocReg {@code true} if descriptor need to register only 
locally when registration is required at all.
+     * @return Class descriptor.
+     * @throws BinaryObjectException In case of error.
+     */
+    public BinaryClassDescriptor descriptorForClass(
+        Class<?> cls,
+        boolean deserialize,
+        boolean failIfUnregistered,
+        boolean onlyLocReg
+    ) throws BinaryObjectException {
         assert cls != null;
 
         BinaryClassDescriptor desc = descByCls.get(cls);
@@ -627,7 +642,7 @@ public class BinaryContext {
             if (failIfUnregistered)
                 throw new UnregisteredClassException(cls);
 
-            desc = registerClassDescriptor(cls, deserialize);
+            desc = registerClassDescriptor(cls, deserialize, onlyLocReg);
         }
         else if (!desc.registered()) {
             if (!desc.userType()) {
@@ -664,7 +679,7 @@ public class BinaryContext {
                 if (failIfUnregistered)
                     throw new UnregisteredClassException(cls);
 
-                desc = registerUserClassDescriptor(desc);
+                desc = registerUserClassDescriptor(desc, onlyLocReg);
             }
         }
 
@@ -717,7 +732,7 @@ public class BinaryContext {
         }
 
         if (desc == null) {
-            desc = registerClassDescriptor(cls, deserialize);
+            desc = registerClassDescriptor(cls, deserialize, false);
 
             assert desc.typeId() == typeId : "Duplicate typeId [typeId=" + 
typeId + ", cls=" + cls
                 + ", desc=" + desc + "]";
@@ -730,9 +745,10 @@ public class BinaryContext {
      * Creates and registers {@link BinaryClassDescriptor} for the given 
{@code class}.
      *
      * @param cls Class.
+     * @param onlyLocReg {@code true} if descriptor need to register only 
locally when registration is required at all.
      * @return Class descriptor.
      */
-    private BinaryClassDescriptor registerClassDescriptor(Class<?> cls, 
boolean deserialize) {
+    private BinaryClassDescriptor registerClassDescriptor(Class<?> cls, 
boolean deserialize, boolean onlyLocReg) {
         BinaryClassDescriptor desc;
 
         String clsName = cls.getName();
@@ -761,7 +777,7 @@ public class BinaryContext {
                 desc = old;
         }
         else
-            desc = registerUserClassDescriptor(cls, deserialize);
+            desc = registerUserClassDescriptor(cls, deserialize, onlyLocReg);
 
         return desc;
     }
@@ -770,9 +786,10 @@ public class BinaryContext {
      * Creates and registers {@link BinaryClassDescriptor} for the given user 
{@code class}.
      *
      * @param cls Class.
+     * @param onlyLocReg {@code true} if descriptor need to register only 
locally.
      * @return Class descriptor.
      */
-    private BinaryClassDescriptor registerUserClassDescriptor(Class<?> cls, 
boolean deserialize) {
+    private BinaryClassDescriptor registerUserClassDescriptor(Class<?> cls, 
boolean deserialize, boolean onlyLocReg) {
         boolean registered;
 
         final String clsName = cls.getName();
@@ -783,7 +800,7 @@ public class BinaryContext {
 
         final int typeId = mapper.typeId(clsName);
 
-        registered = registerUserClassName(typeId, cls.getName(), false);
+        registered = registerUserClassName(typeId, cls.getName(), false, 
onlyLocReg);
 
         BinarySerializer serializer = serializerForClass(cls);
 
@@ -801,9 +818,22 @@ public class BinaryContext {
             registered
         );
 
-        if (!deserialize)
-            metaHnd.addMeta(typeId, new BinaryMetadata(typeId, typeName, 
desc.fieldsMeta(), affFieldName, null,
-                desc.isEnum(), cls.isEnum() ? enumMap(cls) : null).wrap(this), 
false);
+        if (!deserialize) {
+            BinaryMetadata binaryMetadata = new BinaryMetadata(
+                typeId,
+                typeName,
+                desc.fieldsMeta(),
+                affFieldName,
+                null,
+                desc.isEnum(),
+                cls.isEnum() ? enumMap(cls) : null
+            );
+
+            if (onlyLocReg)
+                metaHnd.addMetaLocally(typeId, binaryMetadata.wrap(this), 
false);
+            else
+                metaHnd.addMeta(typeId, binaryMetadata.wrap(this), false);
+        }
 
         descByCls.put(cls, desc);
 
@@ -816,12 +846,13 @@ public class BinaryContext {
      * Creates and registers {@link BinaryClassDescriptor} for the given user 
{@code class}.
      *
      * @param desc Old descriptor that should be re-registered.
+     * @param onlyLocReg {@code true} if descriptor need to register only 
locally.
      * @return Class descriptor.
      */
-    private BinaryClassDescriptor 
registerUserClassDescriptor(BinaryClassDescriptor desc) {
+    private BinaryClassDescriptor 
registerUserClassDescriptor(BinaryClassDescriptor desc, boolean onlyLocReg) {
         boolean registered;
 
-        registered = registerUserClassName(desc.typeId(), 
desc.describedClass().getName(), false);
+        registered = registerUserClassName(desc.typeId(), 
desc.describedClass().getName(), false, onlyLocReg);
 
         if (registered) {
             BinarySerializer serializer = desc.initialSerializer();
@@ -1186,24 +1217,27 @@ public class BinaryContext {
     }
 
     /**
-     * Register "type ID to class name" mapping on all nodes to allow for 
mapping requests resolution form client.
-     * Other {@link BinaryContext}'s "register" methods and method
-     * {@link BinaryContext#descriptorForClass(Class, boolean, boolean)} 
already call this functionality
-     * so use this method only when registering class names whose {@link 
Class} is unknown.
+     * Register "type ID to class name" mapping on all nodes to allow for 
mapping requests resolution form client. Other
+     * {@link BinaryContext}'s "register" methods and method {@link 
BinaryContext#descriptorForClass(Class, boolean,
+     * boolean)} already call this functionality so use this method only when 
registering class names whose {@link
+     * Class} is unknown.
      *
      * @param typeId Type ID.
      * @param clsName Class Name.
-     * @param failIfUnregistered If {@code true} then throw {@link 
UnregisteredBinaryTypeException} with
-     *      {@link MappingExchangeResult} future instead of synchronously 
awaiting for its completion.
+     * @param failIfUnregistered If {@code true} then throw {@link 
UnregisteredBinaryTypeException} with {@link
+     * org.apache.ignite.internal.processors.marshaller.MappingExchangeResult} 
future instead of synchronously awaiting
+     * for its completion.
      * @return {@code True} if the mapping was registered successfully.
      */
-    public boolean registerUserClassName(int typeId, String clsName, boolean 
failIfUnregistered) {
+    public boolean registerUserClassName(int typeId, String clsName, boolean 
failIfUnregistered, boolean onlyLocReg) {
         IgniteCheckedException e = null;
 
         boolean res = false;
 
         try {
-            res = marshCtx.registerClassName(JAVA_ID, typeId, clsName, 
failIfUnregistered);
+            res = onlyLocReg
+                ? marshCtx.registerClassNameLocally(JAVA_ID, typeId, clsName)
+                : marshCtx.registerClassName(JAVA_ID, typeId, clsName, 
failIfUnregistered);
         }
         catch (DuplicateTypeIdException dupEx) {
             // Ignore if trying to register mapped type name of the already 
registered class name and vise versa
@@ -1271,7 +1305,6 @@ public class BinaryContext {
     }
 
     /**
-     *
      * @param typeId Type ID
      * @return Meta data.
      * @throws BinaryObjectException In case of error.
@@ -1294,7 +1327,7 @@ public class BinaryContext {
      * @throws BinaryObjectException In case of error.
      */
     public BinaryType metadata(int typeId, int schemaId) throws 
BinaryObjectException {
-        return metaHnd != null ? metaHnd.metadata(typeId, schemaId): null;
+        return metaHnd != null ? metaHnd.metadata(typeId, schemaId) : null;
     }
 
     /**
@@ -1429,7 +1462,7 @@ public class BinaryContext {
      * @param ldr Class loader being undeployed.
      */
     public void onUndeploy(ClassLoader ldr) {
-        for (Iterator<Map.Entry<Class<?>, BinaryClassDescriptor>> it = 
descByCls.entrySet().iterator(); it.hasNext();) {
+        for (Iterator<Map.Entry<Class<?>, BinaryClassDescriptor>> it = 
descByCls.entrySet().iterator(); it.hasNext(); ) {
             Map.Entry<Class<?>, BinaryClassDescriptor> e = it.next();
 
             // Never undeploy system types.
@@ -1443,7 +1476,6 @@ public class BinaryContext {
     }
 
     /**
-     *
      * @param cls Class
      * @return Enum name to ordinal mapping.
      */
@@ -1546,6 +1578,7 @@ public class BinaryContext {
 
         /**
          * Constructor.
+         *
          * @param clsName Class name.
          * @param mapper ID mapper.
          * @param serializer Serializer.
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadataHandler.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadataHandler.java
index 3652d98..36e8f45 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadataHandler.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadataHandler.java
@@ -38,6 +38,16 @@ public interface BinaryMetadataHandler {
     public void addMeta(int typeId, BinaryType meta, boolean 
failIfUnregistered) throws BinaryObjectException;
 
     /**
+     * Adds meta data locally on current node without sending any messages.
+     *
+     * @param typeId Type ID.
+     * @param meta Metadata.
+     * @param failIfUnregistered Fail if unregistered.
+     * @throws BinaryObjectException In case of error.
+     */
+    public void addMetaLocally(int typeId, BinaryType meta, boolean 
failIfUnregistered) throws BinaryObjectException;
+
+    /**
      * Gets metadata for provided type ID.
      *
      * @param typeId Type ID.
@@ -67,6 +77,7 @@ public interface BinaryMetadataHandler {
 
     /**
      * Gets all metadata known to the node.
+     *
      * @return Metadata collection
      * @throws BinaryObjectException If failed.
      */
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryNoopMetadataHandler.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryNoopMetadataHandler.java
index 4ee2428..669281f 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryNoopMetadataHandler.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryNoopMetadataHandler.java
@@ -43,7 +43,14 @@ public class BinaryNoopMetadataHandler implements 
BinaryMetadataHandler {
     }
 
     /** {@inheritDoc} */
-    @Override public void addMeta(int typeId, BinaryType meta, boolean 
failIfUnregistered) throws BinaryObjectException {
+    @Override public void addMeta(int typeId, BinaryType meta, boolean 
failIfUnregistered)
+        throws BinaryObjectException {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public void addMetaLocally(int typeId, BinaryType meta, boolean 
failIfUnregistered)
+        throws BinaryObjectException {
         // No-op.
     }
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
index f2664c2..b3d3d83 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
@@ -17,36 +17,35 @@
 
 package org.apache.ignite.internal.binary.builder;
 
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
 import org.apache.ignite.binary.BinaryInvalidTypeException;
 import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.binary.BinaryObjectBuilder;
 import org.apache.ignite.binary.BinaryObjectException;
 import org.apache.ignite.binary.BinaryType;
+import org.apache.ignite.internal.binary.BinaryContext;
 import org.apache.ignite.internal.binary.BinaryEnumObjectImpl;
+import org.apache.ignite.internal.binary.BinaryFieldMetadata;
 import org.apache.ignite.internal.binary.BinaryMetadata;
 import org.apache.ignite.internal.binary.BinaryObjectImpl;
-import org.apache.ignite.internal.binary.BinaryWriterExImpl;
-import org.apache.ignite.internal.binary.GridBinaryMarshaller;
-import org.apache.ignite.internal.binary.BinaryContext;
-import org.apache.ignite.internal.binary.BinaryFieldMetadata;
+import org.apache.ignite.internal.binary.BinaryObjectOffheapImpl;
 import org.apache.ignite.internal.binary.BinarySchema;
 import org.apache.ignite.internal.binary.BinarySchemaRegistry;
-import org.apache.ignite.internal.binary.BinaryObjectOffheapImpl;
 import org.apache.ignite.internal.binary.BinaryUtils;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.binary.GridBinaryMarshaller;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteBiTuple;
 import org.apache.ignite.thread.IgniteThread;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
 /**
  *
  */
@@ -361,7 +360,7 @@ public class BinaryObjectBuilderImpl implements 
BinaryObjectBuilder {
                 if (affFieldName0 == null)
                     affFieldName0 = ctx.affinityKeyFieldName(typeId);
 
-                ctx.registerUserClassName(typeId, typeName, 
writer.failIfUnregistered());
+                ctx.registerUserClassName(typeId, typeName, 
writer.failIfUnregistered(), false);
 
                 ctx.updateMetadata(typeId, new BinaryMetadata(typeId, 
typeName, fieldsMeta, affFieldName0,
                     Collections.singleton(curSchema), false, null), 
writer.failIfUnregistered());
@@ -516,8 +515,7 @@ public class BinaryObjectBuilderImpl implements 
BinaryObjectBuilder {
     }
 
     /**
-     * If value of {@link #assignedVals} is null, set it according to
-     * {@link BinaryUtils#FIELDS_SORTED_ORDER}.
+     * If value of {@link #assignedVals} is null, set it according to {@link 
BinaryUtils#FIELDS_SORTED_ORDER}.
      */
     private Map<String, Object> assignedValues() {
         if (assignedVals == null) {
@@ -586,7 +584,7 @@ public class BinaryObjectBuilderImpl implements 
BinaryObjectBuilder {
 
     /** {@inheritDoc} */
     @Override public BinaryObjectBuilder setField(String name, @Nullable 
BinaryObjectBuilder builder) {
-            return setField(name, (Object)builder);
+        return setField(name, (Object)builder);
     }
 
     /**
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
index 8a64747..2f6e432 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpIgniteClient.java
@@ -265,6 +265,12 @@ public class TcpIgniteClient implements IgniteClient {
         }
 
         /** {@inheritDoc} */
+        @Override public void addMetaLocally(int typeId, BinaryType meta, 
boolean failIfUnregistered)
+            throws BinaryObjectException {
+            throw new UnsupportedOperationException("Can't register metadata 
locally for thin client.");
+        }
+
+        /** {@inheritDoc} */
         @Override public BinaryType metadata(int typeId) throws 
BinaryObjectException {
             BinaryType meta = cache.metadata(typeId);
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
index 8d7f104..18a4212 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
@@ -2884,7 +2884,7 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
      * @param success Future result.
      * @param err Error if any.
      */
-    void completeCacheStartFuture(DynamicCacheChangeRequest req, boolean 
success, @Nullable Throwable err) {
+    public void completeCacheStartFuture(DynamicCacheChangeRequest req, 
boolean success, @Nullable Throwable err) {
         if (ctx.localNodeId().equals(req.initiatingNodeId())) {
             DynamicCacheStartFuture fut = 
(DynamicCacheStartFuture)pendingFuts.get(req.requestId());
 
@@ -4099,8 +4099,13 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
             return msg0.needExchange();
         }
 
-        if (msg instanceof DynamicCacheChangeBatch)
-            return 
cachesInfo.onCacheChangeRequested((DynamicCacheChangeBatch)msg, topVer);
+        if (msg instanceof DynamicCacheChangeBatch) {
+            boolean changeRequested = 
cachesInfo.onCacheChangeRequested((DynamicCacheChangeBatch)msg, topVer);
+
+            ctx.query().onCacheChangeRequested((DynamicCacheChangeBatch)msg);
+
+            return changeRequested;
+        }
 
         if (msg instanceof DynamicCacheChangeFailureMessage)
             
cachesInfo.onCacheChangeRequested((DynamicCacheChangeFailureMessage)msg, 
topVer);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
index 4cce520..ac2d237 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
@@ -239,6 +239,11 @@ public class CacheObjectBinaryProcessorImpl extends 
GridProcessorAdapter impleme
                     );
                 }
 
+                @Override public void addMetaLocally(int typeId, BinaryType 
meta, boolean failIfUnregistered)
+                    throws BinaryObjectException {
+                    CacheObjectBinaryProcessorImpl.this.addMetaLocally(typeId, 
meta);
+                }
+
                 @Override public BinaryType metadata(int typeId) throws 
BinaryObjectException {
                     return 
CacheObjectBinaryProcessorImpl.this.metadata(typeId);
                 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index a52405b..3f62f18 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.internal.processors.query;
 
+import javax.cache.Cache;
+import javax.cache.CacheException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -32,13 +34,12 @@ import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicBoolean;
-import javax.cache.Cache;
-import javax.cache.CacheException;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteDataStreamer;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.binary.BinaryObjectException;
 import org.apache.ignite.binary.Binarylizable;
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.CacheKeyConfiguration;
@@ -61,17 +62,21 @@ import 
org.apache.ignite.internal.processors.GridProcessorAdapter;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.CacheObjectContext;
+import org.apache.ignite.internal.processors.cache.DynamicCacheChangeBatch;
+import org.apache.ignite.internal.processors.cache.DynamicCacheChangeRequest;
 import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheContextInfo;
 import org.apache.ignite.internal.processors.cache.IgniteCacheOffheapManager;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
+import 
org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot;
 import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
 import org.apache.ignite.internal.processors.cache.query.CacheQueryFuture;
 import org.apache.ignite.internal.processors.cache.query.GridCacheQueryType;
 import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
+import 
org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
 import 
org.apache.ignite.internal.processors.query.property.QueryBinaryProperty;
 import 
org.apache.ignite.internal.processors.query.schema.SchemaIndexCacheFilter;
 import 
org.apache.ignite.internal.processors.query.schema.SchemaIndexCacheVisitor;
@@ -254,6 +259,8 @@ public class GridQueryProcessor extends 
GridProcessorAdapter {
                     ctxs.queries().evictDetailMetrics();
             }
         }, QRY_DETAIL_METRICS_EVICTION_FREQ, QRY_DETAIL_METRICS_EVICTION_FREQ);
+
+        registerMetadataForRegisteredCaches();
     }
 
     /** {@inheritDoc} */
@@ -948,6 +955,79 @@ public class GridQueryProcessor extends 
GridProcessorAdapter {
     }
 
     /**
+     * Register metadata locally for already registered caches.
+     */
+    private void registerMetadataForRegisteredCaches() {
+        for (DynamicCacheDescriptor cacheDescriptor : 
ctx.cache().cacheDescriptors().values())
+            registerBinaryMetadata(cacheDescriptor.cacheConfiguration(), 
cacheDescriptor.schema());
+    }
+
+    /**
+     * Handle of cache change request.
+     *
+     * @param batch Dynamic cache change batch request.
+     */
+    public void onCacheChangeRequested(DynamicCacheChangeBatch batch) {
+        for (DynamicCacheChangeRequest req : batch.requests()) {
+            if (!req.start())
+                continue;
+
+            try {
+                registerBinaryMetadata(req.startCacheConfiguration(), 
req.schema());
+            }
+            catch (BinaryObjectException e) {
+                ctx.cache().completeCacheStartFuture(req, false, e);
+            }
+        }
+    }
+
+    /**
+     * Register binary metadata locally.
+     *
+     * @param ccfg Cache configuration.
+     * @param schema Schema for which register metadata is required.
+     * @throws BinaryObjectException if register was failed.
+     */
+    private void registerBinaryMetadata(CacheConfiguration ccfg, QuerySchema 
schema) throws BinaryObjectException {
+        if (schema != null) {
+            Collection<QueryEntity> qryEntities = schema.entities();
+
+            if (!F.isEmpty(qryEntities)) {
+                boolean binaryEnabled = 
ctx.cacheObjects().isBinaryEnabled(ccfg);
+
+                if (binaryEnabled) {
+                    for (QueryEntity qryEntity : qryEntities) {
+                        Class<?> keyCls = 
U.box(U.classForName(qryEntity.findKeyType(), null, true));
+                        Class<?> valCls = 
U.box(U.classForName(qryEntity.findValueType(), null, true));
+
+                        if (keyCls != null)
+                            registerDescriptorLocallyIfNeeded(keyCls);
+
+                        if (valCls != null)
+                            registerDescriptorLocallyIfNeeded(valCls);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Register class metadata locally if it didn't do it earlier.
+     *
+     * @param cls Class for which the metadata should be registered.
+     * @throws BinaryObjectException if register was failed.
+     */
+    private void registerDescriptorLocallyIfNeeded(Class<?> cls) throws 
BinaryObjectException {
+        IgniteCacheObjectProcessor cacheObjProc = ctx.cacheObjects();
+
+        if (cacheObjProc instanceof CacheObjectBinaryProcessorImpl) {
+            ((CacheObjectBinaryProcessorImpl)cacheObjProc)
+                .binaryContext()
+                .descriptorForClass(cls, false, false, true);
+        }
+    }
+
+    /**
      * Handle custom discovery message.
      *
      * @param msg Message.
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/binary/TestCachingMetadataHandler.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/binary/TestCachingMetadataHandler.java
index c515f81..a44b0a4 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/binary/TestCachingMetadataHandler.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/binary/TestCachingMetadataHandler.java
@@ -30,7 +30,8 @@ public class TestCachingMetadataHandler implements 
BinaryMetadataHandler {
     private final ConcurrentHashMap<Integer, BinaryType> metas = new 
ConcurrentHashMap<>();
 
     /** {@inheritDoc} */
-    @Override public void addMeta(int typeId, BinaryType meta, boolean 
failIfUnregistered) throws BinaryObjectException {
+    @Override public void addMeta(int typeId, BinaryType meta, boolean 
failIfUnregistered)
+        throws BinaryObjectException {
         BinaryType otherType = metas.put(typeId, meta);
 
         if (otherType != null)
@@ -39,6 +40,12 @@ public class TestCachingMetadataHandler implements 
BinaryMetadataHandler {
     }
 
     /** {@inheritDoc} */
+    @Override public void addMetaLocally(int typeId, BinaryType meta, boolean 
failIfUnregistered)
+        throws BinaryObjectException {
+        addMeta(typeId, meta, failIfUnregistered);
+    }
+
+    /** {@inheritDoc} */
     @Override public BinaryType metadata(int typeId) throws 
BinaryObjectException {
         return metas.get(typeId);
     }
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/CacheRegisterMetadataLocallyTest.java
 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/CacheRegisterMetadataLocallyTest.java
new file mode 100644
index 0000000..baa5e71
--- /dev/null
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/CacheRegisterMetadataLocallyTest.java
@@ -0,0 +1,302 @@
+/*
+ * 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.Collections;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.binary.BinaryType;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.affinity.AffinityKeyMapped;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.managers.communication.GridIoMessage;
+import org.apache.ignite.internal.managers.discovery.CustomMessageWrapper;
+import org.apache.ignite.internal.managers.discovery.DiscoveryCustomMessage;
+import 
org.apache.ignite.internal.processors.cache.binary.MetadataRequestMessage;
+import 
org.apache.ignite.internal.processors.cache.binary.MetadataResponseMessage;
+import 
org.apache.ignite.internal.processors.cache.binary.MetadataUpdateAcceptedMessage;
+import 
org.apache.ignite.internal.processors.cache.binary.MetadataUpdateProposedMessage;
+import org.apache.ignite.lang.IgniteInClosure;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.spi.IgniteSpiException;
+import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
+import org.apache.ignite.spi.discovery.DiscoverySpiCustomMessage;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+/**
+ * Tests, that binary metadata is registered correctly during the start 
without extra request to grid.
+ */
+public class CacheRegisterMetadataLocallyTest extends GridCommonAbstractTest {
+    /** */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new 
TcpDiscoveryVmIpFinder(true);
+
+    /** */
+    private static final String STATIC_CACHE_NAME = "staticCache";
+
+    /** */
+    private static final String DYNAMIC_CACHE_NAME = "dynamicCache";
+
+    /** Holder of sent custom messages. */
+    private final ConcurrentLinkedQueue<Object> customMessages = new 
ConcurrentLinkedQueue<>();
+
+    /** Holder of sent communication messages. */
+    private final ConcurrentLinkedQueue<Object> communicationMessages = new 
ConcurrentLinkedQueue<>();
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String 
igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setDiscoverySpi(new TcpDiscoverySpi() {
+            @Override public void sendCustomEvent(DiscoverySpiCustomMessage 
msg) throws IgniteException {
+                if (msg instanceof CustomMessageWrapper) {
+                    DiscoveryCustomMessage realMsg = 
((CustomMessageWrapper)msg).delegate();
+
+                    if (realMsg instanceof MetadataUpdateProposedMessage || 
realMsg instanceof MetadataUpdateAcceptedMessage)
+                        customMessages.add(realMsg);
+                }
+
+                super.sendCustomEvent(msg);
+            }
+        });
+
+        cfg.setCommunicationSpi(new TcpCommunicationSpi() {
+            @Override public void sendMessage(ClusterNode node, Message msg,
+                IgniteInClosure<IgniteException> ackC) throws 
IgniteSpiException {
+                if (msg instanceof GridIoMessage)
+                    communicationMessages.add(((GridIoMessage)msg).message());
+
+                super.sendMessage(node, msg, ackC);
+            }
+
+            @Override public void sendMessage(ClusterNode node, Message msg) 
throws IgniteSpiException {
+                if (msg instanceof GridIoMessage)
+                    communicationMessages.add(((GridIoMessage)msg).message());
+
+                super.sendMessage(node, msg);
+            }
+        });
+
+        ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(IP_FINDER);
+
+        if (igniteInstanceName.equals("client"))
+            cfg.setClientMode(true);
+
+        cfg.setCacheConfiguration(cacheConfiguration(STATIC_CACHE_NAME, 
StaticKey.class, StaticValue.class));
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+
+        cleanPersistenceDir();
+
+        customMessages.clear();
+        communicationMessages.clear();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testAffinityKeyRegisteredStaticCache() throws Exception {
+        Ignite ignite = startGrid(0);
+
+        assertEquals("affKey", getAffinityKey(ignite, StaticKey.class));
+        assertEquals("affKey", getAffinityKey(ignite, StaticValue.class));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testAffinityKeyRegisteredDynamicCache() throws Exception {
+        Ignite ignite = startGrid(0);
+
+        ignite.createCache(cacheConfiguration(DYNAMIC_CACHE_NAME, 
DynamicKey.class, DynamicValue.class));
+
+        assertEquals("affKey", getAffinityKey(ignite, DynamicKey.class));
+        assertEquals("affKey", getAffinityKey(ignite, DynamicValue.class));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void 
testClientFindsValueByAffinityKeyStaticCacheWithoutExtraRequest() throws 
Exception {
+        Ignite srv = startGrid(0);
+        IgniteCache<StaticKey, StaticValue> cache = 
srv.cache(STATIC_CACHE_NAME);
+
+        testClientAndServerFindsValueByAffinityKey(cache, new StaticKey(1), 
new StaticValue(2));
+
+        assertCustomMessages(2); //MetadataUpdateProposedMessage for update 
schema.
+        assertCommunicationMessages();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void 
testClientFindsValueByAffinityKeyDynamicCacheWithoutExtraRequest() throws 
Exception {
+        Ignite srv = startGrid(0);
+        IgniteCache<DynamicKey, DynamicValue> cache =
+            srv.createCache(cacheConfiguration(DYNAMIC_CACHE_NAME, 
DynamicKey.class, DynamicValue.class));
+
+        testClientAndServerFindsValueByAffinityKey(cache, new DynamicKey(3), 
new DynamicValue(4));
+
+        //Expected only MetadataUpdateProposedMessage for update schema.
+        assertCustomMessages(2);
+        assertCommunicationMessages();
+    }
+
+    /**
+     * @param ignite Ignite instance.
+     * @param keyCls Key class.
+     * @return Name of affinity key field of the given class.
+     */
+    private <K> String getAffinityKey(Ignite ignite, Class<K> keyCls) {
+        BinaryType binType = ignite.binary().type(keyCls);
+
+        return binType.affinityKeyFieldName();
+    }
+
+    /**
+     * @param cache Cache instance.
+     * @param key Test key.
+     * @param val Test value.
+     * @throws Exception If failed.
+     */
+    private <K, V> void 
testClientAndServerFindsValueByAffinityKey(IgniteCache<K, V> cache, K key, V 
val) throws Exception {
+        cache.put(key, val);
+
+        assertTrue(cache.containsKey(key));
+
+        Ignite client = startGrid("client");
+
+        IgniteCache<K, V> clientCache = client.cache(cache.getName());
+
+        assertTrue(clientCache.containsKey(key));
+
+        Ignite server = startGrid(1);
+
+        IgniteCache<K, V> serverCache = server.cache(cache.getName());
+
+        assertTrue(serverCache.containsKey(key));
+    }
+
+    /**
+     * @param name Cache name.
+     * @param keyCls Key {@link Class}.
+     * @param valCls Value {@link Class}.
+     * @param <K> Key type.
+     * @param <V> Value type.
+     * @return Cache configuration
+     */
+    private static <K, V> CacheConfiguration<K, V> cacheConfiguration(String 
name, Class<K> keyCls, Class<V> valCls) {
+        CacheConfiguration<K, V> cfg = new CacheConfiguration<>(name);
+        cfg.setQueryEntities(Collections.singleton(new QueryEntity(keyCls, 
valCls)));
+        return cfg;
+    }
+
+    /**
+     * Expecting that "proposed binary metadata"( {@link 
org.apache.ignite.internal.processors.marshaller.MappingProposedMessage},
+     * {@link 
org.apache.ignite.internal.processors.cache.binary.MetadataUpdateProposedMessage})
 will be skipped because
+     * it should be register locally during the start.
+     *
+     * @param expMsgCnt Count of expected messages.
+     */
+    private void assertCustomMessages(int expMsgCnt) {
+        assertEquals(customMessages.toString(), expMsgCnt, 
customMessages.size());
+
+        customMessages.forEach(cm -> assertTrue(cm.toString(), cm instanceof 
DynamicCacheChangeBatch || cm instanceof MetadataUpdateProposedMessage));
+    }
+
+    /**
+     * Expecting that extra request to binary metadata( {@link 
MetadataRequestMessage}, {@link MetadataResponseMessage})
+     * will be skipped because it should be register locally during the start.
+     */
+    private void assertCommunicationMessages() {
+        communicationMessages.forEach(cm ->
+            assertFalse(cm.toString(), cm instanceof MetadataRequestMessage || 
cm instanceof MetadataResponseMessage)
+        );
+    }
+
+    /** */
+    private static class StaticKey {
+        /** */
+        @AffinityKeyMapped
+        private int affKey;
+
+        /**
+         * @param affKey Affinity key.
+         */
+        StaticKey(int affKey) {
+            this.affKey = affKey;
+        }
+    }
+
+    /** */
+    private static class StaticValue {
+        /** It doesn't make sense on value class. It it just for checking that 
value class also register correctly. */
+        @AffinityKeyMapped
+        private int affKey;
+
+        /**
+         * @param affKey Affinity key.
+         */
+        StaticValue(int affKey) {
+        }
+    }
+
+    /** */
+    private static class DynamicKey {
+        /** */
+        @AffinityKeyMapped
+        private int affKey;
+
+        /**
+         * @param affKey Affinity key.
+         */
+        DynamicKey(int affKey) {
+            this.affKey = affKey;
+        }
+    }
+
+    /** */
+    private static class DynamicValue {
+        /** It doesn't make sense on value class. It it just for checking that 
value class also register correctly. */
+        @AffinityKeyMapped
+        private int affKey;
+
+        /**
+         * @param affKey Affinity key.
+         */
+        DynamicValue(int affKey) {
+            this.affKey = affKey;
+        }
+    }
+}
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java
 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java
index 1b9507b..129a4d0 100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.processors.cache.index;
 
+import javax.cache.CacheException;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.ResultSet;
@@ -29,7 +30,6 @@ import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import javax.cache.CacheException;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
@@ -620,21 +620,21 @@ public abstract class AbstractSchemaSelfTest extends 
AbstractIndexingCommonTest
     public static class ValueClass {
         /** Field 1. */
         @QuerySqlField
-        private String field1;
+        private Long field1;
 
         /**
          * Constructor.
          *
          * @param field1 Field 1.
          */
-        public ValueClass(String field1) {
+        public ValueClass(Long field1) {
             this.field1 = field1;
         }
 
         /**
          * @return Field 1
          */
-        public String field1() {
+        public Long field1() {
             return field1;
         }
     }
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexAbstractSelfTest.java
 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexAbstractSelfTest.java
index 1c8f5e9..f5451ed 100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexAbstractSelfTest.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexAbstractSelfTest.java
@@ -61,9 +61,9 @@ public abstract class H2DynamicIndexAbstractSelfTest extends 
AbstractSchemaSelfT
 
         IgniteCache<KeyClass, ValueClass> cache = client().cache(CACHE_NAME);
 
-        cache.put(new KeyClass(1), new ValueClass("val1"));
-        cache.put(new KeyClass(2), new ValueClass("val2"));
-        cache.put(new KeyClass(3), new ValueClass("val3"));
+        cache.put(new KeyClass(1), new ValueClass(1L));
+        cache.put(new KeyClass(2), new ValueClass(2L));
+        cache.put(new KeyClass(3), new ValueClass(3L));
     }
 
     /** {@inheritDoc} */
@@ -86,19 +86,19 @@ public abstract class H2DynamicIndexAbstractSelfTest 
extends AbstractSchemaSelfT
             + FIELD_NAME_1_ESCAPED + "\" ASC)")).getAll();
 
         // Test that local queries on all nodes use new index.
-        for (int i = 0 ; i < 4; i++) {
+        for (int i = 0; i < 4; i++) {
             if (ignite(i).configuration().isClientMode())
                 continue;
 
             List<List<?>> locRes = ignite(i).cache("cache").query(new 
SqlFieldsQuery("explain select \"id\" from " +
-                "\"cache\".\"ValueClass\" where \"field1\" = 
'A'").setLocal(true)).getAll();
+                "\"cache\".\"ValueClass\" where \"field1\" = 
1").setLocal(true)).getAll();
 
             assertEquals(F.asList(
                 Collections.singletonList("SELECT\n" +
                     "    \"id\"\n" +
                     "FROM \"cache\".\"ValueClass\"\n" +
-                    "    /* \"cache\".\"idx_1\": \"field1\" = 'A' */\n" +
-                    "WHERE \"field1\" = 'A'")
+                    "    /* \"cache\".\"idx_1\": \"field1\" = 1 */\n" +
+                    "WHERE \"field1\" = 1")
             ), locRes);
         }
 
@@ -108,7 +108,7 @@ public abstract class H2DynamicIndexAbstractSelfTest 
extends AbstractSchemaSelfT
 
         assertSize(2);
 
-        cache.put(new KeyClass(4), new ValueClass("someVal"));
+        cache.put(new KeyClass(4), new ValueClass(1L));
 
         assertSize(3);
     }
@@ -162,19 +162,19 @@ public abstract class H2DynamicIndexAbstractSelfTest 
extends AbstractSchemaSelfT
         cache.query(new SqlFieldsQuery("DROP INDEX \"" + IDX_NAME_1_ESCAPED + 
"\""));
 
         // Test that no local queries on all nodes use new index.
-        for (int i = 0 ; i < 4; i++) {
+        for (int i = 0; i < 4; i++) {
             if (ignite(i).configuration().isClientMode())
                 continue;
 
             List<List<?>> locRes = ignite(i).cache("cache").query(new 
SqlFieldsQuery("explain select \"id\" from " +
-                "\"cache\".\"ValueClass\" where \"field1\" = 
'A'").setLocal(true)).getAll();
+                "\"cache\".\"ValueClass\" where \"field1\" = 
1").setLocal(true)).getAll();
 
             assertEquals(F.asList(
                 Collections.singletonList("SELECT\n" +
                     "    \"id\"\n" +
                     "FROM \"cache\".\"ValueClass\"\n" +
                     "    /* \"cache\".\"ValueClass\".__SCAN_ */\n" +
-                    "WHERE \"field1\" = 'A'")
+                    "WHERE \"field1\" = 1")
             ), locRes);
         }
 
@@ -212,49 +212,53 @@ public abstract class H2DynamicIndexAbstractSelfTest 
extends AbstractSchemaSelfT
     public void testIndexState() {
         IgniteCache<KeyClass, ValueClass> cache = cache();
 
-        assertColumnValues("val1", "val2", "val3");
+        assertColumnValues(1L, 2L, 3L);
 
         cache.query(new SqlFieldsQuery("CREATE INDEX \"" + IDX_NAME_1_ESCAPED 
+ "\" ON \"" + TBL_NAME_ESCAPED + "\"(\""
             + FIELD_NAME_1_ESCAPED + "\" ASC)"));
 
-        assertColumnValues("val1", "val2", "val3");
+        assertColumnValues(1L, 2L, 3L);
 
         cache.remove(new KeyClass(2));
 
-        assertColumnValues("val1", "val3");
+        assertColumnValues(1L, 3L);
 
-        cache.put(new KeyClass(0), new ValueClass("someVal"));
+        cache.put(new KeyClass(0), new ValueClass(0L));
 
-        assertColumnValues("someVal", "val1", "val3");
+        assertColumnValues(0L, 1L, 3L);
 
         cache.query(new SqlFieldsQuery("DROP INDEX \"" + IDX_NAME_1_ESCAPED + 
"\""));
 
-        assertColumnValues("someVal", "val1", "val3");
+        assertColumnValues(0L, 1L, 3L);
     }
 
     /**
      * Check that values of {@code field1} match what we expect.
+     *
      * @param vals Expected values.
      */
-    private void assertColumnValues(String... vals) {
+    private void assertColumnValues(Long... vals) {
         List<List<?>> expRes = new ArrayList<>(vals.length);
 
-        for (String v : vals)
+        for (Long v : vals)
             expRes.add(Collections.singletonList(v));
 
-        assertEquals(expRes, cache().query(new SqlFieldsQuery("SELECT \"" + 
FIELD_NAME_1_ESCAPED + "\" FROM \"" +
-            TBL_NAME_ESCAPED + "\" ORDER BY \"id\"")).getAll());
+        List<List<?>> all = cache().query(new SqlFieldsQuery("SELECT \"" + 
FIELD_NAME_1_ESCAPED + "\" FROM \"" +
+            TBL_NAME_ESCAPED + "\" ORDER BY \"id\"")).getAll();
+        assertEquals(expRes, all);
     }
 
     /**
      * Do a {@code SELECT COUNT(*)} query to check index state correctness.
+     *
      * @param expSize Expected number of items in table.
      */
     private void assertSize(long expSize) {
         assertEquals(expSize, cache().size());
 
-        assertEquals(expSize, cache().query(new SqlFieldsQuery("SELECT 
COUNT(*) from \"ValueClass\""))
-            .getAll().get(0).get(0));
+        Object actual = cache().query(new SqlFieldsQuery("SELECT COUNT(*) from 
\"ValueClass\""))
+            .getAll().get(0).get(0);
+        assertEquals(expSize, actual);
     }
 
     /**
@@ -321,8 +325,8 @@ public abstract class H2DynamicIndexAbstractSelfTest 
extends AbstractSchemaSelfT
         entity.setValueType(ValueClass.class.getName());
 
         entity.addQueryField("id", Long.class.getName(), null);
-        entity.addQueryField(FIELD_NAME_1_ESCAPED, String.class.getName(), 
null);
-        entity.addQueryField(FIELD_NAME_2_ESCAPED, String.class.getName(), 
null);
+        entity.addQueryField(FIELD_NAME_1_ESCAPED, Long.class.getName(), null);
+        entity.addQueryField(FIELD_NAME_2_ESCAPED, Long.class.getName(), null);
 
         entity.setKeyFields(Collections.singleton("id"));
 
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 0c68da9..003ffed 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
@@ -27,6 +27,7 @@ import 
org.apache.ignite.internal.processors.cache.CacheOperationsWithExpiration
 import 
org.apache.ignite.internal.processors.cache.CacheQueryAfterDynamicCacheStartFailureTest;
 import org.apache.ignite.internal.processors.cache.CacheQueryFilterExpiredTest;
 import 
org.apache.ignite.internal.processors.cache.CacheRandomOperationsMultithreadedTest;
+import 
org.apache.ignite.internal.processors.cache.CacheRegisterMetadataLocallyTest;
 import 
org.apache.ignite.internal.processors.cache.ClientReconnectAfterClusterRestartTest;
 import org.apache.ignite.internal.processors.cache.ClusterReadOnlyModeSqlTest;
 import org.apache.ignite.internal.processors.cache.GridCacheOffHeapSelfTest;
@@ -83,6 +84,8 @@ import org.junit.runners.Suite;
 
     CacheQueryAfterDynamicCacheStartFailureTest.class,
 
+    CacheRegisterMetadataLocallyTest.class,
+
     IgniteCacheGroupsSqlTest.class,
 
     IgniteDataStreamerTest.class,

Reply via email to