Динамически устанавливать размер фрагмента после выборки из базы данныхJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Динамически устанавливать размер фрагмента после выборки из базы данных

Сообщение Anonymous »

Мне нужно динамически установить размер фрагмента на этапе весеннего пакетного задания, который хранится в базе данных, т. е. размер фрагмента необходимо получить из базы данных и установить в компонент.
Мой запрос выглядит примерно так:

Код: Выделить всё

select CHUNK_SIZE from SOME_TABLE_NAME where ID='some_id_param_value'
Здесь значение идентификатора будет взято из параметров задания, которые задаются с помощью параметра запроса, передаваемого вместе с запросом в Rest Controller( при запуске пакетного задания)
Я хочу получить этот CHUNK_SIZE из базы данных и динамически установить его на этапе задания.
Наше требование состоит в том, чтобы размер фрагмента менялся для шага на основе значения идентификатора подробности из которых хранятся в таблице БД. Например:




ID
CHUNK_SIZE




01
1000


02
2500



Я знаю, что компоненты в задании устанавливаются на время настройки, а параметры задания передаются во время выполнения при запуске задания.
РЕДАКТИРОВАТЬ:
Пример, предоставленный MahmoudBenHassine, использует @JobScope и получает доступ к jobParameters в шаговом компоненте с помощью @Value(" #{jobParameters['id']}"). Я попытался реализовать аналогичный подход с использованием jobExecutionContext следующим образом:
  • Извлекал chunkSize из таблицы базы данных в
    метод beforeStep StepExecutionListener и установите его в

    Код: Выделить всё

    ExecutionContext
    .
  • Аннотировал степ-компонент с помощью @JobScope и использовал

    Код: Выделить всё

    @Value("#{jobExecutionContext['chunk']}")
    для доступа к нему в шаге
    bean.
  • Но я столкнулся со следующей ошибкой:

    Код: Выделить всё

    Error creating bean with name 'scopedTarget.step' defined in class path resource [com/sample/config/SampleBatchConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.Step]: Factory method 'step' threw exception; nested exception is java.lang.NullPointerException
Невозможно получить доступ к ключу-значению фрагмента из jobExecutionContext >, тем самым вызывая исключение NullPointerException.
Нужно ли его как-то продвигать, чтобы к нему можно было получить доступ в степ-компоненте? Если да, то мы будем очень признательны за небольшой пример или руководство.
Мой класс контроллера:

Код: Выделить всё

@RestController
public class SampleController {

@Autowired
JobLauncher sampleJobLauncher;

@Autowired
Job sampleJob;

@GetMapping("/launch")
public BatchStatus launch(@RequestParam(name = "id", required = true) String id){

Map map = new HashMap();
map.put("id",  new JobParameter(id));
map.put("timestamp",  new JobParameter(System.currentTimeMillis));

JobParameters params = new JobParameters(map);
JobExecution j = sampleJobLauncher.run(sampleJob, params);

return j.getStatus();
}
}
Мой класс пакетной конфигурации (содержащий задание и пошаговый компонент):

Код: Выделить всё

@Configuration
public class SampleBatchConfig{

@Autowired
private JobBuilderFactory myJobBuilderFactory;

@Autowired
private StepBuilderFactory myStepBuilderFactory;

@Autowired
private MyRepoClass myRepo; // this class contains the jdbc method to fetch chunksize from the db table

@Autowired
MyReader myReader;

@Autowired
MyWriter myWriter;

@Bean
@JobScope
public Step sampleStep(@Value("#{jobExecutionContext['chunk']}") Integer chunkSize){
return myStepBuilderFactory.get("sampleStep")
.chunk(chunkSize) //TODO ~instead of hardcoding the chunkSize or getting it from the properties file using @Value, the requirement is to fetch it from the db table using the above mentioned query with id job parameter and set it here
.reader(myReader.sampleReader())
.writer(myWriter.sampleWriter())
.listener(new StepExecutionListener() {
@Override
public void beforeStep(StepExecution stepExecution) {
int chunk = myRepo.findChunkSize(stepExecution.getJobExecution().getExecutionContext().get("id")); // this method call fetches chunksize from the db table using the id job parameter
stepExecution.getJobExecution().getExecutionContext().put("chunk", chunk);
}

@Override
public ExitStatus afterStep(StepExecution stepExecution) {
return null;
}
})
.build();
}

@Bean
public Job job(){
return myJobBuilderFactory.get("sampleJob")
.incrementer(new RunIdIncrementer())
.start(sampleStep(null))
.build();
}

}

ПРИМЕЧАНИЕ.
Задание может состоять из нескольких шагов с разными размерами фрагментов, и в этом случае размер фрагмента должен извлекаться отдельно для каждого шага. .


РЕДАКТИРОВАНИЕ 2:
Изменение моего определения шага следующим образом работает, но есть проблема.
Здесь читатель читает список, имеющий 17 предметов в блоке размером 4.

Код: Выделить всё

@Bean
@JobScope
public Step sampleStep(@Value("#{jobParameters['id']}") Integer id){
int chunkSize = myRepo.findChunkSize(id); // this method call fetches chunksize from the db table using the id job parameter
return myStepBuilderFactory.get("sampleStep")
.chunk(chunkSize)
.reader(myReader.sampleReader())
.writer(myWriter.sampleWriter())
.listener(new ChunkListenerSupport() {
@Override
public void afterChunk(ChunkContext context) {
System.out.println("MyJob.afterChunk");
}

@Override
public void beforeChunk(ChunkContext context) {
System.out.println("MyJob.beforeChunk");
}
})
.build();
}
Когда я впервые запускаю задание по URL-адресу, оно работает нормально и печатает следующее: (Размер фрагмента в таблице базы данных установлен на 4)

Код: Выделить всё

2021-05-03 15:06:44.859  INFO 11924 --- [nio-8081-exec-1] o.s.batch.core.job.SimpleStepHandler     : Executing step: [sampleStep]
MyJob.beforeChunk

item = 1

item = 2

item = 3

item = 4

MyJob.afterChunk

MyJob.beforeChunk

item = 5

item = 6

item = 7

item = 8

MyJob.afterChunk

MyJob.beforeChunk

item = 9

item = 10

item = 11

item = 12

MyJob.afterChunk

MyJob.beforeChunk

item = 13

item = 14

item = 15

item = 16

MyJob.afterChunk

MyJob.beforeChunk

item = 17

MyJob.afterChunk
Но если я снова запущу задание, не перезапуская контейнер сервера/spring, будет напечатано следующее:

Код: Выделить всё

2021-05-03 15:11:02.427  INFO 11924 --- [nio-8081-exec-4] o.s.batch.core.job.SimpleStepHandler     : Executing step: [sampleStep]

MyJob.beforeChunk

MyJob.afterChunk
Короче, всё работает нормально ровно один раз, когда сервер перезагружается. Но это не работает при последующих выполнениях заданий без перезапуска сервера.

Подробнее здесь: https://stackoverflow.com/questions/673 ... ng-from-db
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»