diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultMessage.java b/src/main/java/org/springframework/data/redis/connection/DefaultMessage.java index e32d8ad890..8f036a581b 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultMessage.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultMessage.java @@ -15,14 +15,17 @@ */ package org.springframework.data.redis.connection; +import org.springframework.data.redis.connection.util.ByteArrayWrapper; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * Default message implementation. * * @author Costin Leau * @author Christoph Strobl + * @author Thomas Heigl */ public class DefaultMessage implements Message { @@ -39,9 +42,6 @@ public DefaultMessage(byte[] channel, byte[] body) { this.channel = channel; } - /** - * @return - */ public byte[] getChannel() { return channel.clone(); } @@ -50,9 +50,28 @@ public byte[] getBody() { return body.clone(); } + public boolean hasChannel() { + return !ObjectUtils.isEmpty(channel); + } + + public boolean hasBody() { + return !ObjectUtils.isEmpty(body); + } + + public String getChannelAsString() { + return new String(channel); + } + + public String getBodyAsString() { + return new String(body); + } + + public ByteArrayWrapper getChannelAsWrapper() { + return new ByteArrayWrapper(channel); + } + @Override public String toString() { - if (toString == null) { toString = new String(body); } diff --git a/src/main/java/org/springframework/data/redis/connection/Message.java b/src/main/java/org/springframework/data/redis/connection/Message.java index 20c791276d..63f233a354 100644 --- a/src/main/java/org/springframework/data/redis/connection/Message.java +++ b/src/main/java/org/springframework/data/redis/connection/Message.java @@ -17,13 +17,15 @@ import java.io.Serializable; -import org.springframework.lang.Nullable; +import org.springframework.data.redis.connection.util.ByteArrayWrapper; +import org.springframework.util.ObjectUtils; /** * Class encapsulating a Redis message body and its properties. * * @author Costin Leau * @author Christoph Strobl + * @author Thomas Heigl */ public interface Message extends Serializable { @@ -40,4 +42,50 @@ public interface Message extends Serializable { * @return message channel. Never {@literal null}. */ byte[] getChannel(); + + /** + * Check if the message has a channel + * + * @return {@code true} if the message has a channel, otherwise {@code false} + */ + default boolean hasChannel() { + return !ObjectUtils.isEmpty(getChannel()); + } + + /** + * Check if the message has a body + * + * @return {@code true} if the message has a body, otherwise {@code false} + */ + default boolean hasBody() { + return !ObjectUtils.isEmpty(getBody()); + } + + /** + * Returns the string representation of the channel associated with the message. + * + * @return message channel as string. Never {@literal null}. + */ + default String getChannelAsString() { + return new String(getChannel()); + } + + /** + * Returns the string representation of the body (or the payload) of the message + * + * @return body as string. Never {@literal null}. + */ + default String getBodyAsString() { + return new String(getBody()); + } + + /** + * Returns the channel associated with the message wrapped in a {@link ByteArrayWrapper} + * + * @return the wrapped channel + */ + default ByteArrayWrapper getChannelAsWrapper() { + return new ByteArrayWrapper(getChannel()); + } + } diff --git a/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java b/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java index f82bd69690..636bba8635 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java +++ b/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java @@ -808,7 +808,7 @@ public void onMessage(Message message, @Nullable byte[] pattern) { Object value = CollectionUtils.isEmpty(hash) ? null : converter.read(Object.class, new RedisData(hash)); - String channel = !ObjectUtils.isEmpty(message.getChannel()) + String channel = message.hasChannel() ? converter.getConversionService().convert(message.getChannel(), String.class) : null; @@ -826,7 +826,7 @@ public void onMessage(Message message, @Nullable byte[] pattern) { private boolean isKeyExpirationMessage(Message message) { - if (message == null || message.getChannel() == null || message.getBody() == null) { + if (message == null || !message.hasChannel() || !message.hasBody()) { return false; } diff --git a/src/main/java/org/springframework/data/redis/listener/KeyspaceEventMessageListener.java b/src/main/java/org/springframework/data/redis/listener/KeyspaceEventMessageListener.java index f4911aa951..22f15ccec2 100644 --- a/src/main/java/org/springframework/data/redis/listener/KeyspaceEventMessageListener.java +++ b/src/main/java/org/springframework/data/redis/listener/KeyspaceEventMessageListener.java @@ -60,7 +60,7 @@ public KeyspaceEventMessageListener(RedisMessageListenerContainer listenerContai @Override public void onMessage(Message message, @Nullable byte[] pattern) { - if (message == null || ObjectUtils.isEmpty(message.getChannel()) || ObjectUtils.isEmpty(message.getBody())) { + if (message == null || !message.hasChannel() || !message.hasBody()) { return; } diff --git a/src/main/java/org/springframework/data/redis/listener/RedisMessageListenerContainer.java b/src/main/java/org/springframework/data/redis/listener/RedisMessageListenerContainer.java index 2f53a0c769..dced762a77 100644 --- a/src/main/java/org/springframework/data/redis/listener/RedisMessageListenerContainer.java +++ b/src/main/java/org/springframework/data/redis/listener/RedisMessageListenerContainer.java @@ -970,7 +970,7 @@ public void onMessage(Message message, @Nullable byte[] pattern) { } else { pattern = null; // do channel matching first - listeners = channelMapping.get(new ByteArrayWrapper(message.getChannel())); + listeners = channelMapping.get(message.getChannelAsWrapper()); } if (!CollectionUtils.isEmpty(listeners)) { diff --git a/src/test/java/org/springframework/data/redis/connection/DefaultMessageTest.java b/src/test/java/org/springframework/data/redis/connection/DefaultMessageTest.java new file mode 100644 index 0000000000..33aea60273 --- /dev/null +++ b/src/test/java/org/springframework/data/redis/connection/DefaultMessageTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed 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 + * + * https://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.springframework.data.redis.connection; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.data.redis.connection.util.ByteArrayWrapper; + +/** + * @author Thomas Heigl + */ +class DefaultMessageTest { + + private static final String CHANNEL = "AnyChannel"; + private static final String BODY = "AnyBody"; + private static final byte[] EMPTY_BYTES = {}; + private static final byte[] CHANNEL_BYTES = CHANNEL.getBytes(); + private static final byte[] BODY_BYTES = BODY.getBytes(); + + @Test + void testHasChannel() { + assertThat(aMessageWithChannel(EMPTY_BYTES).hasChannel()).isFalse(); + assertThat(aMessageWithChannel(CHANNEL_BYTES).hasChannel()).isTrue(); + } + + @Test + void testHasBody() { + assertThat(aMessageWithBody(EMPTY_BYTES).hasBody()).isFalse(); + assertThat(aMessageWithBody(BODY_BYTES).hasBody()).isTrue(); + } + + @Test + void testGetChannelAsString() { + assertThat(aMessageWithChannel(EMPTY_BYTES).getChannelAsString()).isEmpty(); + assertThat(aMessageWithChannel(CHANNEL_BYTES).getChannelAsString()).isEqualTo(CHANNEL); + } + + @Test + void testGetBodyAsString() { + assertThat(aMessageWithBody(EMPTY_BYTES).getBodyAsString()).isEmpty(); + assertThat(aMessageWithBody(BODY_BYTES).getBodyAsString()).isEqualTo(BODY); + } + + @Test + void testGetChannelAsWrapper() { + assertThat(aMessageWithChannel(EMPTY_BYTES).getChannelAsWrapper()).isEqualTo(new ByteArrayWrapper(EMPTY_BYTES)); + assertThat(aMessageWithChannel(CHANNEL_BYTES).getChannelAsWrapper()).isEqualTo(new ByteArrayWrapper(CHANNEL_BYTES)); + } + + private DefaultMessage aMessageWithChannel(byte[] channel) { + return new DefaultMessage(channel, EMPTY_BYTES); + } + + private DefaultMessage aMessageWithBody(byte[] body) { + return new DefaultMessage(EMPTY_BYTES, body); + } +}