Spring Batch:从JMS队列中读取,步骤不会结束

时间:2017-02-03 21:41:01

标签: spring spring-batch spring-jms

我有一个简单的bach作业,它从JMS队列(ActiveMQ)读取并写入文件。批处理作业按预期运行,并写入文件,以表示已设置为10,000的提交间隔。

在这方面有2项意见

  1. 批处理作业读取队列未结束。

  2. 我看到队列中的所有消息都已被消耗,但只有当新消息被推送到JMS队列并且满足提交间隔时,最后一个块才会被写入文件。

  3. 这是预期的行为吗?我想安排批处理作业,并在那个时间消耗并写入队列中存在的所有消息。有什么建议吗?

    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    
    @Bean
    public TransactionAwareConnectionFactoryProxy activeMQConnectionFactory() {
        ActiveMQConnectionFactory amqConnectionFactory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_BROKER_URL);
        TransactionAwareConnectionFactoryProxy activeMQConnectionFactory = new TransactionAwareConnectionFactoryProxy(amqConnectionFactory);
        return activeMQConnectionFactory;
    }
    
    @Bean
    public ActiveMQQueue defaultQueue() {
        return new ActiveMQQueue("firstQueue");
    }
    
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new ResourcelessTransactionManager();
    }
    
    @Bean
    public JobRepository jobRepository(PlatformTransactionManager transactionManager) throws Exception {
        return new MapJobRepositoryFactoryBean(transactionManager).getObject();
    }
    
    @Bean
    @DependsOn("jobRepository")
    public SimpleJobLauncher simpleJobLauncher(JobRepository jobRepository) {
        SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
        simpleJobLauncher.setJobRepository(jobRepository);
        return simpleJobLauncher;
    }   
    

    如果我将receiveTimeout设置为较小的数字,则不会消耗所有消息,因此设置为上限。

    @Bean
    @DependsOn(value = { "activeMQConnectionFactory", "defaultQueue" })
    public JmsTemplate firstQueueTemplate(ActiveMQQueue defaultQueue, TransactionAwareConnectionFactoryProxy activeMQConnectionFactory) {
        JmsTemplate firstQueueTemplate = new JmsTemplate(activeMQConnectionFactory);
        firstQueueTemplate.setDefaultDestination(defaultQueue);
        firstQueueTemplate.setSessionTransacted(true);
        firstQueueTemplate.setReceiveTimeout(Long.MAX_VALUE);
        return firstQueueTemplate;
    }
    

    配置批处理作业。

    @Bean
    public JmsItemReader<String> jmsItemReader(JmsTemplate firstQueueTemplate) {
        JmsItemReader<String> jmsItemReader = new JmsItemReader<>();
        jmsItemReader.setJmsTemplate(firstQueueTemplate);
        jmsItemReader.setItemType(String.class);
        return jmsItemReader;
    }
    
    
    @Bean
    public ItemWriter<String> flatFileItemWriter() {
        FlatFileItemWriter<String> writer = new FlatFileItemWriter<>();
        writer.setResource(new FileSystemResource("/mypath/output.csv"));
        writer.setLineAggregator(new PassThroughLineAggregator<String>());
        return writer;
    }
    
    @Bean
    @DependsOn(value = { "jmsItemReader", "jmsItemWriter", "jobRepository", "transactionManager" })
    public Step queueReaderStep(JmsItemReader<String> jmsItemReader, ItemWriter<String> flatFileItemWriter, JobRepository jobRepository,
            PlatformTransactionManager transactionManager) throws Exception {
        StepBuilderFactory stepBuilderFactory = new StepBuilderFactory(jobRepository, transactionManager);
        AbstractTaskletStepBuilder<SimpleStepBuilder<String, String>> step = stepBuilderFactory.get("queueReaderStep").<String, String> chunk(10000)
                .reader(jmsItemReader).writer(flatFileItemWriter);
        return step.build();
    }
    
    
    @Bean
    @DependsOn(value = { "jobRepository", "queueReaderStep" })
    public Job jsmReaderJob(JobRepository jobRepository, Step queueReaderStep) {
        return this.jobBuilderFactory.get("jsmReaderJob").repository(jobRepository).incrementer(new RunIdIncrementer())
                .flow(queueReaderStep).end().build();
    }
    

1 个答案:

答案 0 :(得分:3)

Spring Batch提供的JmsItemReader实际上更像是一个模板或示例,因为你注意到它永远不会返回null所以步骤永远不会结束。您需要写一些内容来表明某条消息表明该步骤已完成。