Logan Wlv
Logan Wlv

Reputation: 3744

Spring batch ItemListenerSupport ambiguous for the type when building the step

I have spring job that read a file, process the data then write it in an oracle database.

I'm having an issue when declaring my job, the error :

The method listener(Object) is ambiguous for the type SimpleStepBuilder< Map< String,Object >,Map< String,Object >>

I do not understand the error, why it is not using listener(ItemListener..) method . Any ideas ?

EDIT : Using separate listeners, having 3 objects implementing ItemWriteListener<T>, ItemReadListener<T> and ItemProcessorListener<T,O> and building the step like that :

   //...
    .reader(/* custom ItemReader */)
    .listener(/* custom ItemReadListener<T> */)
    .listener(/* custom ItemWriterListener<T> */)
    .listener(/* custom ItemProcessorListener<T,O> */)
    //...
    .build(); 

The error disapear, but I still don't understand why it does not work with ItemListenerSupport class..

Here is how my step is built :

    SimpleStepBuilder<Map<String, Object>, Map<String, Object>> stepBuilder = stepBuilderFactory
    .get("testStep")
    .<Map<String, Object>, Map<String, Object>>chunk(5000)
    .reader(/* custom ItemReader<Map<String, Object>> object */));
    .processor(/*custom ItemProcessor<Map<String, Object>, Map<String, Object>> object */))
    .writer(/*custom ItemWriter<Map<String,Object> object */)
    .listener(new GenericItemListener<Map<String, Object>, Map<String, Object>>())
    .build();

Here is my custom ItemListenerSupport :

import java.util.List;
import org.springframework.batch.core.listener.ItemListenerSupport;

public class GenericItemListener<I, R> extends ItemListenerSupport<I, R> {

    @Override
    public void onReadError(Exception e) {
        //do something
    }

    @Override
    public void onWriteError(Exception e, List<? extends R> items) {
        //do something
    }

    @Override
    public void onProcessError(I items, Exception e) {
        //do something
    }
}

Upvotes: 4

Views: 3839

Answers (2)

IcedDante
IcedDante

Reputation: 6822

ItemListenerSupport is a convenience class that allows you to create a listener for reading, processing and writing in one place. The idea is that there may be a lot of common logic among the three different tasks and so this becomes a central place.

For that reason, and because a listener is attached at the different steps, you should attach the listener multiple time as needed and cast accordingly:

SimpleStepBuilder<Map<String, Object>, Map<String, Object>> stepBuilder = stepBuilderFactory
.get("testStep")
.<Map<String, Object>, Map<String, Object>>chunk(5000)
.reader(/* custom ItemReader<Map<String, Object>> object */))
  .listener((ItemReadListener)genericItemListener)
.processor(/*custom ItemProcessor<Map<String, Object>, Map<String, Object>> object */))
  .listener((ItemProcessorListener)genericItemListener)
.writer(/*custom ItemWriter<Map<String,Object> object */)
  .listener((ItemWriterListener)genericItemListener)
.listener(new GenericItemListener<Map<String, Object>, Map<String, Object>>())
.build();

Upvotes: 2

frno
frno

Reputation: 2871

I encountered the same problem.

I don't know if it's the best way to handle this but I bypassed it by casting my ItemListenerSupport sub-class to an ItemProcessListener

Here the listener:

class CustomListener extends ItemListenerSupport<Input, Output> {

@Override
public void onProcessError(Input item, Exception e) {
    log.error(item.toString(), e);
}

public ItemProcessListener<? super Input, ? super Output> asItemProcessListener() {
    return this;
}

}

Here the step definition

steps.get("step").<Input, Output>chunk(10)
    .reader(reader)
    .listener(listener.asItemProcessListener())
    .processor(processor)
    .build()

Upvotes: 3

Related Questions