Status

Current state: Under Discussion

Discussion thread: TDB

JIRA: N/A

Please keep the discussion on the mailing list rather than commenting on the wiki (wiki discussions get unwieldy fast).


Note this KIP is the original work of Ray McDermott -  Due to lack of self-service signup for wiki ID and editing permissions, we're adding Ray's text to this KIP.

Motivation

Jackdaw is a Clojure library over the Kafka Streams DSL. In its current state, Jackdaw uses wrappers around the DSL interfaces to enable function passing in Clojure as one would enjoy if using Java.

Such wrappers are verbose and add to complexity to the library. They would not be required if Clojure has first class interop for SAM interfaces.

The new Clojure version 1.12 has many updates to Java interop including SAM interfaces. Unfortunately, it does not quite deliver what we need with respect to thinning down Kafka Streams interop.

We were specifically hoping that passing (fn [] ...) to SAM interfaces would just work and thus we would no longer need to wrap the interface. This feature may eventually be added to the language but it currently only works for interfaces that have been explicitly annotated with @FunctionalInterface. See this JIRA ticket for details.

Java does not require the @FunctionalInterface annotation although it clarifies the intended interface purpose.

The Kafka Streams DSL does not have those annotations and this KIP proposes to add them.


Public Interfaces

No new interfaces or changes to the behavior of existing interfaces will be introduced in this KIP.

These annotations on the interfaces are new but do not affect client calls.  Details of adding the annotation are in the next section.

Proposed Changes

Add @FunctionalInterface to the Kafka Streams DSL and the Processor API (PAPI).

The interface must conform to these rules:

  • have one abstract method
    • can have any number of default methods
    • can have any number of methods directly on Object

The details of each included / excluded interface is as follows:

DSL (org.apache.kafka.streams.kstream)

Interfaces in scope

We will add @FunctionalInterface to these interfaces:

  • Aggregator
    • apply is the only method in the interface (SAM)
  • ForeachAction
    • apply is the only method in the interface (SAM)
  • GlobalKTable
    • queryableStoreName is the only method in the interface (SAM)
  • Initializer
    • apply is the only method in the interface (SAM)
  • KeyValueMapper
    • apply is the only method in the interface (SAM)
  • Merger
    • apply is the only method in the interface (SAM)
  • NamedOperation
    • withName is the only method in the interface (SAM)
  • Predicate
    • test is the only method in the interface (SAM)
  • Reducer
    • apply is the only method in the interface (SAM)
  • TransformerSupplier
    • get is the only method in the interface (SAM)
  • ValueJoiner
    • apply is the only method in the interface (SAM)
  • ValueJoinerWithKey
    • apply is the only method in the interface (SAM)
  • ValueMapper
    • apply is the only method in the interface (SAM)
  • ValueMapperWithKey
    • apply is the only method in the interface (SAM)
  • ValueTransformerSupplier
    • get is the only method in the interface (SAM)
  • ValueTransformerWithKeySupplier
    • get is the only method in the interface (SAM)

PAPI (org.apache.kafka.streams.processor.api)

The PAPI already has two interfaces that have @FunctionalInterface which will be unaffected:

  • FixedKeyProcessorSupplier
  • ProcessorSupplier.

Interfaces in scope

We will add @FunctionalInterface to these interfaces:

  • FixedKeyProcessor
    • process is the only non-default method
  • Processor
    • process is the only non-default method

Compatibility, Deprecation, and Migration Plan

None required

Test Plan

Running the existing tests will be sufficient.

Rejected Alternatives

Leave off the @FunctionalInterface annotation: limits the benefits to non-Java, JVM languages.

  • No labels