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

shishkovilja 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 c3da0f8d13c IGNITE-28960 Add annotation for empty messages (#13446)
c3da0f8d13c is described below

commit c3da0f8d13ccecc4034a801c3feb17f99bea0949
Author: Ilya Shishkov <[email protected]>
AuthorDate: Fri Aug 7 17:40:07 2026 +0300

    IGNITE-28960 Add annotation for empty messages (#13446)
---
 .../org/apache/ignite/internal}/EmptyMessage.java  | 21 +++++++-----
 .../apache/ignite/internal/MessageProcessor.java   | 15 +++------
 .../tcp/messages/HandshakeWaitMessage.java         |  2 ++
 .../internal/codegen/MessageProcessorTest.java     | 18 ++++++++--
 ...{EmptyMessage.java => CorrectEmptyMessage.java} |  6 ++--
 ...age.java => CorrectEmptyMessageSerializer.java} | 39 +++++++++++++++++++---
 ...mptyMessage.java => IncorrectEmptyMessage.java} |  8 +----
 .../query/h2/twostep/msg/GridH2Null.java           |  2 ++
 .../discovery/zk/internal/ZkNoServersMessage.java  |  2 ++
 9 files changed, 76 insertions(+), 37 deletions(-)

diff --git a/modules/core/src/test/resources/codegen/EmptyMessage.java 
b/modules/codegen/src/main/java/org/apache/ignite/internal/EmptyMessage.java
similarity index 66%
copy from modules/core/src/test/resources/codegen/EmptyMessage.java
copy to 
modules/codegen/src/main/java/org/apache/ignite/internal/EmptyMessage.java
index 4a4eb4760df..f3507e4902c 100644
--- a/modules/core/src/test/resources/codegen/EmptyMessage.java
+++ b/modules/codegen/src/main/java/org/apache/ignite/internal/EmptyMessage.java
@@ -17,13 +17,18 @@
 
 package org.apache.ignite.internal;
 
-import java.nio.ByteBuffer;
-import org.apache.ignite.plugin.extensions.communication.Message;
-import org.apache.ignite.plugin.extensions.communication.MessageReader;
-import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
-public class EmptyMessage implements Message {
-    public short directType() {
-        return 0;
-    }
+/**
+ * Annotation for messages, which does not have fields but should have 
generated <code>MessageSerializer</code>.
+ *
+ * @see MessageProcessor
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.TYPE)
+public @interface EmptyMessage {
+    // No-op.
 }
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 4886bb491e4..decddf10e08 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
@@ -72,7 +72,7 @@ import static 
org.apache.ignite.internal.MessageSerializerGenerator.enumType;
  * This processor is typically registered using the {@code 
META-INF/services/javax.annotation.processing.Processor}
  * service file and triggered during the compilation phase.
  */
-@SupportedAnnotationTypes("org.apache.ignite.internal.Order")
+@SupportedAnnotationTypes({"org.apache.ignite.internal.Order", 
"org.apache.ignite.internal.EmptyMessage"})
 @SupportedSourceVersion(SourceVersion.RELEASE_17)
 public class MessageProcessor extends AbstractProcessor {
     /** Base interface that every message must implement. */
@@ -108,13 +108,6 @@ public class MessageProcessor extends AbstractProcessor {
     /** */
     public static final Set<String> NO_PUBLIC_CTOR_MSGS = Set.of(GRID_H2_NULL, 
ZK_NO_SERVERS_MESSAGE);
 
-    /** Messages with no fields. A serializer must be generated due to 
restrictions in our communication process. */
-    static final String[] EMPTY_MESSAGES = {
-        
"org.apache.ignite.spi.communication.tcp.messages.HandshakeWaitMessage",
-        ZK_NO_SERVERS_MESSAGE,
-        GRID_H2_NULL,
-    };
-
     /** Messages with no fields. A serializer generation intentionally 
skipped. */
     static final String[] SKIP_MESSAGES = {
         "org.apache.ignite.internal.processors.odbc.ClientMessage",
@@ -139,7 +132,6 @@ public class MessageProcessor extends AbstractProcessor {
 
         TypeMirror msgType = msgEl.asType();
 
-        List<TypeMirror> emptyMsgs = typesToTypeMirrors(EMPTY_MESSAGES);
         List<TypeMirror> skipMsgs = typesToTypeMirrors(SKIP_MESSAGES);
 
         TypeElement marshallableEl = 
processingEnv.getElementUtils().getTypeElement(MARSHALLABLE_MESSAGE_INTERFACE);
@@ -172,14 +164,15 @@ public class MessageProcessor extends AbstractProcessor {
 
             List<VariableElement> fields = orderedFields(clazz);
 
-            if (fields.isEmpty() && emptyMsgs.stream().noneMatch(t -> 
isAssignable(t, clazz))) {
+            if (fields.isEmpty() && el.getAnnotation(EmptyMessage.class) == 
null) {
                 if (skipMsgs.stream().anyMatch(t -> isAssignable(t, clazz)))
                     continue;
 
                 processingEnv.getMessager().printMessage(
                     Diagnostic.Kind.ERROR,
                     "Message class doesn't have any ordered fields. " +
-                        "Annotate fields with @Order or add to known empty 
classes MessageProcessor#EMPTY_MESSAGES",
+                        "Annotate fields with @Order if you need to serialize 
them, " +
+                        "or with @EmptyMessage if you need to serialize 
message without fields.",
                     clazz);
             }
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/messages/HandshakeWaitMessage.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/messages/HandshakeWaitMessage.java
index e8cb7db6540..5fdf7060993 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/messages/HandshakeWaitMessage.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/messages/HandshakeWaitMessage.java
@@ -17,12 +17,14 @@
 
 package org.apache.ignite.spi.communication.tcp.messages;
 
+import org.apache.ignite.internal.EmptyMessage;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.plugin.extensions.communication.Message;
 
 /**
  * Message requesting to wait until node's SPI context initialize.
  */
+@EmptyMessage
 public class HandshakeWaitMessage implements Message {
     /** Full message size (with message type) in bytes. */
     public static final int MESSAGE_FULL_SIZE = DIRECT_TYPE_SIZE;
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 43aa5b967ed..fe4dc2e4099 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
@@ -129,13 +129,27 @@ public class MessageProcessorTest {
 
     /** */
     @Test
-    public void testEmptyMessage() {
-        Compilation compilation = compile("EmptyMessage.java");
+    public void testIncorrectEmptyMessage() {
+        Compilation compilation = compile("IncorrectEmptyMessage.java");
 
         assertThat(compilation).succeeded();
         assertTrue(compilation.generatedSourceFiles().isEmpty());
     }
 
+    /** */
+    @Test
+    public void testCorrectEmptyMessage() {
+        Compilation compilation = compile("CorrectEmptyMessage.java");
+
+        assertThat(compilation).succeeded();
+
+        assertEquals(1, compilation.generatedSourceFiles().size());
+
+        assertThat(compilation)
+            
.generatedSourceFile("org.apache.ignite.internal.CorrectEmptyMessageSerializer")
+            
.hasSourceEquivalentTo(javaFile("CorrectEmptyMessageSerializer.java"));
+    }
+
     /** */
     @Test
     public void testWrongClassUseOrder() {
diff --git a/modules/core/src/test/resources/codegen/EmptyMessage.java 
b/modules/core/src/test/resources/codegen/CorrectEmptyMessage.java
similarity index 81%
copy from modules/core/src/test/resources/codegen/EmptyMessage.java
copy to modules/core/src/test/resources/codegen/CorrectEmptyMessage.java
index 4a4eb4760df..a080856fae4 100644
--- a/modules/core/src/test/resources/codegen/EmptyMessage.java
+++ b/modules/core/src/test/resources/codegen/CorrectEmptyMessage.java
@@ -17,12 +17,10 @@
 
 package org.apache.ignite.internal;
 
-import java.nio.ByteBuffer;
 import org.apache.ignite.plugin.extensions.communication.Message;
-import org.apache.ignite.plugin.extensions.communication.MessageReader;
-import org.apache.ignite.plugin.extensions.communication.MessageWriter;
 
-public class EmptyMessage implements Message {
+@EmptyMessage
+public class CorrectEmptyMessage implements Message {
     public short directType() {
         return 0;
     }
diff --git a/modules/core/src/test/resources/codegen/EmptyMessage.java 
b/modules/core/src/test/resources/codegen/CorrectEmptyMessageSerializer.java
similarity index 53%
copy from modules/core/src/test/resources/codegen/EmptyMessage.java
copy to 
modules/core/src/test/resources/codegen/CorrectEmptyMessageSerializer.java
index 4a4eb4760df..9dfc2ef935a 100644
--- a/modules/core/src/test/resources/codegen/EmptyMessage.java
+++ b/modules/core/src/test/resources/codegen/CorrectEmptyMessageSerializer.java
@@ -17,13 +17,42 @@
 
 package org.apache.ignite.internal;
 
-import java.nio.ByteBuffer;
-import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.internal.CorrectEmptyMessage;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageSerializer;
 import org.apache.ignite.plugin.extensions.communication.MessageWriter;
 
-public class EmptyMessage implements Message {
-    public short directType() {
-        return 0;
+/**
+ * This class is generated automatically.
+ *
+ * @see org.apache.ignite.internal.MessageProcessor
+ */
+public final class CorrectEmptyMessageSerializer implements 
MessageSerializer<CorrectEmptyMessage> {
+    /** */
+    @Override public final boolean writeTo(CorrectEmptyMessage msg, 
MessageWriter writer) {
+        if (!writer.isHeaderWritten()) {
+            if (!writer.writeHeader(msg.directType()))
+                return false;
+
+            writer.onHeaderWritten();
+        }
+
+        switch (writer.state()) {
+        }
+
+        return true;
+    }
+
+    /** */
+    @Override public final boolean readFrom(CorrectEmptyMessage msg, 
MessageReader reader) {
+        switch (reader.state()) {
+        }
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public final CorrectEmptyMessage createMessage() {
+        return new CorrectEmptyMessage();
     }
 }
diff --git a/modules/core/src/test/resources/codegen/EmptyMessage.java 
b/modules/core/src/test/resources/codegen/IncorrectEmptyMessage.java
similarity index 76%
rename from modules/core/src/test/resources/codegen/EmptyMessage.java
rename to modules/core/src/test/resources/codegen/IncorrectEmptyMessage.java
index 4a4eb4760df..ade246b30c0 100644
--- a/modules/core/src/test/resources/codegen/EmptyMessage.java
+++ b/modules/core/src/test/resources/codegen/IncorrectEmptyMessage.java
@@ -17,13 +17,7 @@
 
 package org.apache.ignite.internal;
 
-import java.nio.ByteBuffer;
 import org.apache.ignite.plugin.extensions.communication.Message;
-import org.apache.ignite.plugin.extensions.communication.MessageReader;
-import org.apache.ignite.plugin.extensions.communication.MessageWriter;
 
-public class EmptyMessage implements Message {
-    public short directType() {
-        return 0;
-    }
+public class IncorrectEmptyMessage implements Message {
 }
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Null.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Null.java
index 4eba0cad3e7..049a26430a3 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Null.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Null.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.processors.query.h2.twostep.msg;
 
+import org.apache.ignite.internal.EmptyMessage;
 import org.apache.ignite.internal.GridKernalContext;
 import org.h2.value.Value;
 import org.h2.value.ValueNull;
@@ -24,6 +25,7 @@ import org.h2.value.ValueNull;
 /**
  * Message for {@link Value#NULL}.
  */
+@EmptyMessage
 public class GridH2Null extends GridH2ValueMessage {
     /** */
     public static final GridH2Null INSTANCE = new GridH2Null();
diff --git 
a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZkNoServersMessage.java
 
b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZkNoServersMessage.java
index d3505a5127c..b034bed32b1 100644
--- 
a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZkNoServersMessage.java
+++ 
b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZkNoServersMessage.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.spi.discovery.zk.internal;
 
+import org.apache.ignite.internal.EmptyMessage;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.spi.discovery.DiscoverySpiCustomMessage;
 import org.jetbrains.annotations.Nullable;
@@ -24,6 +25,7 @@ import org.jetbrains.annotations.Nullable;
 /**
  *
  */
+@EmptyMessage
 class ZkNoServersMessage implements DiscoverySpiCustomMessage, 
ZkInternalMessage {
     /** {@inheritDoc} */
     @Nullable @Override public DiscoverySpiCustomMessage ackMessage() {

Reply via email to