nu.yona.server.batch.jobs.SendSystemMessageBatchJob.java Source code

Java tutorial

Introduction

Here is the source code for nu.yona.server.batch.jobs.SendSystemMessageBatchJob.java

Source

/*******************************************************************************
 * Copyright (c) 2017 Stichting Yona Foundation This Source Code Form is subject to the terms of the Mozilla Public License, v.
 * 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *******************************************************************************/
package nu.yona.server.batch.jobs;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.database.JdbcPagingItemReader;
import org.springframework.batch.item.database.JpaItemWriter;
import org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import nu.yona.server.exceptions.YonaException;
import nu.yona.server.messaging.entities.MessageDestination;
import nu.yona.server.messaging.entities.MessageDestinationRepository;
import nu.yona.server.messaging.entities.SystemMessage;
import nu.yona.server.subscriptions.service.UserAnonymizedDto;
import nu.yona.server.subscriptions.service.UserAnonymizedService;

@Component
public class SendSystemMessageBatchJob {
    private static final Logger logger = LoggerFactory.getLogger(ActivityAggregationBatchJob.class);

    private static final int USERS_CHUNK_SIZE = 50;

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    @Qualifier("sendSystemMessageJobUserAnonymizedReader")
    private ItemReader<UUID> userAnonymizedReader;

    @Autowired
    @Qualifier("sendSystemMessageJobUserAnonymizedProcessor")
    private ItemProcessor<UUID, MessageDestination> userAnonymizedProcessor;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserAnonymizedService userAnonymizedService;

    @Autowired
    private MessageDestinationRepository messageDestinationRepository;

    @Bean("sendSystemMessageJob")
    public Job sendSystemMessagesBatchJob() {
        return jobBuilderFactory.get("sendSystemMessagesBatchJob").incrementer(new RunIdIncrementer())
                .flow(sendSystemMessages()).end().build();
    }

    private Step sendSystemMessages() {
        return stepBuilderFactory.get("sendSystemMessages").<UUID, MessageDestination>chunk(USERS_CHUNK_SIZE)
                .reader(userAnonymizedReader).processor(userAnonymizedProcessor).writer(messageDestinationWriter())
                .build();
    }

    @Bean(name = "sendSystemMessageJobUserAnonymizedReader", destroyMethod = "")
    @StepScope
    public ItemReader<UUID> userAnonymizedReader() {
        return userAnonymizedIdReader();
    }

    @Bean(name = "sendSystemMessageJobUserAnonymizedProcessor", destroyMethod = "")
    @StepScope
    private ItemProcessor<UUID, MessageDestination> userAnonymizedProcessor() {
        return new ItemProcessor<UUID, MessageDestination>() {
            @Value("#{jobParameters['messageText']}")
            private String messageText;

            @Override
            public MessageDestination process(UUID userAnonymizedId) throws Exception {
                logger.debug("Processing user anonymized with id {}", userAnonymizedId);
                UserAnonymizedDto userAnonymized = userAnonymizedService.getUserAnonymized(userAnonymizedId);

                MessageDestination messageDestination = messageDestinationRepository
                        .findOne(userAnonymized.getAnonymousDestination().getId());
                messageDestination.send(SystemMessage.createInstance(messageText));

                return messageDestination;
            }
        };
    }

    private JpaItemWriter<MessageDestination> messageDestinationWriter() {
        JpaItemWriter<MessageDestination> writer = new JpaItemWriter<>();
        writer.setEntityManagerFactory(entityManager.getEntityManagerFactory());

        return writer;
    }

    private ItemReader<UUID> userAnonymizedIdReader() {
        final SqlPagingQueryProviderFactoryBean sqlPagingQueryProviderFactoryBean = createQueryProviderFactory();
        JdbcPagingItemReader<UUID> reader = createReader(sqlPagingQueryProviderFactoryBean);
        logger.info("Reading users anonymized in chunks of {}", USERS_CHUNK_SIZE);
        return reader;
    }

    private SqlPagingQueryProviderFactoryBean createQueryProviderFactory() {
        final SqlPagingQueryProviderFactoryBean sqlPagingQueryProviderFactoryBean = new SqlPagingQueryProviderFactoryBean();
        sqlPagingQueryProviderFactoryBean.setDataSource(dataSource);
        sqlPagingQueryProviderFactoryBean.setSelectClause("select id");
        sqlPagingQueryProviderFactoryBean.setFromClause("from users_anonymized");
        sqlPagingQueryProviderFactoryBean.setSortKey("id");
        return sqlPagingQueryProviderFactoryBean;
    }

    private JdbcPagingItemReader<UUID> createReader(
            final SqlPagingQueryProviderFactoryBean sqlPagingQueryProviderFactoryBean) {
        try {
            JdbcPagingItemReader<UUID> reader = new JdbcPagingItemReader<>();
            reader.setQueryProvider(sqlPagingQueryProviderFactoryBean.getObject());
            reader.setDataSource(dataSource);
            reader.setPageSize(USERS_CHUNK_SIZE);
            reader.setRowMapper(singleUUIDColumnRowMapper());
            reader.afterPropertiesSet();
            reader.setSaveState(true);
            return reader;
        } catch (Exception e) {
            throw YonaException.unexpected(e);
        }
    }

    private RowMapper<UUID> singleUUIDColumnRowMapper() {
        return new RowMapper<UUID>() {

            @Override
            public UUID mapRow(ResultSet rs, int rowNum) throws SQLException {
                return UUID.fromString(rs.getString(1));
            }

        };
    }
}