Claus Ibsen created CAMEL-26019:
-----------------------------------
Summary: camel-spring-redis - unimplemented commands do nothing,
GET of a missing key keeps the body, and more
Key: CAMEL-26019
URL: https://issues.apache.org/jira/browse/CAMEL-26019
Project: Camel
Issue Type: Bug
Components: camel-spring-redis
Affects Versions: 4.18.0, 4.22.0, 4.23.0
Reporter: Claus Ibsen
Fix For: 4.24.0
Found while checking the body types of the spring-redis component for the
catalog (CAMEL-24961).
h4. 1. A command the producer does not implement does nothing and raises no
error
A command of the {{command}} enum that the producer has no method for does
nothing: no error, and the body stays as it was. These are AUTH, BGREWRITEAOF,
BGSAVE, CONFIG, DBSIZE, DEBUG, FLUSHALL, FLUSHDB, INFO, LASTSAVE, MONITOR,
PSUBSCRIBE, PUNSUBSCRIBE, RENAMEX, SAVE, SELECT, SHUTDOWN, SLAVEOF, SUBSCRIBE,
SUBSTR, SYNC, UNSUBSCRIBE and ZSCORE (the generated
{{RedisProducerInvokeOnHeaderFactory}} returns null for them, as it does for a
misspelled command; the general part is in the camel-support issue).
Checked on 4.24.0-SNAPSHOT with {{camel run}} against {{camel infra run
redis}}: after ZADD, {{CamelRedis.Command=ZSCORE}} left the body of the ZRANGE
before it, and {{CamelRedis.Command=NOSUCH}} left the body "Hello", with no
error.
*Proposed change*: implement ZSCORE and the other commands that make sense in a
producer, and fail with an error that names the command for the rest (SUBSCRIBE
and PSUBSCRIBE are consumer commands).
h4. 2. GET of a missing key keeps the body as it was
The body is set to the result of a command only when the result is not null
({{HeaderSelectorProducer.processResult}}). So GET of a missing key leaves the
body as it was, and so do HGET, LPOP, RPOP, LINDEX and the other commands that
read one value: a route cannot tell a miss from a value that equals the old
body.
Checked on 4.24.0-SNAPSHOT with {{camel run}} against {{camel infra run
redis}}: with the body "Other body", GET of the key "nope" and HGET of a
missing field both left "Other body".
*Proposed change*: set the body to null when a command that reads a value finds
none (override {{processResult}} in {{RedisProducer}} for those commands), and
say so in the docs and the upgrade guide.
h4. 3. KEYS finds nothing with the default serializer, and ECHO without a value
fails with a NullPointerException
KEYS sends the pattern through the key serializer of the template
({{RedisClient}}, main 07d2e7a987bc, line 359; {{RedisTemplate.keys}}), which
is the JDK serializer by default. The serialized pattern holds its length, so
{{*}} matches only keys of that serialized length: KEYS with {{v-*}} found
nothing, while the keys v-text, v-bytes and others had been set with SET.
ECHO without the {{CamelRedis.Value}} header fails with {{NullPointerException:
Cannot invoke "String.getBytes()" because "value" is null}} ({{RedisClient}},
line 254).
Both checked on 4.24.0-SNAPSHOT with {{camel run}} against {{camel infra run
redis}}.
*Proposed change*: send the pattern of KEYS as a plain string (with the string
serializer), and fail ECHO with an error that says the header is missing.
h4. 4. A message another client published is dropped with a WARN
The consumer deserializes each message with the {{serializer}}, the JDK
serializer by default ({{RedisConsumer}}, main 07d2e7a987bc, lines 86-90). A
message that another client published, such as {{redis-cli PUBLISH}}, is not
Java-serialized: the consumer logs WARN "Error processing redis message ...
Cannot deserialize" and the message is lost. The docs say the values are
Java-serialized by default, but not that the consumer cannot read the messages
of other clients.
Checked on 4.24.0-SNAPSHOT with {{camel run}} against {{camel infra run
redis}}: {{docker exec camel-redis redis-cli PUBLISH outside "plain text"}}
gave that WARN and no exchange.
*Proposed change*: say in the docs that the consumer needs
{{serializer=#class:org.springframework.data.redis.serializer.StringRedisSerializer}}
to read messages from other clients, and consider giving the payload as bytes
when it cannot be deserialized.
h4. Also read in the code, not run
* SETBIT and GETBIT use the raw bytes of the key ({{RedisClient}}, lines 161
and 168), while the other commands use the key serializer, so with the default
serializer they work on another key than SET and GET.
* {{CamelRedis.Keys}} is documented as a String, but it is read as a Collection
({{ExchangeConverter}}, line 98), and a String does not convert: DEL with a
String header deletes nothing.
* MSETNX drops the Boolean result of the call ({{RedisProducer}}, lines
525-528).
* The consumer does not check the exchange for an exception after the route
({{RedisConsumer}}, line 80), so a failed exchange is not given to the
exception handler.
_Claude Code on behalf of davsclaus_
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)