diff --git a/remoting/src/main/java/org/apache/rocketmq/remoting/protocol/RemotingCommand.java b/remoting/src/main/java/org/apache/rocketmq/remoting/protocol/RemotingCommand.java index bee9b12c8037cd78676f77528932d7a20ea463ca..2f8cb388440fb17a1f97dfb1a177d99f9585e189 100644 --- a/remoting/src/main/java/org/apache/rocketmq/remoting/protocol/RemotingCommand.java +++ b/remoting/src/main/java/org/apache/rocketmq/remoting/protocol/RemotingCommand.java @@ -43,7 +43,7 @@ public class RemotingCommand { private static final Map CANONICAL_NAME_CACHE = new HashMap(); // 1, Oneway // 1, RESPONSE_COMMAND - private static final Map NOT_NULL_ANNOTATION_CACHE = new HashMap(); + private static final Map NULLABLE_FIELD_CACHE = new HashMap(); private static final String STRING_CANONICAL_NAME = String.class.getCanonicalName(); private static final String DOUBLE_CANONICAL_NAME_1 = Double.class.getCanonicalName(); private static final String DOUBLE_CANONICAL_NAME_2 = double.class.getCanonicalName(); @@ -252,11 +252,9 @@ public class RemotingCommand { try { String value = this.extFields.get(fieldName); if (null == value) { - Annotation annotation = getNotNullAnnotation(field); - if (annotation != null) { + if (!isFieldNullable(field)) { throw new RemotingCommandException("the custom field <" + fieldName + "> is null"); } - continue; } @@ -305,16 +303,14 @@ public class RemotingCommand { return field; } - private Annotation getNotNullAnnotation(Field field) { - Annotation annotation = NOT_NULL_ANNOTATION_CACHE.get(field); - - if (annotation == null) { - annotation = field.getAnnotation(CFNotNull.class); - synchronized (NOT_NULL_ANNOTATION_CACHE) { - NOT_NULL_ANNOTATION_CACHE.put(field, annotation); + private boolean isFieldNullable(Field field) { + if (!NULLABLE_FIELD_CACHE.containsKey(field)) { + Annotation annotation = field.getAnnotation(CFNotNull.class); + synchronized (NULLABLE_FIELD_CACHE) { + NULLABLE_FIELD_CACHE.put(field, annotation == null); } } - return annotation; + return NULLABLE_FIELD_CACHE.get(field); } private String getCanonicalName(Class clazz) { diff --git a/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RemotingCommandTest.java b/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RemotingCommandTest.java index e11915b8b8823ae1f84cb4f03f46eafae1eb74e4..2bd41cec839d8365eb46da5e029f03310f74d225 100644 --- a/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RemotingCommandTest.java +++ b/remoting/src/test/java/org/apache/rocketmq/remoting/protocol/RemotingCommandTest.java @@ -16,8 +16,11 @@ */ package org.apache.rocketmq.remoting.protocol; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.nio.ByteBuffer; import org.apache.rocketmq.remoting.CommandCustomHeader; +import org.apache.rocketmq.remoting.annotation.CFNotNull; import org.apache.rocketmq.remoting.exception.RemotingCommandException; import org.junit.Test; @@ -179,6 +182,32 @@ public class RemotingCommandTest { assertThat(((ExtFieldsHeader) decodedHeader).isBooleanValue()).isEqualTo(true); assertThat(((ExtFieldsHeader) decodedHeader).getDoubleValue()).isBetween(0.617, 0.619); } + + @Test + public void testNotNullField() throws Exception { + RemotingCommand remotingCommand = new RemotingCommand(); + Method method = RemotingCommand.class.getDeclaredMethod("isFieldNullable", Field.class); + method.setAccessible(true); + + Field nullString = FieldTestClass.class.getDeclaredField("nullString"); + assertThat(method.invoke(remotingCommand, nullString)).isEqualTo(false); + + Field nullableString = FieldTestClass.class.getDeclaredField("nullable"); + assertThat(method.invoke(remotingCommand, nullableString)).isEqualTo(true); + + Field value = FieldTestClass.class.getDeclaredField("value"); + assertThat(method.invoke(remotingCommand, value)).isEqualTo(false); + } +} + +class FieldTestClass { + @CFNotNull + String nullString = null; + + String nullable = null; + + @CFNotNull + String value = "NotNull"; } class SampleCommandCustomHeader implements CommandCustomHeader {