2013-05-01 10 views
2

TL : DR : 스프링 배치 작업을 사용하여 스프링 배치 작업을 어떻게 작성해야합니까? 트랜잭션 경계가 문제인 것 같습니다. 이것은 고전적인 질문 인 것 같습니다. 그러나 여기 다시 있습니다 :스프링 배치 사용 또는 작업 내에서 작업 시작 방법

다음과 같은 사용 사례가 있습니다 : FTP 서버를 폴링하고 데이터베이스에 BLOB로 발견 된 XML 파일을 저장해야합니다. XML은 0 ... 관심 항목 N 은 외부 웹 서비스에 보내고 응답을 저장해야합니다. 응답은 다시 시도 할 수 없거나 다시 시도 할 수 있으며 은 감사 요청을 위해 각 요청과 응답을 저장해야합니다.

도메인/JPA 모델은 다음과 같습니다. Batch (XML blob 포함)는 0-N BatchRow 오브젝트를 포함합니다. BatchRow는 웹 서비스로 전송할 데이터를 포함하며 웹 서비스 호출에 대한 정보가 인 N ... BatchRowHistory 객체도 포함합니다.

스프링 배치 (스프링 통합 이 통합 이후 다른 가능성이있을 수 있음)를 사용하여이를 구현하도록 요청 받았습니다. 지금 나는 다른 접근 방식으로 고생했습니다. 나는이 과제가 훨씬 복잡하고 어렵 기 때문에 IMHO가 있어야한다고 느낍니다.

나는 다음과 같은 작업에 작업을 분할했습니다

작업 1 :

  • 스텝 11 : 파일 가져 오기 및 BLOB으로 데이터베이스에 저장합니다.

  • 12 단계 : XML을 항목으로 분할하고 해당 항목을 db에 저장합니다.

  • 단계 13 :에 저장된 각 항목에 대해 작업 2를 생성하고 실행하십시오. Job2는 도메인 모델 데이터베이스에 플래그를 작성하여 항목을 표시합니다.

작업 2 :

  • 스텝 21 : dB로 각 항목 및 저장 결과를 웹 서비스를 호출합니다. 다시 시도하고 건너 뛰기 논리가 여기에 있습니다. 작업 2 종류의 작업 1이 예정 주기적으로 (그래서 한 번 분)를 실행한다는 것입니다 가능성이 매뉴얼 등

다시 시작이 구조 뒤에 논리가 필요합니다. Job2는 해당 작업이 일 때마다 실행되며이 중 하나가 성공했거나 다시 시도 한계가 최대로 이고 실패했습니다. 도메인 모델은 기본적으로 결과 만 저장하고 스프링 배치가 쇼 실행을 담당합니다. Manual relaunches 등은 Spring Batch Admin을 통해 처리 할 수 ​​있습니다 (적어도 희망합니다). 또한 Job2는 BatchRow의 ID를 JobParameters 맵에 가지고 있으므로 을 Spring Batch Admin에서 볼 수 있습니다.

질문 1 : 이 작업 구조가 올바른가요? 즉, 새로운 봄 일괄 작업 db 만들기, 그것은 일종의 목표를 물리 치고 어떤 수준에서 바퀴를 다시 만드는 것 같습니다.

질문 2 : 어떻게 Step13에서 Job2 항목을 만들 수 있습니까?

내가 거래와 JobRepository에 먼저 문제를 가지고 있지만, 다음과 같은 설정에 몇 가지 작업을 시작 을 성공 :

<batch:step id="Step13" parent="stepParent"> 
<batch:tasklet> 
    <batch:transaction-attributes propagation="NEVER"/> 
    <batch:chunk reader="rowsWithoutJobReader" processor="batchJobCreator" writer="itemWriter" 
       commit-interval="10" /> 
</batch:tasklet> 
</batch:step> 

<bean id="stepParent" class="org.springframework.batch.core.step.item.FaultTolerantStepFactoryBean" abstract="true"/> 

가 커밋 간격 = "10"을 유의하시기 바랍니다이 10 개 작업을 만들 수 있다는 것을 의미합니다 현재 그리고 그게 다야 ... batchJobCreator가 JobLauncher.run 메소드를 호출했기 때문에 그것이 원활하게 진행되었지만 itemWriter는 업데이트 된 정보 (부울 jobCreated 플래그가 켜짐)로 데이터베이스에 BatchRows를 다시 쓸 수 없습니다. 분명히 그 이유는 propagation.NEVER 트랜잭션 속성에 있지만 그것 없이는 jobLauncher 작업을 만들 수 없습니다.

업데이트가 데이터베이스에 전달되지 않기 때문에, 나는 다시 같은 BatchRows을 얻고 그들은 함께 로그를 혼란 : 그 일을 의미

org.springframework.batch.retry.RetryException: Non-skippable exception in recoverer while processing; nested exception is org.springframework.batch.core.repository.JobExecutionAlreadyRunningException: A job execution for this job is already running: JobInstance: id=1, version=0, JobParameters=[{batchRowId=71}], Job=[foo.bar] 
     at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$2.recover(FaultTolerantChunkProcessor.java:278) 
     at org.springframework.batch.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:420) 
     at org.springframework.batch.retry.support.RetryTemplate.doExecute(RetryTemplate.java:289) 
     at org.springframework.batch.retry.support.RetryTemplate.execute(RetryTemplate.java:187) 
     at org.springframework.batch.core.step.item.BatchRetryTemplate.execute(BatchRetryTemplate.java:215) 
     at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.transform(FaultTolerantChunkProcessor.java:287) 
     at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:190) 
     at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:74) 
     at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:386) 
     at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130) 
     at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:264) 
     at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76) 
     at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367) 
     at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214) 
     at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143) 
     at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:250) 
     at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195) 
     at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135) 
     at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61) 
     at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60) 
     at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144) 
     at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124) 
     at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135) 
     at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:293) 
     at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120) 
     at java.lang.Thread.run(Thread.java:680) 

이미 스프링 배치에서 생성과 시도를하고있다 Step13의 나중 실행에서이 파일을 다시 작성하십시오. 이 은 Job2/Step21에서 jobCreated 플래그를 true로 설정하는 것을 피할 수 있지만 다소 엉성하고 잘못되었습니다.

질문 3 : 나는 더 많은 도메인 객체 접근 방식을 가졌습니다. 나는 스프링을 가지고 있었다. 배치 작업은 매우 정교한 JPQL 쿼리 과 JPAItemReaders를 사용하여 도메인 테이블을 검색했다. 이 접근 방식의 문제점은 Spring Batch의 미세한 기능을 사용하지 않고 을 사용한다는 것입니다. 기록 및 재시도 논리는 입니다. 재 시도 로직을 JPQL 쿼리 에 직접 코딩해야합니다 (예 : BatchRow에 BatchRowHistory가 3 개 이상있는 경우 요소가 실패 했으므로 수동으로 다시 검사해야 함). 글 머리 기호를 물고 각 웹 서비스 호출에 대해 개별 스프링 배치 작업을 만드는 대신이 방법을 계속 진행해야합니까?

필요한 경우 소프트웨어 정보 : Spring Batch 2.1.9, Hibernate 4.1.2, Spring 3.1.2, Java 6.나는 새로운 일자리를 생성 할 필요가 있다고 생각하는 이유는 이 : 독자 동안

  • 루프

    편집 한 긴 이야기에 대한 사전 미안에 티모을 주셔서 감사합니다 null을 반환 또는 예외는

  • 거래

  • 시작

    을 발생합니다

    리더 - 프로세서 -

  • 트랜잭션 끝 배치 크기 N

각각 진입 실패에 대한 전체 N 개의 행에 대한 라이터 루프는 문제; 수동으로 재시작 가능 Spring Batch Admin을 사용하여 실패한 작업을 볼 수 있도록 일괄 처리의 각 행에 대해 실행 (작업은 스프링 일괄 관리에서 재시작 가능합니다. 맞습니까?) 작업 매개 변수 도메인 db의 행 ID 포함) 및 다시 시작하십시오. 작업을 생성하고 도메인 db에 기록을 저장하지 않고 이러한 종류의 동작을 수행하는 방법은 무엇입니까?

답변

0

좋아요, 질문에 응답하는 것이 싫지만 ... 알고 싶습니다.

1) 입력 파일이 XML 인 경우 StaxEventItemReader를 사용하고 1 단계에서 항목을 유지하면 어떨까요?

2) 단계에서 두 번째 작업 시작 !!!! 비록 그것이 작동해야하는지 모르겠지만 ... IMO .. 냄새가 나네 ;-)

JdbcCursorItemReader를 사용하여 항목을 읽고 ItemProcessor에서 웹 서비스를 호출하는 또 다른 단계를 정의하지 마십시오. 그런 다음 결과를 데이터베이스에 씁니다.

어쩌면 웹 서비스를 호출 할 때마다 다른 작업을 생성해야한다는 귀하의 요구 사항을 이해하지 못할 수도 있습니다 !!!

내가 사용 사례에 비슷한 일을했고 그것은이 시나리오 사용하여 수행되었다

작업을 1 : 1 단계 : XML, 프로세스 pojo-> 도메인 OBJ를 읽을 ​​

DB

의 도메인 OBJ 쓰기 작업 2 : 1 단계 :

그것이 도움이 될 것입니다 희망, DB, 공정 = 통화 WS에서 OBJ를 읽어 DB

에 응답을 쓰기

이 간단하고 아주 잘 작동 (다시 시작 포함 및 기능을 생략)

안부

+0

감사합니다. 1 : 원래 파일을 데이터베이스에 저장하여 감사 용으로 을 사용해야합니다. StaxReader는 db afaik에서 직접 해당 파일을 읽을 수 없습니다. 2 : 예, 이것은 매우 쉽게 해결되지 않는 문제인 것 같습니다 .- 구조 정보 : 작업 1은 작업 을 제외한 나머지 부분과 동일하게 보입니다. – tfriman

+0

작업 2는 행복 경로가 걸려있을 때와 거의 같습니다. 즉, IO 문제가없는 경우입니다. 따라서 WS 호출이 성공하면 db에 응답을 멋지게 작성합니다. 문제가 발생하면 트랜잭션이 롤백되기 때문에 db에 이 기록되지 않습니다. 데이터베이스에 WS 호출 결과를 쓸 수있는 경우 어떻게 다시 시도합니까? 요소 건너 뛰기는 데이터베이스에도 기록해야합니다. 그렇게 할 수 있었습니까? RetryListener 및 SkipListener 인터페이스를 알고 있지만 데이터베이스에 (JPA) 항목을 다시 쓸 수 있습니까? – tfriman

관련 문제