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

av pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new fe58e790b45 IGNITE-27414 : Use MessageSerializer for 
TcpDiscoveryClientReconnectMessage v3 - codegen (#12852)
fe58e790b45 is described below

commit fe58e790b45f57e4a6e85c4abb7d43996053c561
Author: Vladimir Steshin <[email protected]>
AuthorDate: Tue Mar 10 18:29:36 2026 +0300

    IGNITE-27414 : Use MessageSerializer for TcpDiscoveryClientReconnectMessage 
v3 - codegen (#12852)
---
 ...Message.java => CalciteMarshalableMessage.java} |   2 +-
 .../query/calcite/message/MessageServiceImpl.java  |   8 +-
 .../query/calcite/message/QueryBatchMessage.java   |   2 +-
 .../query/calcite/message/QueryStartRequest.java   |   2 +-
 .../query/calcite/message/ValueMessage.java        |   2 +-
 .../calcite/metadata/FragmentDescription.java      |   4 +-
 .../apache/ignite/internal/MessageProcessor.java   |   6 +
 .../internal/MessageSerializerGenerator.java       | 161 ++++++++++++++++-----
 .../discovery/DiscoveryMessageFactory.java         |  33 ++++-
 ...ageSerializer.java => MarshallableMessage.java} |  31 ++--
 .../communication/MessageSerializer.java           |   6 +-
 .../ignite/spi/discovery/tcp/ClientImpl.java       |   4 -
 .../ignite/spi/discovery/tcp/ServerImpl.java       |  11 --
 .../spi/discovery/tcp/TcpDiscoveryIoSession.java   |   4 +-
 .../ignite/spi/discovery/tcp/TcpDiscoverySpi.java  |   2 +-
 .../TcpDiscoveryClientReconnectMessage.java        |  55 ++++++-
 .../messages/TcpDiscoveryJoinRequestMessage.java   |  17 +--
 .../TcpDiscoveryNodeAddFinishedMessage.java        |  27 ++--
 .../internal/codegen/MessageProcessorTest.java     |  12 ++
 ...irectByteBufferStreamImplByteOrderSelfTest.java |   2 +-
 .../AbstractMessageSerializationTest.java          |   3 +-
 .../IgniteDiscoveryMessageSerializationTest.java   |   2 +-
 .../test/resources/codegen/AbstractMessage.java    |   3 +
 .../src/test/resources/codegen/ChildMessage.java   |   3 +
 .../resources/codegen/ChildMessageSerializer.java  |  43 ++++--
 .../CustomMapperEnumFieldsMessageSerializer.java   |  15 +-
 .../DefaultMapperEnumFieldsMessageSerializer.java  |  19 +--
 .../codegen/TestCollectionsMessageSerializer.java  | 111 +++++++-------
 .../codegen/TestMapMessageSerializer.java          | 107 +++++++-------
 .../resources/codegen/TestMarshallableMessage.java |  74 ++++++++++
 ...MarshallableMessageMarshallableSerializer.java} |  49 +++++--
 .../resources/codegen/TestMessageSerializer.java   |  67 ++++-----
 32 files changed, 570 insertions(+), 317 deletions(-)

diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/MarshalableMessage.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/CalciteMarshalableMessage.java
similarity index 95%
rename from 
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/MarshalableMessage.java
rename to 
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/CalciteMarshalableMessage.java
index b039c0b7512..b671639ebd6 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/MarshalableMessage.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/CalciteMarshalableMessage.java
@@ -23,7 +23,7 @@ import 
org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 /**
  *
  */
-public interface MarshalableMessage extends CalciteMessage {
+public interface CalciteMarshalableMessage extends CalciteMessage {
     /**
      * Prepares the message before sending.
      *
diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/MessageServiceImpl.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/MessageServiceImpl.java
index 1af28d1fe32..2cea51aa5cf 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/MessageServiceImpl.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/MessageServiceImpl.java
@@ -179,8 +179,8 @@ public class MessageServiceImpl extends AbstractService 
implements MessageServic
     /** */
     protected void prepareMarshal(Message msg) throws IgniteCheckedException {
         try {
-            if (msg instanceof MarshalableMessage)
-                ((MarshalableMessage)msg).prepareMarshal(ctx);
+            if (msg instanceof CalciteMarshalableMessage)
+                ((CalciteMarshalableMessage)msg).prepareMarshal(ctx);
         }
         catch (Exception e) {
             failureProcessor().process(new 
FailureContext(FailureType.CRITICAL_ERROR, e));
@@ -192,8 +192,8 @@ public class MessageServiceImpl extends AbstractService 
implements MessageServic
     /** */
     protected void prepareUnmarshal(Message msg) throws IgniteCheckedException 
{
         try {
-            if (msg instanceof MarshalableMessage)
-                ((MarshalableMessage)msg).prepareUnmarshal(ctx);
+            if (msg instanceof CalciteMarshalableMessage)
+                ((CalciteMarshalableMessage)msg).prepareUnmarshal(ctx);
         }
         catch (Exception e) {
             failureProcessor().process(new 
FailureContext(FailureType.CRITICAL_ERROR, e));
diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryBatchMessage.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryBatchMessage.java
index b722b6ccf37..c21297c3a5c 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryBatchMessage.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryBatchMessage.java
@@ -27,7 +27,7 @@ import 
org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 /**
  *
  */
-public class QueryBatchMessage implements MarshalableMessage, 
ExecutionContextAware {
+public class QueryBatchMessage implements CalciteMarshalableMessage, 
ExecutionContextAware {
     /** */
     @Order(0)
     UUID qryId;
diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java
index 81d843bf3ee..fe45e12a1c8 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java
@@ -31,7 +31,7 @@ import org.jetbrains.annotations.Nullable;
 /**
  *
  */
-public class QueryStartRequest implements MarshalableMessage, 
ExecutionContextAware {
+public class QueryStartRequest implements CalciteMarshalableMessage, 
ExecutionContextAware {
     /** */
     @Order(0)
     String schema;
diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/ValueMessage.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/ValueMessage.java
index 44c3d8d0fb5..901bcbfafa4 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/ValueMessage.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/ValueMessage.java
@@ -21,7 +21,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 
 /** */
-public interface ValueMessage extends MarshalableMessage {
+public interface ValueMessage extends CalciteMarshalableMessage {
     /**
      * @return Wrapped value.
      */
diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/FragmentDescription.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/FragmentDescription.java
index 012591fa1e3..dce4f0f5d2f 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/FragmentDescription.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/FragmentDescription.java
@@ -23,13 +23,13 @@ import java.util.Map;
 import java.util.UUID;
 import org.apache.ignite.internal.Order;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
-import 
org.apache.ignite.internal.processors.query.calcite.message.MarshalableMessage;
+import 
org.apache.ignite.internal.processors.query.calcite.message.CalciteMarshalableMessage;
 import org.apache.ignite.internal.processors.query.calcite.message.MessageType;
 import org.apache.ignite.internal.util.UUIDCollectionMessage;
 import org.apache.ignite.internal.util.typedef.internal.U;
 
 /** */
-public class FragmentDescription implements MarshalableMessage {
+public class FragmentDescription implements CalciteMarshalableMessage {
     /** */
     @Order(0)
     long fragmentId;
diff --git 
a/modules/codegen/src/main/java/org/apache/ignite/internal/MessageProcessor.java
 
b/modules/codegen/src/main/java/org/apache/ignite/internal/MessageProcessor.java
index c4c6ab72073..f6cf23d4b71 100644
--- 
a/modules/codegen/src/main/java/org/apache/ignite/internal/MessageProcessor.java
+++ 
b/modules/codegen/src/main/java/org/apache/ignite/internal/MessageProcessor.java
@@ -68,6 +68,12 @@ public class MessageProcessor extends AbstractProcessor {
     /** Base interface that every message must implement. */
     static final String MESSAGE_INTERFACE = 
"org.apache.ignite.plugin.extensions.communication.Message";
 
+    /** Compressed message. */
+    static final String COMPRESSED_MESSAGE_INTERFACE = 
"org.apache.ignite.internal.managers.communication.CompressedMessage";
+
+    /** Externalizable message. */
+    static final String MARSHALLABLE_MESSAGE_INTERFACE = 
"org.apache.ignite.plugin.extensions.communication.MarshallableMessage";
+
     /** This is the only message with zero fields. A serializer must be 
generated due to restrictions in our communication process. */
     static final String HANDSHAKE_WAIT_MESSAGE = 
"org.apache.ignite.spi.communication.tcp.messages.HandshakeWaitMessage";
 
diff --git 
a/modules/codegen/src/main/java/org/apache/ignite/internal/MessageSerializerGenerator.java
 
b/modules/codegen/src/main/java/org/apache/ignite/internal/MessageSerializerGenerator.java
index 51b756c49fb..355072e0b30 100644
--- 
a/modules/codegen/src/main/java/org/apache/ignite/internal/MessageSerializerGenerator.java
+++ 
b/modules/codegen/src/main/java/org/apache/ignite/internal/MessageSerializerGenerator.java
@@ -56,6 +56,8 @@ import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.SB;
 import org.jetbrains.annotations.Nullable;
 
+import static 
org.apache.ignite.internal.MessageProcessor.COMPRESSED_MESSAGE_INTERFACE;
+import static 
org.apache.ignite.internal.MessageProcessor.MARSHALLABLE_MESSAGE_INTERFACE;
 import static org.apache.ignite.internal.MessageProcessor.MESSAGE_INTERFACE;
 
 /**
@@ -107,23 +109,35 @@ public class MessageSerializerGenerator {
     /** */
     private final ProcessingEnvironment env;
 
+    /** Stored type of the message being processed. */
+    private TypeElement type;
+
+    /** The marshallable message type. */
+    private final TypeMirror marshallableMsgType;
+
     /** */
     private int indent;
 
     /** */
     MessageSerializerGenerator(ProcessingEnvironment env) {
         this.env = env;
+
+        marshallableMsgType = 
env.getElementUtils().getTypeElement(MARSHALLABLE_MESSAGE_INTERFACE).asType();
     }
 
     /** */
     void generate(TypeElement type, List<VariableElement> fields) throws 
Exception {
-        generateMethods(type, fields);
+        assert this.type == null : "Message serializer generator isn't 
stateless and is supposed to be single-use.";
+
+        this.type = type;
+
+        generateMethods(fields);
 
         SystemViewRowAttributeWalkerProcessor.superclasses(env, 
type).forEach(el -> imports.add(el.toString()));
 
-        String serClsName = type.getSimpleName() + "Serializer";
+        String serClsName = type.getSimpleName() + (marshallableMessage() ? 
"Marshallable" : "") + "Serializer";
         String serFqnClsName = env.getElementUtils().getPackageOf(type) + "." 
+ serClsName;
-        String serCode = generateSerializerCode(type);
+        String serCode = generateSerializerCode(serClsName);
 
         try {
             JavaFileObject file = 
env.getFiler().createSourceFile(serFqnClsName);
@@ -151,12 +165,19 @@ public class MessageSerializerGenerator {
     }
 
     /** Generates full code for a serializer class. */
-    private String generateSerializerCode(TypeElement type) throws IOException 
{
+    private String generateSerializerCode(String serClsName) throws 
IOException {
+        if (marshallableMessage()) {
+            fields.add("private final Marshaller marshaller;");
+            fields.add("private final ClassLoader clsLdr;");
+        }
+
         try (Writer writer = new StringWriter()) {
-            writeClassHeader(writer, 
env.getElementUtils().getPackageOf(type).toString(), type.getSimpleName() + 
"Serializer");
+            writeClassHeader(writer, 
env.getElementUtils().getPackageOf(type).toString(), serClsName);
 
             writeClassFields(writer);
 
+            writeConstructor(writer, serClsName);
+
             // Write #writeTo method.
             for (String w: write)
                 writer.write(w + NL);
@@ -177,10 +198,39 @@ public class MessageSerializerGenerator {
         }
     }
 
+    /** */
+    private void writeConstructor(Writer writer, String serClsName) throws 
IOException {
+        if (!marshallableMessage())
+            return;
+
+        ++indent;
+
+        writer.write(identedLine(METHOD_JAVADOC));
+        writer.write(NL);
+        writer.write(identedLine("public " + serClsName + "(Marshaller 
marshaller, ClassLoader clsLdr) {"));
+
+        writer.write(NL);
+
+        ++indent;
+
+        writer.write(identedLine("this.marshaller = marshaller;"));
+        writer.write(NL);
+        writer.write(identedLine("this.clsLdr = clsLdr;"));
+
+        --indent;
+
+        writer.write(NL);
+
+        writer.write(identedLine("}"));
+        writer.write(NL);
+
+        --indent;
+    }
+
     /** Generates code for {@code writeTo} and {@code readFrom}. */
-    private void generateMethods(TypeElement type, List<VariableElement> 
fields) throws Exception {
-        start(type, write, true);
-        start(type, read, false);
+    private void generateMethods(List<VariableElement> fields) throws 
Exception {
+        start(write, true);
+        start(read, false);
 
         indent++;
 
@@ -191,16 +241,14 @@ public class MessageSerializerGenerator {
 
         indent--;
 
-        finish(write);
-        finish(read);
+        finish(write, false, false);
+        finish(read, true, marshallableMessage());
     }
 
     /**
      * Generates start of write/read methods:
      * <pre>
      *     public boolean writeTo(Message m, MessageWriter writer) {
-     *         TestMessage msg = (TestMessage)m;
-     *
      *         if (!writer.isHeaderWritten()) {
      *             if (!writer.writeHeader(msg.directType()))
      *                 return false;
@@ -212,20 +260,17 @@ public class MessageSerializerGenerator {
      * @param code Code lines.
      * @param write Whether write code is generated.
      */
-    private void start(TypeElement type, Collection<String> code, boolean 
write) {
+    private void start(Collection<String> code, boolean write) {
         indent = 1;
 
         code.add(identedLine(METHOD_JAVADOC));
 
-        code.add(identedLine("@Override public boolean %s(Message m, %s) {",
+        code.add(identedLine("@Override public boolean %s(" + 
type.getSimpleName() + " msg, %s) {",
             write ? "writeTo" : "readFrom",
             write ? "MessageWriter writer" : "MessageReader reader"));
 
         indent++;
 
-        code.add(identedLine("%s msg = (%s)m;", 
type.getSimpleName().toString(), type.getSimpleName().toString()));
-        code.add(EMPTY);
-
         if (write) {
             code.add(identedLine("if (!writer.isHeaderWritten()) {"));
 
@@ -233,6 +278,12 @@ public class MessageSerializerGenerator {
 
             returnFalseIfWriteFailed(code, "writer.writeHeader", 
"directType()");
 
+            if (write && marshallableMessage()) {
+                code.add(EMPTY);
+
+                code.add(identedLine("msg.prepareMarshal(marshaller);"));
+            }
+
             code.add(EMPTY);
             code.add(identedLine("writer.onHeaderWritten();"));
 
@@ -401,7 +452,7 @@ public class MessageSerializerGenerator {
                 returnFalseIfWriteFailed(write, field, 
"writer.writeGridLongList", getExpr);
 
             else if (assignableFrom(type, type(MESSAGE_INTERFACE))) {
-                if (sameType(type, 
"org.apache.ignite.internal.managers.communication.CompressedMessage"))
+                if (sameType(type, COMPRESSED_MESSAGE_INTERFACE))
                     throw new IllegalArgumentException(COMPRESSED_MSG_ERROR);
 
                 if (compress)
@@ -508,8 +559,14 @@ public class MessageSerializerGenerator {
 
         String methodName = field.getAnnotation(Order.class).method();
 
-        if (Objects.equals(methodName, ""))
-            code.add(identedLine("if (!%s(((%s)msg).%s))", accessor, 
field.getEnclosingElement().getSimpleName(), argsStr));
+        if (Objects.equals(methodName, "")) {
+            if (type.equals(field.getEnclosingElement()))
+                code.add(identedLine("if (!%s(msg.%s))", accessor, argsStr));
+            else {
+                // Field has to be requested from a super class object.
+                code.add(identedLine("if (!%s(((%s)msg).%s))", accessor, 
field.getEnclosingElement().getSimpleName(), argsStr));
+            }
+        }
         else
             code.add(identedLine("if (!%s(msg.%s))", accessor, argsStr));
 
@@ -531,9 +588,15 @@ public class MessageSerializerGenerator {
         String fieldGetterCall) {
         String methodName = field.getAnnotation(Order.class).method();
 
-        if (Objects.equals(methodName, ""))
-            code.add(identedLine("if (!%s(%s(((%s)msg).%s)))",
-                writerCall, mapperCall, 
field.getEnclosingElement().getSimpleName(), fieldGetterCall));
+        if (Objects.equals(methodName, "")) {
+            if (type.equals(field.getEnclosingElement()))
+                code.add(identedLine("if (!%s(%s(msg.%s)))", writerCall, 
mapperCall, fieldGetterCall));
+            else {
+                // Field has to be requested from a super class object.
+                code.add(identedLine("if (!%s(%s(((%s)msg).%s)))",
+                    writerCall, mapperCall, 
field.getEnclosingElement().getSimpleName(), fieldGetterCall));
+            }
+        }
         else
             code.add(identedLine("if (!%s(%s(msg.%s)))", writerCall, 
mapperCall, fieldGetterCall));
 
@@ -650,7 +713,7 @@ public class MessageSerializerGenerator {
                 returnFalseIfReadFailed(field, "reader.readGridLongList");
 
             else if (assignableFrom(type, type(MESSAGE_INTERFACE))) {
-                if (sameType(type, 
"org.apache.ignite.internal.managers.communication.CompressedMessage"))
+                if (sameType(type, COMPRESSED_MESSAGE_INTERFACE))
                     throw new IllegalArgumentException(COMPRESSED_MSG_ERROR);
 
                 if (compress)
@@ -744,7 +807,7 @@ public class MessageSerializerGenerator {
             if (primitiveType != null)
                 return primitiveType.getKind().toString();
 
-            if (sameType(type, 
"org.apache.ignite.internal.managers.communication.CompressedMessage"))
+            if (sameType(type, COMPRESSED_MESSAGE_INTERFACE))
                 throw new IllegalArgumentException(COMPRESSED_MSG_ERROR);
         }
 
@@ -781,9 +844,15 @@ public class MessageSerializerGenerator {
 
         String methodName = field.getAnnotation(Order.class).method();
 
-        if (Objects.equals(methodName, ""))
-            read.add(identedLine("((%s)msg).%s = %s(%s);",
-                field.getEnclosingElement().getSimpleName(), 
field.getSimpleName().toString(), mtd, argsStr));
+        if (Objects.equals(methodName, "")) {
+            if (type.equals(field.getEnclosingElement()))
+                read.add(identedLine("msg.%s = %s(%s);", 
field.getSimpleName().toString(), mtd, argsStr));
+            else {
+                // Field has to be requested from a super class object.
+                read.add(identedLine("((%s)msg).%s = %s(%s);",
+                    field.getEnclosingElement().getSimpleName(), 
field.getSimpleName().toString(), mtd, argsStr));
+            }
+        }
         else
             read.add(identedLine("msg.%s(%s(%s));", methodName, mtd, argsStr));
 
@@ -813,9 +882,15 @@ public class MessageSerializerGenerator {
 
         String methodName = field.getAnnotation(Order.class).method();
 
-        if (Objects.equals(methodName, ""))
-            read.add(identedLine("((%s)msg).%s = %s;",
-                field.getEnclosingElement().getSimpleName(), 
field.getSimpleName().toString(), readOp));
+        if (Objects.equals(methodName, "")) {
+            if (type.equals(field.getEnclosingElement()))
+                read.add(identedLine("msg.%s = %s;", 
field.getSimpleName().toString(), readOp));
+            else {
+                // Field has to be requested from a super class object.
+                read.add(identedLine("((%s)msg).%s = %s;",
+                    field.getEnclosingElement().getSimpleName(), 
field.getSimpleName().toString(), readOp));
+            }
+        }
         else
             read.add(identedLine("msg.%s(%s);", methodName, readOp));
 
@@ -831,7 +906,7 @@ public class MessageSerializerGenerator {
     }
 
     /** */
-    private void finish(List<String> code) {
+    private void finish(List<String> code, boolean read, boolean marshallable) 
{
         String lastLine = code.get(code.size() - 1);
 
         if (EMPTY.equals(lastLine))
@@ -840,6 +915,12 @@ public class MessageSerializerGenerator {
         code.add(identedLine("}"));
         code.add(EMPTY);
 
+        if (read && marshallable) {
+            code.add(identedLine("msg.finishUnmarshal(marshaller, clsLdr);"));
+
+            code.add(EMPTY);
+        }
+
         code.add(identedLine("return true;"));
     }
 
@@ -906,18 +987,28 @@ public class MessageSerializerGenerator {
         writer.write(NL);
         writer.write("package " + pkgName + ";" + NL + NL);
 
-        
imports.add("org.apache.ignite.plugin.extensions.communication.Message");
+        imports.add(type.toString());
+
+        if (marshallableMessage())
+            imports.add("org.apache.ignite.marshaller.Marshaller");
+
         
imports.add("org.apache.ignite.plugin.extensions.communication.MessageSerializer");
         
imports.add("org.apache.ignite.plugin.extensions.communication.MessageWriter");
         
imports.add("org.apache.ignite.plugin.extensions.communication.MessageReader");
 
-        for (String regularImport: imports)
+        for (String regularImport : imports)
             writer.write("import " + regularImport + ";" + NL);
 
         writer.write(NL);
         writer.write(CLS_JAVADOC);
         writer.write(NL);
-        writer.write("public class " + serClsName + " implements 
MessageSerializer {" + NL);
+
+        writer.write("public class " + serClsName + " implements 
MessageSerializer<" + type.getSimpleName() + "> {" + NL);
+    }
+
+    /** */
+    private boolean marshallableMessage() {
+        return env.getTypeUtils().isAssignable(type.asType(), 
marshallableMsgType);
     }
 
     /** */
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/DiscoveryMessageFactory.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/DiscoveryMessageFactory.java
index bc8dfcba489..14272ac0f0e 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/DiscoveryMessageFactory.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/DiscoveryMessageFactory.java
@@ -59,6 +59,7 @@ import 
org.apache.ignite.internal.processors.query.schema.message.SchemaFinishDi
 import 
org.apache.ignite.internal.processors.query.schema.message.SchemaFinishDiscoveryMessageSerializer;
 import 
org.apache.ignite.internal.processors.query.schema.message.SchemaProposeDiscoveryMessage;
 import 
org.apache.ignite.internal.processors.query.schema.message.SchemaProposeDiscoveryMessageSerializer;
+import org.apache.ignite.marshaller.Marshaller;
 import org.apache.ignite.plugin.extensions.communication.MessageFactory;
 import 
org.apache.ignite.plugin.extensions.communication.MessageFactoryProvider;
 import 
org.apache.ignite.spi.communication.tcp.internal.TcpConnectionRequestDiscoveryMessage;
@@ -87,6 +88,8 @@ import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryClientPingReques
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryClientPingRequestSerializer;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryClientPingResponse;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryClientPingResponseSerializer;
+import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryClientReconnectMessage;
+import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryClientReconnectMessageMarshallableSerializer;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryConnectionCheckMessage;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryConnectionCheckMessageSerializer;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryCustomEventMessage;
@@ -100,13 +103,13 @@ import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryHandshakeRequest
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryHandshakeResponse;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryHandshakeResponseSerializer;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryJoinRequestMessage;
-import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryJoinRequestMessageSerializer;
+import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryJoinRequestMessageMarshallableSerializer;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryLoopbackProblemMessage;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryLoopbackProblemMessageSerializer;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryMetricsUpdateMessage;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryMetricsUpdateMessageSerializer;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryNodeAddFinishedMessage;
-import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryNodeAddFinishedMessageSerializer;
+import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryNodeAddFinishedMessageMarshallableSerializer;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryNodeFailedMessage;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryNodeFailedMessageSerializer;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryNodeFullMetricsMessage;
@@ -125,9 +128,27 @@ import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryServerOnlyCustom
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryServerOnlyCustomEventMessageSerializer;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryStatusCheckMessage;
 import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryStatusCheckMessageSerializer;
+import org.jetbrains.annotations.Nullable;
 
 /** Message factory for discovery messages. */
 public class DiscoveryMessageFactory implements MessageFactoryProvider {
+    /** Custom data marshaller. */
+    private final @Nullable Marshaller cstDataMarshall;
+
+    /** Class loader for the custom data marshalling. */
+    private final @Nullable ClassLoader cstDataMarshallClsLdr;
+
+    /**
+     * @param cstDataMarshall Custom data marshaller.
+     * @param cstDataMarshallClsLdr Class loader for the custom data 
marshalling.
+     */
+    public DiscoveryMessageFactory(@Nullable Marshaller cstDataMarshall, 
@Nullable ClassLoader cstDataMarshallClsLdr) {
+        assert cstDataMarshall == null && cstDataMarshallClsLdr == null || 
cstDataMarshall != null && cstDataMarshallClsLdr != null;
+
+        this.cstDataMarshall = cstDataMarshall;
+        this.cstDataMarshallClsLdr = cstDataMarshallClsLdr;
+    }
+
     /** {@inheritDoc} */
     @Override public void registerAll(MessageFactory factory) {
         factory.register((short)-109, User::new, new UserSerializer());
@@ -163,8 +184,10 @@ public class DiscoveryMessageFactory implements 
MessageFactoryProvider {
         factory.register((short)16, TcpDiscoveryNodeLeftMessage::new, new 
TcpDiscoveryNodeLeftMessageSerializer());
         factory.register((short)17, TcpDiscoveryNodeFailedMessage::new, new 
TcpDiscoveryNodeFailedMessageSerializer());
         factory.register((short)18, TcpDiscoveryStatusCheckMessage::new, new 
TcpDiscoveryStatusCheckMessageSerializer());
-        factory.register((short)19, TcpDiscoveryNodeAddFinishedMessage::new, 
new TcpDiscoveryNodeAddFinishedMessageSerializer());
-        factory.register((short)20, TcpDiscoveryJoinRequestMessage::new, new 
TcpDiscoveryJoinRequestMessageSerializer());
+        factory.register((short)19, TcpDiscoveryNodeAddFinishedMessage::new,
+            new 
TcpDiscoveryNodeAddFinishedMessageMarshallableSerializer(cstDataMarshall, 
cstDataMarshallClsLdr));
+        factory.register((short)20, TcpDiscoveryJoinRequestMessage::new,
+            new 
TcpDiscoveryJoinRequestMessageMarshallableSerializer(cstDataMarshall, 
cstDataMarshallClsLdr));
         factory.register((short)21, TcpDiscoveryCustomEventMessage::new, new 
TcpDiscoveryCustomEventMessageSerializer());
         factory.register((short)22, 
TcpDiscoveryServerOnlyCustomEventMessage::new,
             new TcpDiscoveryServerOnlyCustomEventMessageSerializer());
@@ -173,6 +196,8 @@ public class DiscoveryMessageFactory implements 
MessageFactoryProvider {
         factory.register((short)25, 
DistributedMetaStorageUpdateAckMessage::new, new 
DistributedMetaStorageUpdateAckMessageSerializer());
         factory.register((short)26, DistributedMetaStorageCasMessage::new, new 
DistributedMetaStorageCasMessageSerializer());
         factory.register((short)27, DistributedMetaStorageCasAckMessage::new, 
new DistributedMetaStorageCasAckMessageSerializer());
+        factory.register((short)28, TcpDiscoveryClientReconnectMessage::new,
+            new 
TcpDiscoveryClientReconnectMessageMarshallableSerializer(cstDataMarshall, 
cstDataMarshallClsLdr));
 
         // DiscoveryCustomMessage
         factory.register((short)500, CacheStatisticsModeChangeMessage::new, 
new CacheStatisticsModeChangeMessageSerializer());
diff --git 
a/modules/core/src/main/java/org/apache/ignite/plugin/extensions/communication/MessageSerializer.java
 
b/modules/core/src/main/java/org/apache/ignite/plugin/extensions/communication/MarshallableMessage.java
similarity index 58%
copy from 
modules/core/src/main/java/org/apache/ignite/plugin/extensions/communication/MessageSerializer.java
copy to 
modules/core/src/main/java/org/apache/ignite/plugin/extensions/communication/MarshallableMessage.java
index 706b1891572..f58e6cb3241 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/plugin/extensions/communication/MessageSerializer.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/plugin/extensions/communication/MarshallableMessage.java
@@ -17,25 +17,20 @@
 
 package org.apache.ignite.plugin.extensions.communication;
 
-/**
- * Interface for message serialization logic.
- */
-public interface MessageSerializer {
-    /**
-     * Writes this message to provided byte buffer.
-     *
-     * @param msg Message instance.
-     * @param writer Writer.
-     * @return Whether message was fully written.
-     */
-    public boolean writeTo(Message msg, MessageWriter writer);
+import org.apache.ignite.marshaller.Marshaller;
+
+/** A {@link Message} which still requires external custom pre-marshalling and 
post-unmarshalling. */
+public interface MarshallableMessage extends Message {
+    /** @param marsh External custom marshaller. */
+    public default void prepareMarshal(Marshaller marsh) {
+        throw new UnsupportedOperationException();
+    }
 
     /**
-     * Reads this message from provided byte buffer.
-     *
-     * @param msg Message instance.
-     * @param reader Reader.
-     * @return Whether message was fully read.
+     * @param marsh External custom marshaller.
+     * @param clsLdr External class loader to post-unmarshall.
      */
-    public boolean readFrom(Message msg, MessageReader reader);
+    public default void finishUnmarshal(Marshaller marsh, ClassLoader clsLdr) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/plugin/extensions/communication/MessageSerializer.java
 
b/modules/core/src/main/java/org/apache/ignite/plugin/extensions/communication/MessageSerializer.java
index 706b1891572..90df0601693 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/plugin/extensions/communication/MessageSerializer.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/plugin/extensions/communication/MessageSerializer.java
@@ -20,7 +20,7 @@ package org.apache.ignite.plugin.extensions.communication;
 /**
  * Interface for message serialization logic.
  */
-public interface MessageSerializer {
+public interface MessageSerializer<M extends Message> {
     /**
      * Writes this message to provided byte buffer.
      *
@@ -28,7 +28,7 @@ public interface MessageSerializer {
      * @param writer Writer.
      * @return Whether message was fully written.
      */
-    public boolean writeTo(Message msg, MessageWriter writer);
+    public boolean writeTo(M msg, MessageWriter writer);
 
     /**
      * Reads this message from provided byte buffer.
@@ -37,5 +37,5 @@ public interface MessageSerializer {
      * @param reader Reader.
      * @return Whether message was fully read.
      */
-    public boolean readFrom(Message msg, MessageReader reader);
+    public boolean readFrom(M msg, MessageReader reader);
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ClientImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ClientImpl.java
index be87617d45b..aea469edc80 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ClientImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ClientImpl.java
@@ -788,8 +788,6 @@ class ClientImpl extends TcpDiscoveryImpl {
 
                     TcpDiscoveryJoinRequestMessage joinReqMsg = new 
TcpDiscoveryJoinRequestMessage(node, discoveryData);
 
-                    joinReqMsg.prepareMarshal(spi.marshaller());
-
                     TcpDiscoveryNode nodef = node;
 
                     joinReqMsg.spanContainer().span(
@@ -2310,8 +2308,6 @@ class ClientImpl extends TcpDiscoveryImpl {
                         delayDiscoData.clear();
                     }
 
-                    msg.finishUnmarshal(spi.marshaller(), 
U.resolveClassLoader(spi.ignite().configuration()));
-
                     locNode.setAttributes(msg.clientNodeAttributes());
 
                     clearNodeSensitiveData(locNode);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java
index 01a3733da98..61052671449 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java
@@ -1124,8 +1124,6 @@ class ServerImpl extends TcpDiscoveryImpl {
 
         TcpDiscoveryJoinRequestMessage joinReqMsg = new 
TcpDiscoveryJoinRequestMessage(locNode, discoveryData);
 
-        joinReqMsg.prepareMarshal(spi.marshaller());
-
         joinReqMsg.spanContainer().span(
             
tracing.create(TraceableMessagesTable.traceName(joinReqMsg.getClass()))
                 .addTag(SpanTags.tag(SpanTags.EVENT_NODE, SpanTags.ID), () -> 
locNode.id().toString())
@@ -2493,8 +2491,6 @@ class ServerImpl extends TcpDiscoveryImpl {
                 if (addFinishMsg.clientDiscoData() != null) {
                     addFinishMsg = new 
TcpDiscoveryNodeAddFinishedMessage(addFinishMsg);
 
-                    addFinishMsg.prepareMarshal(spi.marshaller());
-
                     msg = addFinishMsg;
 
                     DiscoveryDataPacket discoData = 
addFinishMsg.clientDiscoData();
@@ -3308,9 +3304,6 @@ class ServerImpl extends TcpDiscoveryImpl {
             if (msg instanceof TraceableMessage)
                 tracing.messages().beforeSend((TraceableMessage)msg);
 
-            if (msg instanceof TcpDiscoveryJoinRequestMessage)
-                
((TcpDiscoveryJoinRequestMessage)msg).prepareMarshal(spi.marshaller());
-
             sendMessageToClients(msg);
 
             List<TcpDiscoveryNode> failedNodes;
@@ -4869,8 +4862,6 @@ class ServerImpl extends TcpDiscoveryImpl {
                         addFinishMsg.clientDiscoData(msg.gridDiscoveryData());
 
                         addFinishMsg.clientNodeAttributes(node.attributes());
-
-                        addFinishMsg.prepareMarshal(spi.marshaller());
                     }
 
                     addFinishMsg = tracing.messages().branch(addFinishMsg, 
msg);
@@ -6966,8 +6957,6 @@ class ServerImpl extends TcpDiscoveryImpl {
                         else if (msg instanceof 
TcpDiscoveryJoinRequestMessage) {
                             TcpDiscoveryJoinRequestMessage req = 
(TcpDiscoveryJoinRequestMessage)msg;
 
-                            req.finishUnmarshal(spi.marshaller(), 
U.resolveClassLoader(spi.ignite().configuration()));
-
                             // Current node holds connection with the node 
that is joining the cluster. Therefore, it can
                             // save certificates with which the connection was 
established to joining node attributes.
                             if (spi.nodeAuth != null && 
nodeId.equals(req.node().id()))
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryIoSession.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryIoSession.java
index 4658abb1456..30e9b1b73f8 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryIoSession.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryIoSession.java
@@ -79,7 +79,7 @@ public class TcpDiscoveryIoSession {
     private final Socket sock;
 
     /** */
-    final DirectMessageWriter msgWriter;
+    private final DirectMessageWriter msgWriter;
 
     /** */
     private final DirectMessageReader msgReader;
@@ -91,7 +91,7 @@ public class TcpDiscoveryIoSession {
     private final CompositeInputStream in;
 
     /** Intermediate buffer for serializing discovery messages. */
-    final ByteBuffer msgBuf;
+    private final ByteBuffer msgBuf;
 
     /**
      * Creates a new discovery I/O session bound to the given socket.
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
index 0d99d795a19..c91dffcb5e7 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
@@ -2119,7 +2119,7 @@ public class TcpDiscoverySpi extends IgniteSpiAdapter 
implements IgniteDiscovery
         registerMBean(igniteInstanceName, new TcpDiscoverySpiMBeanImpl(this), 
TcpDiscoverySpiMBean.class);
 
         msgFactory = new IgniteMessageFactoryImpl(
-            new MessageFactoryProvider[] { new DiscoveryMessageFactory() });
+            new MessageFactoryProvider[] { new 
DiscoveryMessageFactory(marshaller(), 
U.resolveClassLoader(ignite().configuration())) });
 
         impl.spiStart(igniteInstanceName);
     }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryClientReconnectMessage.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryClientReconnectMessage.java
index 3a826058c06..9d18e1d5b3c 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryClientReconnectMessage.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryClientReconnectMessage.java
@@ -20,28 +20,46 @@ package org.apache.ignite.spi.discovery.tcp.messages;
 import java.util.Collection;
 import java.util.Objects;
 import java.util.UUID;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.Order;
+import org.apache.ignite.internal.managers.discovery.DiscoveryMessageFactory;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.plugin.extensions.communication.MarshallableMessage;
 
 /**
  * Message telling that client node is reconnecting to topology.
  */
 @TcpDiscoveryEnsureDelivery
-public class TcpDiscoveryClientReconnectMessage extends 
TcpDiscoveryAbstractMessage {
+public class TcpDiscoveryClientReconnectMessage extends 
TcpDiscoveryAbstractMessage implements MarshallableMessage {
     /** */
     private static final long serialVersionUID = 0L;
 
     /** New router nodeID. */
-    private final UUID routerNodeId;
+    @Order(0)
+    UUID routerNodeId;
 
     /** Last message ID. */
-    private final IgniteUuid lastMsgId;
+    @Order(1)
+    IgniteUuid lastMsgId;
 
     /** Pending messages. */
     @GridToStringExclude
     private Collection<TcpDiscoveryAbstractMessage> msgs;
 
+    /** Srialized bytes of {@link #msgs}. */
+    @Order(2)
+    byte[] msgsBytes;
+
+    /** Constructor for {@link DiscoveryMessageFactory}. */
+    public TcpDiscoveryClientReconnectMessage() {
+        // No-op.
+    }
+
     /**
      * @param creatorNodeId Creator node ID.
      * @param routerNodeId New router node ID.
@@ -111,6 +129,37 @@ public class TcpDiscoveryClientReconnectMessage extends 
TcpDiscoveryAbstractMess
             Objects.equals(lastMsgId, other.lastMsgId);
     }
 
+    /** {@inheritDoc} */
+    @Override public void prepareMarshal(Marshaller marsh) {
+        if (msgs != null && msgsBytes == null) {
+            try {
+                msgsBytes = U.marshal(marsh, msgs);
+            }
+            catch (IgniteCheckedException e) {
+                throw new IgniteException("Failed to marshal the pending 
messages.", e);
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void finishUnmarshal(Marshaller marsh, ClassLoader 
clsLdr) {
+        if (msgsBytes != null && msgs == null) {
+            try {
+                msgs = U.unmarshal(marsh, msgsBytes, clsLdr);
+
+                msgsBytes = null;
+            }
+            catch (IgniteCheckedException e) {
+                throw new IgniteException("Failed to unmarshal the pending 
messages.", e);
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public short directType() {
+        return 28;
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(TcpDiscoveryClientReconnectMessage.class, this, 
"super", super.toString());
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryJoinRequestMessage.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryJoinRequestMessage.java
index 6ddbb8f7af2..8932c3f7af9 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryJoinRequestMessage.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryJoinRequestMessage.java
@@ -23,7 +23,7 @@ import org.apache.ignite.internal.Order;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.marshaller.Marshaller;
-import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MarshallableMessage;
 import org.apache.ignite.spi.discovery.tcp.internal.DiscoveryDataPacket;
 import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode;
 
@@ -33,7 +33,7 @@ import static 
org.apache.ignite.internal.util.lang.ClusterNodeFunc.eqNodes;
  * Initial message sent by a node that wants to enter topology.
  * Sent to random node during SPI start. Then forwarded directly to 
coordinator.
  */
-public class TcpDiscoveryJoinRequestMessage extends 
TcpDiscoveryAbstractTraceableMessage implements Message {
+public class TcpDiscoveryJoinRequestMessage extends 
TcpDiscoveryAbstractTraceableMessage implements MarshallableMessage {
     /** */
     private static final long serialVersionUID = 0L;
 
@@ -95,10 +95,8 @@ public class TcpDiscoveryJoinRequestMessage extends 
TcpDiscoveryAbstractTraceabl
         setFlag(RESPONDED_FLAG_POS, responded);
     }
 
-    /**
-     * @param marsh Marshaller.
-     */
-    public void prepareMarshal(Marshaller marsh) {
+    /** {@inheritDoc} */
+    @Override public void prepareMarshal(Marshaller marsh) {
         if (node != null && nodeBytes == null) {
             try {
                 nodeBytes = U.marshal(marsh, node);
@@ -109,11 +107,8 @@ public class TcpDiscoveryJoinRequestMessage extends 
TcpDiscoveryAbstractTraceabl
         }
     }
 
-    /**
-     * @param marsh Marshaller.
-     * @param clsLdr Class loader.
-     */
-    public void finishUnmarshal(Marshaller marsh, ClassLoader clsLdr) {
+    /** {@inheritDoc} */
+    @Override public void finishUnmarshal(Marshaller marsh, ClassLoader 
clsLdr) {
         if (nodeBytes != null && node == null) {
             try {
                 node = U.unmarshal(marsh, nodeBytes, clsLdr);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryNodeAddFinishedMessage.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryNodeAddFinishedMessage.java
index 86fecaed00f..820c42156b5 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryNodeAddFinishedMessage.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryNodeAddFinishedMessage.java
@@ -23,11 +23,10 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.internal.Order;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
-import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.marshaller.Marshaller;
-import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MarshallableMessage;
 import org.apache.ignite.spi.discovery.tcp.internal.DiscoveryDataPacket;
 import org.jetbrains.annotations.Nullable;
 
@@ -36,7 +35,7 @@ import org.jetbrains.annotations.Nullable;
  */
 @TcpDiscoveryEnsureDelivery
 @TcpDiscoveryRedirectToClient
-public class TcpDiscoveryNodeAddFinishedMessage extends 
TcpDiscoveryAbstractTraceableMessage implements Message {
+public class TcpDiscoveryNodeAddFinishedMessage extends 
TcpDiscoveryAbstractTraceableMessage implements MarshallableMessage {
     /** */
     private static final long serialVersionUID = 0L;
 
@@ -85,6 +84,7 @@ public class TcpDiscoveryNodeAddFinishedMessage extends 
TcpDiscoveryAbstractTrac
         nodeId = msg.nodeId;
         clientDiscoData = msg.clientDiscoData;
         clientNodeAttrs = msg.clientNodeAttrs;
+        clientNodeAttrsBytes = msg.clientNodeAttrsBytes;
     }
 
     /**
@@ -126,35 +126,28 @@ public class TcpDiscoveryNodeAddFinishedMessage extends 
TcpDiscoveryAbstractTrac
         this.clientNodeAttrs = clientNodeAttrs;
     }
 
-    /**
-     * @param marsh Marshaller.
-     */
-    public void prepareMarshal(Marshaller marsh) {
+    /** {@inheritDoc} */
+    @Override public void prepareMarshal(Marshaller marsh) {
         if (clientNodeAttrs != null && clientNodeAttrsBytes == null) {
             try {
                 clientNodeAttrsBytes = U.marshal(marsh, clientNodeAttrs);
             }
             catch (IgniteCheckedException e) {
-                throw new IgniteException("Failed to marshal client node 
attributes", e);
+                throw new IgniteException("Failed to marshal client node 
attributes.", e);
             }
         }
     }
 
-    /**
-     * @param marsh Marshaller.
-     * @param clsLdr Class loader.
-     */
-    public void finishUnmarshal(Marshaller marsh, ClassLoader clsLdr) {
-        if (F.isEmpty(clientNodeAttrsBytes))
-            clientNodeAttrs = null;
-        else {
+    /** {@inheritDoc} */
+    @Override public void finishUnmarshal(Marshaller marsh, ClassLoader 
clsLdr) {
+        if (clientNodeAttrsBytes != null && clientNodeAttrs == null) {
             try {
                 clientNodeAttrs = U.unmarshal(marsh, clientNodeAttrsBytes, 
clsLdr);
 
                 clientNodeAttrsBytes = null;
             }
             catch (IgniteCheckedException e) {
-                throw new IgniteException("Failed to unmarshal client node 
attributes", e);
+                throw new IgniteException("Failed to unmarshal client node 
attributes.", e);
             }
         }
     }
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/codegen/MessageProcessorTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/codegen/MessageProcessorTest.java
index 019364513a2..ee30d719dcc 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/codegen/MessageProcessorTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/codegen/MessageProcessorTest.java
@@ -228,6 +228,18 @@ public class MessageProcessorTest {
             
.hasSourceEquivalentTo(javaFile("CustomMapperEnumFieldsMessageSerializer.java"));
     }
 
+    /** */
+    @Test
+    public void testMarshallableMessage() {
+        Compilation compilation = compile("TestMarshallableMessage.java");
+
+        assertThat(compilation).succeeded();
+
+        assertThat(compilation)
+            
.generatedSourceFile("org.apache.ignite.internal.TestMarshallableMessageMarshallableSerializer")
+            
.hasSourceEquivalentTo(javaFile("TestMarshallableMessageMarshallableSerializer.java"));
+    }
+
     /**
      * Negative test for a coflict situation when two enum mappers are used 
for the same enum in different messages.
      */
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/direct/stream/DirectByteBufferStreamImplByteOrderSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/direct/stream/DirectByteBufferStreamImplByteOrderSelfTest.java
index cb6c40576fe..44f44be77f7 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/direct/stream/DirectByteBufferStreamImplByteOrderSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/direct/stream/DirectByteBufferStreamImplByteOrderSelfTest.java
@@ -101,7 +101,7 @@ public class DirectByteBufferStreamImplByteOrderSelfTest {
             @Override public MessageSerializer serializer(short type) {
                 return null;
             }
-        }, null);
+        });
 
         stream.setBuffer(buff);
 
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/managers/communication/AbstractMessageSerializationTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/managers/communication/AbstractMessageSerializationTest.java
index 317ff20a961..2f28cfc4146 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/managers/communication/AbstractMessageSerializationTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/managers/communication/AbstractMessageSerializationTest.java
@@ -435,7 +435,8 @@ public abstract class AbstractMessageSerializationTest {
         @Override public byte[] readByteArray() {
             readField(byte[].class);
 
-            return new byte[0];
+            // Messages may try to post-marshall non-null byte data.
+            return null;
         }
 
         /** {@inheritDoc} */
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/IgniteDiscoveryMessageSerializationTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/IgniteDiscoveryMessageSerializationTest.java
index 6adada121f2..f6eaab9c754 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/IgniteDiscoveryMessageSerializationTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/IgniteDiscoveryMessageSerializationTest.java
@@ -24,6 +24,6 @@ import 
org.apache.ignite.plugin.extensions.communication.MessageFactoryProvider;
 public class IgniteDiscoveryMessageSerializationTest extends 
AbstractMessageSerializationTest {
     /** {@inheritDoc} */
     @Override protected MessageFactoryProvider messageFactory() {
-        return new DiscoveryMessageFactory();
+        return new DiscoveryMessageFactory(null, null);
     }
 }
diff --git a/modules/core/src/test/resources/codegen/AbstractMessage.java 
b/modules/core/src/test/resources/codegen/AbstractMessage.java
index a309841ba5c..d63c3cc5f2f 100644
--- a/modules/core/src/test/resources/codegen/AbstractMessage.java
+++ b/modules/core/src/test/resources/codegen/AbstractMessage.java
@@ -26,6 +26,9 @@ public abstract class AbstractMessage implements Message {
     @Order(0)
     int id;
 
+    @Order(1)
+    byte flags;
+
     public short directType() {
         return 0;
     }
diff --git a/modules/core/src/test/resources/codegen/ChildMessage.java 
b/modules/core/src/test/resources/codegen/ChildMessage.java
index fa97a6cbc44..b89460948a8 100644
--- a/modules/core/src/test/resources/codegen/ChildMessage.java
+++ b/modules/core/src/test/resources/codegen/ChildMessage.java
@@ -23,4 +23,7 @@ import java.nio.ByteBuffer;
 public class ChildMessage extends AbstractMessage {
     @Order(0)
     String str;
+
+    @Order(1)
+    byte flags;
 }
diff --git 
a/modules/core/src/test/resources/codegen/ChildMessageSerializer.java 
b/modules/core/src/test/resources/codegen/ChildMessageSerializer.java
index f7989a079c7..9ca035db404 100644
--- a/modules/core/src/test/resources/codegen/ChildMessageSerializer.java
+++ b/modules/core/src/test/resources/codegen/ChildMessageSerializer.java
@@ -19,7 +19,6 @@ package org.apache.ignite.internal;
 
 import org.apache.ignite.internal.AbstractMessage;
 import org.apache.ignite.internal.ChildMessage;
-import org.apache.ignite.plugin.extensions.communication.Message;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
 import org.apache.ignite.plugin.extensions.communication.MessageSerializer;
 import org.apache.ignite.plugin.extensions.communication.MessageWriter;
@@ -29,11 +28,9 @@ import 
org.apache.ignite.plugin.extensions.communication.MessageWriter;
  *
  * @see org.apache.ignite.internal.MessageProcessor
  */
-public class ChildMessageSerializer implements MessageSerializer {
+public class ChildMessageSerializer implements MessageSerializer<ChildMessage> 
{
     /** */
-    @Override public boolean writeTo(Message m, MessageWriter writer) {
-        ChildMessage msg = (ChildMessage)m;
-
+    @Override public boolean writeTo(ChildMessage msg, MessageWriter writer) {
         if (!writer.isHeaderWritten()) {
             if (!writer.writeHeader(msg.directType()))
                 return false;
@@ -49,7 +46,19 @@ public class ChildMessageSerializer implements 
MessageSerializer {
                 writer.incrementState();
 
             case 1:
-                if (!writer.writeString(((ChildMessage)msg).str))
+                if (!writer.writeByte(((AbstractMessage)msg).flags))
+                    return false;
+
+                writer.incrementState();
+
+            case 2:
+                if (!writer.writeString(msg.str))
+                    return false;
+
+                writer.incrementState();
+
+            case 3:
+                if (!writer.writeByte(msg.flags))
                     return false;
 
                 writer.incrementState();
@@ -59,9 +68,7 @@ public class ChildMessageSerializer implements 
MessageSerializer {
     }
 
     /** */
-    @Override public boolean readFrom(Message m, MessageReader reader) {
-        ChildMessage msg = (ChildMessage)m;
-
+    @Override public boolean readFrom(ChildMessage msg, MessageReader reader) {
         switch (reader.state()) {
             case 0:
                 ((AbstractMessage)msg).id = reader.readInt();
@@ -72,7 +79,23 @@ public class ChildMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 1:
-                ((ChildMessage)msg).str = reader.readString();
+                ((AbstractMessage)msg).flags = reader.readByte();
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 2:
+                msg.str = reader.readString();
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 3:
+                msg.flags = reader.readByte();
 
                 if (!reader.isLastRead())
                     return false;
diff --git 
a/modules/core/src/test/resources/codegen/CustomMapperEnumFieldsMessageSerializer.java
 
b/modules/core/src/test/resources/codegen/CustomMapperEnumFieldsMessageSerializer.java
index 180f067c2f1..db939d08257 100644
--- 
a/modules/core/src/test/resources/codegen/CustomMapperEnumFieldsMessageSerializer.java
+++ 
b/modules/core/src/test/resources/codegen/CustomMapperEnumFieldsMessageSerializer.java
@@ -19,7 +19,6 @@ package org.apache.ignite.internal;
 
 import org.apache.ignite.internal.CustomMapperEnumFieldsMessage;
 import org.apache.ignite.internal.TransactionIsolationEnumMapper;
-import org.apache.ignite.plugin.extensions.communication.Message;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
 import org.apache.ignite.plugin.extensions.communication.MessageSerializer;
 import org.apache.ignite.plugin.extensions.communication.MessageWriter;
@@ -31,14 +30,12 @@ import org.apache.ignite.transactions.TransactionIsolation;
  *
  * @see org.apache.ignite.internal.MessageProcessor
  */
-public class CustomMapperEnumFieldsMessageSerializer implements 
MessageSerializer {
+public class CustomMapperEnumFieldsMessageSerializer implements 
MessageSerializer<CustomMapperEnumFieldsMessage> {
     /** */
     private final EnumMapper<TransactionIsolation> transactionIsolationMapper 
= new TransactionIsolationEnumMapper();
 
     /** */
-    @Override public boolean writeTo(Message m, MessageWriter writer) {
-        CustomMapperEnumFieldsMessage msg = (CustomMapperEnumFieldsMessage)m;
-
+    @Override public boolean writeTo(CustomMapperEnumFieldsMessage msg, 
MessageWriter writer) {
         if (!writer.isHeaderWritten()) {
             if (!writer.writeHeader(msg.directType()))
                 return false;
@@ -48,7 +45,7 @@ public class CustomMapperEnumFieldsMessageSerializer 
implements MessageSerialize
 
         switch (writer.state()) {
             case 0:
-                if 
(!writer.writeByte(transactionIsolationMapper.encode(((CustomMapperEnumFieldsMessage)msg).txMode)))
+                if 
(!writer.writeByte(transactionIsolationMapper.encode(msg.txMode)))
                     return false;
 
                 writer.incrementState();
@@ -58,12 +55,10 @@ public class CustomMapperEnumFieldsMessageSerializer 
implements MessageSerialize
     }
 
     /** */
-    @Override public boolean readFrom(Message m, MessageReader reader) {
-        CustomMapperEnumFieldsMessage msg = (CustomMapperEnumFieldsMessage)m;
-
+    @Override public boolean readFrom(CustomMapperEnumFieldsMessage msg, 
MessageReader reader) {
         switch (reader.state()) {
             case 0:
-                ((CustomMapperEnumFieldsMessage)msg).txMode = 
transactionIsolationMapper.decode(reader.readByte());
+                msg.txMode = 
transactionIsolationMapper.decode(reader.readByte());
 
                 if (!reader.isLastRead())
                     return false;
diff --git 
a/modules/core/src/test/resources/codegen/DefaultMapperEnumFieldsMessageSerializer.java
 
b/modules/core/src/test/resources/codegen/DefaultMapperEnumFieldsMessageSerializer.java
index ce0dfcfab17..245f1f29ae8 100644
--- 
a/modules/core/src/test/resources/codegen/DefaultMapperEnumFieldsMessageSerializer.java
+++ 
b/modules/core/src/test/resources/codegen/DefaultMapperEnumFieldsMessageSerializer.java
@@ -19,7 +19,6 @@ package org.apache.ignite.internal;
 
 import org.apache.ignite.internal.DefaultMapperEnumFieldsMessage;
 import org.apache.ignite.internal.processors.cache.GridCacheOperation;
-import org.apache.ignite.plugin.extensions.communication.Message;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
 import org.apache.ignite.plugin.extensions.communication.MessageSerializer;
 import org.apache.ignite.plugin.extensions.communication.MessageWriter;
@@ -31,16 +30,14 @@ import org.apache.ignite.transactions.TransactionIsolation;
  *
  * @see org.apache.ignite.internal.MessageProcessor
  */
-public class DefaultMapperEnumFieldsMessageSerializer implements 
MessageSerializer {
+public class DefaultMapperEnumFieldsMessageSerializer implements 
MessageSerializer<DefaultMapperEnumFieldsMessage> {
     /** */
     private final GridCacheOperation[] gridCacheOperationVals = 
GridCacheOperation.values();
     /** */
     private final TransactionIsolation[] transactionIsolationVals = 
TransactionIsolation.values();
 
     /** */
-    @Override public boolean writeTo(Message m, MessageWriter writer) {
-        DefaultMapperEnumFieldsMessage msg = (DefaultMapperEnumFieldsMessage)m;
-
+    @Override public boolean writeTo(DefaultMapperEnumFieldsMessage msg, 
MessageWriter writer) {
         if (!writer.isHeaderWritten()) {
             if (!writer.writeHeader(msg.directType()))
                 return false;
@@ -50,13 +47,13 @@ public class DefaultMapperEnumFieldsMessageSerializer 
implements MessageSerializ
 
         switch (writer.state()) {
             case 0:
-                if 
(!writer.writeByte(DefaultEnumMapper.INSTANCE.encode(((DefaultMapperEnumFieldsMessage)msg).publicEnum)))
+                if 
(!writer.writeByte(DefaultEnumMapper.INSTANCE.encode(msg.publicEnum)))
                     return false;
 
                 writer.incrementState();
 
             case 1:
-                if 
(!writer.writeByte(DefaultEnumMapper.INSTANCE.encode(((DefaultMapperEnumFieldsMessage)msg).internalEnum)))
+                if 
(!writer.writeByte(DefaultEnumMapper.INSTANCE.encode(msg.internalEnum)))
                     return false;
 
                 writer.incrementState();
@@ -66,12 +63,10 @@ public class DefaultMapperEnumFieldsMessageSerializer 
implements MessageSerializ
     }
 
     /** */
-    @Override public boolean readFrom(Message m, MessageReader reader) {
-        DefaultMapperEnumFieldsMessage msg = (DefaultMapperEnumFieldsMessage)m;
-
+    @Override public boolean readFrom(DefaultMapperEnumFieldsMessage msg, 
MessageReader reader) {
         switch (reader.state()) {
             case 0:
-                ((DefaultMapperEnumFieldsMessage)msg).publicEnum = 
DefaultEnumMapper.INSTANCE.decode(transactionIsolationVals, reader.readByte());
+                msg.publicEnum = 
DefaultEnumMapper.INSTANCE.decode(transactionIsolationVals, reader.readByte());
 
                 if (!reader.isLastRead())
                     return false;
@@ -79,7 +74,7 @@ public class DefaultMapperEnumFieldsMessageSerializer 
implements MessageSerializ
                 reader.incrementState();
 
             case 1:
-                ((DefaultMapperEnumFieldsMessage)msg).internalEnum = 
DefaultEnumMapper.INSTANCE.decode(gridCacheOperationVals, reader.readByte());
+                msg.internalEnum = 
DefaultEnumMapper.INSTANCE.decode(gridCacheOperationVals, reader.readByte());
 
                 if (!reader.isLastRead())
                     return false;
diff --git 
a/modules/core/src/test/resources/codegen/TestCollectionsMessageSerializer.java 
b/modules/core/src/test/resources/codegen/TestCollectionsMessageSerializer.java
index 00335f38db6..2f4f365cc83 100644
--- 
a/modules/core/src/test/resources/codegen/TestCollectionsMessageSerializer.java
+++ 
b/modules/core/src/test/resources/codegen/TestCollectionsMessageSerializer.java
@@ -18,7 +18,6 @@
 package org.apache.ignite.internal;
 
 import org.apache.ignite.internal.TestCollectionsMessage;
-import org.apache.ignite.plugin.extensions.communication.Message;
 import 
org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
 import org.apache.ignite.plugin.extensions.communication.MessageSerializer;
@@ -29,11 +28,9 @@ import 
org.apache.ignite.plugin.extensions.communication.MessageWriter;
  *
  * @see org.apache.ignite.internal.MessageProcessor
  */
-public class TestCollectionsMessageSerializer implements MessageSerializer {
+public class TestCollectionsMessageSerializer implements 
MessageSerializer<TestCollectionsMessage> {
     /** */
-    @Override public boolean writeTo(Message m, MessageWriter writer) {
-        TestCollectionsMessage msg = (TestCollectionsMessage)m;
-
+    @Override public boolean writeTo(TestCollectionsMessage msg, MessageWriter 
writer) {
         if (!writer.isHeaderWritten()) {
             if (!writer.writeHeader(msg.directType()))
                 return false;
@@ -43,151 +40,151 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
 
         switch (writer.state()) {
             case 0:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).booleanArrayList, 
MessageCollectionItemType.BOOLEAN_ARR))
+                if (!writer.writeCollection(msg.booleanArrayList, 
MessageCollectionItemType.BOOLEAN_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 1:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).byteArrayList, 
MessageCollectionItemType.BYTE_ARR))
+                if (!writer.writeCollection(msg.byteArrayList, 
MessageCollectionItemType.BYTE_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 2:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).shortArrayList, 
MessageCollectionItemType.SHORT_ARR))
+                if (!writer.writeCollection(msg.shortArrayList, 
MessageCollectionItemType.SHORT_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 3:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).intArrayList, 
MessageCollectionItemType.INT_ARR))
+                if (!writer.writeCollection(msg.intArrayList, 
MessageCollectionItemType.INT_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 4:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).longArrayList, 
MessageCollectionItemType.LONG_ARR))
+                if (!writer.writeCollection(msg.longArrayList, 
MessageCollectionItemType.LONG_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 5:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).charArrayList, 
MessageCollectionItemType.CHAR_ARR))
+                if (!writer.writeCollection(msg.charArrayList, 
MessageCollectionItemType.CHAR_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 6:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).floatArrayList, 
MessageCollectionItemType.FLOAT_ARR))
+                if (!writer.writeCollection(msg.floatArrayList, 
MessageCollectionItemType.FLOAT_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 7:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).doubleArrayList, 
MessageCollectionItemType.DOUBLE_ARR))
+                if (!writer.writeCollection(msg.doubleArrayList, 
MessageCollectionItemType.DOUBLE_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 8:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).stringList, 
MessageCollectionItemType.STRING))
+                if (!writer.writeCollection(msg.stringList, 
MessageCollectionItemType.STRING))
                     return false;
 
                 writer.incrementState();
 
             case 9:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).uuidList, 
MessageCollectionItemType.UUID))
+                if (!writer.writeCollection(msg.uuidList, 
MessageCollectionItemType.UUID))
                     return false;
 
                 writer.incrementState();
 
             case 10:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).bitSetList, 
MessageCollectionItemType.BIT_SET))
+                if (!writer.writeCollection(msg.bitSetList, 
MessageCollectionItemType.BIT_SET))
                     return false;
 
                 writer.incrementState();
 
             case 11:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).igniteUuidList, 
MessageCollectionItemType.IGNITE_UUID))
+                if (!writer.writeCollection(msg.igniteUuidList, 
MessageCollectionItemType.IGNITE_UUID))
                     return false;
 
                 writer.incrementState();
 
             case 12:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).affTopVersionList, 
MessageCollectionItemType.AFFINITY_TOPOLOGY_VERSION))
+                if (!writer.writeCollection(msg.affTopVersionList, 
MessageCollectionItemType.AFFINITY_TOPOLOGY_VERSION))
                     return false;
 
                 writer.incrementState();
 
             case 13:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).boxedBooleanList, 
MessageCollectionItemType.BOOLEAN))
+                if (!writer.writeCollection(msg.boxedBooleanList, 
MessageCollectionItemType.BOOLEAN))
                     return false;
 
                 writer.incrementState();
 
             case 14:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).boxedByteList, 
MessageCollectionItemType.BYTE))
+                if (!writer.writeCollection(msg.boxedByteList, 
MessageCollectionItemType.BYTE))
                     return false;
 
                 writer.incrementState();
 
             case 15:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).boxedShortList, 
MessageCollectionItemType.SHORT))
+                if (!writer.writeCollection(msg.boxedShortList, 
MessageCollectionItemType.SHORT))
                     return false;
 
                 writer.incrementState();
 
             case 16:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).boxedIntList, 
MessageCollectionItemType.INT))
+                if (!writer.writeCollection(msg.boxedIntList, 
MessageCollectionItemType.INT))
                     return false;
 
                 writer.incrementState();
 
             case 17:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).boxedLongList, 
MessageCollectionItemType.LONG))
+                if (!writer.writeCollection(msg.boxedLongList, 
MessageCollectionItemType.LONG))
                     return false;
 
                 writer.incrementState();
 
             case 18:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).boxedCharList, 
MessageCollectionItemType.CHAR))
+                if (!writer.writeCollection(msg.boxedCharList, 
MessageCollectionItemType.CHAR))
                     return false;
 
                 writer.incrementState();
 
             case 19:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).boxedFloatList, 
MessageCollectionItemType.FLOAT))
+                if (!writer.writeCollection(msg.boxedFloatList, 
MessageCollectionItemType.FLOAT))
                     return false;
 
                 writer.incrementState();
 
             case 20:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).boxedDoubleList, 
MessageCollectionItemType.DOUBLE))
+                if (!writer.writeCollection(msg.boxedDoubleList, 
MessageCollectionItemType.DOUBLE))
                     return false;
 
                 writer.incrementState();
 
             case 21:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).messageList, 
MessageCollectionItemType.MSG))
+                if (!writer.writeCollection(msg.messageList, 
MessageCollectionItemType.MSG))
                     return false;
 
                 writer.incrementState();
 
             case 22:
-                if 
(!writer.writeCollection(((TestCollectionsMessage)msg).gridLongListList, 
MessageCollectionItemType.GRID_LONG_LIST))
+                if (!writer.writeCollection(msg.gridLongListList, 
MessageCollectionItemType.GRID_LONG_LIST))
                     return false;
 
                 writer.incrementState();
 
             case 23:
-                if 
(!writer.writeSet(((TestCollectionsMessage)msg).boxedIntegerSet, 
MessageCollectionItemType.INT))
+                if (!writer.writeSet(msg.boxedIntegerSet, 
MessageCollectionItemType.INT))
                     return false;
 
                 writer.incrementState();
 
             case 24:
-                if (!writer.writeSet(((TestCollectionsMessage)msg).bitSetSet, 
MessageCollectionItemType.BIT_SET))
+                if (!writer.writeSet(msg.bitSetSet, 
MessageCollectionItemType.BIT_SET))
                     return false;
 
                 writer.incrementState();
@@ -197,12 +194,10 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
     }
 
     /** */
-    @Override public boolean readFrom(Message m, MessageReader reader) {
-        TestCollectionsMessage msg = (TestCollectionsMessage)m;
-
+    @Override public boolean readFrom(TestCollectionsMessage msg, 
MessageReader reader) {
         switch (reader.state()) {
             case 0:
-                ((TestCollectionsMessage)msg).booleanArrayList = 
reader.readCollection(MessageCollectionItemType.BOOLEAN_ARR);
+                msg.booleanArrayList = 
reader.readCollection(MessageCollectionItemType.BOOLEAN_ARR);
 
                 if (!reader.isLastRead())
                     return false;
@@ -210,7 +205,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 1:
-                ((TestCollectionsMessage)msg).byteArrayList = 
reader.readCollection(MessageCollectionItemType.BYTE_ARR);
+                msg.byteArrayList = 
reader.readCollection(MessageCollectionItemType.BYTE_ARR);
 
                 if (!reader.isLastRead())
                     return false;
@@ -218,7 +213,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 2:
-                ((TestCollectionsMessage)msg).shortArrayList = 
reader.readCollection(MessageCollectionItemType.SHORT_ARR);
+                msg.shortArrayList = 
reader.readCollection(MessageCollectionItemType.SHORT_ARR);
 
                 if (!reader.isLastRead())
                     return false;
@@ -226,7 +221,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 3:
-                ((TestCollectionsMessage)msg).intArrayList = 
reader.readCollection(MessageCollectionItemType.INT_ARR);
+                msg.intArrayList = 
reader.readCollection(MessageCollectionItemType.INT_ARR);
 
                 if (!reader.isLastRead())
                     return false;
@@ -234,7 +229,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 4:
-                ((TestCollectionsMessage)msg).longArrayList = 
reader.readCollection(MessageCollectionItemType.LONG_ARR);
+                msg.longArrayList = 
reader.readCollection(MessageCollectionItemType.LONG_ARR);
 
                 if (!reader.isLastRead())
                     return false;
@@ -242,7 +237,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 5:
-                ((TestCollectionsMessage)msg).charArrayList = 
reader.readCollection(MessageCollectionItemType.CHAR_ARR);
+                msg.charArrayList = 
reader.readCollection(MessageCollectionItemType.CHAR_ARR);
 
                 if (!reader.isLastRead())
                     return false;
@@ -250,7 +245,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 6:
-                ((TestCollectionsMessage)msg).floatArrayList = 
reader.readCollection(MessageCollectionItemType.FLOAT_ARR);
+                msg.floatArrayList = 
reader.readCollection(MessageCollectionItemType.FLOAT_ARR);
 
                 if (!reader.isLastRead())
                     return false;
@@ -258,7 +253,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 7:
-                ((TestCollectionsMessage)msg).doubleArrayList = 
reader.readCollection(MessageCollectionItemType.DOUBLE_ARR);
+                msg.doubleArrayList = 
reader.readCollection(MessageCollectionItemType.DOUBLE_ARR);
 
                 if (!reader.isLastRead())
                     return false;
@@ -266,7 +261,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 8:
-                ((TestCollectionsMessage)msg).stringList = 
reader.readCollection(MessageCollectionItemType.STRING);
+                msg.stringList = 
reader.readCollection(MessageCollectionItemType.STRING);
 
                 if (!reader.isLastRead())
                     return false;
@@ -274,7 +269,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 9:
-                ((TestCollectionsMessage)msg).uuidList = 
reader.readCollection(MessageCollectionItemType.UUID);
+                msg.uuidList = 
reader.readCollection(MessageCollectionItemType.UUID);
 
                 if (!reader.isLastRead())
                     return false;
@@ -282,7 +277,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 10:
-                ((TestCollectionsMessage)msg).bitSetList = 
reader.readCollection(MessageCollectionItemType.BIT_SET);
+                msg.bitSetList = 
reader.readCollection(MessageCollectionItemType.BIT_SET);
 
                 if (!reader.isLastRead())
                     return false;
@@ -290,7 +285,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 11:
-                ((TestCollectionsMessage)msg).igniteUuidList = 
reader.readCollection(MessageCollectionItemType.IGNITE_UUID);
+                msg.igniteUuidList = 
reader.readCollection(MessageCollectionItemType.IGNITE_UUID);
 
                 if (!reader.isLastRead())
                     return false;
@@ -298,7 +293,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 12:
-                ((TestCollectionsMessage)msg).affTopVersionList = 
reader.readCollection(MessageCollectionItemType.AFFINITY_TOPOLOGY_VERSION);
+                msg.affTopVersionList = 
reader.readCollection(MessageCollectionItemType.AFFINITY_TOPOLOGY_VERSION);
 
                 if (!reader.isLastRead())
                     return false;
@@ -306,7 +301,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 13:
-                ((TestCollectionsMessage)msg).boxedBooleanList = 
reader.readCollection(MessageCollectionItemType.BOOLEAN);
+                msg.boxedBooleanList = 
reader.readCollection(MessageCollectionItemType.BOOLEAN);
 
                 if (!reader.isLastRead())
                     return false;
@@ -314,7 +309,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 14:
-                ((TestCollectionsMessage)msg).boxedByteList = 
reader.readCollection(MessageCollectionItemType.BYTE);
+                msg.boxedByteList = 
reader.readCollection(MessageCollectionItemType.BYTE);
 
                 if (!reader.isLastRead())
                     return false;
@@ -322,7 +317,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 15:
-                ((TestCollectionsMessage)msg).boxedShortList = 
reader.readCollection(MessageCollectionItemType.SHORT);
+                msg.boxedShortList = 
reader.readCollection(MessageCollectionItemType.SHORT);
 
                 if (!reader.isLastRead())
                     return false;
@@ -330,7 +325,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 16:
-                ((TestCollectionsMessage)msg).boxedIntList = 
reader.readCollection(MessageCollectionItemType.INT);
+                msg.boxedIntList = 
reader.readCollection(MessageCollectionItemType.INT);
 
                 if (!reader.isLastRead())
                     return false;
@@ -338,7 +333,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 17:
-                ((TestCollectionsMessage)msg).boxedLongList = 
reader.readCollection(MessageCollectionItemType.LONG);
+                msg.boxedLongList = 
reader.readCollection(MessageCollectionItemType.LONG);
 
                 if (!reader.isLastRead())
                     return false;
@@ -346,7 +341,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 18:
-                ((TestCollectionsMessage)msg).boxedCharList = 
reader.readCollection(MessageCollectionItemType.CHAR);
+                msg.boxedCharList = 
reader.readCollection(MessageCollectionItemType.CHAR);
 
                 if (!reader.isLastRead())
                     return false;
@@ -354,7 +349,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 19:
-                ((TestCollectionsMessage)msg).boxedFloatList = 
reader.readCollection(MessageCollectionItemType.FLOAT);
+                msg.boxedFloatList = 
reader.readCollection(MessageCollectionItemType.FLOAT);
 
                 if (!reader.isLastRead())
                     return false;
@@ -362,7 +357,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 20:
-                ((TestCollectionsMessage)msg).boxedDoubleList = 
reader.readCollection(MessageCollectionItemType.DOUBLE);
+                msg.boxedDoubleList = 
reader.readCollection(MessageCollectionItemType.DOUBLE);
 
                 if (!reader.isLastRead())
                     return false;
@@ -370,7 +365,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 21:
-                ((TestCollectionsMessage)msg).messageList = 
reader.readCollection(MessageCollectionItemType.MSG);
+                msg.messageList = 
reader.readCollection(MessageCollectionItemType.MSG);
 
                 if (!reader.isLastRead())
                     return false;
@@ -378,7 +373,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 22:
-                ((TestCollectionsMessage)msg).gridLongListList = 
reader.readCollection(MessageCollectionItemType.GRID_LONG_LIST);
+                msg.gridLongListList = 
reader.readCollection(MessageCollectionItemType.GRID_LONG_LIST);
 
                 if (!reader.isLastRead())
                     return false;
@@ -386,7 +381,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 23:
-                ((TestCollectionsMessage)msg).boxedIntegerSet = 
reader.readSet(MessageCollectionItemType.INT);
+                msg.boxedIntegerSet = 
reader.readSet(MessageCollectionItemType.INT);
 
                 if (!reader.isLastRead())
                     return false;
@@ -394,7 +389,7 @@ public class TestCollectionsMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 24:
-                ((TestCollectionsMessage)msg).bitSetSet = 
reader.readSet(MessageCollectionItemType.BIT_SET);
+                msg.bitSetSet = 
reader.readSet(MessageCollectionItemType.BIT_SET);
 
                 if (!reader.isLastRead())
                     return false;
diff --git 
a/modules/core/src/test/resources/codegen/TestMapMessageSerializer.java 
b/modules/core/src/test/resources/codegen/TestMapMessageSerializer.java
index 9753dd90e53..42d0773b7e2 100644
--- a/modules/core/src/test/resources/codegen/TestMapMessageSerializer.java
+++ b/modules/core/src/test/resources/codegen/TestMapMessageSerializer.java
@@ -18,7 +18,6 @@
 package org.apache.ignite.internal;
 
 import org.apache.ignite.internal.TestMapMessage;
-import org.apache.ignite.plugin.extensions.communication.Message;
 import 
org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
 import org.apache.ignite.plugin.extensions.communication.MessageSerializer;
@@ -29,11 +28,9 @@ import 
org.apache.ignite.plugin.extensions.communication.MessageWriter;
  *
  * @see org.apache.ignite.internal.MessageProcessor
  */
-public class TestMapMessageSerializer implements MessageSerializer {
+public class TestMapMessageSerializer implements 
MessageSerializer<TestMapMessage> {
     /** */
-    @Override public boolean writeTo(Message m, MessageWriter writer) {
-        TestMapMessage msg = (TestMapMessage)m;
-
+    @Override public boolean writeTo(TestMapMessage msg, MessageWriter writer) 
{
         if (!writer.isHeaderWritten()) {
             if (!writer.writeHeader(msg.directType()))
                 return false;
@@ -43,145 +40,145 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
 
         switch (writer.state()) {
             case 0:
-                if 
(!writer.writeMap(((TestMapMessage)msg).booleanArrayBoxedLongMap, 
MessageCollectionItemType.BOOLEAN_ARR, MessageCollectionItemType.LONG))
+                if (!writer.writeMap(msg.booleanArrayBoxedLongMap, 
MessageCollectionItemType.BOOLEAN_ARR, MessageCollectionItemType.LONG))
                     return false;
 
                 writer.incrementState();
 
             case 1:
-                if 
(!writer.writeMap(((TestMapMessage)msg).byteArrayBooleanArrayMap, 
MessageCollectionItemType.BYTE_ARR, MessageCollectionItemType.BOOLEAN_ARR))
+                if (!writer.writeMap(msg.byteArrayBooleanArrayMap, 
MessageCollectionItemType.BYTE_ARR, MessageCollectionItemType.BOOLEAN_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 2:
-                if 
(!writer.writeMap(((TestMapMessage)msg).shortArrayByteArrayMap, 
MessageCollectionItemType.SHORT_ARR, MessageCollectionItemType.BYTE_ARR))
+                if (!writer.writeMap(msg.shortArrayByteArrayMap, 
MessageCollectionItemType.SHORT_ARR, MessageCollectionItemType.BYTE_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 3:
-                if 
(!writer.writeMap(((TestMapMessage)msg).intArrayShortArrayMap, 
MessageCollectionItemType.INT_ARR, MessageCollectionItemType.SHORT_ARR))
+                if (!writer.writeMap(msg.intArrayShortArrayMap, 
MessageCollectionItemType.INT_ARR, MessageCollectionItemType.SHORT_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 4:
-                if 
(!writer.writeMap(((TestMapMessage)msg).longArrayIntArrayMap, 
MessageCollectionItemType.LONG_ARR, MessageCollectionItemType.INT_ARR))
+                if (!writer.writeMap(msg.longArrayIntArrayMap, 
MessageCollectionItemType.LONG_ARR, MessageCollectionItemType.INT_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 5:
-                if 
(!writer.writeMap(((TestMapMessage)msg).charArrayLongArrayMap, 
MessageCollectionItemType.CHAR_ARR, MessageCollectionItemType.LONG_ARR))
+                if (!writer.writeMap(msg.charArrayLongArrayMap, 
MessageCollectionItemType.CHAR_ARR, MessageCollectionItemType.LONG_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 6:
-                if 
(!writer.writeMap(((TestMapMessage)msg).floatArrayCharArrayMap, 
MessageCollectionItemType.FLOAT_ARR, MessageCollectionItemType.CHAR_ARR))
+                if (!writer.writeMap(msg.floatArrayCharArrayMap, 
MessageCollectionItemType.FLOAT_ARR, MessageCollectionItemType.CHAR_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 7:
-                if 
(!writer.writeMap(((TestMapMessage)msg).doubleArrayFloatArrayMap, 
MessageCollectionItemType.DOUBLE_ARR, MessageCollectionItemType.FLOAT_ARR))
+                if (!writer.writeMap(msg.doubleArrayFloatArrayMap, 
MessageCollectionItemType.DOUBLE_ARR, MessageCollectionItemType.FLOAT_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 8:
-                if 
(!writer.writeMap(((TestMapMessage)msg).stringDoubleArrayMap, 
MessageCollectionItemType.STRING, MessageCollectionItemType.DOUBLE_ARR))
+                if (!writer.writeMap(msg.stringDoubleArrayMap, 
MessageCollectionItemType.STRING, MessageCollectionItemType.DOUBLE_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 9:
-                if (!writer.writeMap(((TestMapMessage)msg).uuidStringMap, 
MessageCollectionItemType.UUID, MessageCollectionItemType.STRING))
+                if (!writer.writeMap(msg.uuidStringMap, 
MessageCollectionItemType.UUID, MessageCollectionItemType.STRING))
                     return false;
 
                 writer.incrementState();
 
             case 10:
-                if (!writer.writeMap(((TestMapMessage)msg).bitSetUuidMap, 
MessageCollectionItemType.BIT_SET, MessageCollectionItemType.UUID))
+                if (!writer.writeMap(msg.bitSetUuidMap, 
MessageCollectionItemType.BIT_SET, MessageCollectionItemType.UUID))
                     return false;
 
                 writer.incrementState();
 
             case 11:
-                if 
(!writer.writeMap(((TestMapMessage)msg).igniteUuidBitSetMap, 
MessageCollectionItemType.IGNITE_UUID, MessageCollectionItemType.BIT_SET))
+                if (!writer.writeMap(msg.igniteUuidBitSetMap, 
MessageCollectionItemType.IGNITE_UUID, MessageCollectionItemType.BIT_SET))
                     return false;
 
                 writer.incrementState();
 
             case 12:
-                if 
(!writer.writeMap(((TestMapMessage)msg).affTopVersionIgniteUuidMap, 
MessageCollectionItemType.AFFINITY_TOPOLOGY_VERSION, 
MessageCollectionItemType.IGNITE_UUID))
+                if (!writer.writeMap(msg.affTopVersionIgniteUuidMap, 
MessageCollectionItemType.AFFINITY_TOPOLOGY_VERSION, 
MessageCollectionItemType.IGNITE_UUID))
                     return false;
 
                 writer.incrementState();
 
             case 13:
-                if 
(!writer.writeMap(((TestMapMessage)msg).boxedBooleanAffTopVersionMap, 
MessageCollectionItemType.BOOLEAN, 
MessageCollectionItemType.AFFINITY_TOPOLOGY_VERSION))
+                if (!writer.writeMap(msg.boxedBooleanAffTopVersionMap, 
MessageCollectionItemType.BOOLEAN, 
MessageCollectionItemType.AFFINITY_TOPOLOGY_VERSION))
                     return false;
 
                 writer.incrementState();
 
             case 14:
-                if 
(!writer.writeMap(((TestMapMessage)msg).boxedByteBoxedBooleanMap, 
MessageCollectionItemType.BYTE, MessageCollectionItemType.BOOLEAN))
+                if (!writer.writeMap(msg.boxedByteBoxedBooleanMap, 
MessageCollectionItemType.BYTE, MessageCollectionItemType.BOOLEAN))
                     return false;
 
                 writer.incrementState();
 
             case 15:
-                if 
(!writer.writeMap(((TestMapMessage)msg).boxedShortBoxedByteMap, 
MessageCollectionItemType.SHORT, MessageCollectionItemType.BYTE))
+                if (!writer.writeMap(msg.boxedShortBoxedByteMap, 
MessageCollectionItemType.SHORT, MessageCollectionItemType.BYTE))
                     return false;
 
                 writer.incrementState();
 
             case 16:
-                if 
(!writer.writeMap(((TestMapMessage)msg).boxedIntBoxedShortMap, 
MessageCollectionItemType.INT, MessageCollectionItemType.SHORT))
+                if (!writer.writeMap(msg.boxedIntBoxedShortMap, 
MessageCollectionItemType.INT, MessageCollectionItemType.SHORT))
                     return false;
 
                 writer.incrementState();
 
             case 17:
-                if 
(!writer.writeMap(((TestMapMessage)msg).boxedLongBoxedIntMap, 
MessageCollectionItemType.LONG, MessageCollectionItemType.INT))
+                if (!writer.writeMap(msg.boxedLongBoxedIntMap, 
MessageCollectionItemType.LONG, MessageCollectionItemType.INT))
                     return false;
 
                 writer.incrementState();
 
             case 18:
-                if 
(!writer.writeMap(((TestMapMessage)msg).boxedCharBoxedLongMap, 
MessageCollectionItemType.CHAR, MessageCollectionItemType.LONG))
+                if (!writer.writeMap(msg.boxedCharBoxedLongMap, 
MessageCollectionItemType.CHAR, MessageCollectionItemType.LONG))
                     return false;
 
                 writer.incrementState();
 
             case 19:
-                if 
(!writer.writeMap(((TestMapMessage)msg).boxedFloatBoxedCharMap, 
MessageCollectionItemType.FLOAT, MessageCollectionItemType.CHAR))
+                if (!writer.writeMap(msg.boxedFloatBoxedCharMap, 
MessageCollectionItemType.FLOAT, MessageCollectionItemType.CHAR))
                     return false;
 
                 writer.incrementState();
 
             case 20:
-                if 
(!writer.writeMap(((TestMapMessage)msg).boxedDoubleBoxedFloatMap, 
MessageCollectionItemType.DOUBLE, MessageCollectionItemType.FLOAT))
+                if (!writer.writeMap(msg.boxedDoubleBoxedFloatMap, 
MessageCollectionItemType.DOUBLE, MessageCollectionItemType.FLOAT))
                     return false;
 
                 writer.incrementState();
 
             case 21:
-                if 
(!writer.writeMap(((TestMapMessage)msg).messageBoxedDoubleMap, 
MessageCollectionItemType.MSG, MessageCollectionItemType.DOUBLE))
+                if (!writer.writeMap(msg.messageBoxedDoubleMap, 
MessageCollectionItemType.MSG, MessageCollectionItemType.DOUBLE))
                     return false;
 
                 writer.incrementState();
 
             case 22:
-                if 
(!writer.writeMap(((TestMapMessage)msg).integerGridLongListMap, 
MessageCollectionItemType.INT, MessageCollectionItemType.GRID_LONG_LIST))
+                if (!writer.writeMap(msg.integerGridLongListMap, 
MessageCollectionItemType.INT, MessageCollectionItemType.GRID_LONG_LIST))
                     return false;
 
                 writer.incrementState();
 
             case 23:
-                if 
(!writer.writeMap(((TestMapMessage)msg).gridLongListIntegerMap, 
MessageCollectionItemType.GRID_LONG_LIST, MessageCollectionItemType.INT))
+                if (!writer.writeMap(msg.gridLongListIntegerMap, 
MessageCollectionItemType.GRID_LONG_LIST, MessageCollectionItemType.INT))
                     return false;
 
                 writer.incrementState();
@@ -191,12 +188,10 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
     }
 
     /** */
-    @Override public boolean readFrom(Message m, MessageReader reader) {
-        TestMapMessage msg = (TestMapMessage)m;
-
+    @Override public boolean readFrom(TestMapMessage msg, MessageReader 
reader) {
         switch (reader.state()) {
             case 0:
-                ((TestMapMessage)msg).booleanArrayBoxedLongMap = 
reader.readMap(MessageCollectionItemType.BOOLEAN_ARR, 
MessageCollectionItemType.LONG, false);
+                msg.booleanArrayBoxedLongMap = 
reader.readMap(MessageCollectionItemType.BOOLEAN_ARR, 
MessageCollectionItemType.LONG, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -204,7 +199,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 1:
-                ((TestMapMessage)msg).byteArrayBooleanArrayMap = 
reader.readMap(MessageCollectionItemType.BYTE_ARR, 
MessageCollectionItemType.BOOLEAN_ARR, false);
+                msg.byteArrayBooleanArrayMap = 
reader.readMap(MessageCollectionItemType.BYTE_ARR, 
MessageCollectionItemType.BOOLEAN_ARR, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -212,7 +207,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 2:
-                ((TestMapMessage)msg).shortArrayByteArrayMap = 
reader.readMap(MessageCollectionItemType.SHORT_ARR, 
MessageCollectionItemType.BYTE_ARR, false);
+                msg.shortArrayByteArrayMap = 
reader.readMap(MessageCollectionItemType.SHORT_ARR, 
MessageCollectionItemType.BYTE_ARR, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -220,7 +215,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 3:
-                ((TestMapMessage)msg).intArrayShortArrayMap = 
reader.readMap(MessageCollectionItemType.INT_ARR, 
MessageCollectionItemType.SHORT_ARR, false);
+                msg.intArrayShortArrayMap = 
reader.readMap(MessageCollectionItemType.INT_ARR, 
MessageCollectionItemType.SHORT_ARR, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -228,7 +223,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 4:
-                ((TestMapMessage)msg).longArrayIntArrayMap = 
reader.readMap(MessageCollectionItemType.LONG_ARR, 
MessageCollectionItemType.INT_ARR, false);
+                msg.longArrayIntArrayMap = 
reader.readMap(MessageCollectionItemType.LONG_ARR, 
MessageCollectionItemType.INT_ARR, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -236,7 +231,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 5:
-                ((TestMapMessage)msg).charArrayLongArrayMap = 
reader.readMap(MessageCollectionItemType.CHAR_ARR, 
MessageCollectionItemType.LONG_ARR, false);
+                msg.charArrayLongArrayMap = 
reader.readMap(MessageCollectionItemType.CHAR_ARR, 
MessageCollectionItemType.LONG_ARR, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -244,7 +239,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 6:
-                ((TestMapMessage)msg).floatArrayCharArrayMap = 
reader.readMap(MessageCollectionItemType.FLOAT_ARR, 
MessageCollectionItemType.CHAR_ARR, false);
+                msg.floatArrayCharArrayMap = 
reader.readMap(MessageCollectionItemType.FLOAT_ARR, 
MessageCollectionItemType.CHAR_ARR, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -252,7 +247,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 7:
-                ((TestMapMessage)msg).doubleArrayFloatArrayMap = 
reader.readMap(MessageCollectionItemType.DOUBLE_ARR, 
MessageCollectionItemType.FLOAT_ARR, false);
+                msg.doubleArrayFloatArrayMap = 
reader.readMap(MessageCollectionItemType.DOUBLE_ARR, 
MessageCollectionItemType.FLOAT_ARR, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -260,7 +255,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 8:
-                ((TestMapMessage)msg).stringDoubleArrayMap = 
reader.readMap(MessageCollectionItemType.STRING, 
MessageCollectionItemType.DOUBLE_ARR, false);
+                msg.stringDoubleArrayMap = 
reader.readMap(MessageCollectionItemType.STRING, 
MessageCollectionItemType.DOUBLE_ARR, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -268,7 +263,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 9:
-                ((TestMapMessage)msg).uuidStringMap = 
reader.readMap(MessageCollectionItemType.UUID, 
MessageCollectionItemType.STRING, false);
+                msg.uuidStringMap = 
reader.readMap(MessageCollectionItemType.UUID, 
MessageCollectionItemType.STRING, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -276,7 +271,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 10:
-                ((TestMapMessage)msg).bitSetUuidMap = 
reader.readMap(MessageCollectionItemType.BIT_SET, 
MessageCollectionItemType.UUID, false);
+                msg.bitSetUuidMap = 
reader.readMap(MessageCollectionItemType.BIT_SET, 
MessageCollectionItemType.UUID, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -284,7 +279,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 11:
-                ((TestMapMessage)msg).igniteUuidBitSetMap = 
reader.readMap(MessageCollectionItemType.IGNITE_UUID, 
MessageCollectionItemType.BIT_SET, false);
+                msg.igniteUuidBitSetMap = 
reader.readMap(MessageCollectionItemType.IGNITE_UUID, 
MessageCollectionItemType.BIT_SET, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -292,7 +287,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 12:
-                ((TestMapMessage)msg).affTopVersionIgniteUuidMap = 
reader.readMap(MessageCollectionItemType.AFFINITY_TOPOLOGY_VERSION, 
MessageCollectionItemType.IGNITE_UUID, false);
+                msg.affTopVersionIgniteUuidMap = 
reader.readMap(MessageCollectionItemType.AFFINITY_TOPOLOGY_VERSION, 
MessageCollectionItemType.IGNITE_UUID, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -300,7 +295,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 13:
-                ((TestMapMessage)msg).boxedBooleanAffTopVersionMap = 
reader.readMap(MessageCollectionItemType.BOOLEAN, 
MessageCollectionItemType.AFFINITY_TOPOLOGY_VERSION, false);
+                msg.boxedBooleanAffTopVersionMap = 
reader.readMap(MessageCollectionItemType.BOOLEAN, 
MessageCollectionItemType.AFFINITY_TOPOLOGY_VERSION, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -308,7 +303,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 14:
-                ((TestMapMessage)msg).boxedByteBoxedBooleanMap = 
reader.readMap(MessageCollectionItemType.BYTE, 
MessageCollectionItemType.BOOLEAN, false);
+                msg.boxedByteBoxedBooleanMap = 
reader.readMap(MessageCollectionItemType.BYTE, 
MessageCollectionItemType.BOOLEAN, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -316,7 +311,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 15:
-                ((TestMapMessage)msg).boxedShortBoxedByteMap = 
reader.readMap(MessageCollectionItemType.SHORT, MessageCollectionItemType.BYTE, 
false);
+                msg.boxedShortBoxedByteMap = 
reader.readMap(MessageCollectionItemType.SHORT, MessageCollectionItemType.BYTE, 
false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -324,7 +319,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 16:
-                ((TestMapMessage)msg).boxedIntBoxedShortMap = 
reader.readMap(MessageCollectionItemType.INT, MessageCollectionItemType.SHORT, 
false);
+                msg.boxedIntBoxedShortMap = 
reader.readMap(MessageCollectionItemType.INT, MessageCollectionItemType.SHORT, 
false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -332,7 +327,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 17:
-                ((TestMapMessage)msg).boxedLongBoxedIntMap = 
reader.readMap(MessageCollectionItemType.LONG, MessageCollectionItemType.INT, 
false);
+                msg.boxedLongBoxedIntMap = 
reader.readMap(MessageCollectionItemType.LONG, MessageCollectionItemType.INT, 
false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -340,7 +335,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 18:
-                ((TestMapMessage)msg).boxedCharBoxedLongMap = 
reader.readMap(MessageCollectionItemType.CHAR, MessageCollectionItemType.LONG, 
false);
+                msg.boxedCharBoxedLongMap = 
reader.readMap(MessageCollectionItemType.CHAR, MessageCollectionItemType.LONG, 
false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -348,7 +343,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 19:
-                ((TestMapMessage)msg).boxedFloatBoxedCharMap = 
reader.readMap(MessageCollectionItemType.FLOAT, MessageCollectionItemType.CHAR, 
false);
+                msg.boxedFloatBoxedCharMap = 
reader.readMap(MessageCollectionItemType.FLOAT, MessageCollectionItemType.CHAR, 
false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -356,7 +351,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 20:
-                ((TestMapMessage)msg).boxedDoubleBoxedFloatMap = 
reader.readMap(MessageCollectionItemType.DOUBLE, 
MessageCollectionItemType.FLOAT, false);
+                msg.boxedDoubleBoxedFloatMap = 
reader.readMap(MessageCollectionItemType.DOUBLE, 
MessageCollectionItemType.FLOAT, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -364,7 +359,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 21:
-                ((TestMapMessage)msg).messageBoxedDoubleMap = 
reader.readMap(MessageCollectionItemType.MSG, MessageCollectionItemType.DOUBLE, 
false);
+                msg.messageBoxedDoubleMap = 
reader.readMap(MessageCollectionItemType.MSG, MessageCollectionItemType.DOUBLE, 
false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -372,7 +367,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 22:
-                ((TestMapMessage)msg).integerGridLongListMap = 
reader.readMap(MessageCollectionItemType.INT, 
MessageCollectionItemType.GRID_LONG_LIST, false);
+                msg.integerGridLongListMap = 
reader.readMap(MessageCollectionItemType.INT, 
MessageCollectionItemType.GRID_LONG_LIST, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -380,7 +375,7 @@ public class TestMapMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 23:
-                ((TestMapMessage)msg).gridLongListIntegerMap = 
reader.readMap(MessageCollectionItemType.GRID_LONG_LIST, 
MessageCollectionItemType.INT, false);
+                msg.gridLongListIntegerMap = 
reader.readMap(MessageCollectionItemType.GRID_LONG_LIST, 
MessageCollectionItemType.INT, false);
 
                 if (!reader.isLastRead())
                     return false;
diff --git 
a/modules/core/src/test/resources/codegen/TestMarshallableMessage.java 
b/modules/core/src/test/resources/codegen/TestMarshallableMessage.java
new file mode 100644
index 00000000000..58a871692d3
--- /dev/null
+++ b/modules/core/src/test/resources/codegen/TestMarshallableMessage.java
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+import java.util.BitSet;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.internal.util.GridLongList;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.plugin.extensions.communication.MarshallableMessage;
+
+public class TestMarshallableMessage implements MarshallableMessage {
+    @Order(0)
+    int iv;
+
+    @Order(1)
+    String sv;
+
+    Object cstData;
+
+    @Order(2)
+    byte[] cstDataBytes;
+
+    /** {@inheritDoc} */
+    @Override public void prepareMarshal(Marshaller marsh) {
+        if (cstData != null && cstDataBytes == null) {
+            try {
+                cstDataBytes = U.marshal(marsh, cstData);
+            }
+            catch (IgniteCheckedException e) {
+                throw new IgniteException("Failed to marshal custom data.", e);
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void finishUnmarshal(Marshaller marsh, ClassLoader 
clsLdr) {
+        if (cstDataBytes != null && cstData == null) {
+            try {
+                cstData = U.unmarshal(marsh, cstDataBytes, clsLdr);
+
+                cstDataBytes = null;
+            }
+            catch (IgniteCheckedException e) {
+                throw new IgniteException("Failed to unmarshal custom data.", 
e);
+            }
+        }
+    }
+
+    public short directType() {
+        return 0;
+    }
+}
diff --git 
a/modules/core/src/test/resources/codegen/ChildMessageSerializer.java 
b/modules/core/src/test/resources/codegen/TestMarshallableMessageMarshallableSerializer.java
similarity index 59%
copy from modules/core/src/test/resources/codegen/ChildMessageSerializer.java
copy to 
modules/core/src/test/resources/codegen/TestMarshallableMessageMarshallableSerializer.java
index f7989a079c7..365ec8b80bf 100644
--- a/modules/core/src/test/resources/codegen/ChildMessageSerializer.java
+++ 
b/modules/core/src/test/resources/codegen/TestMarshallableMessageMarshallableSerializer.java
@@ -17,9 +17,8 @@
 
 package org.apache.ignite.internal;
 
-import org.apache.ignite.internal.AbstractMessage;
-import org.apache.ignite.internal.ChildMessage;
-import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.internal.TestMarshallableMessage;
+import org.apache.ignite.marshaller.Marshaller;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
 import org.apache.ignite.plugin.extensions.communication.MessageSerializer;
 import org.apache.ignite.plugin.extensions.communication.MessageWriter;
@@ -29,27 +28,43 @@ import 
org.apache.ignite.plugin.extensions.communication.MessageWriter;
  *
  * @see org.apache.ignite.internal.MessageProcessor
  */
-public class ChildMessageSerializer implements MessageSerializer {
+public class TestMarshallableMessageMarshallableSerializer implements 
MessageSerializer<TestMarshallableMessage> {
     /** */
-    @Override public boolean writeTo(Message m, MessageWriter writer) {
-        ChildMessage msg = (ChildMessage)m;
+    private final ClassLoader clsLdr;
+    /** */
+    private final Marshaller marshaller;
 
+    /** */
+    public TestMarshallableMessageMarshallableSerializer(Marshaller 
marshaller, ClassLoader clsLdr) {
+        this.marshaller = marshaller;
+        this.clsLdr = clsLdr;
+    }
+    /** */
+    @Override public boolean writeTo(TestMarshallableMessage msg, 
MessageWriter writer) {
         if (!writer.isHeaderWritten()) {
             if (!writer.writeHeader(msg.directType()))
                 return false;
 
+            msg.prepareMarshal(marshaller);
+
             writer.onHeaderWritten();
         }
 
         switch (writer.state()) {
             case 0:
-                if (!writer.writeInt(((AbstractMessage)msg).id))
+                if (!writer.writeInt(msg.iv))
                     return false;
 
                 writer.incrementState();
 
             case 1:
-                if (!writer.writeString(((ChildMessage)msg).str))
+                if (!writer.writeString(msg.sv))
+                    return false;
+
+                writer.incrementState();
+
+            case 2:
+                if (!writer.writeByteArray(msg.cstDataBytes))
                     return false;
 
                 writer.incrementState();
@@ -59,12 +74,10 @@ public class ChildMessageSerializer implements 
MessageSerializer {
     }
 
     /** */
-    @Override public boolean readFrom(Message m, MessageReader reader) {
-        ChildMessage msg = (ChildMessage)m;
-
+    @Override public boolean readFrom(TestMarshallableMessage msg, 
MessageReader reader) {
         switch (reader.state()) {
             case 0:
-                ((AbstractMessage)msg).id = reader.readInt();
+                msg.iv = reader.readInt();
 
                 if (!reader.isLastRead())
                     return false;
@@ -72,7 +85,15 @@ public class ChildMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 1:
-                ((ChildMessage)msg).str = reader.readString();
+                msg.sv = reader.readString();
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 2:
+                msg.cstDataBytes = reader.readByteArray();
 
                 if (!reader.isLastRead())
                     return false;
@@ -80,6 +101,8 @@ public class ChildMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
         }
 
+        msg.finishUnmarshal(marshaller, clsLdr);
+
         return true;
     }
 }
\ No newline at end of file
diff --git a/modules/core/src/test/resources/codegen/TestMessageSerializer.java 
b/modules/core/src/test/resources/codegen/TestMessageSerializer.java
index 10a7eb4a8a8..f14de0fc03b 100644
--- a/modules/core/src/test/resources/codegen/TestMessageSerializer.java
+++ b/modules/core/src/test/resources/codegen/TestMessageSerializer.java
@@ -19,7 +19,6 @@ package org.apache.ignite.internal;
 
 import org.apache.ignite.internal.TestMessage;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
-import org.apache.ignite.plugin.extensions.communication.Message;
 import 
org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
 import org.apache.ignite.plugin.extensions.communication.MessageSerializer;
@@ -30,11 +29,9 @@ import 
org.apache.ignite.plugin.extensions.communication.MessageWriter;
  *
  * @see org.apache.ignite.internal.MessageProcessor
  */
-public class TestMessageSerializer implements MessageSerializer {
+public class TestMessageSerializer implements MessageSerializer<TestMessage> {
     /** */
-    @Override public boolean writeTo(Message m, MessageWriter writer) {
-        TestMessage msg = (TestMessage)m;
-
+    @Override public boolean writeTo(TestMessage msg, MessageWriter writer) {
         if (!writer.isHeaderWritten()) {
             if (!writer.writeHeader(msg.directType()))
                 return false;
@@ -44,67 +41,67 @@ public class TestMessageSerializer implements 
MessageSerializer {
 
         switch (writer.state()) {
             case 0:
-                if (!writer.writeInt(((TestMessage)msg).id))
+                if (!writer.writeInt(msg.id))
                     return false;
 
                 writer.incrementState();
 
             case 1:
-                if (!writer.writeByteArray(((TestMessage)msg).byteArr))
+                if (!writer.writeByteArray(msg.byteArr))
                     return false;
 
                 writer.incrementState();
 
             case 2:
-                if (!writer.writeString(((TestMessage)msg).str))
+                if (!writer.writeString(msg.str))
                     return false;
 
                 writer.incrementState();
 
             case 3:
-                if (!writer.writeObjectArray(((TestMessage)msg).strArr, 
MessageCollectionItemType.STRING))
+                if (!writer.writeObjectArray(msg.strArr, 
MessageCollectionItemType.STRING))
                     return false;
 
                 writer.incrementState();
 
             case 4:
-                if (!writer.writeObjectArray(((TestMessage)msg).intMatrix, 
MessageCollectionItemType.INT_ARR))
+                if (!writer.writeObjectArray(msg.intMatrix, 
MessageCollectionItemType.INT_ARR))
                     return false;
 
                 writer.incrementState();
 
             case 5:
-                if (!writer.writeMessage(((TestMessage)msg).ver))
+                if (!writer.writeMessage(msg.ver))
                     return false;
 
                 writer.incrementState();
 
             case 6:
-                if (!writer.writeObjectArray(((TestMessage)msg).verArr, 
MessageCollectionItemType.MSG))
+                if (!writer.writeObjectArray(msg.verArr, 
MessageCollectionItemType.MSG))
                     return false;
 
                 writer.incrementState();
 
             case 7:
-                if (!writer.writeUuid(((TestMessage)msg).uuid))
+                if (!writer.writeUuid(msg.uuid))
                     return false;
 
                 writer.incrementState();
 
             case 8:
-                if (!writer.writeIgniteUuid(((TestMessage)msg).ignUuid))
+                if (!writer.writeIgniteUuid(msg.ignUuid))
                     return false;
 
                 writer.incrementState();
 
             case 9:
-                if 
(!writer.writeAffinityTopologyVersion(((TestMessage)msg).topVer))
+                if (!writer.writeAffinityTopologyVersion(msg.topVer))
                     return false;
 
                 writer.incrementState();
 
             case 10:
-                if (!writer.writeBitSet(((TestMessage)msg).bitSet))
+                if (!writer.writeBitSet(msg.bitSet))
                     return false;
 
                 writer.incrementState();
@@ -116,19 +113,19 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 writer.incrementState();
 
             case 12:
-                if 
(!writer.writeKeyCacheObject(((TestMessage)msg).keyCacheObject))
+                if (!writer.writeKeyCacheObject(msg.keyCacheObject))
                     return false;
 
                 writer.incrementState();
 
             case 13:
-                if (!writer.writeCacheObject(((TestMessage)msg).cacheObject))
+                if (!writer.writeCacheObject(msg.cacheObject))
                     return false;
 
                 writer.incrementState();
 
             case 14:
-                if (!writer.writeGridLongList(((TestMessage)msg).gridLongList))
+                if (!writer.writeGridLongList(msg.gridLongList))
                     return false;
 
                 writer.incrementState();
@@ -138,12 +135,10 @@ public class TestMessageSerializer implements 
MessageSerializer {
     }
 
     /** */
-    @Override public boolean readFrom(Message m, MessageReader reader) {
-        TestMessage msg = (TestMessage)m;
-
+    @Override public boolean readFrom(TestMessage msg, MessageReader reader) {
         switch (reader.state()) {
             case 0:
-                ((TestMessage)msg).id = reader.readInt();
+                msg.id = reader.readInt();
 
                 if (!reader.isLastRead())
                     return false;
@@ -151,7 +146,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 1:
-                ((TestMessage)msg).byteArr = reader.readByteArray();
+                msg.byteArr = reader.readByteArray();
 
                 if (!reader.isLastRead())
                     return false;
@@ -159,7 +154,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 2:
-                ((TestMessage)msg).str = reader.readString();
+                msg.str = reader.readString();
 
                 if (!reader.isLastRead())
                     return false;
@@ -167,7 +162,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 3:
-                ((TestMessage)msg).strArr = 
reader.readObjectArray(MessageCollectionItemType.STRING, String.class);
+                msg.strArr = 
reader.readObjectArray(MessageCollectionItemType.STRING, String.class);
 
                 if (!reader.isLastRead())
                     return false;
@@ -175,7 +170,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 4:
-                ((TestMessage)msg).intMatrix = 
reader.readObjectArray(MessageCollectionItemType.INT, int[].class);
+                msg.intMatrix = 
reader.readObjectArray(MessageCollectionItemType.INT, int[].class);
 
                 if (!reader.isLastRead())
                     return false;
@@ -183,7 +178,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 5:
-                ((TestMessage)msg).ver = reader.readMessage();
+                msg.ver = reader.readMessage();
 
                 if (!reader.isLastRead())
                     return false;
@@ -191,7 +186,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 6:
-                ((TestMessage)msg).verArr = 
reader.readObjectArray(MessageCollectionItemType.MSG, GridCacheVersion.class);
+                msg.verArr = 
reader.readObjectArray(MessageCollectionItemType.MSG, GridCacheVersion.class);
 
                 if (!reader.isLastRead())
                     return false;
@@ -199,7 +194,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 7:
-                ((TestMessage)msg).uuid = reader.readUuid();
+                msg.uuid = reader.readUuid();
 
                 if (!reader.isLastRead())
                     return false;
@@ -207,7 +202,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 8:
-                ((TestMessage)msg).ignUuid = reader.readIgniteUuid();
+                msg.ignUuid = reader.readIgniteUuid();
 
                 if (!reader.isLastRead())
                     return false;
@@ -215,7 +210,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 9:
-                ((TestMessage)msg).topVer = 
reader.readAffinityTopologyVersion();
+                msg.topVer = reader.readAffinityTopologyVersion();
 
                 if (!reader.isLastRead())
                     return false;
@@ -223,7 +218,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 10:
-                ((TestMessage)msg).bitSet = reader.readBitSet();
+                msg.bitSet = reader.readBitSet();
 
                 if (!reader.isLastRead())
                     return false;
@@ -239,7 +234,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 12:
-                ((TestMessage)msg).keyCacheObject = 
reader.readKeyCacheObject();
+                msg.keyCacheObject = reader.readKeyCacheObject();
 
                 if (!reader.isLastRead())
                     return false;
@@ -247,7 +242,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 13:
-                ((TestMessage)msg).cacheObject = reader.readCacheObject();
+                msg.cacheObject = reader.readCacheObject();
 
                 if (!reader.isLastRead())
                     return false;
@@ -255,7 +250,7 @@ public class TestMessageSerializer implements 
MessageSerializer {
                 reader.incrementState();
 
             case 14:
-                ((TestMessage)msg).gridLongList = reader.readGridLongList();
+                msg.gridLongList = reader.readGridLongList();
 
                 if (!reader.isLastRead())
                     return false;

Reply via email to