javamongodbspring-batchditemwriter

How to use MongoItemWriter to write a List<T>


My processor return a List of Object but I don't find a solution to override the MongoItemWriter to write some List of object and not object.

I tried this. My processor :

 @Override
  public List<PEntity> process(PSEntity item) {
    log.trace("Traitement d'une entrée PSEntity: {}", item);

    List<PL> r = this.r.findRP(item.getP());
    if (r.isEmpty()) {
      return null;
    }
    for (PL r : r) {
      r.setRr(true);
      r.setHr(LocalDateTime.now());
    }
    List<PLEntity> pLEntities =
        r.stream().map(this.pDM::ppDMEntity).toList();
    return pLEntities;
  }

My writer

public class RMongoWriter<T> extends MongoItemWriter<List<T>> {
  private MongoOperations template;
  private MongoItemWriter<T> delegate;

  @Override
  public void write(final List<? extends List<T>> lists) throws Exception {
    for (final List<T> list : lists) {
      delegate.write(list);
    }
  }
  @Bean
  public MongoItemWriter<List<PLEntity>> writer(MongoTemplate mongoTemplate,
      BatchConfigurationProperties batchConfigurationProperties) {
    MongoItemWriter<List<PlaqueLueEntity>> writer = new MongoItemWriter<>();
    writer.setTemplate(mongoTemplate);
    writer.setCollection(String.valueOf(CollectionEnum.COLLECTION.PL));
    return writer;
  }

And I defined in my BatchConfiguration:

  @Bean
  public MongoItemWriter<List<PLEntity>> rWriter() {
    return new RMongoWriter().writer(mongoTemplate, batchConfigurationProperties);
  }

But before I can debug on my writer I got this error:

class org.bson.Document cannot be cast to class java.util.Collection (org.bson.Document is in unnamed module of loader 'app'; java.util.Collection is in module java.base of loader 'bootstrap')

And : Attempt to update step execution id=1 with wrong version (1), where current version is 2


Solution

  • I don't find a solution to override the MongoItemWriter to write some List of object and not object.

    The way you defined your custom item writer is correct:

    public class RMongoWriter<T> extends MongoItemWriter<List<T>> {
    
       private MongoItemWriter<T> delegate;
    
       //...
    
    }
    

    However, you should not call the delegate for each list like this:

      @Override
      public void write(final List<? extends List<T>> lists) throws Exception {
        for (final List<T> list : lists) {
          delegate.write(list);
        }
      }
    

    What you should do instead is "flatten" the items in a single list and call the delegate once, something like this:

      @Override
      public void write(final List<? extends List<T>> lists) throws Exception {
        List<T> flatList = new ArrayList();
        for (final List<T> list : lists) {
           for (T item: list) {
              flatList.add(item);
           }
        }
        delegate.write(flatList);
      }
    

    Please note that I did not compile that snippet, so I will let you adapt it if needed, but you got the idea.