Github user srdo commented on a diff in the pull request:
https://github.com/apache/storm/pull/2428#discussion_r153035015
--- Diff:
external/storm-kafka-client/src/main/java/org/apache/storm/kafka/spout/KafkaSpoutConfig.java
---
@@ -320,20 +320,17 @@ private Builder(Builder<?, ?> builder,
SerializableDeserializer<K> keyDes, Class
// when they change the key/value types.
this.translator = (RecordTranslator<K, V>) builder.translator;
this.retryService = builder.retryService;
-
- if (keyDesClazz != null) {
-
this.kafkaProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, keyDesClazz);
- }
+
if (keyDes != null) {
this.kafkaProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
keyDes.getClass());
- }
- if (valueDesClazz != null) {
-
this.kafkaProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
valueDesClazz);
- }
- if (valueDes != null) {
+ } else if (keyDesClazz != null) {
--- End diff --
One of the changes in https://github.com/apache/storm/pull/2215 is to make
users set most Kafka properties through setProp instead of duplicating
configuration parameters in KafkaSpoutConfig. These properties include key and
value deserializers.
In order to provide backward compatibility that PR tries to ensure that if
the keyDes/keyDesClazz field is set, then the corresponding kafkaProps property
is also set. The spout doesn't use the fields anymore, it only reads from the
kafkaProps map. The setKey/setValue methods were also deprecated, and users
were directed to use setProp instead. Additionally the convenience builder
methods were changed so they didn't set the keyDes/keyDesClazz fields, but just
set properties in kafkaProps instead.
The issue Alexandre hit during testing was that he was doing something like
`kafkaSpoutConfig.getKeyDeserializer().getClass()` on a KafkaSpoutConfig built
from one of the convenience builders. Since keyDes/keyDesClazz aren't being set
by the default builders anymore, this causes an NPE.
I think we still want to be able to provide the simplified KafkaSpoutConfig
API to 1.x, and we still want to encourage users to use setProp instead of
setKey/setValue. In order to fix the NPE we also have to set keyDes/keyDesClazz
in the convenience builder methods again.
Without this change the code behaves in a very confusing way when mixing
use of setKey/setValue and setProp. The added unit tests demonstrate cases
where the current code would act counterintuitively. Try pasting the current
code into the modified Builder constructor, and you'll see test failures.
The modified constructor is used when setKey/setValue is called. With the
current code, calling e.g. setKey will actually overwrite both the key and
value properties in kafkaProps if keyDesClazz and valueDesClazz were set in the
old Builder.
For example, if you did
`KafkaSpoutConfig.builder(topic).setProp(MyValueDeserializer.class).setKey(MyKeyDeserializer.class)`,
you end up with a KafkaSpoutConfig where the value deserializer is
`StringDeserializer`. This is because the `builder` method now sets both
keyDesClazz and valueDesClazz by default. When setKey calls the copy
constructor, it overwrites both the key and value deserializer properties in
kafkaProps with the values of the key/valueDesClazz fields. The updated code
makes sure that if you call setKey, then only the key deserializer property
will be set.
The change isn't necessary for the constructor further up, because it isn't
a copy constructor. The problem with the copy constructor is that it takes in a
kafkaProps that already might contain settings for key/value deserializers and
overwrites them. The unmodified constructor has an empty kafkaProps, so there's
no issue.
---