You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2015/06/30 12:52:08 UTC

[47/50] [abbrv] incubator-ignite git commit: ignite-950: getting fields through reflection when class peresents on node

ignite-950: getting fields through reflection when class peresents on node


Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/28f8edaf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/28f8edaf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/28f8edaf

Branch: refs/heads/ignite-950
Commit: 28f8edafdfc72f8779143337501cb99d6e697946
Parents: 2e8bdec
Author: Denis Magda <dm...@gridgain.com>
Authored: Mon Jun 29 13:51:10 2015 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Mon Jun 29 13:51:10 2015 +0300

----------------------------------------------------------------------
 .../cache/CacheIndexedObjectImpl.java           | 113 +++++++++++-------
 .../processors/cache/CacheObjectContext.java    |  17 +--
 .../cache/KeyCacheIndexedObjectImpl.java        |  25 +---
 .../cacheobject/IgniteCacheObjectProcessor.java |  14 ++-
 .../IgniteCacheObjectProcessorImpl.java         |  16 +--
 .../processors/query/GridQueryProcessor.java    | 114 ++++++++++++++-----
 .../optimized/IgniteFieldNotFoundException.java |  11 ++
 7 files changed, 192 insertions(+), 118 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/28f8edaf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java
index 8cf7085..7963245 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java
@@ -26,6 +26,7 @@ import org.jetbrains.annotations.*;
 import sun.misc.*;
 
 import java.io.*;
+import java.lang.reflect.*;
 import java.nio.*;
 import java.util.concurrent.*;
 
@@ -44,6 +45,9 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
     private static final long BYTE_ARR_OFF = UNSAFE.arrayBaseOffset(byte[].class);
 
     /** */
+    private Boolean hasClass;
+
+    /** */
     protected int start;
 
     /** */
@@ -93,9 +97,6 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
     public CacheIndexedObjectImpl(Object val, byte[] valBytes, int start, int len) {
         assert val != null || (valBytes != null && start >= 0 && len > 0);
 
-        if (valBytes != null && val != null)
-            val = null;
-
         this.val = val;
         this.valBytes = valBytes;
         this.start = start;
@@ -111,25 +112,25 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
     @Override public byte[] valueBytes(CacheObjectContext ctx) throws IgniteCheckedException {
         toMarshaledFormIfNeeded(ctx);
 
-        shrinkToSize();
-
         return valBytes;
     }
 
     /** {@inheritDoc} */
     @Override public CacheObject prepareForCache(CacheObjectContext ctx) {
-        return detach();
+        return this;
     }
 
     /** {@inheritDoc} */
     @Override public void finishUnmarshal(CacheObjectContext ctx, ClassLoader ldr) throws IgniteCheckedException {
-        // No-op
+        assert valBytes != null;
+
+        if (val == null && keepDeserialized(ctx, true))
+            val = ctx.processor().unmarshal(ctx, valBytes, start, len, ldr);
     }
 
     /** {@inheritDoc} */
     @Override public void prepareMarshal(CacheObjectContext ctx) throws IgniteCheckedException {
         toMarshaledFormIfNeeded(ctx);
-        shrinkToSize();
     }
 
     /** {@inheritDoc} */
@@ -164,10 +165,21 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
      *
      * @param fieldName Field name.
      * @param marsh Marshaller.
+     * @param field Field instance to get access through reflection.
      * @return {@code true} if has.
      * @throws IgniteCheckedException In case of error.
      */
-    public boolean hasField(String fieldName, OptimizedMarshallerExt marsh) throws IgniteCheckedException {
+    public boolean hasField(String fieldName, OptimizedMarshallerExt marsh, Field field) throws IgniteCheckedException {
+        if (field != null && val != null) {
+            try {
+                field.get(val);
+                return true;
+            }
+            catch (Exception e) {
+                return false;
+            }
+        }
+
         assert valBytes != null;
 
         return marsh.hasField(fieldName, valBytes, start, len);
@@ -178,11 +190,22 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
      *
      * @param fieldName Field name.
      * @param marsh Marshaller.
+     * @param field Field instance to get access through reflection.
      * @return Field.
      * @throws IgniteFieldNotFoundException In case if there is no such a field.
      * @throws IgniteCheckedException In case of error.
      */
-    public Object field(String fieldName, OptimizedMarshallerExt marsh) throws IgniteCheckedException {
+    public Object field(String fieldName, OptimizedMarshallerExt marsh, Field field) throws IgniteCheckedException {
+        if (field != null && val != null) {
+            try {
+                return field.get(val);
+            }
+            catch (Exception e) {
+                throw new IgniteFieldNotFoundException("Object doesn't have the field [obj=" + val + ", field="
+                    + fieldName + "]", e);
+            }
+        }
+
         assert valBytes != null;
 
         return marsh.readField(fieldName, valBytes, start, len, val != null ? val.getClass().getClassLoader() : null);
@@ -204,8 +227,8 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
             Object val = ctx.processor().unmarshal(ctx, valBytes, start, len,
                 ctx.kernalContext().config().getClassLoader());
 
-            //if (ctx.storeValue())
-            //    this.val = val;
+            if (keepDeserialized(ctx, false))
+                this.val = val;
 
             return val;
         }
@@ -314,27 +337,6 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
     }
 
     /**
-     * Detaches object.
-     *
-     * @return Detached object wrapped by {@code CacheIndexedObjectImpl}.
-     */
-    protected CacheIndexedObjectImpl detach() {
-        shrinkToSize();
-
-        return this;
-    }
-
-    /**
-     * Checks whether the object is already detached or not.
-     *
-     * @return {@code true} if detached.
-     */
-    protected boolean detached() {
-        return true;
-        //return start == 0 && len == valBytes.length;
-    }
-
-    /**
      * Marshals {@link #val} to {@link #valBytes} if needed.
      *
      * @param ctx Cache object context.
@@ -349,22 +351,49 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
             start = 0;
             len = valBytes.length;
 
-            val = null;
+            if (!keepDeserialized(ctx, false))
+                val = null;
         }
     }
 
     /**
-     * Shrinks byte array to size boundaries.
+     * Checks whether to keep deserialized version of the object or not.
+     *
+     * @param ctx Cache object context.
+     * @param checkCls Check class definition presence on node flag.
+     * @return {@code true} if keep, {@code false} otherwise.
      */
-    private void shrinkToSize() {
-        if (detached())
-            return;
+    protected boolean keepDeserialized(CacheObjectContext ctx, boolean checkCls) {
+        if (ctx.copyOnGet())
+            return false;
 
-        byte[] arr = new byte[len];
+        return checkCls ? hasClassOnNode(ctx) : true;
+    }
 
-        U.arrayCopy(valBytes, start, arr, 0, len);
+    /**
+     * Checks whether a node has a class definition of a marhsaller object or not.
+     *
+     * @param ctx Cache object context.
+     * @return {@code true} if has, {@code false} otherwise.
+     */
+    private boolean hasClassOnNode(CacheObjectContext ctx) {
+        if (val != null)
+            return true;
+
+        if (hasClass != null)
+            return hasClass;
+
+        assert valBytes != null;
+
+        try {
+            Class<?> cls = ctx.kernalContext().marshallerContext().getClass(typeId(), null);
+
+            hasClass = cls != null;
+        }
+        catch (Exception e) {
+            hasClass = false;
+        }
 
-        valBytes = arr;
-        start = 0;
+        return hasClass;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/28f8edaf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java
index 4e5ca5f..74e8ad5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java
@@ -48,27 +48,23 @@ public class CacheObjectContext {
     /** */
     private boolean p2pEnabled;
 
-    /** */
-    private boolean systemCache;
-
     /**
      * @param kernalCtx Kernal context.
      * @param dfltAffMapper Default affinity mapper.
      * @param cpyOnGet Copy on get flag.
      * @param storeVal {@code True} if should store unmarshalled value in cache.
-     * @param systemCache Whether the object will be stored in a system cache or not.
+     * @param
      */
     public CacheObjectContext(GridKernalContext kernalCtx,
         AffinityKeyMapper dfltAffMapper,
         boolean cpyOnGet,
-        boolean storeVal,
-        boolean systemCache) {
+        boolean storeVal
+        ) {
         this.kernalCtx = kernalCtx;
         this.p2pEnabled = kernalCtx.config().isPeerClassLoadingEnabled();
         this.dfltAffMapper = dfltAffMapper;
         this.cpyOnGet = cpyOnGet;
         this.storeVal = storeVal;
-        this.systemCache = systemCache;
 
         proc = kernalCtx.cacheObjects();
     }
@@ -95,13 +91,6 @@ public class CacheObjectContext {
     }
 
     /**
-     * @return {@code true} if the object is stored in a system cache.
-     */
-    public boolean systemCache() {
-        return systemCache;
-    }
-
-    /**
      * @return Default affinity mapper.
      */
     public AffinityKeyMapper defaultAffMapper() {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/28f8edaf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheIndexedObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheIndexedObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheIndexedObjectImpl.java
index e9c8973..e0a0c8d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheIndexedObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheIndexedObjectImpl.java
@@ -56,21 +56,10 @@ public class KeyCacheIndexedObjectImpl extends CacheIndexedObjectImpl implements
     }
 
     /** {@inheritDoc} */
-    @SuppressWarnings("unchecked")
-    @Nullable @Override public <T> T value(CacheObjectContext ctx, boolean cpy) {
-        return (T)this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public CacheObject prepareForCache(CacheObjectContext ctx) {
-        return this;
-    }
-
-    /** {@inheritDoc} */
     @Override public void finishUnmarshal(CacheObjectContext ctx, ClassLoader ldr) throws IgniteCheckedException {
         assert val != null || valBytes != null;
 
-        if (val == null && ctx.storeValue())
+        if (val == null)
             val = ctx.processor().unmarshal(ctx, valBytes, start, len, ldr);
     }
 
@@ -88,13 +77,6 @@ public class KeyCacheIndexedObjectImpl extends CacheIndexedObjectImpl implements
     }
 
     /** {@inheritDoc} */
-    @Override public Object deserialize(CacheObjectContext ctx) {
-        assert val != null;
-
-        return val;
-    }
-
-    /** {@inheritDoc} */
     @Override public int hashCode() {
         assert val != null;
 
@@ -110,4 +92,9 @@ public class KeyCacheIndexedObjectImpl extends CacheIndexedObjectImpl implements
 
         return val.equals(other.val);
     }
+
+    /** {@inheritDoc} */
+    @Override protected boolean keepDeserialized(CacheObjectContext ctx, boolean checkCls) {
+        return true;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/28f8edaf/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
index 7d1eec3..aa5a550 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
@@ -25,6 +25,8 @@ import org.apache.ignite.internal.processors.cache.*;
 import org.apache.ignite.marshaller.optimized.*;
 import org.jetbrains.annotations.*;
 
+import java.lang.reflect.*;
+
 /**
  * Cache objects processor.
  */
@@ -82,21 +84,25 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
     public boolean isPortableEnabled();
 
     /**
-     * @param obj Portable object to get field from.
+     * Retrieves field from the given object. Object should be an instance of {@link CacheObject}.
+     *
+     * @param obj Object to get field from.
      * @param fieldName Field name.
+     * @param field Field instance to get access through reflection.
      * @throws IgniteFieldNotFoundException In case if there is no such a field.
      * @return Field value.
      */
-    public Object field(Object obj, String fieldName) throws IgniteFieldNotFoundException;
+    public Object field(Object obj, String fieldName, @Nullable Field field) throws IgniteFieldNotFoundException;
 
     /**
-     * Checks whether field is set in the object.
+     * Checks whether field is set in the object. Object should be an instance of {@link CacheObject}.
      *
      * @param obj Object.
      * @param fieldName Field name.
+     * @param field Field instance to get access through reflection.
      * @return {@code true} if field is set.
      */
-    public boolean hasField(Object obj, String fieldName);
+    public boolean hasField(Object obj, String fieldName, @Nullable Field field);
 
     /**
      * Checks whether this functionality is globally supported.

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/28f8edaf/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
index 730b5d5..3bca8ee 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
@@ -31,6 +31,7 @@ import org.apache.ignite.marshaller.*;
 import org.apache.ignite.marshaller.optimized.*;
 import org.jetbrains.annotations.*;
 
+import java.lang.reflect.*;
 import java.math.*;
 import java.util.*;
 import java.util.concurrent.*;
@@ -290,8 +291,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
         CacheObjectContext res = new CacheObjectContext(ctx,
             ccfg.getAffinityMapper() != null ? ccfg.getAffinityMapper() : new GridCacheDefaultAffinityKeyMapper(),
             ccfg.isCopyOnRead() && memMode != OFFHEAP_VALUES,
-            storeVal,
-            GridCacheUtils.isSystemCache(ccfg.getName()));
+            storeVal);
 
         ctx.resource().injectGeneric(res.defaultAffMapper());
 
@@ -334,11 +334,11 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
     }
 
     /** {@inheritDoc} */
-    @Override public Object field(Object obj, String fieldName) throws IgniteFieldNotFoundException {
+    @Override public Object field(Object obj, String fieldName, Field field) throws IgniteFieldNotFoundException {
         assert optMarshExt != null;
 
         try {
-            return ((CacheIndexedObjectImpl)obj).field(fieldName, optMarshExt);
+            return ((CacheIndexedObjectImpl)obj).field(fieldName, optMarshExt, field);
         }
         catch (IgniteFieldNotFoundException e) {
             throw e;
@@ -353,12 +353,12 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
     }
 
     /** {@inheritDoc} */
-    @Override public boolean hasField(Object obj, String fieldName) {
+    @Override public boolean hasField(Object obj, String fieldName, Field field) {
         if (obj instanceof CacheIndexedObjectImpl) {
             assert optMarshExt != null;
 
             try {
-                return ((CacheIndexedObjectImpl)obj).hasField(fieldName, optMarshExt);
+                return ((CacheIndexedObjectImpl)obj).hasField(fieldName, optMarshExt, null);
             }
             catch (IgniteCheckedException e) {
                 throw new IgniteException(e);
@@ -511,7 +511,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
             try {
                 toMarshaledFormIfNeeded(ctx);
 
-                /*if (ctx.storeValue()) {
+                if (keepDeserialized(ctx, true)) {
                     ClassLoader ldr = ctx.p2pEnabled() ?
                         IgniteUtils.detectClass(this.val).getClassLoader() : val.getClass().getClassLoader();
 
@@ -519,7 +519,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
                         ctx.processor().unmarshal(ctx, valBytes, start, len, ldr);
 
                     return new CacheIndexedObjectImpl(val, valBytes, start, len);
-                }*/
+                }
 
                 return new CacheIndexedObjectImpl(null, valBytes, start, len);
             }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/28f8edaf/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
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 3ce561a..14e69bf 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
@@ -130,25 +130,23 @@ public class GridQueryProcessor extends GridProcessorAdapter {
 
                     TypeDescriptor desc = new TypeDescriptor();
 
-                    Class<?> valCls = U.classForName(meta.getValueType(), null);
+                    Class<?> keyCls = meta.getKeyType() != null ? U.classForName(meta.getKeyType(), null) : null;
+                    Class<?> valCls = meta.getValueType() != null ? U.classForName(meta.getValueType(), null) : null;
 
                     desc.name(valCls != null ? typeName(valCls) : meta.getValueType());
 
                     desc.valueClass(valCls != null ? valCls : Object.class);
-                    desc.keyClass(
-                        meta.getKeyType() == null ?
-                            Object.class :
-                            U.classForName(meta.getKeyType(), Object.class));
+                    desc.keyClass(keyCls != null ? keyCls : Object.class);
 
                     TypeId typeId;
 
                     if (valCls == null || ctx.cacheObjects().isPortableEnabled()) {
-                        processCacheTypeMeta(meta, desc, PORTABLE_PROPERTY);
+                        processCacheTypeMeta(meta, desc, PORTABLE_PROPERTY, keyCls, valCls);
 
                         typeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(meta.getValueType()));
                     }
                     else if (ctx.cacheObjects().enableFieldsIndexing(valCls)) {
-                        processCacheTypeMeta(meta, desc, INDEXED_FIELDS_PROPERTY);
+                        processCacheTypeMeta(meta, desc, INDEXED_FIELDS_PROPERTY, keyCls, valCls);
 
                         typeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(valCls.getName()));
                     }
@@ -1240,17 +1238,19 @@ public class GridQueryProcessor extends GridProcessorAdapter {
      *
      * @param meta Declared metadata.
      * @param d Type descriptor.
-     * @param propertyType PropertyType.
+     * @param propType PropertyType.
+     * @param keyCls Key class.
+     * @param valCls Value class.
      * @throws IgniteCheckedException If failed.
      */
-    private void processCacheTypeMeta(CacheTypeMetadata meta, TypeDescriptor d, PropertyType propertyType)
-        throws IgniteCheckedException {
-        assert propertyType != CLASS_PROPERTY;
+    private void processCacheTypeMeta(CacheTypeMetadata meta, TypeDescriptor d, PropertyType propType,
+        @Nullable Class<?> keyCls, @Nullable Class<?> valCls) throws IgniteCheckedException {
+        assert propType != CLASS_PROPERTY;
 
         for (Map.Entry<String, Class<?>> entry : meta.getAscendingFields().entrySet()) {
-            Property prop = propertyType == PORTABLE_PROPERTY ?
+            Property prop = propType == PORTABLE_PROPERTY ?
                 buildPortableProperty(entry.getKey(), entry.getValue()) :
-                buildIndexedFieldsProperty(entry.getKey(), entry.getValue());
+                buildIndexedFieldsProperty(entry.getKey(), entry.getValue(), keyCls, valCls);
 
             d.addProperty(prop, false);
 
@@ -1262,9 +1262,9 @@ public class GridQueryProcessor extends GridProcessorAdapter {
         }
 
         for (Map.Entry<String, Class<?>> entry : meta.getDescendingFields().entrySet()) {
-            Property prop = propertyType == PORTABLE_PROPERTY ?
+            Property prop = propType == PORTABLE_PROPERTY ?
                 buildPortableProperty(entry.getKey(), entry.getValue()) :
-                buildIndexedFieldsProperty(entry.getKey(), entry.getValue());
+                buildIndexedFieldsProperty(entry.getKey(), entry.getValue(), keyCls, valCls);
 
             d.addProperty(prop, false);
 
@@ -1276,9 +1276,9 @@ public class GridQueryProcessor extends GridProcessorAdapter {
         }
 
         for (String txtIdx : meta.getTextFields()) {
-            Property prop = propertyType == PORTABLE_PROPERTY ?
+            Property prop = propType == PORTABLE_PROPERTY ?
                 buildPortableProperty(txtIdx, String.class) :
-                buildIndexedFieldsProperty(txtIdx, String.class);
+                buildIndexedFieldsProperty(txtIdx, String.class, keyCls, valCls);
 
             d.addProperty(prop, false);
 
@@ -1296,9 +1296,9 @@ public class GridQueryProcessor extends GridProcessorAdapter {
                 int order = 0;
 
                 for (Map.Entry<String, IgniteBiTuple<Class<?>, Boolean>> idxField : idxFields.entrySet()) {
-                    Property prop = propertyType == PORTABLE_PROPERTY ?
+                    Property prop = propType == PORTABLE_PROPERTY ?
                         buildPortableProperty(idxField.getKey(), idxField.getValue().get1()) :
-                        buildIndexedFieldsProperty(idxField.getKey(), idxField.getValue().get1());
+                        buildIndexedFieldsProperty(idxField.getKey(), idxField.getValue().get1(), keyCls, valCls);
 
                     d.addProperty(prop, false);
 
@@ -1312,9 +1312,9 @@ public class GridQueryProcessor extends GridProcessorAdapter {
         }
 
         for (Map.Entry<String, Class<?>> entry : meta.getQueryFields().entrySet()) {
-            Property prop = propertyType == PORTABLE_PROPERTY ?
+            Property prop = propType == PORTABLE_PROPERTY ?
                 buildPortableProperty(entry.getKey(), entry.getValue()) :
-                buildIndexedFieldsProperty(entry.getKey(), entry.getValue());
+                buildIndexedFieldsProperty(entry.getKey(), entry.getValue(), keyCls, valCls);
 
             if (!d.props.containsKey(prop.name()))
                 d.addProperty(prop, false);
@@ -1421,15 +1421,18 @@ public class GridQueryProcessor extends GridProcessorAdapter {
      * @param pathStr String representing path to the property. May contains dots '.' to identify
      *      nested fields.
      * @param resType Result type.
+     * @param keyCls Key class.
+     * @param valCls Value class.
      * @return Portable property.
      */
-    private IndexedFieldsProperty buildIndexedFieldsProperty(String pathStr, Class<?> resType) {
+    private IndexedFieldsProperty buildIndexedFieldsProperty(String pathStr, Class<?> resType,
+        @Nullable Class<?> keyCls, @Nullable Class<?> valCls) {
         String[] path = pathStr.split("\\.");
 
         IndexedFieldsProperty res = null;
 
         for (String prop : path)
-            res = new IndexedFieldsProperty(prop, res, resType);
+            res = new IndexedFieldsProperty(prop, res, resType, keyCls, valCls);
 
         return res;
     }
@@ -1699,9 +1702,9 @@ public class GridQueryProcessor extends GridProcessorAdapter {
                 if (isKeyProp0 == 0) {
                     // Key is allowed to be a non-portable object here.
                     // We check key before value consistently with ClassProperty.
-                    if (ctx.cacheObjects().isPortableObject(key) && ctx.cacheObjects().hasField(key, propName))
+                    if (ctx.cacheObjects().isPortableObject(key) && ctx.cacheObjects().hasField(key, propName, null))
                         isKeyProp = isKeyProp0 = 1;
-                    else if (ctx.cacheObjects().hasField(val, propName))
+                    else if (ctx.cacheObjects().hasField(val, propName, null))
                         isKeyProp = isKeyProp0 = -1;
                     else {
                         U.warn(log, "Neither key nor value have property " +
@@ -1714,7 +1717,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
                 obj = isKeyProp0 == 1 ? key : val;
             }
 
-            return ctx.cacheObjects().field(obj, propName);
+            return ctx.cacheObjects().field(obj, propName, null);
         }
 
         /** {@inheritDoc} */
@@ -1741,17 +1744,49 @@ public class GridQueryProcessor extends GridProcessorAdapter {
         /** Result class. */
         private Class<?> type;
 
+        /** Key field */
+        private Field keyField;
+
+        /** Value field */
+        private Field valueField;
+
         /**
          * Constructor.
          *
          * @param propName Property name.
          * @param parent Parent property.
          * @param type Result type.
+         * @param keyCls Key class.
+         * @param valCls Value class.
          */
-        private IndexedFieldsProperty(String propName, IndexedFieldsProperty parent, Class<?> type) {
+        private IndexedFieldsProperty(String propName, IndexedFieldsProperty parent, Class<?> type,
+            @Nullable Class<?> keyCls, @Nullable Class<?> valCls) {
             this.propName = propName;
             this.parent = parent;
             this.type = type;
+
+            if (keyCls != null) {
+                try {
+                    keyField = keyCls.getDeclaredField(propName);
+
+                    keyField.setAccessible(true);
+                } catch (NoSuchFieldException e) {
+                    // No-op
+                }
+            }
+            else if (valCls != null && keyField == null) {
+                try {
+                    valueField = valCls.getDeclaredField(propName);
+
+                    valueField.setAccessible(true);
+                } catch (NoSuchFieldException e) {
+                    // No-op
+                }
+            }
+
+            if ((keyCls != null || valCls != null) && keyField == null && valueField == null)
+                U.warn(log, "Neither key nor value class has field " +
+                    "[fieldName=" + propName + ", key=" + keyCls + ", val=" + valCls + "]");
         }
 
         /** {@inheritDoc} */
@@ -1768,28 +1803,45 @@ public class GridQueryProcessor extends GridProcessorAdapter {
                     throw new IgniteCheckedException("Non-indexed object received as a result of property extraction " +
                         "[parent=" + parent + ", propName=" + propName + ", obj=" + obj + ']');
 
-                return ctx.cacheObjects().field(obj, propName);
+                return ctx.cacheObjects().field(obj, propName, keyField != null ? keyField : valueField);
             }
             else {
                 if (key instanceof CacheIndexedObjectImpl) {
                     try {
-                        return ctx.cacheObjects().field(key, propName);
+
+                        return ctx.cacheObjects().field(key, propName, keyField);
                     }
                     catch (IgniteFieldNotFoundException e) {
                         // Ignore
                     }
                 }
+                else if (keyField != null) {
+                    try {
+                        return keyField.get(key);
+                    }
+                    catch (Exception e) {
+                        throw new IgniteCheckedException(e);
+                    }
+                }
 
                 if (val instanceof CacheIndexedObjectImpl) {
                     try {
-                        return ctx.cacheObjects().field(val, propName);
+                        return ctx.cacheObjects().field(val, propName, valueField);
                     }
                     catch (IgniteFieldNotFoundException e) {
                         // Ignore
                     }
                 }
+                else if (valueField != null) {
+                    try {
+                        return valueField.get(val);
+                    }
+                    catch (Exception e) {
+                        throw new IgniteCheckedException(e);
+                    }
+                }
 
-                U.warn(log, "Neither key nor value have property " +
+                U.warn(log, "Neither key nor value has property " +
                     "[propName=" + propName + ", key=" + key + ", val=" + val + "]");
 
                 return null;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/28f8edaf/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/IgniteFieldNotFoundException.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/IgniteFieldNotFoundException.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/IgniteFieldNotFoundException.java
index e5c3b5f..ac9808f 100644
--- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/IgniteFieldNotFoundException.java
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/IgniteFieldNotFoundException.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.marshaller.optimized;
 
 import org.apache.ignite.*;
+import org.jetbrains.annotations.*;
 
 /**
  * Exception is thrown when there is an attempt to retrieve or deserialize an unexisting field from byte array
@@ -35,4 +36,14 @@ public class IgniteFieldNotFoundException extends IgniteCheckedException {
     public IgniteFieldNotFoundException(String msg) {
         super(msg);
     }
+
+    /**
+     * Creates new exception with given error message and optional nested exception.
+     *
+     * @param msg Error message.
+     * @param cause Optional nested exception (can be {@code null}).
+     */
+    public IgniteFieldNotFoundException(String msg, @Nullable Throwable cause) {
+        super(msg, cause);
+    }
 }