You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2015/11/27 10:37:02 UTC

[3/4] ignite git commit: IGNITE-1956: Added binary enums support.

IGNITE-1956: Added binary enums support.


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

Branch: refs/heads/ignite-1.5
Commit: 663e78dc65dcf6d8369f13ef8bf6c4aeacb6299d
Parents: 30c9b8d
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Fri Nov 27 12:37:27 2015 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Fri Nov 27 12:37:27 2015 +0300

----------------------------------------------------------------------
 .../java/org/apache/ignite/IgniteBinary.java    |   9 +
 .../org/apache/ignite/binary/BinaryObject.java  |   8 +
 .../org/apache/ignite/binary/BinaryType.java    |   7 +
 .../ignite/binary/BinaryTypeConfiguration.java  |  21 +
 .../communication/GridIoMessageFactory.java     |   8 +-
 .../internal/portable/BinaryEnumObjectImpl.java | 311 +++++++++++++
 .../internal/portable/BinaryMetadata.java       |  16 +-
 .../internal/portable/BinaryObjectExImpl.java   |   5 +
 .../internal/portable/BinaryObjectImpl.java     |   3 -
 .../internal/portable/BinaryTypeImpl.java       |   9 +-
 .../internal/portable/BinaryWriteMode.java      |   3 +
 .../internal/portable/BinaryWriterExImpl.java   |  19 +
 .../portable/PortableClassDescriptor.java       |  23 +-
 .../internal/portable/PortableContext.java      |  39 +-
 .../ignite/internal/portable/PortableUtils.java | 147 +++++-
 .../builder/BinaryObjectBuilderImpl.java        |   2 +-
 .../builder/PortableBuilderSerializer.java      |  10 +-
 .../internal/processors/cache/CacheObject.java  |   3 +
 .../processors/cache/CacheObjectContext.java    |  19 +
 .../portable/CacheObjectBinaryProcessor.java    |  11 +-
 .../CacheObjectBinaryProcessorImpl.java         |  18 +-
 .../cache/portable/IgniteBinaryImpl.java        |  12 +
 .../processors/cacheobject/NoOpBinary.java      |   5 +
 .../platform/PlatformContextImpl.java           |  53 ++-
 .../transactions/PlatformTransactions.java      |   4 +-
 .../platform/utils/PlatformUtils.java           |   1 +
 .../PlatformDotNetBinaryTypeConfiguration.java  |  23 +
 .../internal/portable/BinaryEnumsSelfTest.java  | 446 +++++++++++++++++++
 .../portable/BinaryMarshallerSelfTest.java      |  37 +-
 .../platform/PlatformComputeEchoTask.java       |   4 +-
 .../IgnitePortableObjectsTestSuite.java         |   2 +
 .../impl/binary/binary_type_updater_impl.cpp    |   4 +-
 .../Binary/BinaryBuilderSelfTest.cs             |  97 ++--
 .../Binary/BinarySelfTest.cs                    |  48 +-
 .../Cache/CacheAbstractTest.cs                  |  17 +-
 .../Compute/ComputeApiTest.cs                   |   6 +
 .../Config/Compute/compute-grid1.xml            |   3 +-
 .../Config/native-client-test-cache-store.xml   |   1 +
 .../Services/ServiceProxyTest.cs                |  22 +-
 .../Apache.Ignite.Core.csproj                   |   5 +-
 .../Binary/BinaryTypeConfiguration.cs           |  16 +-
 .../dotnet/Apache.Ignite.Core/Binary/IBinary.cs | 136 ++++++
 .../Apache.Ignite.Core/Binary/IBinaryObject.cs  |  23 +-
 .../Apache.Ignite.Core/Binary/IBinaryType.cs    |  13 +
 .../Apache.Ignite.Core/Binary/IIgniteBinary.cs  | 120 -----
 .../dotnet/Apache.Ignite.Core/IIgnite.cs        |   6 +-
 .../Apache.Ignite.Core/Impl/Binary/Binary.cs    | 216 +++++++++
 .../Impl/Binary/BinaryEnum.cs                   | 134 ++++++
 .../Impl/Binary/BinaryFullTypeDescriptor.cs     |  14 +-
 .../Impl/Binary/BinaryObject.cs                 |  29 ++
 .../Impl/Binary/BinaryObjectBuilder.cs          |  44 +-
 .../Impl/Binary/BinaryReader.cs                 |  51 ++-
 .../Binary/BinarySurrogateTypeDescriptor.cs     |   6 +
 .../Impl/Binary/BinarySystemHandlers.cs         |  34 +-
 .../Impl/Binary/BinaryUtils.cs                  |  96 ++--
 .../Impl/Binary/BinaryWriter.cs                 | 104 +++--
 .../Impl/Binary/IBinaryTypeDescriptor.cs        |  50 +--
 .../Impl/Binary/IgniteBinary.cs                 | 192 --------
 .../Impl/Binary/Marshaller.cs                   |  88 ++--
 .../Impl/Binary/Metadata/BinaryType.cs          | 184 ++++----
 .../Impl/Binary/Metadata/BinaryTypeHolder.cs    |  34 +-
 .../Binary/Structure/BinaryStructureTracker.cs  |   2 +-
 .../dotnet/Apache.Ignite.Core/Impl/Ignite.cs    |  11 +-
 .../Apache.Ignite.Core/Impl/IgniteProxy.cs      |   2 +-
 .../Apache.Ignite.Core/Impl/PlatformTarget.cs   |  11 +-
 .../Impl/Transactions/TransactionsImpl.cs       |   4 +-
 .../examples/Config/example-cache-query.xml     |   9 +-
 .../dotnet/examples/Config/example-cache.xml    |   9 +-
 68 files changed, 2354 insertions(+), 765 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/IgniteBinary.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteBinary.java b/modules/core/src/main/java/org/apache/ignite/IgniteBinary.java
index 30db9d9..a1c656b 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteBinary.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteBinary.java
@@ -351,4 +351,13 @@ public interface IgniteBinary {
      * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
      */
     public Collection<BinaryType> types() throws BinaryObjectException;
+
+    /**
+     * Create enum object.
+     *
+     * @param typeName Type name.
+     * @param ord Ordinal.
+     * @return Enum object.
+     */
+    public BinaryObject buildEnum(String typeName, int ord);
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/binary/BinaryObject.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/binary/BinaryObject.java b/modules/core/src/main/java/org/apache/ignite/binary/BinaryObject.java
index 249daab..f4afd8d 100644
--- a/modules/core/src/main/java/org/apache/ignite/binary/BinaryObject.java
+++ b/modules/core/src/main/java/org/apache/ignite/binary/BinaryObject.java
@@ -139,4 +139,12 @@ public interface BinaryObject extends Serializable, Cloneable {
      * @return Copy of this binary object.
      */
     public BinaryObject clone() throws CloneNotSupportedException;
+
+    /**
+     * Get ordinal for this enum object. Use {@link BinaryType#isEnum()} to check if object is of enum type.
+     *
+     * @return Ordinal.
+     * @throws BinaryObjectException If object is not enum.
+     */
+    public int enumOrdinal() throws BinaryObjectException;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/binary/BinaryType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/binary/BinaryType.java b/modules/core/src/main/java/org/apache/ignite/binary/BinaryType.java
index debd7e5..f184a8c 100644
--- a/modules/core/src/main/java/org/apache/ignite/binary/BinaryType.java
+++ b/modules/core/src/main/java/org/apache/ignite/binary/BinaryType.java
@@ -72,4 +72,11 @@ public interface BinaryType {
      * @return Affinity key field name.
      */
     public String affinityKeyFieldName();
+
+    /**
+     * Check whether type represents enum or not.
+     *
+     * @return {@code True} if type is enum.
+     */
+    public boolean isEnum();
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java b/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java
index d216866..a694eaf 100644
--- a/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java
@@ -38,6 +38,9 @@ public class BinaryTypeConfiguration {
     /** Serializer. */
     private BinarySerializer serializer;
 
+    /** Enum flag. */
+    private boolean isEnum;
+
     /**
      */
     public BinaryTypeConfiguration() {
@@ -105,6 +108,24 @@ public class BinaryTypeConfiguration {
         this.serializer = serializer;
     }
 
+    /**
+     * Gets whether this is enum type.
+     *
+     * @return {@code True} if enum.
+     */
+    public boolean isEnum() {
+        return isEnum;
+    }
+
+    /**
+     * Sets whether this is enum type.
+     *
+     * @param isEnum {@code True} if enum.
+     */
+    public void setEnum(boolean isEnum) {
+        this.isEnum = isEnum;
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(BinaryTypeConfiguration.class, this, super.toString());

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
index 02bd5ec..c9b8e27 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
@@ -31,6 +31,7 @@ import org.apache.ignite.internal.managers.deployment.GridDeploymentInfoBean;
 import org.apache.ignite.internal.managers.deployment.GridDeploymentRequest;
 import org.apache.ignite.internal.managers.deployment.GridDeploymentResponse;
 import org.apache.ignite.internal.managers.eventstorage.GridEventStorageMessage;
+import org.apache.ignite.internal.portable.BinaryEnumObjectImpl;
 import org.apache.ignite.internal.portable.BinaryObjectImpl;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheEntryInfoCollection;
@@ -714,7 +715,12 @@ public class GridIoMessageFactory implements MessageFactory {
 
                 break;
 
-            // [-3..118] - this
+            case 119:
+                msg = new BinaryEnumObjectImpl();
+
+                break;
+
+            // [-3..119] - this
             // [120..123] - DR
             // [-4..-22] - SQL
             default:

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryEnumObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryEnumObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryEnumObjectImpl.java
new file mode 100644
index 0000000..e13c076
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryEnumObjectImpl.java
@@ -0,0 +1,311 @@
+/*
+ * 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.portable;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryType;
+import org.apache.ignite.internal.GridDirectTransient;
+import org.apache.ignite.internal.processors.cache.CacheObject;
+import org.apache.ignite.internal.processors.cache.CacheObjectContext;
+import org.apache.ignite.internal.processors.cache.portable.CacheObjectBinaryProcessorImpl;
+import org.apache.ignite.internal.util.typedef.internal.SB;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.nio.ByteBuffer;
+
+/**
+ * Binary enum object.
+ */
+public class BinaryEnumObjectImpl implements BinaryObjectEx, Externalizable, CacheObject {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Context. */
+    @GridDirectTransient
+    private PortableContext ctx;
+
+    /** Type ID. */
+    private int typeId;
+
+    /** Raw data. */
+    private String clsName;
+
+    /** Ordinal. */
+    private int ord;
+
+    /**
+     * {@link Externalizable} support.
+     */
+    public BinaryEnumObjectImpl() {
+        // No-op.
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param ctx Context.
+     * @param typeId Type ID.
+     * @param clsName Class name.
+     * @param ord Ordinal.
+     */
+    public BinaryEnumObjectImpl(PortableContext ctx, int typeId, @Nullable String clsName, int ord) {
+        assert ctx != null;
+
+        this.ctx = ctx;
+        this.typeId = typeId;
+        this.clsName = clsName;
+        this.ord = ord;
+    }
+
+    /**
+     * @return Class name.
+     */
+    @Nullable public String className() {
+        return clsName;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int typeId() {
+        return typeId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public BinaryType type() throws BinaryObjectException {
+        return ctx.metadata(typeId());
+    }
+
+    /** {@inheritDoc} */
+    @Override public <F> F field(String fieldName) throws BinaryObjectException {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean hasField(String fieldName) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
+    @Override public <T> T deserialize() throws BinaryObjectException {
+        Class cls = PortableUtils.resolveClass(ctx, typeId, clsName, null);
+
+        return BinaryEnumCache.get(cls, ord);
+    }
+
+    /** {@inheritDoc} */
+    @Override public BinaryObject clone() throws CloneNotSupportedException {
+        return (BinaryObject)super.clone();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int enumOrdinal() throws BinaryObjectException {
+        return ord;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        return 31 * typeId + ord;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (obj != null && (obj instanceof BinaryEnumObjectImpl)) {
+            BinaryEnumObjectImpl other = (BinaryEnumObjectImpl)obj;
+
+            return typeId == other.typeId && ord == other.ord;
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        // 1. Try deserializing the object.
+        try {
+            Object val = deserialize();
+
+            return new SB().a(val).toString();
+        }
+        catch (Exception e) {
+            // No-op.
+        }
+
+        // 2. Try getting meta.
+        BinaryType type;
+
+        try {
+            type = type();
+        }
+        catch (Exception e) {
+            type = null;
+        }
+
+        if (type != null) {
+            return type.typeName() + "[ordinal=" + ord  + ']';
+        }
+        else {
+            if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID)
+                return "BinaryEnum[clsName=" + clsName + ", ordinal=" + ord + ']';
+            else
+                return "BinaryEnum[typeId=" + typeId + ", ordinal=" + ord + ']';
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject(ctx);
+
+        out.writeInt(typeId);
+        out.writeObject(clsName);
+        out.writeInt(ord);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        ctx = (PortableContext)in.readObject();
+
+        typeId = in.readInt();
+        clsName = (String)in.readObject();
+        ord = in.readInt();
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public <T> T value(CacheObjectContext ctx, boolean cpy) {
+        return deserialize();
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte[] valueBytes(CacheObjectContext cacheCtx) throws IgniteCheckedException {
+        return ctx.marshaller().marshal(this);
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte cacheObjectType() {
+        return TYPE_BINARY;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isPlatformType() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public CacheObject prepareForCache(CacheObjectContext ctx) {
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void finishUnmarshal(CacheObjectContext ctx, ClassLoader ldr) throws IgniteCheckedException {
+        this.ctx = ((CacheObjectBinaryProcessorImpl)ctx.processor()).portableContext();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void prepareMarshal(CacheObjectContext ctx) throws IgniteCheckedException {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte directType() {
+        return 119;
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte fieldsCount() {
+        return 3;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+        writer.setBuffer(buf);
+
+        if (!writer.isHeaderWritten()) {
+            if (!writer.writeHeader(directType(), fieldsCount()))
+                return false;
+
+            writer.onHeaderWritten();
+        }
+
+        switch (writer.state()) {
+            case 0:
+                if (!writer.writeString("clsName", clsName))
+                    return false;
+
+                writer.incrementState();
+
+            case 1:
+                if (!writer.writeInt("ord", ord))
+                    return false;
+
+                writer.incrementState();
+
+            case 2:
+                if (!writer.writeInt("typeId", typeId))
+                    return false;
+
+                writer.incrementState();
+
+        }
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+        reader.setBuffer(buf);
+
+        if (!reader.beforeMessageRead())
+            return false;
+
+        switch (reader.state()) {
+            case 0:
+                clsName = reader.readString("clsName");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 1:
+                ord = reader.readInt("ord");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 2:
+                typeId = reader.readInt("typeId");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+        }
+
+        return reader.afterMessageRead(BinaryEnumObjectImpl.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadata.java
index a464d6e..8ba2e23 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadata.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadata.java
@@ -52,6 +52,9 @@ public class BinaryMetadata implements Externalizable {
     /** Schemas associated with type. */
     private Collection<PortableSchema> schemas;
 
+    /** Whether this is enum type. */
+    private boolean isEnum;
+
     /**
      * For {@link Externalizable}.
      */
@@ -67,9 +70,10 @@ public class BinaryMetadata implements Externalizable {
      * @param fields Fields map.
      * @param affKeyFieldName Affinity key field name.
      * @param schemas Schemas.
+     * @param isEnum Enum flag.
      */
     public BinaryMetadata(int typeId, String typeName, @Nullable Map<String, Integer> fields,
-        @Nullable String affKeyFieldName, @Nullable Collection<PortableSchema> schemas) {
+        @Nullable String affKeyFieldName, @Nullable Collection<PortableSchema> schemas, boolean isEnum) {
         assert typeName != null;
 
         this.typeId = typeId;
@@ -77,6 +81,7 @@ public class BinaryMetadata implements Externalizable {
         this.fields = fields;
         this.affKeyFieldName = affKeyFieldName;
         this.schemas = schemas;
+        this.isEnum = isEnum;
     }
 
     /**
@@ -132,6 +137,13 @@ public class BinaryMetadata implements Externalizable {
     }
 
     /**
+     * @return {@code True} if this is enum type.
+     */
+    public boolean isEnum() {
+        return isEnum;
+    }
+
+    /**
      * Wrap metadata into binary type.
      *
      * @param ctx Portable context.
@@ -148,6 +160,7 @@ public class BinaryMetadata implements Externalizable {
         U.writeMap(out, fields);
         U.writeString(out, affKeyFieldName);
         U.writeCollection(out, schemas);
+        out.writeBoolean(isEnum);
     }
 
     /** {@inheritDoc} */
@@ -157,6 +170,7 @@ public class BinaryMetadata implements Externalizable {
         fields = U.readMap(in);
         affKeyFieldName = U.readString(in);
         schemas = U.readCollection(in);
+        isEnum = in.readBoolean();
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectExImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectExImpl.java
index 7497bd3..2ea71ec 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectExImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectExImpl.java
@@ -66,6 +66,11 @@ public abstract class BinaryObjectExImpl implements BinaryObjectEx {
      */
     @Nullable public abstract <F> F field(int fieldId) throws BinaryObjectException;
 
+    /** {@inheritDoc} */
+    @Override public int enumOrdinal() throws BinaryObjectException {
+        throw new BinaryObjectException("Object is not enum.");
+    }
+
     /**
      * Get field by offset.
      *

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectImpl.java
index f683ed9..87a03dc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectImpl.java
@@ -66,9 +66,6 @@ import static org.apache.ignite.internal.portable.GridPortableMarshaller.UUID;
 @IgniteCodeGeneratingFail // Fields arr and start should not be generated by MessageCodeGenerator.
 public final class BinaryObjectImpl extends BinaryObjectExImpl implements Externalizable, KeyCacheObject {
     /** */
-    public static final byte TYPE_BINARY = 100;
-
-    /** */
     private static final long serialVersionUID = 0L;
 
     /** */

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryTypeImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryTypeImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryTypeImpl.java
index c3fee7e..9512cdb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryTypeImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryTypeImpl.java
@@ -72,9 +72,12 @@ public class BinaryTypeImpl implements BinaryType {
         return meta.affinityKeyFieldName();
     }
 
-    /**
-     * @return Portable context.
-     */
+    /** {@inheritDoc} */
+    @Override public boolean isEnum() {
+        return meta.isEnum();
+    }
+
+    /** {@inheritDoc} */
     public PortableContext context() {
         return ctx;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriteMode.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriteMode.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriteMode.java
index a26b741..bd73ad0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriteMode.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriteMode.java
@@ -141,6 +141,9 @@ public enum BinaryWriteMode {
     /** */
     ENUM(GridPortableMarshaller.ENUM),
 
+    /** Portable enum. */
+    PORTABLE_ENUM(GridPortableMarshaller.ENUM),
+
     /** */
     ENUM_ARR(GridPortableMarshaller.ENUM_ARR),
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriterExImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriterExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriterExImpl.java
index ec47f57..9d1d037 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriterExImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriterExImpl.java
@@ -803,6 +803,25 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
     }
 
     /**
+     * @param val Value.
+     */
+    void doWritePortableEnum(BinaryEnumObjectImpl val) {
+        assert val != null;
+
+        int typeId = val.typeId();
+
+        out.unsafeEnsure(1 + 4);
+
+        out.unsafeWriteByte(ENUM);
+        out.unsafeWriteInt(typeId);
+
+        if (typeId == UNREGISTERED_TYPE_ID)
+            doWriteString(val.className());
+
+        out.writeInt(val.enumOrdinal());
+    }
+
+    /**
      * @param val Array.
      */
     void doWriteEnumArray(@Nullable Object[] val) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java
index fa6ea3a..dba15f5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java
@@ -161,8 +161,12 @@ public class PortableClassDescriptor {
 
         if (excluded)
             mode = BinaryWriteMode.EXCLUSION;
-        else
-            mode = serializer != null ? BinaryWriteMode.PORTABLE : PortableUtils.mode(cls);
+        else {
+            if (cls == BinaryEnumObjectImpl.class)
+                mode = BinaryWriteMode.PORTABLE_ENUM;
+            else
+                mode = serializer != null ? BinaryWriteMode.PORTABLE : PortableUtils.mode(cls);
+        }
 
         switch (mode) {
             case P_BYTE:
@@ -205,6 +209,7 @@ public class PortableClassDescriptor {
             case MAP_ENTRY:
             case PORTABLE_OBJ:
             case ENUM:
+            case PORTABLE_ENUM:
             case ENUM_ARR:
             case CLASS:
             case EXCLUSION:
@@ -286,6 +291,13 @@ public class PortableClassDescriptor {
     }
 
     /**
+     * @return {@code True} if enum.
+     */
+    boolean isEnum() {
+        return mode == BinaryWriteMode.ENUM;
+    }
+
+    /**
      * @return Described class.
      */
     Class<?> describedClass() {
@@ -534,6 +546,11 @@ public class PortableClassDescriptor {
 
                 break;
 
+            case PORTABLE_ENUM:
+                writer.doWritePortableEnum((BinaryEnumObjectImpl)obj);
+
+                break;
+
             case ENUM_ARR:
                 writer.doWriteEnumArray((Object[])obj);
 
@@ -576,7 +593,7 @@ public class PortableClassDescriptor {
                                 PortableSchema newSchema = collector.schema();
 
                                 BinaryMetadata meta = new BinaryMetadata(typeId, typeName, collector.meta(),
-                                    affKeyFieldName, Collections.singleton(newSchema));
+                                    affKeyFieldName, Collections.singleton(newSchema), false);
 
                                 ctx.updateMetadata(typeId, meta);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java
index ab96ed1..ae0d940 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java
@@ -117,6 +117,9 @@ public class PortableContext implements Externalizable {
     /** */
     private BinaryMetadataHandler metaHnd;
 
+    /** Actual marshaller. */
+    private BinaryMarshaller marsh;
+
     /** */
     private MarshallerContext marshCtx;
 
@@ -222,6 +225,13 @@ public class PortableContext implements Externalizable {
     }
 
     /**
+     * @return Marshaller.
+     */
+    public BinaryMarshaller marshaller() {
+        return marsh;
+    }
+
+    /**
      * @param marsh Portable marshaller.
      * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
      */
@@ -229,6 +239,8 @@ public class PortableContext implements Externalizable {
         if (marsh == null)
             return;
 
+        this.marsh = marsh;
+
         marshCtx = marsh.getContext();
 
         BinaryConfiguration binaryCfg = cfg.getBinaryConfiguration();
@@ -293,16 +305,16 @@ public class PortableContext implements Externalizable {
 
                     for (String clsName0 : classesInPackage(pkgName))
                         descs.add(clsName0, idMapper, serializer, affFields.get(clsName0),
-                            true);
+                            typeCfg.isEnum(), true);
                 }
                 else
                     descs.add(clsName, idMapper, serializer, affFields.get(clsName),
-                        false);
+                        typeCfg.isEnum(), false);
             }
         }
 
         for (TypeDescriptor desc : descs.descriptors()) {
-            registerUserType(desc.clsName, desc.idMapper, desc.serializer, desc.affKeyFieldName);
+            registerUserType(desc.clsName, desc.idMapper, desc.serializer, desc.affKeyFieldName, desc.isEnum);
         }
 
         BinaryInternalIdMapper dfltMapper = BinaryInternalIdMapper.create(globalIdMapper);
@@ -535,7 +547,8 @@ public class PortableContext implements Externalizable {
 
         Collection<PortableSchema> schemas = desc.schema() != null ? Collections.singleton(desc.schema()) : null;
 
-        metaHnd.addMeta(typeId, new BinaryMetadata(typeId, typeName, desc.fieldsMeta(), affFieldName, schemas).wrap(this));
+        metaHnd.addMeta(typeId, 
+            new BinaryMetadata(typeId, typeName, desc.fieldsMeta(), affFieldName, schemas, desc.isEnum()).wrap(this));
 
         // perform put() instead of putIfAbsent() because "registered" flag might have been changed or class loader
         // might have reloaded described class.
@@ -628,7 +641,7 @@ public class PortableContext implements Externalizable {
      * @return Affinity field name or {@code null} if field name was not found.
      */
     private String affinityFieldName(Class cls) {
-        for (; cls != Object.class; cls = cls.getSuperclass()) {
+        for (; cls != Object.class && cls != null; cls = cls.getSuperclass()) {
             for (Field f : cls.getDeclaredFields()) {
                 if (f.getAnnotation(AffinityKeyMapped.class) != null)
                     return f.getName();
@@ -701,13 +714,15 @@ public class PortableContext implements Externalizable {
      * @param idMapper ID mapper.
      * @param serializer Serializer.
      * @param affKeyFieldName Affinity key field name.
+     * @param isEnum If enum.
      * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
      */
     @SuppressWarnings("ErrorNotRethrown")
     public void registerUserType(String clsName,
         BinaryIdMapper idMapper,
         @Nullable BinarySerializer serializer,
-        @Nullable String affKeyFieldName)
+        @Nullable String affKeyFieldName,
+        boolean isEnum)
         throws BinaryObjectException {
         assert idMapper != null;
 
@@ -765,7 +780,7 @@ public class PortableContext implements Externalizable {
             descByCls.put(cls, desc);
         }
 
-        metaHnd.addMeta(id, new BinaryMetadata(id, typeName, fieldsMeta, affKeyFieldName, schemas).wrap(this));
+        metaHnd.addMeta(id, new BinaryMetadata(id, typeName, fieldsMeta, affKeyFieldName, schemas, isEnum).wrap(this));
     }
 
     /**
@@ -940,6 +955,7 @@ public class PortableContext implements Externalizable {
          * @param idMapper ID mapper.
          * @param serializer Serializer.
          * @param affKeyFieldName Affinity key field name.
+         * @param isEnum Enum flag.
          * @param canOverride Whether this descriptor can be override.
          * @throws org.apache.ignite.binary.BinaryObjectException If failed.
          */
@@ -947,12 +963,14 @@ public class PortableContext implements Externalizable {
             BinaryIdMapper idMapper,
             BinarySerializer serializer,
             String affKeyFieldName,
+            boolean isEnum,
             boolean canOverride)
             throws BinaryObjectException {
             TypeDescriptor desc = new TypeDescriptor(clsName,
                 idMapper,
                 serializer,
                 affKeyFieldName,
+                isEnum,
                 canOverride);
 
             TypeDescriptor oldDesc = descs.get(clsName);
@@ -989,6 +1007,9 @@ public class PortableContext implements Externalizable {
         /** Affinity key field name. */
         private String affKeyFieldName;
 
+        /** Enum flag. */
+        private boolean isEnum;
+
         /** Whether this descriptor can be override. */
         private boolean canOverride;
 
@@ -999,14 +1020,16 @@ public class PortableContext implements Externalizable {
          * @param idMapper ID mapper.
          * @param serializer Serializer.
          * @param affKeyFieldName Affinity key field name.
+         * @param isEnum Enum type.
          * @param canOverride Whether this descriptor can be override.
          */
         private TypeDescriptor(String clsName, BinaryIdMapper idMapper, BinarySerializer serializer,
-            String affKeyFieldName, boolean canOverride) {
+            String affKeyFieldName, boolean isEnum, boolean canOverride) {
             this.clsName = clsName;
             this.idMapper = idMapper;
             this.serializer = serializer;
             this.affKeyFieldName = affKeyFieldName;
+            this.isEnum = isEnum;
             this.canOverride = canOverride;
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
index a83405d..e543c41 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
@@ -877,6 +877,16 @@ public class PortableUtils {
                 );
             }
 
+            // Check enum flag.
+            if (oldMeta.isEnum() != newMeta.isEnum()) {
+                if (oldMeta.isEnum())
+                    throw new BinaryObjectException("Binary type already registered as enum: " +
+                        newMeta.typeName());
+                else
+                    throw new BinaryObjectException("Binary type already registered as non-enum: " +
+                        newMeta.typeName());
+            }
+
             // Check and merge fields.
             boolean changed = false;
 
@@ -908,7 +918,7 @@ public class PortableUtils {
 
             // Return either old meta if no changes detected, or new merged meta.
             return changed ? new BinaryMetadata(oldMeta.typeId(), oldMeta.typeName(), mergedFields,
-                oldMeta.affinityKeyFieldName(), mergedSchemas) : oldMeta;
+                oldMeta.affinityKeyFieldName(), mergedSchemas, oldMeta.isEnum()) : oldMeta;
         }
     }
 
@@ -1314,6 +1324,37 @@ public class PortableUtils {
     }
 
     /**
+     * Read plain type.
+     *
+     * @param in Input stream.
+     * @return Plain type.
+     */
+    private static EnumType doReadEnumType(PortableInputStream in) {
+        int typeId = in.readInt();
+
+        if (typeId != UNREGISTERED_TYPE_ID)
+            return new EnumType(typeId, null);
+        else {
+            String clsName = doReadClassName(in);
+
+            return new EnumType(UNREGISTERED_TYPE_ID, clsName);
+        }
+    }
+
+    /**
+     * @param in Input stream.
+     * @return Class name.
+     */
+    private static String doReadClassName(PortableInputStream in) {
+        byte flag = in.readByte();
+
+        if (flag != STRING)
+            throw new BinaryObjectException("Failed to read class name [position=" + (in.position() - 1) + ']');
+
+        return doReadString(in);
+    }
+
+    /**
      * @param typeId Type id.
      * @return Value.
      */
@@ -1327,13 +1368,41 @@ public class PortableUtils {
         if (typeId != UNREGISTERED_TYPE_ID)
             cls = ctx.descriptorForTypeId(true, typeId, ldr).describedClass();
         else {
-            byte flag = in.readByte();
+            String clsName = doReadClassName(in);
+
+            try {
+                cls = U.forName(clsName, ldr);
+            }
+            catch (ClassNotFoundException e) {
+                throw new BinaryInvalidTypeException("Failed to load the class: " + clsName, e);
+            }
 
-            if (flag != STRING)
-                throw new BinaryObjectException("No class definition for typeId: " + typeId);
+            // forces registering of class by type id, at least locally
+            ctx.descriptorForClass(cls);
+        }
+
+        return cls;
+    }
+
+    /**
+     * Resolve the class.
+     *
+     * @param ctx Portable context.
+     * @param typeId Type ID.
+     * @param clsName Class name.
+     * @param ldr Class loaded.
+     * @return Resovled class.
+     */
+    public static Class resolveClass(PortableContext ctx, int typeId, @Nullable String clsName,
+        @Nullable ClassLoader ldr) {
+        Class cls;
 
-            String clsName = doReadString(in);
+        if (typeId == OBJECT_TYPE_ID)
+            return Object.class;
 
+        if (typeId != UNREGISTERED_TYPE_ID)
+            cls = ctx.descriptorForTypeId(true, typeId, ldr).describedClass();
+        else {
             try {
                 cls = U.forName(clsName, ldr);
             }
@@ -1349,6 +1418,43 @@ public class PortableUtils {
     }
 
     /**
+     * Read portable enum.
+     *
+     * @param in Input stream.
+     * @param ctx Portable context.
+     * @param type Plain type.
+     * @return Enum.
+     */
+    private static BinaryEnumObjectImpl doReadPortableEnum(PortableInputStream in, PortableContext ctx,
+        EnumType type) {
+        return new BinaryEnumObjectImpl(ctx, type.typeId, type.clsName, in.readInt());
+    }
+
+    /**
+     * Read portable enum array.
+     *
+     * @param in Input stream.
+     * @param ctx Portable context.
+     * @return Enum array.
+     */
+    private static Object[] doReadPortableEnumArray(PortableInputStream in, PortableContext ctx) {
+        int len = in.readInt();
+
+        Object[] arr = (Object[]) Array.newInstance(BinaryObject.class, len);
+
+        for (int i = 0; i < len; i++) {
+            byte flag = in.readByte();
+
+            if (flag == NULL)
+                arr[i] = null;
+            else
+                arr[i] = doReadPortableEnum(in, ctx, doReadEnumType(in));
+        }
+
+        return arr;
+    }
+
+    /**
      * Having target class in place we simply read ordinal and create final representation.
      *
      * @param cls Enum class.
@@ -1589,10 +1695,12 @@ public class PortableUtils {
                 return doReadPortableObject(in, ctx);
 
             case ENUM:
-                return doReadEnum(in, doReadClass(in, ctx, ldr));
+                return doReadPortableEnum(in, ctx, doReadEnumType(in));
 
             case ENUM_ARR:
-                return doReadEnumArray(in, ctx, ldr, doReadClass(in, ctx, ldr));
+                doReadEnumType(in); // Simply skip this part as we do not need it.
+
+                return doReadPortableEnumArray(in, ctx);
 
             case CLASS:
                 return doReadClass(in, ctx, ldr);
@@ -1843,4 +1951,29 @@ public class PortableUtils {
     public static int positionForHandle(PortableInputStream in) {
         return in.position() - 1;
     }
+
+    /**
+     * Enum type.
+     */
+    private static class EnumType {
+        /** Type ID. */
+        private final int typeId;
+
+        /** Class name. */
+        private final String clsName;
+
+        /**
+         * Constructor.
+         *
+         * @param typeId Type ID.
+         * @param clsName Class name.
+         */
+        public EnumType(int typeId, @Nullable String clsName) {
+            assert typeId != UNREGISTERED_TYPE_ID && clsName == null ||
+                typeId == UNREGISTERED_TYPE_ID && clsName != null;
+
+            this.typeId = typeId;
+            this.clsName = clsName;
+        }
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java
index d330c72..5c2c713 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java
@@ -377,7 +377,7 @@ public class BinaryObjectBuilderImpl implements BinaryObjectBuilder {
                 PortableSchema curSchema = writer.currentSchema();
 
                 ctx.updateMetadata(typeId, new BinaryMetadata(typeId, typeName, fieldsMeta,
-                    ctx.affinityKeyFieldName(typeId), Collections.singleton(curSchema)));
+                    ctx.affinityKeyFieldName(typeId), Collections.singleton(curSchema), false));
 
                 schemaReg.addSchema(curSchema.schemaId(), curSchema);
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializer.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializer.java
index ee7bd65..52f84c6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializer.java
@@ -18,8 +18,10 @@
 package org.apache.ignite.internal.portable.builder;
 
 import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.internal.portable.BinaryMetadata;
 import org.apache.ignite.internal.portable.GridPortableMarshaller;
 import org.apache.ignite.internal.portable.BinaryObjectExImpl;
+import org.apache.ignite.internal.portable.PortableContext;
 import org.apache.ignite.internal.portable.PortableUtils;
 import org.apache.ignite.internal.portable.BinaryWriterExImpl;
 import org.apache.ignite.internal.util.*;
@@ -97,8 +99,14 @@ class PortableBuilderSerializer {
         }
 
         if (val.getClass().isEnum()) {
+            String typeName = PortableContext.typeName(val.getClass().getName());
+            int typeId = writer.context().typeId(typeName);
+
+            BinaryMetadata meta = new BinaryMetadata(typeId, typeName, null, null, null, true);
+            writer.context().updateMetadata(typeId, meta);
+
             writer.writeByte(GridPortableMarshaller.ENUM);
-            writer.writeInt(writer.context().typeId(val.getClass().getName()));
+            writer.writeInt(typeId);
             writer.writeInt(((Enum)val).ordinal());
 
             return;

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java
index 81129bd..2385335 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java
@@ -31,6 +31,9 @@ public interface CacheObject extends Message {
     /** */
     public static final byte TYPE_BYTE_ARR = 2;
 
+    /** */
+    public static final byte TYPE_BINARY = 100;
+
     /**
      * @param ctx Context.
      * @param cpy If {@code true} need to copy value.

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/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 b4ac5f4..b99c99f 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
@@ -176,6 +176,23 @@ import org.apache.ignite.internal.util.typedef.F;
     }
 
     /**
+     * Unwrap array of portables if needed.
+     *
+     * @param arr Array.
+     * @param keepPortable Keep portable flag.
+     * @param cpy Copy.
+     * @return Result.
+     */
+    public Object[] unwrapPortablesInArrayIfNeeded(Object[] arr, boolean keepPortable, boolean cpy) {
+        Object[] res = new Object[arr.length];
+
+        for (int i = 0; i < arr.length; i++)
+            res[i] = unwrapPortable(arr[i], keepPortable, cpy);
+
+        return res;
+    }
+
+    /**
      * Unwraps map.
      *
      * @param map Map to unwrap.
@@ -252,6 +269,8 @@ import org.apache.ignite.internal.util.typedef.F;
             return unwrapPortablesIfNeeded((Collection<Object>)o, keepPortable, cpy);
         else if (o instanceof Map)
             return unwrapPortablesIfNeeded((Map<Object, Object>)o, keepPortable, cpy);
+        else if (o instanceof Object[])
+            return unwrapPortablesInArrayIfNeeded((Object[])o, keepPortable, cpy);
         else if (o instanceof CacheObject) {
             CacheObject co = (CacheObject)o;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessor.java
index e4db77c..7ef4b91 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessor.java
@@ -57,10 +57,11 @@ public interface CacheObjectBinaryProcessor extends IgniteCacheObjectProcessor {
      * @param typeName Type name.
      * @param affKeyFieldName Affinity key field name.
      * @param fieldTypeIds Fields map.
+     * @param isEnum Enum flag.
      * @throws IgniteException In case of error.
      */
     public void updateMetadata(int typeId, String typeName, @Nullable String affKeyFieldName,
-        Map<String, Integer> fieldTypeIds) throws IgniteException;
+        Map<String, Integer> fieldTypeIds, boolean isEnum) throws IgniteException;
 
     /**
      * @param typeId Type ID.
@@ -83,6 +84,14 @@ public interface CacheObjectBinaryProcessor extends IgniteCacheObjectProcessor {
     public Collection<BinaryType> metadata() throws IgniteException;
 
     /**
+     * @param typeName Type name.
+     * @param ord ordinal.
+     * @return Enum object.
+     * @throws IgniteException If failed.
+     */
+    public BinaryObject buildEnum(String typeName, int ord) throws IgniteException;
+
+    /**
      * @return Portables interface.
      * @throws IgniteException If failed.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java
index eef39be..5b70f2a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java
@@ -30,6 +30,7 @@ import org.apache.ignite.cluster.ClusterTopologyException;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
+import org.apache.ignite.internal.portable.BinaryEnumObjectImpl;
 import org.apache.ignite.internal.portable.BinaryMetadata;
 import org.apache.ignite.internal.portable.BinaryMetadataHandler;
 import org.apache.ignite.internal.portable.BinaryObjectEx;
@@ -467,8 +468,10 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
 
     /** {@inheritDoc} */
     @Override public void updateMetadata(int typeId, String typeName, @Nullable String affKeyFieldName,
-        Map<String, Integer> fieldTypeIds) throws BinaryObjectException {
-        portableCtx.updateMetadata(typeId, new BinaryMetadata(typeId, typeName, fieldTypeIds, affKeyFieldName, null));
+        Map<String, Integer> fieldTypeIds, boolean isEnum) throws BinaryObjectException {
+        BinaryMetadata meta = new BinaryMetadata(typeId, typeName, fieldTypeIds, affKeyFieldName, null, isEnum);
+
+        portableCtx.updateMetadata(typeId, meta);
     }
 
     /** {@inheritDoc} */
@@ -555,6 +558,17 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
     }
 
     /** {@inheritDoc} */
+    @Override public BinaryObject buildEnum(String typeName, int ord) throws IgniteException {
+        typeName = PortableContext.typeName(typeName);
+
+        int typeId = portableCtx.typeId(typeName);
+
+        updateMetadata(typeId, typeName, null, null, true);
+
+        return new BinaryEnumObjectImpl(portableCtx, typeId, null, ord);
+    }
+
+    /** {@inheritDoc} */
     @Override public IgniteBinary binary() throws IgniteException {
         return portables;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/IgniteBinaryImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/IgniteBinaryImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/IgniteBinaryImpl.java
index 41aa68c..7008502 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/IgniteBinaryImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/IgniteBinaryImpl.java
@@ -143,6 +143,18 @@ public class IgniteBinaryImpl implements IgniteBinary {
         }
     }
 
+    /** {@inheritDoc} */
+    @Override public BinaryObject buildEnum(String typeName, int ord) {
+        guard();
+
+        try {
+            return proc.buildEnum(typeName, ord);
+        }
+        finally {
+            unguard();
+        }
+    }
+
     /**
      * @return Portable processor.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/NoOpBinary.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/NoOpBinary.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/NoOpBinary.java
index 252baed..80e7b39 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/NoOpBinary.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/NoOpBinary.java
@@ -69,6 +69,11 @@ public class NoOpBinary implements IgniteBinary {
     }
 
     /** {@inheritDoc} */
+    @Override public BinaryObject buildEnum(String typeName, int ord) {
+        throw unsupported();
+    }
+
+    /** {@inheritDoc} */
     private BinaryObjectException unsupported() {
         return new BinaryObjectException("Binary marshaller is not configured.");
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
index 7db752a..71f42e2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
@@ -69,7 +69,6 @@ import org.apache.ignite.internal.processors.platform.utils.PlatformReaderBiClos
 import org.apache.ignite.internal.processors.platform.utils.PlatformReaderClosure;
 import org.apache.ignite.internal.processors.platform.utils.PlatformUtils;
 import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.internal.util.typedef.T4;
 import org.apache.ignite.lang.IgniteBiTuple;
 import org.jetbrains.annotations.Nullable;
 
@@ -341,9 +340,9 @@ public class PlatformContextImpl implements PlatformContext {
     /** {@inheritDoc} */
     @SuppressWarnings("ConstantConditions")
     @Override public void processMetadata(BinaryRawReaderEx reader) {
-        Collection<T4<Integer, String, String, Map<String, Integer>>> metas = PlatformUtils.readCollection(reader,
-            new PlatformReaderClosure<T4<Integer, String, String, Map<String, Integer>>>() {
-                @Override public T4<Integer, String, String, Map<String, Integer>> read(BinaryRawReaderEx reader) {
+        Collection<Metadata> metas = PlatformUtils.readCollection(reader,
+            new PlatformReaderClosure<Metadata>() {
+                @Override public Metadata read(BinaryRawReaderEx reader) {
                     int typeId = reader.readInt();
                     String typeName = reader.readString();
                     String affKey = reader.readString();
@@ -355,13 +354,15 @@ public class PlatformContextImpl implements PlatformContext {
                             }
                         });
 
-                    return new T4<>(typeId, typeName, affKey, fields);
+                    boolean isEnum = reader.readBoolean();
+
+                    return new Metadata(typeId, typeName, affKey, fields, isEnum);
                 }
             }
         );
 
-        for (T4<Integer, String, String, Map<String, Integer>> meta : metas)
-            cacheObjProc.updateMetadata(meta.get1(), meta.get2(), meta.get3(), meta.get4());
+        for (Metadata meta : metas)
+            cacheObjProc.updateMetadata(meta.typeId, meta.typeName, meta.affKey, meta.fields, meta.isEnum);
     }
 
     /** {@inheritDoc} */
@@ -398,6 +399,7 @@ public class PlatformContextImpl implements PlatformContext {
             writer.writeString(meta.typeName());
             writer.writeString(meta.affinityKeyFieldName());
             writer.writeMap(fields);
+            writer.writeBoolean(meta.isEnum());
         }
     }
 
@@ -615,4 +617,41 @@ public class PlatformContextImpl implements PlatformContext {
     @Override public PlatformClusterNodeFilter createClusterNodeFilter(Object filter) {
         return new PlatformClusterNodeFilterImpl(filter, this);
     }
+
+    /**
+     * Metadata holder.
+     */
+    private static class Metadata {
+        /** Type ID. */
+        private final int typeId;
+
+        /** Type name. */
+        private final String typeName;
+
+        /** Affinity key. */
+        private final String affKey;
+
+        /** Fields map. */
+        private final Map<String, Integer> fields;
+
+        /** Enum flag. */
+        private final boolean isEnum;
+
+        /**
+         * Constructor.
+         *
+         * @param typeId Type ID.
+         * @param typeName Type name.
+         * @param affKey Affinity key.
+         * @param fields Fields.
+         * @param isEnum Enum flag.
+         */
+        public Metadata(int typeId, String typeName, String affKey, Map<String, Integer> fields, boolean isEnum) {
+            this.typeId = typeId;
+            this.typeName = typeName;
+            this.affKey = affKey;
+            this.fields = fields;
+            this.isEnum = isEnum;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/transactions/PlatformTransactions.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/transactions/PlatformTransactions.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/transactions/PlatformTransactions.java
index 5f5f5c3..d97e071 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/transactions/PlatformTransactions.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/transactions/PlatformTransactions.java
@@ -236,8 +236,8 @@ public class PlatformTransactions extends PlatformAbstractTarget {
             case OP_CACHE_CONFIG_PARAMETERS:
                 TransactionConfiguration txCfg = platformCtx.kernalContext().config().getTransactionConfiguration();
 
-                writer.writeEnum(txCfg.getDefaultTxConcurrency());
-                writer.writeEnum(txCfg.getDefaultTxIsolation());
+                writer.writeInt(txCfg.getDefaultTxConcurrency().ordinal());
+                writer.writeInt(txCfg.getDefaultTxIsolation().ordinal());
                 writer.writeLong(txCfg.getDefaultTxTimeout());
 
                 break;

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
index 14c040c..6572764 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
@@ -787,6 +787,7 @@ public class PlatformUtils {
                     writer.writeString(typ.getSerializer());
                     writer.writeString(typ.getAffinityKeyFieldName());
                     writer.writeObject(typ.getKeepDeserialized());
+                    writer.writeBoolean(typ.isEnum());
                 }
             });
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetBinaryTypeConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetBinaryTypeConfiguration.java b/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetBinaryTypeConfiguration.java
index df28aef..cae5760 100644
--- a/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetBinaryTypeConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetBinaryTypeConfiguration.java
@@ -42,6 +42,9 @@ public class PlatformDotNetBinaryTypeConfiguration {
     /** Whether to cache deserialized value. */
     private Boolean keepDeserialized;
 
+    /** Enum flag. */
+    private boolean isEnum;
+
     /**
      * Default constructor.
      */
@@ -60,6 +63,7 @@ public class PlatformDotNetBinaryTypeConfiguration {
         serializer = cfg.getSerializer();
         affinityKeyFieldName = cfg.getAffinityKeyFieldName();
         keepDeserialized = cfg.isKeepDeserialized();
+        isEnum = cfg.isEnum();
     }
 
     /**
@@ -164,6 +168,25 @@ public class PlatformDotNetBinaryTypeConfiguration {
         this.keepDeserialized = keepDeserialized;
     }
 
+    /**
+     * Gets whether this is enum type.
+     *
+     * @return {@code True} if enum.
+     */
+    public boolean isEnum() {
+        return isEnum;
+    }
+
+    /**
+     * Sets whether this is enum type.
+     *
+     * @param isEnum {@code True} if enum.
+     */
+    public void setEnum(boolean isEnum) {
+        this.isEnum = isEnum;
+    }
+
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(PlatformDotNetBinaryTypeConfiguration.class, this);

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryEnumsSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryEnumsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryEnumsSelfTest.java
new file mode 100644
index 0000000..3bc3922
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryEnumsSelfTest.java
@@ -0,0 +1,446 @@
+/*
+ * 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.portable;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.binary.BinaryTypeConfiguration;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.configuration.BinaryConfiguration;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+/**
+ * Contains tests for binary enums.
+ */
+@SuppressWarnings("unchecked")
+public class BinaryEnumsSelfTest extends GridCommonAbstractTest {
+    /** Cache name. */
+    private static String CACHE_NAME = "cache";
+
+    /** Whether to register types or not. */
+    private boolean register;
+
+    /** Node 1. */
+    private Ignite node1;
+
+    /** Node 2. */
+    private Ignite node2;
+
+    /** Cache 1. */
+    private IgniteCache cache1;
+
+    /** Cache 2. */
+    private IgniteCache cache2;
+
+    /** Binary cache 1. */
+    private IgniteCache cacheBinary1;
+
+    /** Binary cache 2. */
+    private IgniteCache cacheBinary2;
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        register = false;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        if (register) {
+            BinaryConfiguration bCfg = new BinaryConfiguration();
+
+            BinaryTypeConfiguration enumCfg = new BinaryTypeConfiguration(EnumType.class.getName());
+            enumCfg.setEnum(true);
+
+            bCfg.setTypeConfigurations(Arrays.asList(enumCfg, new BinaryTypeConfiguration(EnumHolder.class.getName())));
+
+            cfg.setBinaryConfiguration(bCfg);
+        }
+
+        cfg.setMarshaller(new BinaryMarshaller());
+
+        CacheConfiguration ccfg = new CacheConfiguration();
+        ccfg.setName(CACHE_NAME);
+        ccfg.setCacheMode(CacheMode.PARTITIONED);
+
+        cfg.setCacheConfiguration(ccfg);
+
+        return cfg;
+    }
+
+    /**
+     * Start up routine.
+     *
+     * @throws Exception If failed.
+     */
+    private void startUp(boolean register) throws Exception {
+        this.register = register;
+
+        node1 = startGrid(0);
+        cache1 = node1.cache(CACHE_NAME);
+        cacheBinary1 = cache1.withKeepBinary();
+
+        node2 = startGrid(1);
+        cache2 = node2.cache(CACHE_NAME);
+        cacheBinary2 = cache2.withKeepBinary();
+    }
+
+    /**
+     * Test operations on simple type which is registered in advance.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSimpleRegistered() throws Exception {
+        checkSimple(true);
+    }
+
+    /**
+     * Test operations on simple type which is not registered in advance.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSimpleNotRegistered() throws Exception {
+        checkSimple(false);
+    }
+
+    /**
+     * Test operations when enum is nested into an object (registered).
+     *
+     * @throws Exception If failed.
+     */
+    public void testNestedRegistered() throws Exception {
+        checkNested(true);
+    }
+
+    /**
+     * Test operations when enum is nested into an object (not registered).
+     *
+     * @throws Exception If failed.
+     */
+    public void testNestedNotRegistered() throws Exception {
+        checkNested(false);
+    }
+
+    /**
+     * Test builder operations on simple type which is registered in advance.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSimpleBuilderRegistered() throws Exception {
+        checkSimpleBuilder(true);
+    }
+
+    /**
+     * Test builder operations on simple type which is not registered in advance.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSimpleBuilderNotRegistered() throws Exception {
+        checkSimpleBuilder(false);
+    }
+
+    /**
+     * Test builder operations when enum is nested into an object (registered).
+     *
+     * @throws Exception If failed.
+     */
+    public void testNestedBuilderRegistered() throws Exception {
+        checkNestedBuilder(true);
+    }
+
+    /**
+     * Test builder operations when enum is nested into an object (not registered).
+     *
+     * @throws Exception If failed.
+     */
+    public void testNestedBuilderNotRegistered() throws Exception {
+        checkNestedBuilder(false);
+    }
+
+    /**
+     * Check simple serialization - deserialization.
+     *
+     * @param registered If type should be registered in advance.
+     * @throws Exception If failed.
+     */
+    public void checkSimple(boolean registered) throws Exception {
+        startUp(registered);
+
+        cache1.put(1, EnumType.ONE);
+
+        validateSimple(1, EnumType.ONE, registered);
+    }
+
+    /**
+     * Check nested serialization - deserialization.
+     *
+     * @param registered If type should be registered in advance.
+     * @throws Exception If failed.
+     */
+    private void checkNested(boolean registered) throws Exception {
+        startUp(registered);
+
+        cache1.put(1, new EnumHolder(EnumType.ONE));
+
+        validateNested(1, EnumType.ONE, registered);
+    }
+
+    /**
+     * Check nested builder serialization - deserialization.
+     *
+     * @param registered If type should be registered in advance.
+     * @throws Exception If failed.
+     */
+    private void checkNestedBuilder(boolean registered) throws Exception {
+        startUp(registered);
+
+        BinaryObject obj = node1.binary().builder("EnumHolder").setField("val", EnumType.ONE).build();
+
+        assert node1.binary().type("EnumHolder") != null;
+        assert node1.binary().type("EnumType") != null;
+
+        cacheBinary1.put(1, obj);
+
+        validateNested(1, EnumType.ONE, registered);
+
+        obj = (BinaryObject)cacheBinary1.get(1);
+        obj = node1.binary().builder(obj).setField("val", EnumType.TWO).build();
+
+        cacheBinary1.put(1, obj);
+
+        validateNested(1, EnumType.TWO, registered);
+    }
+
+    /**
+     * Validate nested object.
+     *
+     * @param key Key.
+     * @param val Value.
+     * @param registered Registered flag.
+     * @throws Exception If failed.
+     */
+    private void validateNested(int key, EnumType val, boolean registered) throws Exception {
+        if (registered) {
+            EnumHolder res1 = (EnumHolder) cache1.get(key);
+            EnumHolder res2 = (EnumHolder) cache2.get(key);
+
+            assertEquals(val, res1.val);
+            assertEquals(val, res2.val);
+        }
+
+        BinaryObject resBinary1 = (BinaryObject)cacheBinary1.get(key);
+        BinaryObject resBinary2 = (BinaryObject)cacheBinary2.get(key);
+
+        validate((BinaryObject)resBinary1.field("val"), val);
+        validate((BinaryObject)resBinary2.field("val"), val);
+    }
+
+    /**
+     * Check simple serialization - deserialization using builder.
+     *
+     * @param registered If type should be registered in advance.
+     * @throws Exception If failed.
+     */
+    public void checkSimpleBuilder(boolean registered) throws Exception {
+        startUp(registered);
+
+        BinaryObject binary = node1.binary().buildEnum(EnumType.class.getSimpleName(), EnumType.ONE.ordinal());
+
+        cacheBinary1.put(1, binary);
+
+        validateSimple(1, EnumType.ONE, registered);
+    }
+
+    /**
+     * Test enum array (registered).
+     *
+     * @throws Exception If failed.
+     */
+    public void testSimpleArrayRegistered() throws Exception {
+        checkSimpleArray(true);
+    }
+
+    /**
+     * Test enum array (not registered).
+     *
+     * @throws Exception If failed.
+     */
+    public void testSimpleArrayNotRegistered() throws Exception {
+        checkSimpleArray(false);
+    }
+
+    /**
+     * Test enum array created using builder (registered).
+     *
+     * @throws Exception If failed.
+     */
+    public void testSimpleBuilderArrayRegistered() throws Exception {
+        checkSimpleBuilderArray(true);
+    }
+
+    /**
+     * Test enum array created using builder (not registered).
+     *
+     * @throws Exception If failed.
+     */
+    public void testSimpleBuilderArrayNotRegistered() throws Exception {
+        checkSimpleBuilderArray(false);
+    }
+
+    /**
+     * Check arrays with builder.
+     *
+     * @param registered Registered flag.
+     * @throws Exception If failed.
+     */
+    public void checkSimpleArray(boolean registered) throws Exception {
+        startUp(registered);
+
+        cache1.put(1, new EnumType[] { EnumType.ONE, EnumType.TWO });
+
+        validateSimpleArray(registered);
+    }
+
+    /**
+     * Check arrays with builder.
+     *
+     * @param registered Registered flag.
+     * @throws Exception If failed.
+     */
+    public void checkSimpleBuilderArray(boolean registered) throws Exception {
+        startUp(registered);
+
+        BinaryObject binaryOne = node1.binary().buildEnum(EnumType.class.getSimpleName(), EnumType.ONE.ordinal());
+        BinaryObject binaryTwo = node1.binary().buildEnum(EnumType.class.getSimpleName(), EnumType.TWO.ordinal());
+
+        cacheBinary1.put(1, new BinaryObject[] { binaryOne, binaryTwo });
+
+        validateSimpleArray(registered);
+    }
+
+    /**
+     * Validate simple array.
+     *
+     * @param registered Registered flag.
+     */
+    private void validateSimpleArray(boolean registered) {
+        if (registered) {
+            Object[] arr1 = (Object[])cache1.get(1);
+            Object[] arr2 = (Object[])cache2.get(1);
+
+            assertEquals(2, arr1.length);
+            assertEquals(2, arr2.length);
+
+            assertEquals(EnumType.ONE, arr1[0]);
+            assertEquals(EnumType.TWO, arr1[1]);
+
+            assertEquals(EnumType.ONE, arr2[0]);
+            assertEquals(EnumType.TWO, arr2[1]);
+        }
+
+        Object[] arrBinary1 = (Object[])cacheBinary1.get(1);
+        Object[] arrBinary2 = (Object[])cacheBinary2.get(1);
+
+        assertEquals(2, arrBinary1.length);
+        assertEquals(2, arrBinary2.length);
+
+        validate((BinaryObject) arrBinary1[0], EnumType.ONE);
+        validate((BinaryObject) arrBinary1[1], EnumType.TWO);
+
+        validate((BinaryObject) arrBinary2[0], EnumType.ONE);
+        validate((BinaryObject) arrBinary2[1], EnumType.TWO);
+    }
+
+    /**
+     * Internal check routine for simple scenario.
+     *
+     * @param key Key.
+     * @param val Value.
+     * @param registered Registered flag.
+     * @throws Exception If failed.
+     */
+    private void validateSimple(int key, EnumType val, boolean registered) throws Exception {
+        if (registered) {
+            assertEquals(val, cache1.get(key));
+            assertEquals(val, cache2.get(key));
+        }
+
+        validate((BinaryObject) cacheBinary1.get(key), val);
+        validate((BinaryObject) cacheBinary2.get(key), val);
+    }
+
+    /**
+     * Validate single value.
+     *
+     * @param obj Binary value.
+     * @param val Expected value.
+     */
+    private void validate(BinaryObject obj, EnumType val) {
+        assertTrue(obj.type().isEnum());
+
+        assertEquals(node1.binary().typeId(EnumType.class.getName()), obj.type().typeId());
+        assertEquals(node2.binary().typeId(EnumType.class.getName()), obj.type().typeId());
+
+        assertEquals(val.ordinal(), obj.enumOrdinal());
+    }
+
+    /**
+     * Enumeration holder.
+     */
+    public static class EnumHolder implements Serializable {
+        /** Value. */
+        public EnumType val;
+
+        /**
+         * Default constructor.
+         */
+        @SuppressWarnings("UnusedDeclaration")
+        public EnumHolder() {
+            // No-op.
+        }
+
+        /**
+         * Constructor.
+         *
+         * @param val Value.
+         */
+        public EnumHolder(EnumType val) {
+            this.val = val;
+        }
+    }
+
+    /**
+     * Enumeration for tests.
+     */
+    public static enum EnumType {
+        ONE,
+        TWO
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java
index 655582e..9f7822c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java
@@ -487,8 +487,8 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
         assertArrayEquals(obj.objArr, (Object[])po.field("objArr"));
         assertEquals(obj.col, po.field("col"));
         assertEquals(obj.map, po.field("map"));
-        assertEquals(new Integer(obj.enumVal.ordinal()), new Integer(((Enum<?>)po.field("enumVal")).ordinal()));
-        assertArrayEquals(ordinals(obj.enumArr), ordinals((Enum<?>[])po.field("enumArr")));
+        assertEquals(new Integer(obj.enumVal.ordinal()), new Integer(((BinaryObject)po.field("enumVal")).enumOrdinal()));
+        assertArrayEquals(ordinals(obj.enumArr), ordinals((BinaryObject[])po.field("enumArr")));
         assertNull(po.field("unknown"));
 
         BinaryObject innerPo = po.field("inner");
@@ -523,8 +523,8 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
         assertEquals(obj.inner.col, innerPo.field("col"));
         assertEquals(obj.inner.map, innerPo.field("map"));
         assertEquals(new Integer(obj.inner.enumVal.ordinal()),
-            new Integer(((Enum<?>)innerPo.field("enumVal")).ordinal()));
-        assertArrayEquals(ordinals(obj.inner.enumArr), ordinals((Enum<?>[])innerPo.field("enumArr")));
+            new Integer(((BinaryObject)innerPo.field("enumVal")).enumOrdinal()));
+        assertArrayEquals(ordinals(obj.inner.enumArr), ordinals((BinaryObject[])innerPo.field("enumArr")));
         assertNull(innerPo.field("inner"));
         assertNull(innerPo.field("unknown"));
     }
@@ -572,8 +572,8 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
         assertArrayEquals(obj.objArr, (Object[])po.field("_objArr"));
         assertEquals(obj.col, po.field("_col"));
         assertEquals(obj.map, po.field("_map"));
-        assertEquals(new Integer(obj.enumVal.ordinal()), new Integer(((Enum<?>)po.field("_enumVal")).ordinal()));
-        assertArrayEquals(ordinals(obj.enumArr), ordinals((Enum<?>[])po.field("_enumArr")));
+        assertEquals(new Integer(obj.enumVal.ordinal()), new Integer(((BinaryObject)po.field("_enumVal")).enumOrdinal()));
+        assertArrayEquals(ordinals(obj.enumArr), ordinals((BinaryObject[])po.field("_enumArr")));
         assertNull(po.field("unknown"));
 
         BinaryObject simplePo = po.field("_simple");
@@ -608,8 +608,8 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
         assertEquals(obj.simple.col, simplePo.field("col"));
         assertEquals(obj.simple.map, simplePo.field("map"));
         assertEquals(new Integer(obj.simple.enumVal.ordinal()),
-            new Integer(((Enum<?>)simplePo.field("enumVal")).ordinal()));
-        assertArrayEquals(ordinals(obj.simple.enumArr), ordinals((Enum<?>[])simplePo.field("enumArr")));
+            new Integer(((BinaryObject)simplePo.field("enumVal")).enumOrdinal()));
+        assertArrayEquals(ordinals(obj.simple.enumArr), ordinals((BinaryObject[])simplePo.field("enumArr")));
         assertNull(simplePo.field("simple"));
         assertNull(simplePo.field("portable"));
         assertNull(simplePo.field("unknown"));
@@ -645,8 +645,8 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
         assertEquals(obj.portable.col, portablePo.field("_col"));
         assertEquals(obj.portable.map, portablePo.field("_map"));
         assertEquals(new Integer(obj.portable.enumVal.ordinal()),
-            new Integer(((Enum<?>)portablePo.field("_enumVal")).ordinal()));
-        assertArrayEquals(ordinals(obj.portable.enumArr), ordinals((Enum<?>[])portablePo.field("_enumArr")));
+            new Integer(((BinaryObject)portablePo.field("_enumVal")).enumOrdinal()));
+        assertArrayEquals(ordinals(obj.portable.enumArr), ordinals((BinaryObject[])portablePo.field("_enumArr")));
         assertNull(portablePo.field("_simple"));
         assertNull(portablePo.field("_portable"));
         assertNull(portablePo.field("unknown"));
@@ -684,8 +684,8 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
         assertArrayEquals(obj.objArr, (Object[])po.field("objArr"));
         assertEquals(obj.col, po.field("col"));
         assertEquals(obj.map, po.field("map"));
-        assertEquals(new Integer(obj.enumVal.ordinal()), new Integer(((Enum<?>)po.field("enumVal")).ordinal()));
-        assertArrayEquals(ordinals(obj.enumArr), ordinals((Enum<?>[])po.field("enumArr")));
+        assertEquals(new Integer(obj.enumVal.ordinal()), new Integer(((BinaryObject)po.field("enumVal")).enumOrdinal()));
+        assertArrayEquals(ordinals(obj.enumArr), ordinals((BinaryObject[])po.field("enumArr")));
         assertNull(po.field("unknown"));
 
         assertEquals(obj, po.deserialize());
@@ -2203,6 +2203,19 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     * @param enumArr Enum array.
+     * @return Ordinals.
+     */
+    private <T extends Enum<?>> Integer[] ordinals(BinaryObject[] enumArr) {
+        Integer[] ords = new Integer[enumArr.length];
+
+        for (int i = 0; i < enumArr.length; i++)
+            ords[i] = enumArr[i].enumOrdinal();
+
+        return ords;
+    }
+
+    /**
      * @param po Portable object.
      * @param off Offset.
      * @return Value.

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java b/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java
index c464945..a284883 100644
--- a/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java
+++ b/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java
@@ -194,9 +194,9 @@ public class PlatformComputeEchoTask extends ComputeTaskAdapter<Integer, Object>
                 case TYPE_ENUM_FIELD:
                     IgniteCache<Integer, BinaryObject> cache = ignite.cache(null).withKeepBinary();
                     BinaryObject obj = cache.get(TYPE_ENUM_FIELD);
-                    PlatformComputeEnum val = obj.field("interopEnum");
+                    BinaryObject val = obj.field("interopEnum");
 
-                    return val;
+                    return val.deserialize();
 
                 default:
                     throw new IgniteException("Unknown type: " + type);

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePortableObjectsTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePortableObjectsTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePortableObjectsTestSuite.java
index 16eeb2b..629835b 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePortableObjectsTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePortableObjectsTestSuite.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.testsuites;
 
 import junit.framework.TestSuite;
+import org.apache.ignite.internal.portable.BinaryEnumsSelfTest;
 import org.apache.ignite.internal.portable.GridPortableAffinityKeySelfTest;
 import org.apache.ignite.internal.portable.BinaryObjectBuilderAdditionalSelfTest;
 import org.apache.ignite.internal.portable.BinaryObjectBuilderSelfTest;
@@ -72,6 +73,7 @@ public class IgnitePortableObjectsTestSuite extends TestSuite {
         suite.addTestSuite(BinaryFieldsOffheapSelfTest.class);
         suite.addTestSuite(BinaryFooterOffsetsHeapSelfTest.class);
         suite.addTestSuite(BinaryFooterOffsetsOffheapSelfTest.class);
+        suite.addTestSuite(BinaryEnumsSelfTest.class);
         suite.addTestSuite(GridPortableMetaDataSelfTest.class);
         suite.addTestSuite(GridPortableAffinityKeySelfTest.class);
         suite.addTestSuite(GridPortableWildcardsSelfTest.class);

http://git-wip-us.apache.org/repos/asf/ignite/blob/663e78dc/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp b/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp
index 2e86ccd..6c3bf7f 100644
--- a/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp
+++ b/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp
@@ -32,7 +32,7 @@ namespace ignite
     {
         namespace binary
         {
-            /** Operation: Clear. */
+            /** Operation: metadata update. */
             const int32_t OP_METADATA = -1;
 
             BinaryTypeUpdaterImpl::BinaryTypeUpdaterImpl(SharedPointer<IgniteEnvironment> env,
@@ -78,6 +78,8 @@ namespace ignite
                 else
                     rawWriter.WriteInt32(0);
 
+                rawWriter.WriteBool(false); // Enums are not supported for now.
+
                 out.Synchronize();
 
                 long long res = env.Get()->Context()->TargetInStreamOutLong(javaRef, OP_METADATA, mem.Get()->PointerLong(), &jniErr);