2017-11-23 20 views
1

나는 봄 부팅 1.5을 사용하여 스프링 배치 응용 프로그램을 쓰고 있어요을 다시 읽고, 내 수업은 다음과 같습니다 : -스프링 배치 MultiResourceItemReader의 첫 번째 자원

CustomMultiResourceItemReader.java

@StepScoped 
@Component 
public class CustomMultiResourceItemReader 
     extends MultiResourceItemReader<MyDTO> { 

    public MultiResourceXmlItemReader(
      @NonNull final MyResourceAwareItemReader itemReader, 
      @NonNull final ApplicationContext ctx) 
      throws IOException { 
     setResources(
       ctx.getResources(
         String.format(
           "file:%s/*.xml", "~/data"))); // gives me a Resource[] array fine 
     setDelegate(itemReader); 
    } 

    @PreDestroy 
    void destroy() { 
     close(); 
    } 
} 

MyResourceAwareItemReader.java

@RequiredArgsConstructor 
@StepScope 
@Component 
@Slf4j 
public class MyResourceAwareItemReader 
     implements ResourceAwareItemReaderItemStream<MyDTO> { 
    private static final String RESOURCE_NAME_KEY = "RESOURCE_NAME_KEY"; 
    @NonNull private final Unmarshaller unmarshaller; // JaxB Unmarshaller 
    private Resource resource; 

    @Override 
    public void setResource(Resource resource) { 
     this.resource = resource; // **gets called only once** 
    } 

    @Override 
    public MyDTO read() throws Exception { 
     final MyDTO dto = (MyDTO) unmarshaller.unmarshal(resource.getFile()); // Standard JaxB unmarshalling. 
     return dto; 
    } 

    @Override 
    public void open(ExecutionContext executionContext) throws ItemStreamException { 
     if (executionContext.containsKey(RESOURCE_NAME_KEY)) { 

     } else if (resource != null) { 
      executionContext.put(RESOURCE_NAME_KEY, resource.getFilename()); 
     } 
    } 

    @Override 
    public void update(ExecutionContext executionContext) throws ItemStreamException { 
     if (resource != null) executionContext.put(RESOURCE_NAME_KEY, resource.getFilename()); 
    } 

    @Override 
    public void close() throws ItemStreamException {} 
} 

문제는 delegate 독자의 setResource 메소드입니다 (MyResourceAwareItemReader.java)는 처음에 한 번만 호출됩니다. read 메서드가 여러 번 호출되는 동안 결과적으로 다음 항목을 예상 한대로 읽는 대신 동일한 항목을 여러 번 읽습니다.

나는 또한 MultiResouceItemReader in Spring Batch의 소스 코드를 탐색했습니다. 위임 클래스의 읽기 메소드는 각 항목을 읽은 후 null을 반환해야한다고 생각합니다. 코드를 읽으면 분명히 그 일을하는 것처럼 보입니다.

이 작업을 수행하는 방법이 약간 분실되었습니다. 도움이 많이 접수되었습니다.

답변

0

MultiResourceItemReader은 매번 null을 반환하지 않습니다. 더 이상 읽을 리소스가 없으면 NULL을 반환하고 그렇지 않으면 다음 리소스를 대리자에게 반환합니다. - 실제 독자

read() 메서드에서 문제가 발생할 수 있습니다. y ou는 다음 파일으로 이동하지 않습니다. 자신을 구현할 때 MultiResourceItemReader 다음 리소스 항목으로 이동하는 것은 귀하의 책임입니다.

이것은 MultiResourceItemReader에 이식되는 방법입니다. 자신 만의 비슷한 구현이 필요합니다.

private T readNextItem() throws Exception { 

     T item = delegate.read(); 

     while (item == null) { 

      currentResource++; 

      if (currentResource >= resources.length) { 
       return null; 
      } 

      delegate.close(); 
      delegate.setResource(resources[currentResource]); 
      delegate.open(new ExecutionContext()); 

      item = delegate.read(); 
     } 

     return item; 
    } 

리소스 인덱스를 유지 관리해야합니다. MultiResourceItemReader의 구현을 확인하십시오. 당신은 그것으로 더 찾고 정확히 유사한 방식으로

+0

내가 ** ** 구현하지 않은 내 자신의'MultiResourceItemReader'; 방금 생성자에 2 개의 속성을 설정했습니다. 나는 내 자신의'ResourceAwareItemStreamReader'를 구현했고 읽기 메소드에서 리소스를 읽고 리턴했다. 하지만 Spring 배치의'MultiResourceItemReader.java' 코드를 보면 델리게이트의 read 메소드가 null을 반환 할 때'Resource []'인덱스를 증가시킵니다. – aprofromindia

0

을 할 필요가, ItemReader 문서는, 명확하게 독자 필수 입력 데이터 세트의 끝에 반환 null을 자세히 설명합니다. 다음과 같이 그러니까 기본적으로 나는 boolean 플래그 내 ItemReader을 구현 : -

@RequiredArgsConstructor 
@StepScope 
@Component 
@Slf4j 
public class MyResourceAwareItemReader 
     implements ResourceAwareItemReaderItemStream<MyDTO> { 
    private static final String RESOURCE_NAME_KEY = "RESOURCE_NAME_KEY"; 
    @NonNull private final Unmarshaller unmarshaller; // JaxB Unmarshaller 
    private Resource resource; 
    private boolean isResourceRead; 

    @Override 
    public void setResource(Resource resource) { 
     this.resource = resource; 
     isResourceRead = false; 
    } 

    @Override 
    public MyDTO read() throws Exception { 
     if(isResourceRead == true) return null; 

     final MyDTO dto = (MyDTO) unmarshaller.unmarshal(resource.getFile()); 
     isResourceRead = true; 
     return dto; 
    } 

    @Override 
    public void open(ExecutionContext executionContext) throws ItemStreamException { 
     if (executionContext.containsKey(RESOURCE_NAME_KEY)) { 

     } else if (resource != null) { 
      executionContext.put(RESOURCE_NAME_KEY, resource.getFilename()); 
     } 
    } 

    @Override 
    public void update(ExecutionContext executionContext) throws ItemStreamException { 
     if (resource != null) executionContext.put(RESOURCE_NAME_KEY, resource.getFilename()); 
    } 

    @Override 
    public void close() throws ItemStreamException {} 
}