如何在spring批处理中抛出自定义异常?

时间:2016-06-27 12:19:29

标签: java spring exception-handling spring-batch

我遇到过一个场景,我必须在使用spring批处理的批处理中跟踪各种条件下的各种异常。 例如:如果在读取数据库不可用时抛出某种类型的异常并发送邮件说明数据库不可用并终止批处理。 如果表不可用,则抛出一些其他异常并发送邮件说明表不可用并终止批处理。 如果数据不符合sql语句中指定的条件,则不要做任何事情,因为这是正常的作业终止。 到目前为止,我所能实现的只是使用StepExecutionListener,我可以看到批处理是否读取任何记录或什么是failureException但不是我想要的方式。 任何帮助/建议都可以。

我的context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:batch="http://www.springframework.org/schema/batch" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

    <import resource="classpath:context-datasource.xml" />

    <bean
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

        <property name="location">
            <value>springbatch.properties</value>
        </property>
    </bean>

    <bean id="validator"
        class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

    <bean id="jobRepository"
        class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean" />

    <bean id="jobLauncher"
        class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
        <property name="jobRepository" ref="jobRepository" />
    </bean>


    <!-- ItemReader which reads from database and returns the row mapped by 
        rowMapper -->
    <bean id="databaseItemReader"
        class="org.springframework.batch.item.database.JdbcCursorItemReader">

        <property name="dataSource" ref="dataSource" />

        <property name="sql" value="SELECT * FROM employee1" />

        <property name="rowMapper">
            <bean class="com.abc.springbatch.jdbc.EmployeeRowMapper" />
        </property>

    </bean>


    <!-- ItemWriter writes a line into output flat file -->
    <bean id="databaseItemWriter"
        class="org.springframework.batch.item.database.JdbcBatchItemWriter">

        <property name="dataSource" ref="dataSource" />

        <property name="sql">
            <value>
                <![CDATA[        
                    insert into actemployee(empId, firstName, lastName,additionalInfo) 
                    values (?, ?, ?, ?)
                ]]>
            </value>
        </property>

        <property name="itemPreparedStatementSetter">
            <bean class="com.abc.springbatch.jdbc.EmployeePreparedStatementSetter" />
        </property>

    </bean>


    <!-- Optional ItemProcessor to perform business logic/filtering on the input 
        records -->
    <bean id="itemProcessor" class="com.abc.springbatch.EmployeeItemProcessor">
        <property name="validator" ref="validator" />
    </bean>

    <!-- Step will need a transaction manager -->
    <bean id="transactionManager"
        class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />


    <bean id="recordSkipListener" class="com.abc.springbatch.RecordSkipListener" />

    <bean id="customItemReadListener" class="com.abc.springbatch.CustomItemReadListener" />

    <bean id="stepExecutionListener" class="com.abc.springbatch.BatchStepExecutionListner">
        <constructor-arg ref="mailSender" />
        <constructor-arg ref="preConfiguredMessage" />
    </bean>

    <!-- Actual Job -->
    <batch:job id="employeeToActiveEmployee">
        <batch:step id="step1">
            <batch:tasklet transaction-manager="transactionManager">
                <batch:chunk reader="databaseItemReader" writer="databaseItemWriter"
                    processor="itemProcessor" commit-interval="10" skip-limit="500" retry-limit="5">
                    <batch:listeners>
                        <batch:listener ref="customItemReadListener"/>
                    </batch:listeners>
                    <!-- Retry included here to retry for specified times in case the following exception occurs -->
                    <batch:retryable-exception-classes>
                        <batch:include
                            class="org.springframework.dao.DeadlockLoserDataAccessException" />
                    </batch:retryable-exception-classes>
                    <batch:skippable-exception-classes>
                        <batch:include class="javax.validation.ValidationException" />
                    </batch:skippable-exception-classes>
                </batch:chunk>

            </batch:tasklet>
            <batch:listeners>
                <batch:listener ref="recordSkipListener" />
                <batch:listener ref="stepExecutionListener" />
            </batch:listeners>
        </batch:step>
    </batch:job>




    <!-- Email API bean configuarion -->

    <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
        <property name="host" value="${constant.order.mailHost.response}" />
        <property name="port" value="${constant.order.mailPort.response}" />
        <property name="username" value="${constant.order.mailUsername.response}" />
        <property name="password" value="XXXXXX" />
        <property name="javaMailProperties">
            <props>
                <prop key="mail.transport.protocol">smtp</prop>
                <prop key="mail.smtp.auth">false</prop>
                <prop key="mail.smtp.starttls.enable">true</prop>
                <prop key="mail.debug">true</prop>
            </props>
        </property>
    </bean>
    <bean id="preConfiguredMessage" class="org.springframework.mail.SimpleMailMessage">
        <property name="from" value="abc@xyz.com" />
        <property name="to" value="abc@xyz.com" />
        <property name="subject" value="Skipped Records" />
    </bean>


</beans>


<!-- Email API bean configuarion -->

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="host" value="${constant.order.mailHost.response}" />
    <property name="port" value="${constant.order.mailPort.response}" />
    <property name="username" value="${constant.order.mailUsername.response}" />
    <property name="password" value="XXXXXX" />
    <property name="javaMailProperties">
        <props>
            <prop key="mail.transport.protocol">smtp</prop>
            <prop key="mail.smtp.auth">false</prop>
            <prop key="mail.smtp.starttls.enable">true</prop>
            <prop key="mail.debug">true</prop>
        </props>
    </property>
</bean>
<bean id="preConfiguredMessage" class="org.springframework.mail.SimpleMailMessage">
    <property name="from" value="abc@xyz.com" />
    <property name="to" value="abc@xyz.com" />
    <property name="subject" value="Skipped Records" />
</bean>

StepExecutionListener.java

public class BatchStepExecutionListner implements StepExecutionListener {

    private JavaMailSender mailSender;

    private SimpleMailMessage simpleMailMessage;

    public BatchStepExecutionListner(JavaMailSender mailSender, SimpleMailMessage preConfiguredMessage) {
        // TODO Auto-generated constructor stub
        this.mailSender = mailSender;
        this.simpleMailMessage = preConfiguredMessage;
    }

    @Override
    public void beforeStep(StepExecution stepExecution) {
        // TODO Auto-generated method stub

    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        // TODO Auto-generated method stub
        stepExecution.getReadCount();
        MimeMessage message = mailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);

            helper.setFrom(simpleMailMessage.getFrom());
            helper.setTo(simpleMailMessage.getTo());
            helper.setSubject(simpleMailMessage.getSubject());
            helper.setText("These are the skipped records");

            FileSystemResource file = new FileSystemResource("filename.txt");
            helper.addAttachment(file.getFilename(), file);

        } catch (MessagingException e) {
            throw new MailParseException(e);
        }
        //mailSender.send(message);

        return null;
    }

}

由于

2 个答案:

答案 0 :(得分:1)

如果数据库已关闭,则在初始化应用程序上下文时(在进入作业执行之前),您将无法创建数据源。除此之外,你真的应该考虑限制什么是合理的&#34;在应用程序中捕获。通常(至少在我们的商店中)数据库故障,网络问题或丢弃表将被视为灾难性的&#34;失败,所以我们不打算在应用程序代码中捕获它们。

应该有其他工具来监控网络/系统/数据库运行状况和配置管理工具,以确保您的数据库具有适当的DDL。您的应用程序层中的任何进一步检查都是多余的。

答案 1 :(得分:1)

ItemWriteListener具有onWriteError(),而ItemReadListener具有onReadError()方法。这可以用来处理不同的异常并采取行动。