2013-10-03 5 views
2

편집스프링 배치의 @StepScope는 CGLIB 서브 클래스

내가 문제를 복제하는 테스트 프로젝트를 생성을 생성 할 수 없습니다. https://github.com/tomverelst/test-batch에서 찾을 수 있습니다.

먼저 HSQL 데이터베이스를 시작하려면 maven 명령 exec:java을 실행하십시오. 그런 다음 JUnit 테스트 MigrationJobConfigurationTest을 실행하여 Spring 애플리케이션 컨텍스트를로드 할 수있다.

Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy34]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy34 

이 나의 작업의 구성에서 @StepScope 주석에 의해 발생 : 봄로드 내 작업의 구성 때

원래 질문은

내 스프링 배치 응용 프로그램을 시작, 나는 다음과 같은 예외를 얻을 . 이미 JDK 프록시로 프록시 처리 된 CGLIB를 사용하여 클래스를 프록시하려고 시도하지만이 JDK 프록시가 어디서 오는지 알지 못합니다.

또한 @Scope(value = "step", proxyMode = ScopedProxyMode.NO)을 사용해 보았지만 자체 호출을 계속하는 JDK 프록시를 호출 할 때 스택 오버플로 오류가 발생합니다.

@StepScope 주석을 제거하면 응용 프로그램이 올바르게 시작되지만 내 작업에이 응용 프로그램을 사용할 수 있어야합니다.

봄 설정

<context:component-scan base-package="com.jnj.rn2.batch" /> 

<context:annotation-config /> 

<aop:aspectj-autoproxy proxy-target-class="true" /> 

<bean class="org.springframework.batch.core.scope.StepScope" /> 

// Job repository etc 
... 

MigrationJobConfiguration

@Configuration 
public class MigrationJobConfiguration { 

    @Autowired 
    private JobBuilderFactory jobs; 

    @Autowired 
    private StepBuilderFactory steps; 

    @Autowired 
    private MigrationService migrationService; 

    @Bean 
    public Job migrationJob() { 
     return jobs.get("migrationJob") 
      .start(migrateCrfStep()) 
      .next(indexRequestsStep()) 
      .build(); 
    } 

    @Bean 
    public Step migrateCrfStep() { 
     return steps.get("migrateCrfStep") 
      .tasklet(migrateCrfTasklet()) 
      .build(); 
    } 

    @Bean 
    public Step indexRequestsStep() { 
     return steps.get("indexRequestsStep") 
      .<LegacyRequest,LegacyRequest> chunk(5) 
      .reader(indexRequestReader()) 
      .processor(indexRequestProcessor()) 
      .writer(indexRequestWriter()) 
      .build(); 
    } 

    @Bean 
    @StepScope 
    public MigrateCrfTasklet migrateCrfTasklet() { 
     return new MigrateCrfTasklet(); 
    } 

    @Bean 
    @StepScope 
    public IndexRequestItemReader indexRequestReader() { 
     return new IndexRequestItemReader(); 
    } 

    @Bean 
    @StepScope 
    public IndexRequestItemProcessor indexRequestProcessor() { 
     return new IndexRequestItemProcessor(); 
    } 

    @Bean 
    @StepScope 
    public IndexRequestItemWriter indexRequestWriter() { 
     return new IndexRequestItemWriter(); 
    } 

    // Setters 
    ... 
} 

답변

4

실제 답변을 드릴 수는 없지만 내가 제공 한 예제를 디버깅했습니다. 이 일어나고 :

  • @Configuration 정의 리더 원래 빈이 scopedTarget.reader로 등록되는 동안 리더 @Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS)
  • CGLIB 하위 만들고 reader로 등록하여 주석이 주석 @StepScope 본다.
  • StepScope 범위 내 킥 및 후 처리 step 범위가 지정된 콩. CGLIB가 확장 된 reader 정의를 감지하고 =>ERROR에 대한 프록시를 생성하려고 시도합니다.

충돌하는 프록시 메커니즘이 두 가지 있습니다. 정말로 이상한 일이 일어나고 있습니다. 이것은 절대로 작동하지 않을 것 같습니다. Spring JIRA를 통해 검색을 시도 할 것입니다.


UPDATE

찾을 솔루션 - 당신은 단계 범위에 대한 disable auto-proxying해야합니다

<bean class="org.springframework.batch.core.scope.StepScope"> 
    <property name="autoProxy" value="false" /> 
</bean> 
+1

이것은 내가 만든 테스트 프로젝트에서 작동하지만, 어떤 이유로 내 주요 프로젝트에 아직 없습니다. 나는'@ EnableBatchProcessing'을 사용하여 XML에서 Java Config로 바뀌 었습니다. –

+1

@Pavel @StepScope를 사용할 때 어떻게 autoProxy를 false로 설정할 수 있습니까? 이것은 XML 구성이없는 경우입니다. – gsndev

+0

@gsndev XML 구성을 사용하지 않는다면 내 대답에 설명 된 충돌이 발생하지 않을 것입니다 (OP 문제 일 수도 있습니다). XML 설정없이 비슷한 예외가 발생한다면 별도의 질문을해볼 것을 제안합니다. –

1

Easly 구성 파일에서 <bean class="org.springframework.batch.core.scope.StepScope" />을 제거; (official documentation of Step scope에 설명 된대로) 일괄 처리 네임 스페이스에 정의되어 있으므로 명시 적으로 추가 할 필요가 없습니다.

+0

이 같은 예외로 발생합니다. –

+0

이 증상이 해결되었습니다. 봄 범위 지정 규칙은 간접적 인 것이지만 일단 이해하면 이해할 수 있습니다. –