Hey Viktor,

Good summary. I agree that option 1) seems like the simplest choice and, as
you note, we can always add the default implementation later. I'll leave
Ismael to make a case for the circular forwarding approach ;)

-Jason

On Fri, Aug 24, 2018 at 3:02 AM, Viktor Somogyi-Vass <
viktorsomo...@gmail.com> wrote:

> I think in the first draft I didn't provide an implementation for them as
> it seemed very simple and straightforward. I looked up a couple of
> implementations of the ExtendedSerializers on github and the general
> behavior seems to be that they delegate to the 2 argument (headerless)
> method:
>
> https://github.com/khoitnm/practice-spring-kafka-grpc/blob/
> a6fc9b3395762c4889807baedd822f4653d5dcdd/kafka-common/src/
> main/java/org/tnmk/common/kafka/serialization/protobuf/
> ProtobufSerializer.java
> https://github.com/hong-zhu/nxgen/blob/5cf1427d4e1a8f5c7fab47955af32a
> 0d4f4873af/nxgen-kafka-client/src/main/java/nxgen/kafka/
> client/event/serdes/EventSerializer.java
> https://github.com/jerry-jx/spring-kafka/blob/
> ac323ec5b8b9a0ca975db2f7322ff6878fce481a/spring-kafka/src/
> main/java/org/springframework/kafka/support/serializer/JsonSerializer.java
> https://github.com/enzobonggio/nonblocking-kafka/blob/
> bc1a379b2d9593b46cf9604063bc5b38e2785d19/src/main/java/com/
> example/kafka/producer/CustomJsonSerializer.java
>
> Of course 4 example is not representative but it shows that these users
> usually delegate to the "headerless" (2 argument) method. I've tried to
> look it up on other code search sites but haven't had much luck so far.
> Given these examples and the way they implement them I'd say it's more
> common to delegate to the headerless method, that's why I think it's a good
> approach for us too. Now having a default implementation for that is again
> a good question. I think current use cases wouldn't change in either case
> (unless we deprecate the headerless one).
> For the new use cases it depends what do we want to propagate going
> forward. Do we want only one method to exist or two? As Ismael highlighted
> it might be confusing if we have 2 methods, both with default
> implementation and in this case we want to push the 3 argument one for
> users.
>
> So I see three possible ways:
> 1.) Don't provide a default implementation for the headerless method. This
> supports the current implementations and encourages the delegation style in
> future implementations. This might be the simplest option.
> 2.) Provide a default implementation for the headerless method. This would
> be a bit confusing, so we'd likely push the use of the 3 parameter method
> and deprecate the headerless. This would however further litter the code
> base with deprecation warnings as we're using the headerless method in a
> lot of places (think of the current serializers/deserializers). So in this
> case we would want to clean up the code base a little where we can and may
> remove the headerless method entirely in Kafka 3. But they would hang
> around until that point. I think in this case the implementation for the
> headerless is a detail question as that is deprecated so we don't expect
> new implementations to use that method.
> If we decide to move this way, we have explored two options so far:
> returning null / empty array or throwing exceptions. (And I honestly
> started to like the latter as calling that with no real implementation is
> really a programming error.)
> 3.) We can do it in multiple steps. In the first step we do 1 and later 2.
> I think it would also make sense as the Kafka code base heavily uses the
> headerless method still (think of the existing serializers/deserializers)
> and it would give us time to eliminate/change those use cases.
>
> Cheers,
> Viktor
>
> On Thu, Aug 23, 2018 at 11:55 PM Jason Gustafson <ja...@confluent.io>
> wrote:
>
> > To clarify, what I am suggesting is to only remove the default
> > implementation for these methods. So users would be required to implement
> > serialize(topic, data) and deserialize(topic, data).
> >
> > -Jason
> >
> > On Thu, Aug 23, 2018 at 1:48 PM, Jason Gustafson <ja...@confluent.io>
> > wrote:
> >
> > > Hey Viktor,
> > >
> > > Thinking about it a little more, I wonder if we should just not
> provide a
> > > default method for serialize(topic, data) and deserialize(topic, data).
> > > Implementing these methods is a trivial burden for users and it feels
> > like
> > > there's no good solution which allows both methods to have default
> > > implementations.
> > >
> > > Also, ack on KIP-331. Thanks for the pointer.
> > >
> > > -Jason
> > >
> > > On Thu, Aug 23, 2018 at 12:30 PM, Viktor Somogyi-Vass <
> > > viktorsomo...@gmail.com> wrote:
> > >
> > >> Hi Ismael,
> > >>
> > >> Regarding the deprecation of the 2 parameter method: should we do this
> > >> with
> > >> the Serializer interface as well?
> > >>
> > >> I've updated the "Rejected Alternatives" with a few.
> > >> I've added this circular reference one too but actually there's a way
> > >> (pretty heavyweight) by adding a guard class that prevents recursive
> > >> invocation of either methods. I've tried this out but it seems to me
> an
> > >> overshoot. So just for the sake of completeness I'll copy it here. :)
> > >>
> > >> public interface Deserializer<T> extends Closeable {
> > >>
> > >>     class Guard {
> > >>
> > >>         private Set<Object> objects = Collections.synchronizedSet(new
> > >> HashSet<>()); // might as well use concurrent hashmap
> > >>
> > >>         private void methodCallInProgress(Object x) {
> > >>             objects.add(x);
> > >>         }
> > >>
> > >>         private boolean isMethodCallInProgress(Object x) {
> > >>             return objects.contains(x);
> > >>         }
> > >>
> > >>         private void clearMethodCallInProgress(Object x) {
> > >>             objects.remove(x);
> > >>         }
> > >>
> > >>         private <T> T guard(Supplier<T> supplier) {
> > >>             if (GUARD.isMethodCallInProgress(this)) {
> > >>                 throw new IllegalStateException("You must implement
> one
> > of
> > >> the deserialize methods");
> > >>             } else {
> > >>                 try {
> > >>                     GUARD.methodCallInProgress(this);
> > >>                     return supplier.get();
> > >>                 } finally {
> > >>                     GUARD.clearMethodCallInProgress(this);
> > >>                 }
> > >>             }
> > >>         }
> > >>     }
> > >>
> > >>     Guard GUARD = new Guard();
> > >>
> > >>     void configure(Map<String, ?> configs, boolean isKey);
> > >>
> > >>     default T deserialize(String topic, byte[] data) {
> > >>         return GUARD.guard(() -> deserialize(topic, null, data));
> > >>     }
> > >>
> > >>     default T deserialize(String topic, Headers headers, byte[] data)
> {
> > >>         return GUARD.guard(() -> deserialize(topic, data));
> > >>     }
> > >>
> > >>     @Override
> > >>     void close();
> > >> }
> > >>
> > >>
> > >> Cheers,
> > >> Viktor
> > >>
> > >> On Thu, Aug 23, 2018 at 3:50 PM Ismael Juma <ism...@juma.me.uk>
> wrote:
> > >>
> > >> > Also, we may consider deprecating the deserialize method that does
> not
> > >> take
> > >> > headers. Yes, it's a convenience, but it also adds confusion.
> > >> >
> > >> > Ismael
> > >> >
> > >> > On Thu, Aug 23, 2018 at 6:48 AM Ismael Juma <ism...@juma.me.uk>
> > wrote:
> > >> >
> > >> > > I think the KIP needs the rejected alternatives section to have
> more
> > >> > > detail. For example, another option would be something like the
> > >> > following,
> > >> > > which works great as long as one overrides one of the methods, but
> > >> pretty
> > >> > > bad if one doesn't. :)
> > >> > >
> > >> > > default T deserialize(String topic, byte[] data) {
> > >> > >     return deserialize(topic, null, data);
> > >> > > }
> > >> > >
> > >> > > default T deserialize(String topic, Headers headers, byte[] data)
> {
> > //
> > >> > > This is the new method
> > >> > >     return deserialize(topic, data);
> > >> > > }
> > >> > >
> > >> > >
> > >> > > On Thu, Aug 23, 2018 at 3:57 AM Viktor Somogyi-Vass <
> > >> > > viktorsomo...@gmail.com> wrote:
> > >> > >
> > >> > >> Hi Jason,
> > >> > >>
> > >> > >> Thanks for the feedback.
> > >> > >> 1. I chose to return null here because according to the
> > >> documentation it
> > >> > >> may return null data, therefore the users of this methods are
> > >> perpared
> > >> > for
> > >> > >> getting a null. Thinking of it though it may be better to throw
> an
> > >> > >> exception by default because it'd indicate a programming error.
> > >> However,
> > >> > >> would that be a backward incompatible change? I'm simply thinking
> > of
> > >> > this
> > >> > >> because this is a new behavior that we'd introduce but I'm not
> sure
> > >> yet
> > >> > if
> > >> > >> it'd cause problems.
> > >> > >> Do you think it'd make sense to do the same in `serialize`?
> > >> > >> 2. Yes, I believe that is covered in KIP-331:
> > >> > >>
> > >> > >>
> > >> > https://cwiki.apache.org/confluence/display/KAFKA/KIP-331+
> > >> Add+default+implementation+to+close%28%29+and+configure%28%
> > >> 29+for+Serializer%2C+Deserializer+and+Serde
> > >> > >>
> > >> > >> Cheers,
> > >> > >> Viktor
> > >> > >>
> > >> > >> On Wed, Aug 22, 2018 at 6:11 PM Jason Gustafson <
> > ja...@confluent.io>
> > >> > >> wrote:
> > >> > >>
> > >> > >> > Hey Viktor,
> > >> > >> >
> > >> > >> > This is a nice cleanup. Just a couple quick questions:
> > >> > >> >
> > >> > >> > 1. Rather than returning null for the default
> `deserialize(topic,
> > >> > >> data)`,
> > >> > >> > would it be better to throw UnsupportedOperationException? I
> > assume
> > >> > that
> > >> > >> > internally we'll always invoke the api which takes headers.
> > >> Similarly
> > >> > >> for
> > >> > >> > `serialize(topic, data)`.
> > >> > >> > 2. Would it make sense to have default no-op implementations
> for
> > >> > >> > `configure` and `close`?
> > >> > >> >
> > >> > >> > Thanks,
> > >> > >> > Jason
> > >> > >> >
> > >> > >> > On Wed, Aug 22, 2018 at 5:27 AM, Satish Duggana <
> > >> > >> satish.dugg...@gmail.com>
> > >> > >> > wrote:
> > >> > >> >
> > >> > >> > > +1
> > >> > >> > >
> > >> > >> > > On Wed, Aug 22, 2018 at 4:45 PM, Ted Yu <yuzhih...@gmail.com
> >
> > >> > wrote:
> > >> > >> > >
> > >> > >> > > > +1
> > >> > >> > > > -------- Original message --------From: Kamal
> Chandraprakash
> > <
> > >> > >> > > > kamal.chandraprak...@gmail.com> Date: 8/22/18  3:19 AM
> > >> > (GMT-08:00)
> > >> > >> > To:
> > >> > >> > > > dev@kafka.apache.org Subject: Re: [VOTE] KIP-336:
> > Consolidate
> > >> > >> > > > ExtendedSerializer/Serializer and
> > >> > ExtendedDeserializer/Deserializer
> > >> > >> > > > +1
> > >> > >> > > >
> > >> > >> > > > Thanks for the KIP!
> > >> > >> > > >
> > >> > >> > > > On Wed, Aug 22, 2018 at 2:48 PM Viktor Somogyi-Vass <
> > >> > >> > > > viktorsomo...@gmail.com>
> > >> > >> > > > wrote:
> > >> > >> > > >
> > >> > >> > > > > Hi All,
> > >> > >> > > > >
> > >> > >> > > > > I'd like to start a vote on this KIP (
> > >> > >> > > > > https://cwiki.apache.org/confluence/pages/viewpage.
> > >> > >> > > > action?pageId=87298242)
> > >> > >> > > > > which aims to refactor ExtendedSerializer/Serializer and
> > >> > >> > > > > ExtendedDeserializer/Deserializer.
> > >> > >> > > > >
> > >> > >> > > > > To summarize what's the motivation:
> > >> > >> > > > >
> > >> > >> > > > > When headers were introduced by KIP-82 the
> > ExtendedSerializer
> > >> > and
> > >> > >> > > > > ExtendedDeserializer classes were created in order to
> keep
> > >> > >> interface
> > >> > >> > > > > compatibility but still add `T deserialize(String topic,
> > >> Headers
> > >> > >> > > headers,
> > >> > >> > > > > byte[] data);` and `byte[] serialize(String topic,
> Headers
> > >> > >> headers, T
> > >> > >> > > > > data);` methods that consume the headers for
> > >> > >> > > > serialization/deserialization.
> > >> > >> > > > > The reason for doing so was that Kafka at that time
> needed
> > be
> > >> > >> > > compatbile
> > >> > >> > > > > with Java 7. Since we're not compiling on Java 7 anymore
> > >> > >> (KAFKA-4423)
> > >> > >> > > > we'll
> > >> > >> > > > > try consolidate the way we're using these in a backward
> > >> > compatible
> > >> > >> > > > fashion:
> > >> > >> > > > > deprecating the Extended* classes and moving the
> > >> aforementioned
> > >> > >> > methods
> > >> > >> > > > up
> > >> > >> > > > > in the class hierarchy.
> > >> > >> > > > >
> > >> > >> > > > > I'd be happy to get votes or additional feedback on this.
> > >> > >> > > > >
> > >> > >> > > > > Viktor
> > >> > >> > > > >
> > >> > >> > > >
> > >> > >> > >
> > >> > >> >
> > >> > >>
> > >> > >
> > >> >
> > >>
> > >
> > >
> >
>

Reply via email to