Skip to content

Make listener API less error prone #4808

Open
@micheljung

Description

@micheljung

Say you implement a skip listener like so in Kotlin:

class LoggingSkipListener<I, O>() : SkipListener<I, O> {
  override fun onSkipInRead(t: Throwable) {}
  override fun onSkipInWrite(item: O, t: Throwable) {}
  override fun onSkipInProcess(item: I, t: Throwable) {}
}

in your step, you accidentally use listener before faultTolerant:

    // WHOOPS - this calls listener(Object) rather than listener(SkipListener)
    .listener(LoggingSkipListener(inputKeyExtractor, outputKeyExtractor))
    .faultTolerant()

Which results in SimpleStepBuilder.listener(Object) being called rather than FaultTolerantStepBuilder.listener(SkipListener).

You realize your mistake and fix it:

    .faultTolerant()
    .listener(LoggingSkipListener(inputKeyExtractor, outputKeyExtractor))

Now it works. But damn, your I, O results in item being nullable. To fix this, you change them to I : Any, O : Any.
This will again result in listener(Object) being used (don't ask me why) but you don't notice it.

This is problematic because listener(Object) doesn't know the interface SkipListener and there are no annotated methods. Therefore, your listener is silently not registered anymore.

It seems that this would be easily fixable with something like

if (listener instanceof SkipListener) {
  skipListeners.add((SkipListener<I, O>) listener);
  return this;
}

I'd even go a step further and prevent listeners being passed that don't get registered:

if (listener instanceof SkipListener) {
  skipListeners.add((SkipListener<I, O>) listener);
  return this;
}

...

if (skipListenerMethods.isEmpty()) {
  throw new IllegalArgumentException("No skip listener methods found in: " + listener);
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions