javaspring-batch

Spring Batch 5.1.2 unable to invoke custom Repository method


Created a District domain

@Entity
@Table(name = "DISTRICT_T")
public class DistrictT implements Serializable {
   @Id
   @Column(name = "DISTRICT_ID")
   private Long districtId;
   
   @Column(name = "MSC_CODE")
   private String mscCode;

   @Column(name ="DISTRICT_NAME")
    private String districtName;

   @Column(name = "ACTIVE_IND")
   private Boolean activeInd;
}

@Repository
public interface DistrictRepository extends PagingAndSortingRepository<DistrictT, Long> {
      List<DistrictT> findByActiveIndIsTrue();
}

@Bean
public RepositoryItemReader<DistrictT> districtItemReader(DistrictRepository repository) {
    return new RepositoryItemReaderBuilder<DistrictT>().name("districtItemReader")
        .pageSize(2)
    .repository(districtRepository)
    .methodName("findByActiveIndIsTrue")
    .sorts(Map.of("districtId", Sort.Direction.ASC))
    .build();
}

When running job, Spring throws exception below:

org.springframework.batch.item.adapter.DynamicMethodInvocationException: java.lang.NoSuchMethodException: jdk.proxy2.$Proxy84.findByActiveIndIsTrue(org.springframework.data.domain.PageRequest)
    at org.springframework.batch.item.data.RepositoryItemReader.doInvoke(RepositoryItemReader.java:275) ~[spring-batch-infrastructure-5.1.2.jar:5.1.2]

Any idea on how to fix error?


Solution

  • The exception or the error that you are getting means that your function findByActiveIndIsTrue() is getting invoked along with a parameter 'org.springframework.data.domain.PageRequest', which the function does not expects as per the function definition in the DistrictRepository. To solve the issue, you would need to modify the function findByActiveIndIsTrue() to accept an argument of type Pageable, like below:

    @Repository
    public interface DistrictRepository extends PagingAndSortingRepository<DistrictT, Long> {
         Page<DistrictT> findByActiveIndIsTrue(Pageable pageable);
    }
    

    Whenever we use a function that returns a List in Spring Data JPA, pagination is automatically handled by Spring. However, the function does not know by itself to accept Pageable as a function argument.

    Additionally, if you want to pass specific PageRequest arguments to your repository function, you can use the .arguments() while calling your function findByActiveIndIsTrue() in the RepositoryItemReader configuration like:

    @Bean
    public RepositoryItemReader<DistrictT> districtItemReader(DistrictRepository repository) {
        return new RepositoryItemReaderBuilder<DistrictT>().name("districtItemReader")
            .pageSize(2)
            .repository(districtRepository)
            .methodName("findByActiveIndIsTrue")
            .arguments(List.of(PageRequest.of(0, 5)))  // in case you want to pass specific PageRequest parameters
            .sorts(Map.of("districtId", Sort.Direction.ASC))
            .build();
    }