2016-06-27 2 views
1

스프링 배치를 사용하여 작성한 일괄 처리의 다양한 조건에 대한 다양한 예외를 추적해야하는 시나리오를 발견했습니다. 예 : 데이터베이스를 읽을 수없는 경우 특정 유형의 예외를 throw하고 데이터베이스를 사용할 수 없다는 메일을 보내고 일괄 처리를 종료하십시오. 테이블을 사용할 수없는 경우 다른 예외를 throw하고 메일을 보내면 테이블을 사용할 수없고 배치를 종료합니다. 그리고 데이터가 SQL 문에 지정된 조건을 충족시키지 않으면 정상적인 작업 종료이므로 아무 것도하지 않습니다. 지금까지 StepExecutionListener를 사용하여 일괄 처리가 모든 레코드를 읽었는지 또는 failureException인지는 알 수 있지만 원하는 방식으로 볼 수는 없습니다. 도움이나 제안 사항이 있습니다.스프링 배치에서 맞춤 예외를 throw하는 방법은 무엇입니까?

내 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="[email protected]" /> 
     <property name="to" value="[email protected]" /> 
     <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="[email protected]" /> 
    <property name="to" value="[email protected]" /> 
    <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; 
    } 

} 

감사

+0

Google에서 평가하고 개선 할 수 있도록 사용하려고 시도한 코드를 포함시킬 수 있습니까? :-) – Sometowngeek

+0

@Sometowngeek 코드를 넣었습니다. 나는 그것이 도움이되기를 바랍니다. 감사합니다 –

+0

질문을 이해하려고합니다 ... 데이터베이스 서버가 다운되었거나 데이터베이스 스키마의 일부를 사용할 수 없는지 묻는 질문을합니까? – Sometowngeek

답변

1

데이터베이스가 다운되면, 데이터 소스 등을 만드는 데 실패 할 수 있습니다 응용 프로그램 컨텍스트를 초기화합니다 (작업 실행에 들어가기 훨씬 전에). 그 외에도, 응용 프로그램 내에서 "합리적인"범위를 제한하는 것에 대해 실제로 생각해야합니다. 일반적으로 (적어도 상점에서는) DB 장애, 네트워크 문제 또는 테이블 삭제는 "치명적인"실패로 간주되므로 응용 프로그램 코드에서이를 포착하지 않아도됩니다.

네트워크/시스템/데이터베이스 상태 및 구성 관리 도구를 모니터링하여 데이터베이스에 적절한 DDL이 있는지 확인해야하는 다른 도구가 있어야합니다. 응용 프로그램 계층의 추가 검사는 중복 될 수 있습니다.

+0

시간을내어 쿼리에 응답 해 주셔서 감사합니다. 귀하의 답변은 도움이되지만 요구 사항은 이것만으로도 스프링 배치 만 사용하여 해결해야하므로 다른 도구를 사용하여 자원을 확인할 수는 없습니다. –

+0

시스템 상태를 점검 할 다른 팀이 있습니까? 서버 자체가 다운되었거나 RAM에서 빠져서 JVM을 시작할 수 없다면 어떻게 될까요? 명령 행 인수가 유효하지 않아 작업을 시작할 수 없다면 어떻게 될까요? 누군가 JAR을 옮기거나 클래스 패스를 변경하여 가져올 수 없으면 어떻게 될까요?이러한 시나리오에서 작업의 코드 양은 전자 메일 경고를 보낼 수 없습니다. –

+0

그 외에도 데이터베이스가 다운되면'ApplicationContext'를 생성 할 수없고 작업 인스턴스를 시작할 수 없습니다. 이 경우'JobExecutionListener' (또는'StepExecutionListener'의'afterStep()')에서'afterJob()'메소드를 절대 쓰지 않을 것이고 이메일은 보내지지 않을 것입니다. 누가 이러한 요구 사항을 제공합니까?! –

1

ItemWriteListener에는 onWriteError()가 있고 ItemReadListener에는 onReadError() 메서드가 있습니다. 다른 예외를 처리하고 조치를 취할 때 사용할 수 있습니다.

+0

안녕하세요 Shankar, 나는 이미 이것을 시도했지만 onReadError()는 읽기에 문제가있을 때까지 치지 않습니다.이 경우 읽기가 시작되지 않았으므로 onReadError는 ItemReadListener이므로 알림을받지 않습니다. 감사합니다. . –

+0

그런 다음 StepExecutionListener를 사용하십시오. 그 afterStep() 메서드에서 상태를 확인합니다. stepExexuction.getFailureExceptions()는 오류를 catch하는 데 필요한 정보를 더 많이 제공해야합니다. –

+0

안녕 Shankar, 내가 그 질문에 언급했듯이 내가 한 일이다. 나는 더 나은 방법을 찾고 있었다 :) –

관련 문제