This is an automated email from the ASF dual-hosted git repository.
anton-vinogradov 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 3209af44754 IGNITE-28938 Split MarshallableMessage: a message with a
custom wire form needs no marshaller (#13427)
3209af44754 is described below
commit 3209af447549c029a9f7eae390187accc80034e9
Author: Anton Vinogradov <[email protected]>
AuthorDate: Wed Aug 5 19:29:54 2026 +0300
IGNITE-28938 Split MarshallableMessage: a message with a custom wire form
needs no marshaller (#13427)
---
.../calcite/message/CalciteMessageFactory.java | 4 +-
.../query/calcite/metadata/ColocationGroup.java | 10 ++--
.../internal/MessageMarshallerGenerator.java | 15 +++++
.../apache/ignite/internal/MessageProcessor.java | 11 +++-
.../ignite/internal/CoreMessagesProvider.java | 4 +-
.../org/apache/ignite/internal/IgniteKernal.java | 8 +--
.../ignite/internal/SelfMarshallingMessage.java | 38 ++++++++++++
.../communication/IgniteMessageFactoryImpl.java | 5 +-
.../communication/MessageUnmarshalOnceCheck.java | 7 ++-
...er.java => AbstractMessageFactoryProvider.java} | 21 ++++---
.../processors/cache/GridCacheEntryInfo.java | 13 ++--
.../preloader/GridDhtPartitionsFullMessage.java | 10 ++--
.../preloader/GridDhtPartitionsSingleMessage.java | 10 ++--
.../distributed/near/GridNearTxPrepareRequest.java | 9 ++-
.../discovery/tcp/internal/TcpDiscoveryNode.java | 10 ++--
.../internal/codegen/MessageProcessorTest.java | 33 +++++++++-
...MessageFactoryMarshallerInitializationTest.java | 4 +-
.../tcp/DiscoveryUnmarshalVulnerabilityTest.java | 4 +-
.../codegen/TestSelfMarshallingMessage.java | 37 ++++++++++++
.../TestSelfMarshallingMessageMarshaller.java | 41 +++++++++++++
.../TestSelfMarshallingMessageSerializer.java | 70 ++++++++++++++++++++++
.../codegen/WrongSelfMarshallingMessage.java | 37 ++++++++++++
.../discovery/zk/internal/ZkMessageFactory.java | 4 +-
23 files changed, 336 insertions(+), 69 deletions(-)
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/CalciteMessageFactory.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/CalciteMessageFactory.java
index dafc92a558b..4978f0717bf 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/CalciteMessageFactory.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/CalciteMessageFactory.java
@@ -18,7 +18,7 @@
package org.apache.ignite.internal.processors.query.calcite.message;
import org.apache.ignite.internal.managers.communication.IgniteMessageFactory;
-import
org.apache.ignite.internal.plugin.AbstractMarshallableMessageFactoryProvider;
+import org.apache.ignite.internal.plugin.AbstractMessageFactoryProvider;
import
org.apache.ignite.internal.processors.query.calcite.metadata.ColocationGroup;
import
org.apache.ignite.internal.processors.query.calcite.metadata.FragmentDescription;
import
org.apache.ignite.internal.processors.query.calcite.metadata.FragmentMapping;
@@ -27,7 +27,7 @@ import
org.apache.ignite.plugin.extensions.communication.Message;
/**
* Message factory.
*/
-public class CalciteMessageFactory extends
AbstractMarshallableMessageFactoryProvider {
+public class CalciteMessageFactory extends AbstractMessageFactoryProvider {
/** */
public static final short MIN_MESSAGE_TYPE = 300;
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/ColocationGroup.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/ColocationGroup.java
index e0b4738bced..336e2210664 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/ColocationGroup.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/ColocationGroup.java
@@ -29,19 +29,17 @@ import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
-import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.internal.MarshallableMessage;
import org.apache.ignite.internal.Order;
+import org.apache.ignite.internal.SelfMarshallingMessage;
import
org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState;
import org.apache.ignite.internal.processors.query.calcite.util.Commons;
import org.apache.ignite.internal.util.GridIntIterator;
import org.apache.ignite.internal.util.GridIntList;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.marshaller.Marshaller;
/** */
-public class ColocationGroup implements MarshallableMessage {
+public class ColocationGroup implements SelfMarshallingMessage {
/** */
@Order(0)
long[] srcIds;
@@ -314,7 +312,7 @@ public class ColocationGroup implements MarshallableMessage
{
}
/** {@inheritDoc} */
- @Override public void marshal(Marshaller marsh) throws
IgniteCheckedException {
+ @Override public void selfMarshal() {
if (!F.isEmpty(marshalledAssignments) || assignments == null ||
primaryAssignment)
return;
@@ -343,7 +341,7 @@ public class ColocationGroup implements MarshallableMessage
{
}
/** {@inheritDoc} */
- @Override public void unmarshal(Marshaller marsh, ClassLoader clsLdr)
throws IgniteCheckedException {
+ @Override public void selfUnmarshal() {
if (F.isEmpty(marshalledAssignments))
return;
diff --git
a/modules/codegen/src/main/java/org/apache/ignite/internal/MessageMarshallerGenerator.java
b/modules/codegen/src/main/java/org/apache/ignite/internal/MessageMarshallerGenerator.java
index ab2ebef2280..34e60541417 100644
---
a/modules/codegen/src/main/java/org/apache/ignite/internal/MessageMarshallerGenerator.java
+++
b/modules/codegen/src/main/java/org/apache/ignite/internal/MessageMarshallerGenerator.java
@@ -51,6 +51,7 @@ import static
org.apache.ignite.internal.MessageProcessor.KEY_CACHE_OBJECT_CLS;
import static
org.apache.ignite.internal.MessageProcessor.MARSHALLABLE_MESSAGE_INTERFACE;
import static org.apache.ignite.internal.MessageProcessor.MESSAGE_INTERFACE;
import static
org.apache.ignite.internal.MessageProcessor.NON_MARSHALLABLE_MESSAGE_INTERFACE;
+import static
org.apache.ignite.internal.MessageProcessor.SELF_MARSHALLING_MESSAGE_INTERFACE;
/**
* Generates {@code *Marshaller} classes for {@code Message} types that are
not {@code NonMarshallableMessage}.
@@ -95,6 +96,9 @@ public class MessageMarshallerGenerator extends
MessageCompanionGenerator {
/** */
private final TypeMirror nonMarshallableType;
+ /** */
+ private final TypeMirror selfMarshallingMsgType;
+
/** */
private final TypeMirror cacheGrpIdMsgType;
@@ -107,6 +111,9 @@ public class MessageMarshallerGenerator extends
MessageCompanionGenerator {
/** */
private boolean marshallable;
+ /** Whether the message marshals fields of its own, so the generated
methods call its step. */
+ private boolean selfMarshalling;
+
/** */
private boolean hasMarshalled;
@@ -133,6 +140,7 @@ public class MessageMarshallerGenerator extends
MessageCompanionGenerator {
msgType = type(MESSAGE_INTERFACE);
cacheObjType = type(CACHE_OBJECT_CLS);
nonMarshallableType = type(NON_MARSHALLABLE_MESSAGE_INTERFACE);
+ selfMarshallingMsgType = type(SELF_MARSHALLING_MESSAGE_INTERFACE);
cacheGrpIdMsgType = type(GRID_CACHE_GROUP_ID_MESSAGE_CLS);
mapType = type(Map.class.getName());
colType = type(Collection.class.getName());
@@ -160,6 +168,7 @@ public class MessageMarshallerGenerator extends
MessageCompanionGenerator {
}
marshallable = marshallableMsgType != null &&
assignableFrom(type.asType(), marshallableMsgType);
+ selfMarshalling = selfMarshallingMsgType != null &&
assignableFrom(type.asType(), selfMarshallingMsgType);
hasMarshalled = kinds.values().stream().anyMatch(k -> k ==
MarshalledKind.BLOB || k == MarshalledKind.ELEMENT_BLOBS);
generateMarshalMethod(fields);
@@ -233,6 +242,9 @@ public class MessageMarshallerGenerator extends
MessageCompanionGenerator {
if (needsCtx(orderedFields))
appendBlock(body, List.of(ctxResolutionLine()));
+ if (selfMarshalling)
+ appendBlock(body, List.of(indentedLine("msg.selfMarshal();")));
+
appendMarshalledFieldsPrepare(body);
appendMarshalledPrepare(body);
@@ -305,6 +317,9 @@ public class MessageMarshallerGenerator extends
MessageCompanionGenerator {
appendMarshalledMapFinish(body);
appendMarshalledElementBlobsFinish(body);
+ if (selfMarshalling)
+ appendBlock(body,
List.of(indentedLine("msg.selfUnmarshal();")));
+
prependMsgFactoryResolution(body);
});
}
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 23e110b1eb4..4886bb491e4 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
@@ -84,6 +84,9 @@ public class MessageProcessor extends AbstractProcessor {
/** Externalizable message. */
static final String MARSHALLABLE_MESSAGE_INTERFACE =
"org.apache.ignite.internal.MarshallableMessage";
+ /** Message that reshapes its own fields before they go on the wire. */
+ static final String SELF_MARSHALLING_MESSAGE_INTERFACE =
"org.apache.ignite.internal.SelfMarshallingMessage";
+
/** Marker of messages with no marshaller. */
static final String NON_MARSHALLABLE_MESSAGE_INTERFACE =
"org.apache.ignite.plugin.extensions.communication.NonMarshallableMessage";
@@ -141,6 +144,7 @@ public class MessageProcessor extends AbstractProcessor {
TypeElement marshallableEl =
processingEnv.getElementUtils().getTypeElement(MARSHALLABLE_MESSAGE_INTERFACE);
TypeElement nonMarshallableEl =
processingEnv.getElementUtils().getTypeElement(NON_MARSHALLABLE_MESSAGE_INTERFACE);
+ TypeElement selfMarshallingEl =
processingEnv.getElementUtils().getTypeElement(SELF_MARSHALLING_MESSAGE_INTERFACE);
Map<TypeElement, List<VariableElement>> msgFields = new HashMap<>();
@@ -155,9 +159,12 @@ public class MessageProcessor extends AbstractProcessor {
// No marshaller is generated for a NonMarshallableMessage, so
declared marshalling logic would silently never run.
if (nonMarshallableEl != null &&
isAssignable(nonMarshallableEl.asType(), clazz)
- && ((marshallableEl != null &&
isAssignable(marshallableEl.asType(), clazz)) || hasMarshalledFields(clazz))) {
+ && ((marshallableEl != null &&
isAssignable(marshallableEl.asType(), clazz))
+ || (selfMarshallingEl != null &&
isAssignable(selfMarshallingEl.asType(), clazz))
+ || hasMarshalledFields(clazz))) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "NonMarshallableMessage must not implement
MarshallableMessage or declare @Marshalled fields", clazz);
+ "NonMarshallableMessage must not implement
MarshallableMessage or SelfMarshallingMessage, " +
+ "nor declare @Marshalled fields", clazz);
}
if (clazz.getModifiers().contains(Modifier.ABSTRACT))
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java
b/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java
index d95dbd5c207..9412a9ab9fa 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java
@@ -44,7 +44,7 @@ import
org.apache.ignite.internal.managers.encryption.NodeEncryptionKeys;
import org.apache.ignite.internal.managers.eventstorage.EventsDataBagItem;
import
org.apache.ignite.internal.managers.eventstorage.GridEventStorageRequest;
import
org.apache.ignite.internal.managers.eventstorage.GridEventStorageResponse;
-import
org.apache.ignite.internal.plugin.AbstractMarshallableMessageFactoryProvider;
+import org.apache.ignite.internal.plugin.AbstractMessageFactoryProvider;
import
org.apache.ignite.internal.processors.authentication.AuthentificationDataBagItem;
import org.apache.ignite.internal.processors.authentication.User;
import
org.apache.ignite.internal.processors.authentication.UserAcceptedMessage;
@@ -323,7 +323,7 @@ import
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryStatusCheckMessa
import org.jetbrains.annotations.Nullable;
/** */
-public class CoreMessagesProvider extends
AbstractMarshallableMessageFactoryProvider {
+public class CoreMessagesProvider extends AbstractMessageFactoryProvider {
/** Node ID message type. */
public static final short NODE_ID_MSG_TYPE = 11500;
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index 1330973d8c1..db961ddbae9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -110,7 +110,7 @@ import
org.apache.ignite.internal.managers.indexing.GridIndexingManager;
import
org.apache.ignite.internal.managers.loadbalancer.GridLoadBalancerManager;
import org.apache.ignite.internal.managers.systemview.GridSystemViewManager;
import
org.apache.ignite.internal.managers.systemview.IgniteConfigurationIterable;
-import
org.apache.ignite.internal.plugin.AbstractMarshallableMessageFactoryProvider;
+import org.apache.ignite.internal.plugin.AbstractMessageFactoryProvider;
import org.apache.ignite.internal.plugin.IgniteLogInfoProvider;
import org.apache.ignite.internal.plugin.IgniteLogInfoProviderImpl;
import org.apache.ignite.internal.processors.GridProcessor;
@@ -1339,13 +1339,13 @@ public class IgniteKernal implements IgniteEx,
Externalizable {
}
/**
- * Re-init {@link AbstractMarshallableMessageFactoryProvider} with a
proper marshaller.
+ * Re-init {@link AbstractMessageFactoryProvider} with a proper marshaller.
*
* @param factoryProvider Message factory provider.
*/
private void initProvider(MessageFactoryProvider factoryProvider) {
- if (factoryProvider instanceof
AbstractMarshallableMessageFactoryProvider) {
-
((AbstractMarshallableMessageFactoryProvider)factoryProvider).init(ctx.marshallerContext().jdkMarshaller(),
+ if (factoryProvider instanceof AbstractMessageFactoryProvider) {
+
((AbstractMessageFactoryProvider)factoryProvider).init(ctx.marshallerContext().jdkMarshaller(),
ctx.marshaller());
}
}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/SelfMarshallingMessage.java
b/modules/core/src/main/java/org/apache/ignite/internal/SelfMarshallingMessage.java
new file mode 100644
index 00000000000..3f3eb87844d
--- /dev/null
+++
b/modules/core/src/main/java/org/apache/ignite/internal/SelfMarshallingMessage.java
@@ -0,0 +1,38 @@
+/*
+ * 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 org.apache.ignite.plugin.extensions.communication.Message;
+
+/**
+ * A {@link Message} that reshapes its own fields before they go on the wire
and back after they arrive: copying a
+ * value into the field that is actually sent, packing bits, recalculating a
TTL. A message needing a
+ * {@code Marshaller} for that implements {@code MarshallableMessage} instead;
here there is none to use.
+ *
+ * @deprecated A message carries data, it is not a place to compute. Each use
of this interface is a message doing
+ * work that belongs to the code building or reading it, so treat the current
ones as debt and add no new ones: do the
+ * conversion where the message is filled in and where it is consumed.
+ */
+@Deprecated
+public interface SelfMarshallingMessage extends Message {
+ /** Called before anything else is marshalled, so a field this step fills
still goes on the wire. */
+ public void selfMarshal();
+
+ /** Called after everything else is unmarshalled, so this step sees the
fields already read back. */
+ public void selfUnmarshal();
+}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/IgniteMessageFactoryImpl.java
b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/IgniteMessageFactoryImpl.java
index a44bbf2706e..26fc5435315 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/IgniteMessageFactoryImpl.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/IgniteMessageFactoryImpl.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.managers.communication;
import java.lang.reflect.Array;
import org.apache.ignite.IgniteException;
import org.apache.ignite.internal.MarshallableMessage;
+import org.apache.ignite.internal.SelfMarshallingMessage;
import org.apache.ignite.internal.processors.cache.DeployableMessage;
import org.apache.ignite.internal.processors.cache.GridCacheMessage;
import org.apache.ignite.internal.processors.cache.GridCacheMessageDeployer;
@@ -92,8 +93,8 @@ public class IgniteMessageFactoryImpl<M extends Message, CM
extends GridCacheMes
try {
Message msg = serializer.createMessage();
- if (marshaller == null && msg instanceof MarshallableMessage) {
- throw new IgniteException("Failed to register a message: it
implements MarshallableMessage but no" +
+ if (marshaller == null && (msg instanceof MarshallableMessage ||
msg instanceof SelfMarshallingMessage)) {
+ throw new IgniteException("Failed to register a message: it
marshals fields of its own but no" +
" marshaller is provided [directType=" + directType +
", cls=" + msg.getClass().getName() + ']');
}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/MessageUnmarshalOnceCheck.java
b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/MessageUnmarshalOnceCheck.java
index aa2e48289a7..f411d2d6ccd 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/MessageUnmarshalOnceCheck.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/MessageUnmarshalOnceCheck.java
@@ -24,6 +24,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.internal.MarshallableMessage;
+import org.apache.ignite.internal.SelfMarshallingMessage;
import org.apache.ignite.plugin.extensions.communication.Message;
/**
@@ -53,11 +54,11 @@ public class MessageUnmarshalOnceCheck {
* @param msg Message about to be finish-unmarshalled.
* @param cacheMode {@code true} for the cache-aware pass, {@code false}
for the cache-free pass; the two passes
* over one message are legitimate and tracked separately, so only a
repeat of the same pass is reported.
- * @return {@code true} if {@code msg} is not a {@link
MarshallableMessage} or is finish-unmarshalled the first
- * time in this pass.
+ * @return {@code true} if {@code msg} marshals no field of its own, or is
finish-unmarshalled the first time in
+ * this pass.
*/
public static boolean firstUnmarshal(Message msg, boolean cacheMode) {
- if (!(msg instanceof MarshallableMessage))
+ if (!(msg instanceof MarshallableMessage) && !(msg instanceof
SelfMarshallingMessage))
return true;
// Static set: evict entries whose message was already collected, so
it doesn't grow across the suite.
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/plugin/AbstractMarshallableMessageFactoryProvider.java
b/modules/core/src/main/java/org/apache/ignite/internal/plugin/AbstractMessageFactoryProvider.java
similarity index 90%
rename from
modules/core/src/main/java/org/apache/ignite/internal/plugin/AbstractMarshallableMessageFactoryProvider.java
rename to
modules/core/src/main/java/org/apache/ignite/internal/plugin/AbstractMessageFactoryProvider.java
index 083be41b16d..44b21069ae0 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/plugin/AbstractMarshallableMessageFactoryProvider.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/plugin/AbstractMessageFactoryProvider.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.plugin;
import java.lang.reflect.Constructor;
import org.apache.ignite.IgniteException;
import org.apache.ignite.internal.MarshallableMessage;
+import org.apache.ignite.internal.SelfMarshallingMessage;
import org.apache.ignite.internal.UseBinaryMarshaller;
import org.apache.ignite.internal.binary.BinaryMarshaller;
import org.apache.ignite.internal.managers.communication.IgniteMessageFactory;
@@ -38,7 +39,7 @@ import org.jetbrains.annotations.Nullable;
* An extension of {@link MessageFactoryProvider} allowing to use provided
schema-aware marshaller
* to register {@link MarshallableMessage}.
*/
-public abstract class AbstractMarshallableMessageFactoryProvider implements
MessageFactoryProvider {
+public abstract class AbstractMessageFactoryProvider implements
MessageFactoryProvider {
/** Generated-companion constructors per message class, including cached
negative lookups. */
private static final ClassValue<Companions> COMPANIONS = new
ClassValue<>() {
@Override protected Companions computeValue(Class<?> cls) {
@@ -74,18 +75,20 @@ public abstract class
AbstractMarshallableMessageFactoryProvider implements Mess
MessageSerializer<T> serializer = loadGenerated(cls, "Serializer",
null, true);
- // A MarshallableMessage always gets a generated marshaller (the hook
call alone is a statement), so its
- // absence is a build problem. For the rest the generator skips
statement-free marshallers, so absence
- // legitimately means "nothing to marshal"; the message and its
companions ship in the same jar, hence
- // a missing class cannot be a packaging accident that spares the
(required) serializer.
+ // A message that marshals a part of its fields itself always gets a
generated marshaller (its own call alone
+ // is a statement), so its absence is a build problem. For the rest
the generator skips statement-free
+ // marshallers, so absence legitimately means "nothing to marshal";
the message and its companions ship in the
+ // same jar, hence a missing class cannot be a packaging accident that
spares the (required) serializer.
MessageMarshaller<T> marshaller;
if (NonMarshallableMessage.class.isAssignableFrom(cls))
marshaller = null;
- else if (MarshallableMessage.class.isAssignableFrom(cls))
- marshaller = loadGenerated(cls, "Marshaller", marsh, true);
- else
- marshaller = loadGenerated(cls, "Marshaller", marsh, false);
+ else {
+ boolean required = MarshallableMessage.class.isAssignableFrom(cls)
+ || SelfMarshallingMessage.class.isAssignableFrom(cls);
+
+ marshaller = loadGenerated(cls, "Marshaller", marsh, required);
+ }
// Deployers are generated for GridCacheMessage subclasses only, so
the class lookup is skipped for the rest;
// a DeployableMessage left without a deployer is then rejected at
registration.
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryInfo.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryInfo.java
index 3d5c2fe4d5a..90012c72bda 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryInfo.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryInfo.java
@@ -18,21 +18,18 @@
package org.apache.ignite.internal.processors.cache;
import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.internal.MarshallableMessage;
import org.apache.ignite.internal.Order;
-import org.apache.ignite.internal.UseBinaryMarshaller;
+import org.apache.ignite.internal.SelfMarshallingMessage;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
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.CacheIdAware;
/**
* Entry information that gets passed over wire.
*/
-@UseBinaryMarshaller
-public class GridCacheEntryInfo implements MarshallableMessage, CacheIdAware {
+public class GridCacheEntryInfo implements SelfMarshallingMessage,
CacheIdAware {
/** */
private static final int SIZE_OVERHEAD = 3 * 8 /* reference */ + 4 /* int
*/ + 2 * 8 /* long */ + 32 /* version */;
@@ -193,9 +190,9 @@ public class GridCacheEntryInfo implements
MarshallableMessage, CacheIdAware {
return SIZE_OVERHEAD + size;
}
- // TODO IGNITE-28920: move the expireTime rebase out of the marshalling
hooks.
+ // TODO IGNITE-28920: the rebase still runs inside the message; move it to
the code filling and reading the entry.
/** {@inheritDoc} */
- @Override public void marshal(Marshaller marsh) throws
IgniteCheckedException {
+ @Override public void selfMarshal() {
if (expireTime == 0)
expireTime = -1;
else {
@@ -207,7 +204,7 @@ public class GridCacheEntryInfo implements
MarshallableMessage, CacheIdAware {
}
/** {@inheritDoc} */
- @Override public void unmarshal(Marshaller marsh, ClassLoader clsLdr)
throws IgniteCheckedException {
+ @Override public void selfUnmarshal() {
long remaining = expireTime;
expireTime = remaining < 0 ? 0 : U.currentTimeMillis() + remaining;
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsFullMessage.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsFullMessage.java
index 0f80b015b48..b01ab9d81b6 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsFullMessage.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsFullMessage.java
@@ -25,11 +25,10 @@ import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
-import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.internal.Compress;
-import org.apache.ignite.internal.MarshallableMessage;
import org.apache.ignite.internal.Order;
+import org.apache.ignite.internal.SelfMarshallingMessage;
import org.apache.ignite.internal.managers.communication.ErrorMessage;
import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
@@ -40,7 +39,6 @@ import
org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.S;
-import org.apache.ignite.marshaller.Marshaller;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -49,7 +47,7 @@ import org.jetbrains.annotations.Nullable;
* GridDhtPartitionsSingleMessage}s were received. <br> May be also compacted
as part of {@link
* CacheAffinityChangeMessage} for node left or failed case.<br>
*/
-public class GridDhtPartitionsFullMessage extends
GridDhtPartitionsAbstractMessage implements MarshallableMessage {
+public class GridDhtPartitionsFullMessage extends
GridDhtPartitionsAbstractMessage implements SelfMarshallingMessage {
/** */
private static final byte REBALANCED_FLAG_MASK = 0x01;
@@ -388,7 +386,7 @@ public class GridDhtPartitionsFullMessage extends
GridDhtPartitionsAbstractMessa
}
/** {@inheritDoc} */
- @Override public void marshal(Marshaller marsh) throws
IgniteCheckedException {
+ @Override public void selfMarshal() {
if (!F.isEmpty(parts) && locParts == null)
locParts = copyPartitionsMap(parts);
}
@@ -408,7 +406,7 @@ public class GridDhtPartitionsFullMessage extends
GridDhtPartitionsAbstractMessa
}
/** {@inheritDoc} */
- @Override public void unmarshal(Marshaller marsh, ClassLoader clsLdr)
throws IgniteCheckedException {
+ @Override public void selfUnmarshal() {
if (locParts != null && parts == null) {
parts = copyPartitionsMap(locParts);
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsSingleMessage.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsSingleMessage.java
index d2df0a081d0..e003492c58c 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsSingleMessage.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsSingleMessage.java
@@ -21,17 +21,15 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.Compress;
-import org.apache.ignite.internal.MarshallableMessage;
import org.apache.ignite.internal.Order;
+import org.apache.ignite.internal.SelfMarshallingMessage;
import org.apache.ignite.internal.managers.communication.ErrorMessage;
import
org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.S;
-import org.apache.ignite.marshaller.Marshaller;
import org.jetbrains.annotations.Nullable;
/**
@@ -39,7 +37,7 @@ import org.jetbrains.annotations.Nullable;
*
* Sent in response to {@link GridDhtPartitionsSingleRequest} and during
processing partitions exchange future.
*/
-public class GridDhtPartitionsSingleMessage extends
GridDhtPartitionsAbstractMessage implements MarshallableMessage {
+public class GridDhtPartitionsSingleMessage extends
GridDhtPartitionsAbstractMessage implements SelfMarshallingMessage {
/** Local partitions. */
@Order(0)
@Compress
@@ -292,12 +290,12 @@ public class GridDhtPartitionsSingleMessage extends
GridDhtPartitionsAbstractMes
}
/** {@inheritDoc} */
- @Override public void marshal(Marshaller marsh) throws
IgniteCheckedException {
+ @Override public void selfMarshal() {
// No-op.
}
/** {@inheritDoc} */
- @Override public void unmarshal(Marshaller marsh, ClassLoader clsLdr)
throws IgniteCheckedException {
+ @Override public void selfUnmarshal() {
if (dupPartsData != null) {
assert parts != null;
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
index 3860c4cd009..fc5074f8941 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
@@ -22,8 +22,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
-import org.apache.ignite.internal.MarshallableMessage;
import org.apache.ignite.internal.Order;
+import org.apache.ignite.internal.SelfMarshallingMessage;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import
org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxPrepareRequest;
@@ -34,13 +34,12 @@ 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.lang.IgniteUuid;
-import org.apache.ignite.marshaller.Marshaller;
import org.jetbrains.annotations.Nullable;
/**
* Near transaction prepare request to primary node. 'Near' means 'Initiating
node' here, not 'Near Cache'.
*/
-public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest
implements MarshallableMessage {
+public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest
implements SelfMarshallingMessage {
/** */
private static final int NEAR_FLAG_MASK = 0x01;
@@ -294,7 +293,7 @@ public class GridNearTxPrepareRequest extends
GridDistributedTxPrepareRequest im
}
/** {@inheritDoc} */
- @Override public void marshal(Marshaller marsh) {
+ @Override public void selfMarshal() {
// Of all tx messages, only the near prepare request transfers entry
expiry policies.
if (writes() != null) {
for (IgniteTxEntry e : writes())
@@ -308,7 +307,7 @@ public class GridNearTxPrepareRequest extends
GridDistributedTxPrepareRequest im
}
/** {@inheritDoc} */
- @Override public void unmarshal(Marshaller marsh, ClassLoader clsLdr) {
+ @Override public void selfUnmarshal() {
// No-op.
}
diff --git
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
index 46f0fe8684a..7c7f795b918 100644
---
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
+++
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
@@ -30,15 +30,14 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
-import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cache.CacheMetrics;
import org.apache.ignite.cluster.ClusterMetrics;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.internal.ClusterMetricsSnapshot;
import org.apache.ignite.internal.IgniteNodeAttributes;
-import org.apache.ignite.internal.MarshallableMessage;
import org.apache.ignite.internal.Marshalled;
import org.apache.ignite.internal.Order;
+import org.apache.ignite.internal.SelfMarshallingMessage;
import org.apache.ignite.internal.managers.discovery.IgniteClusterNode;
import org.apache.ignite.internal.processors.cluster.NodeMetricsMessage;
import org.apache.ignite.internal.util.lang.GridMetadataAwareAdapter;
@@ -49,7 +48,6 @@ import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgnitePredicate;
import org.apache.ignite.lang.IgniteProductVersion;
-import org.apache.ignite.marshaller.Marshaller;
import org.apache.ignite.spi.discovery.DiscoveryMetricsProvider;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.jetbrains.annotations.Nullable;
@@ -64,7 +62,7 @@ import static
org.apache.ignite.internal.util.lang.ClusterNodeFunc.eqNodes;
* <tt>public</tt> due to certain limitations of Java technology.
*/
public class TcpDiscoveryNode extends GridMetadataAwareAdapter implements
IgniteClusterNode,
- Comparable<TcpDiscoveryNode>, Externalizable, MarshallableMessage {
+ Comparable<TcpDiscoveryNode>, Externalizable, SelfMarshallingMessage {
/** */
private static final long serialVersionUID = 0L;
@@ -223,12 +221,12 @@ public class TcpDiscoveryNode extends
GridMetadataAwareAdapter implements Ignite
}
/** {@inheritDoc} */
- @Override public void marshal(Marshaller marsh) throws
IgniteCheckedException {
+ @Override public void selfMarshal() {
metricsMsg = new NodeMetricsMessage(metrics);
}
/** {@inheritDoc} */
- @Override public void unmarshal(Marshaller marsh, ClassLoader clsLdr)
throws IgniteCheckedException {
+ @Override public void selfUnmarshal() {
if (metricsMsg != null)
metrics = new ClusterMetricsSnapshot(metricsMsg);
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 8fa7bc91c6b..43aa5b967ed 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
@@ -372,6 +372,24 @@ public class MessageProcessorTest {
.hasSourceEquivalentTo(javaFile("TestMarshallableMessageMarshaller.java"));
}
+ /** The self-marshalling step is called from the generated marshaller,
statically. */
+ @Test
+ public void testSelfMarshallingMessage() {
+ Compilation compilation = compile("TestSelfMarshallingMessage.java");
+
+ assertThat(compilation).succeeded();
+
+ assertEquals(2, compilation.generatedSourceFiles().size());
+
+ assertThat(compilation)
+
.generatedSourceFile("org.apache.ignite.internal.TestSelfMarshallingMessageSerializer")
+
.hasSourceEquivalentTo(javaFile("TestSelfMarshallingMessageSerializer.java"));
+
+ assertThat(compilation)
+
.generatedSourceFile("org.apache.ignite.internal.TestSelfMarshallingMessageMarshaller")
+
.hasSourceEquivalentTo(javaFile("TestSelfMarshallingMessageMarshaller.java"));
+ }
+
/**
* Negative test for a coflict situation when two enum mappers are used
for the same enum in different messages.
*/
@@ -611,8 +629,19 @@ public class MessageProcessorTest {
assertThat(compilation).failed();
- assertThat(compilation)
- .hadErrorContaining("NonMarshallableMessage must not implement
MarshallableMessage or declare @Marshalled fields");
+ assertThat(compilation).hadErrorContaining("NonMarshallableMessage
must not implement MarshallableMessage " +
+ "or SelfMarshallingMessage, nor declare @Marshalled fields");
+ }
+
+ /** A self-marshalling step of a {@code NonMarshallableMessage} would
never run: it gets no marshaller to call it. */
+ @Test
+ public void testNonMarshallableSelfMarshallingFailed() {
+ Compilation compilation = compile("WrongSelfMarshallingMessage.java");
+
+ assertThat(compilation).failed();
+
+ assertThat(compilation).hadErrorContaining("NonMarshallableMessage
must not implement MarshallableMessage " +
+ "or SelfMarshallingMessage, nor declare @Marshalled fields");
}
/** */
diff --git
a/modules/core/src/test/java/org/apache/ignite/internal/managers/communication/MessageFactoryMarshallerInitializationTest.java
b/modules/core/src/test/java/org/apache/ignite/internal/managers/communication/MessageFactoryMarshallerInitializationTest.java
index f6fcc89dad5..b4f8532b9df 100644
---
a/modules/core/src/test/java/org/apache/ignite/internal/managers/communication/MessageFactoryMarshallerInitializationTest.java
+++
b/modules/core/src/test/java/org/apache/ignite/internal/managers/communication/MessageFactoryMarshallerInitializationTest.java
@@ -21,7 +21,7 @@ import java.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.IgniteConfiguration;
-import
org.apache.ignite.internal.plugin.AbstractMarshallableMessageFactoryProvider;
+import org.apache.ignite.internal.plugin.AbstractMessageFactoryProvider;
import org.apache.ignite.marshaller.Marshaller;
import org.apache.ignite.plugin.AbstractTestPluginProvider;
import org.apache.ignite.plugin.ExtensionRegistry;
@@ -94,7 +94,7 @@ public class MessageFactoryMarshallerInitializationTest
extends GridCommonAbstra
}
/** Message factory provider, which counts initializations. */
- private static class TestMessageFactoryProvider extends
AbstractMarshallableMessageFactoryProvider {
+ private static class TestMessageFactoryProvider extends
AbstractMessageFactoryProvider {
/** {@inheritDoc} */
@Override public void registerAll(IgniteMessageFactory factory) {
// No-op.
diff --git
a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/DiscoveryUnmarshalVulnerabilityTest.java
b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/DiscoveryUnmarshalVulnerabilityTest.java
index f0c4fa25f9f..b5e2c457ffe 100644
---
a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/DiscoveryUnmarshalVulnerabilityTest.java
+++
b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/DiscoveryUnmarshalVulnerabilityTest.java
@@ -38,7 +38,7 @@ import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.direct.DirectMessageWriter;
import org.apache.ignite.internal.managers.communication.IgniteMessageFactory;
import org.apache.ignite.internal.managers.communication.MessageMarshalling;
-import
org.apache.ignite.internal.plugin.AbstractMarshallableMessageFactoryProvider;
+import org.apache.ignite.internal.plugin.AbstractMessageFactoryProvider;
import org.apache.ignite.internal.processors.cache.CacheObjectContext;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.marshaller.Marshallers;
@@ -344,7 +344,7 @@ public abstract class DiscoveryUnmarshalVulnerabilityTest
extends GridCommonAbst
public static class TestMessageFactoryPlugin extends
AbstractTestPluginProvider {
/** {@inheritDoc} */
@Override public void initExtensions(PluginContext ctx,
ExtensionRegistry registry) {
- registry.registerExtension(MessageFactoryProvider.class, new
AbstractMarshallableMessageFactoryProvider() {
+ registry.registerExtension(MessageFactoryProvider.class, new
AbstractMessageFactoryProvider() {
/** {@inheritDoc} */
@Override public void registerAll(IgniteMessageFactory
factory) {
factory.register(
diff --git
a/modules/core/src/test/resources/codegen/TestSelfMarshallingMessage.java
b/modules/core/src/test/resources/codegen/TestSelfMarshallingMessage.java
new file mode 100644
index 00000000000..d67250092d4
--- /dev/null
+++ b/modules/core/src/test/resources/codegen/TestSelfMarshallingMessage.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+public class TestSelfMarshallingMessage implements SelfMarshallingMessage {
+ long ttl;
+
+ @Order(0)
+ long ttlOnWire;
+
+ @Override public void selfMarshal() {
+ ttlOnWire = ttl;
+ }
+
+ @Override public void selfUnmarshal() {
+ ttl = ttlOnWire;
+ }
+
+ public short directType() {
+ return 0;
+ }
+}
diff --git
a/modules/core/src/test/resources/codegen/TestSelfMarshallingMessageMarshaller.java
b/modules/core/src/test/resources/codegen/TestSelfMarshallingMessageMarshaller.java
new file mode 100644
index 00000000000..bbecc98571e
--- /dev/null
+++
b/modules/core/src/test/resources/codegen/TestSelfMarshallingMessageMarshaller.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.TestSelfMarshallingMessage;
+import org.apache.ignite.internal.processors.cache.CacheObjectContext;
+import org.apache.ignite.plugin.extensions.communication.MessageMarshaller;
+
+/**
+ * This class is generated automatically.
+ *
+ * @see org.apache.ignite.internal.MessageProcessor
+ */
+public final class TestSelfMarshallingMessageMarshaller implements
MessageMarshaller<TestSelfMarshallingMessage> {
+ /** */
+ @Override public void marshal(TestSelfMarshallingMessage msg,
GridKernalContext kctx, CacheObjectContext cacheObjCtx) throws
IgniteCheckedException {
+ msg.selfMarshal();
+ }
+
+ /** */
+ @Override public void unmarshal(TestSelfMarshallingMessage msg,
GridKernalContext kctx, CacheObjectContext cacheObjCtx, ClassLoader clsLdr)
throws IgniteCheckedException {
+ msg.selfUnmarshal();
+ }
+}
diff --git
a/modules/core/src/test/resources/codegen/TestSelfMarshallingMessageSerializer.java
b/modules/core/src/test/resources/codegen/TestSelfMarshallingMessageSerializer.java
new file mode 100644
index 00000000000..ceb51075839
--- /dev/null
+++
b/modules/core/src/test/resources/codegen/TestSelfMarshallingMessageSerializer.java
@@ -0,0 +1,70 @@
+/*
+ * 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 org.apache.ignite.internal.TestSelfMarshallingMessage;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageSerializer;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+
+/**
+ * This class is generated automatically.
+ *
+ * @see org.apache.ignite.internal.MessageProcessor
+ */
+public final class TestSelfMarshallingMessageSerializer implements
MessageSerializer<TestSelfMarshallingMessage> {
+ /** */
+ @Override public final boolean writeTo(TestSelfMarshallingMessage msg,
MessageWriter writer) {
+ if (!writer.isHeaderWritten()) {
+ if (!writer.writeHeader(msg.directType()))
+ return false;
+
+ writer.onHeaderWritten();
+ }
+
+ switch (writer.state()) {
+ case 0:
+ if (!writer.writeLong(msg.ttlOnWire))
+ return false;
+
+ writer.incrementState();
+ }
+
+ return true;
+ }
+
+ /** */
+ @Override public final boolean readFrom(TestSelfMarshallingMessage msg,
MessageReader reader) {
+ switch (reader.state()) {
+ case 0:
+ msg.ttlOnWire = reader.readLong();
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public final TestSelfMarshallingMessage createMessage() {
+ return new TestSelfMarshallingMessage();
+ }
+}
diff --git
a/modules/core/src/test/resources/codegen/WrongSelfMarshallingMessage.java
b/modules/core/src/test/resources/codegen/WrongSelfMarshallingMessage.java
new file mode 100644
index 00000000000..b0d5f255a02
--- /dev/null
+++ b/modules/core/src/test/resources/codegen/WrongSelfMarshallingMessage.java
@@ -0,0 +1,37 @@
+/*
+ * 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
org.apache.ignite.plugin.extensions.communication.NonMarshallableMessage;
+
+public class WrongSelfMarshallingMessage implements NonMarshallableMessage,
SelfMarshallingMessage {
+ @Order(0)
+ int id;
+
+ @Override public void selfMarshal() {
+ // No-op.
+ }
+
+ @Override public void selfUnmarshal() {
+ // No-op.
+ }
+
+ public short directType() {
+ return 0;
+ }
+}
diff --git
a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZkMessageFactory.java
b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZkMessageFactory.java
index c7b32818666..4432f981bd7 100644
---
a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZkMessageFactory.java
+++
b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZkMessageFactory.java
@@ -18,10 +18,10 @@
package org.apache.ignite.spi.discovery.zk.internal;
import org.apache.ignite.internal.managers.communication.IgniteMessageFactory;
-import
org.apache.ignite.internal.plugin.AbstractMarshallableMessageFactoryProvider;
+import org.apache.ignite.internal.plugin.AbstractMessageFactoryProvider;
/** */
-public class ZkMessageFactory extends
AbstractMarshallableMessageFactoryProvider {
+public class ZkMessageFactory extends AbstractMessageFactoryProvider {
/** {@inheritDoc} */
@Override public void registerAll(IgniteMessageFactory factory) {
register(factory, ZkCommunicationErrorResolveFinishMessage.class,
(short)400);