Description
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);
}