Как обойти InvalidIsolationLevelException в весеннем пакете? - PullRequest
0 голосов
/ 11 июня 2019

Я использую Spring Batch и получаю InvalidIsolationLevelException при выполнении пакетного задания. Работа выполнялась, когда я использовал MapJobRepositoryFactoryBean, но мне нужно создать таблицы BATCH_ * для базы данных.

В приложении уже настроен менеджер транзакций.

Моя весенняя версия - 4.3.18.RELEASE и использует Oracle SQL для базы данных.

Это моя пакетная конфигурация:

@Configuration
@ComponentScan({"com..."})
public class BatchConfig {
    private static final Logger LOGGER = LoggerFactory.getLogger(BatchConfig.class);

    private static final String REPORTS_STEP_NAME = "reportStep";
    private static final String REPORTS_JOB_NAME = "reportsJob";
    private static final int REPORTS_STEP_CHUNK_SIZE = 20;
    private static final String MAX_END_DATE = "2999-12-31 00:00:00";
    private static final String MAX_END_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    private static final String END_DATE_PARAM = "endDate";
    private static final String REPORT_STATUS_PARAM = "reportSend";
    private static final YesNo NO = new YesNo("N");

    @Autowired
    private ApplicationConfig applicationConfig;

    @Autowired
    private ReportProcessor reportProcessor;

    @Autowired
    private ReportItemWriter reportItemWriter;

    @Bean
    public JobBuilderFactory jobBuilderFactory() throws Exception {
        JobBuilderFactory jobBuilderFactory = new JobBuilderFactory(jobRepository());
        return jobBuilderFactory;
    }

    @Bean
    public StepBuilderFactory stepBuilderFactory() throws Exception {
        StepBuilderFactory stepBuilderFactory = new StepBuilderFactory(jobRepository(), applicationConfig.transactionManager());
        return stepBuilderFactory;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
        jpaTransactionManager.setDataSource(dataSource());
        jpaTransactionManager.setEntityManagerFactory(applicationConfig.entityManagerFactory().getObject());
        return jpaTransactionManager;
    }

    @Bean
    public JobRegistry jobRegistry() {
        return new MapJobRegistry();
    }

    @Bean
    public JobExplorer jobExplorer() throws Exception {
        JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();
        jobExplorerFactoryBean.setDataSource(dataSource());
        jobExplorerFactoryBean.afterPropertiesSet();
        return jobExplorerFactoryBean.getObject();
    }

    @Bean
    public JobOperator jobOperator() throws Exception {
        SimpleJobOperator jobOperator = new SimpleJobOperator();
        jobOperator.setJobExplorer(jobExplorer());
        jobOperator.setJobRegistry(jobRegistry());
        jobOperator.setJobLauncher(jobLauncher());
        jobOperator.setJobRepository(jobRepository());
        return jobOperator;
    }

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("...");
        dataSource.setUrl("...");
        dataSource.setUsername("...");
        dataSource.setPassword("...");
        return dataSource;
    }

    @Bean
    public JobRepository jobRepository() throws Exception {
        JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
        jobRepositoryFactoryBean.setDataSource(dataSource());
        jobRepositoryFactoryBean.setTransactionManager(transactionManager());
        jobRepositoryFactoryBean.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE");
        return jobRepositoryFactoryBean.getObject();
    }

    @Bean
    public JobLauncher jobLauncher() throws Exception {
        SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
        simpleJobLauncher.setJobRepository(jobRepository());
        return simpleJobLauncher;
    }

    public JpaPagingItemReader<FishingVessel> readFishingVesselRecords() throws ParseException {
        LOGGER.info("Inside JpaPagingItemReader");
        JpaPagingItemReader<FishingVessel> fishingVesselsReader = new JpaPagingItemReader<>();
        fishingVesselsReader.setEntityManagerFactory(applicationConfig.entityManagerFactory().getObject());
        fishingVesselsReader.setQueryString(FishingVessel.FISHING_VESSEL_REPORTS);
        fishingVesselsReader.setTransacted(false);
        fishingVesselsReader.setSaveState(false);
        Map<String, Object> params = createQueryParams();
        fishingVesselsReader.setParameterValues(params);
        fishingVesselsReader.setPageSize(100);
        return fishingVesselsReader;
    }

    private Map<String, Object> createQueryParams() throws ParseException {
        Map<String, Object> params = new HashMap<>();
        DateFormatter dateFormatter = new DateFormatter(MAX_END_DATE_FORMAT);
        Date date = dateFormatter.parse(MAX_END_DATE, Locale.ENGLISH);
        params.put(END_DATE_PARAM, date);
        //params.put(REPORT_STATUS_PARAM, NO);
        return params;
    }

    @Bean
    public Step reportsStep() throws Exception {
        DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
        attribute.setPropagationBehavior(Propagation.REQUIRED.value());
        attribute.setIsolationLevel(Isolation.SERIALIZABLE.value());
        attribute.setTimeout(30);

        return stepBuilderFactory()
                .get(REPORTS_STEP_NAME)
                .<FishingVessel, FishingVessel>chunk(REPORTS_STEP_CHUNK_SIZE)
                .reader(readFishingVesselRecords())
                .processor(reportProcessor)
                .writer(reportItemWriter)
                .transactionAttribute(attribute)
                .build();
    }

    @Bean
    public Job reportsJob() throws Exception {
        return jobBuilderFactory()
                .get(REPORTS_JOB_NAME)
                .start(reportsStep())
                .build();
    }
}

Это конфигурация приложения, которая уже существовала в приложении:

@Configuration
@ComponentScan({
    "com....components",
    "com....services",
    "com....converters",
    "com....controllers",
    "com....fluxFolder",
    "com....processors",
    "com....flux.service",
    "com....flux.gateway"
})
@EnableJpaRepositories("com....repositories")
@EnableTransactionManagement
@EnableJpaAuditing
@EnableWebMvc
@Import({SecurityConfig.class})
@PropertySource("classpath:application.properties")
public class ApplicationConfig {
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setPersistenceXmlLocation("classpath:/META-INF/persistence.xml");
        return factory;
    }

    @Bean
    @Primary
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
        return transactionManager;
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Bean
    public ViewResolver viewResolver() {
        UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
        viewResolver.setViewClass(JsfView.class);
        viewResolver.setSuffix(".xhtml");
        return viewResolver;
    }
}

И это мой контроллер для инициализации пакетного задания:

@RestController
public class BatchController {
    private static final String JOB_ID = "JobID";

    private JobExecution jobExecution;

    @Autowired
    private JobOperator jobOperator;

    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    private Job reportsJob;

    @Autowired
    private JobExplorer jobExplorer;

    @GetMapping("/batch/enable")
    public String batchTest() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
        JobParameters jobParameters = new JobParametersBuilder()
                .addString(JOB_ID, String.valueOf(System.currentTimeMillis()))
                .toJobParameters();
        JobInstance job;
        jobExecution = new JobExecution(jobLauncher.run(reportsJob, jobParameters));
        return "batch job started";
    }

    @GetMapping("/batch/disable")
    public String disable() {
        String jobName = jobExecution.getJobInstance().getJobName();
        Set<JobExecution> jobExecutions = jobExplorer.findRunningJobExecutions(jobName);
        for (JobExecution je : jobExecutions) {
            try {
                jobOperator.stop(je.getId());
            } catch (NoSuchJobExecutionException e) {

            } catch (JobExecutionNotRunningException e) {

            }
        }
        return jobName + " disabled.";
    }
}

Это трассировка стека, которую я получаю:

14: 01: 30,945 ОШИБКА [io.undertow.request] (задание по умолчанию-1) UT005023: Запрос на обработку исключений в /.../batch/enable: org.springframework .web.util.NestedServletException: обработка запроса не удалась; вложенными исключение org.springframework.transaction.InvalidIsolationLevelException: DefaultJpaDiale ct не поддерживает пользовательские уровни изоляции из-за ограничения в стандарте JPA. Конкретные меры могут быть реализованы в пользовательских вариантах JpaDialect. в org.springframework.web.servlet.FrameworkServlet.processRequest (FrameworkServlet.java:982) в org.springframework.web.servlet.FrameworkServlet.doGet (FrameworkServlet.java:861) на javax.servlet.http.HttpServlet.service (HttpServlet.java:687) в org.springframework.web.servlet.FrameworkServlet.service (FrameworkServlet.java:846) на javax.servlet.http.HttpServlet.service (HttpServlet.java:790) в io.undertow.servlet.handlers.ServletHandler.handleRequest (ServletHandler.java:86) в io.undertow.servlet.handlers.FilterHandler $ FilterChainImpl.doFilter (FilterHandler.java:130) в org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal (CharacterEncodingFilter.java:197) в org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:107) в io.undertow.servlet.core.ManagedFilter.doFilter (ManagedFilter.java:60) в io.undertow.servlet.handlers.FilterHandler $ FilterChainImpl.doFilter (FilterHandler.java:132) в org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.java:317) в org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke (FilterSecurityInterceptor.java:127) в org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter (FilterSecurityInterceptor.java:91) в org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.java:331) в org.springframework.security.web.access.ExceptionTranslationFilter.doFilter (ExceptionTranslationFilter.java:114) в org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.java:331) в org.springframework.security.web.session.SessionManagementFilter.doFilter (SessionManagementFilter.java:137) в org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.java:331) в org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter (AnonymousAuthenticationFilter.java:111) в org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.java:331) в org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter (SecurityContextHolderAwareRequestFilter.java:170) в org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.java:331) в org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter (RequestCacheAwareFilter.java:63) в org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.java:331)по адресу org.springframework.security.web.session.ConcurrentSessionFilter.doFilter (ConcurrentSessionFilter.java:155) по адресу org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChain.swe.f..authentication.AbstractAuthenticationProcessingFilter.(LogoutFilter.java:116) в org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.java:331) в org.springframework.security.web.header.HeaderWriterFilterF ():org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:107) в org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.j)rg.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter (SecurityContextPersistenceFilter.java:105) в org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilwork.pr.j.context.request.async.WebAsyncManagerIntegrationFilter.FilterChainProxy.java:331) в org.springframework.security.web.FilterChainProxy.doFilterInternal (FilterChainProxy.java:214) в org.springframework.security.web.FilterChainProxy.doFilter (FilterChag.pr).filter.DelegatingFilterProxy.invokeDelegate (DelegatingFilterProxy.java:347) в org.springframework.web.filter.DelegatingFilterProxy.doFilter (DelegatingFilterProxy.java:263) в io.undertow.servlet.core.ManagedFilter.doFilter (ManagedFilter.java:60) в io.undertow.servlet.handlers.FilterHandler $ FilterChainImpl.doFilter (FilterHandler.java:132) в io.undertow.servlet.handlers.FilterHandler.handleRequlerj85: FilterH:по адресу io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest (ServletSecurityRoleHandler.java:62) по адресу io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest.SecurityContextAssociationHandler.) в io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest (ServletAuthenticationCallHandler.java:57) в io.undertow.server.handlers.PredicateHandler.handleRequest (PredicateateHandler.java!.security.handlers.AuthenticationMechanismsHandler.handleRequest (AuthenticationMechanismsHandler.java:58) при io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest (CachedAuthenticatedSessionHandler.java:72) в io.undertow.security.handlers.NotificationReceiverHandler.handleRequest (NotificationReceiverHandler.java: 50)в io.undertow.security.handlers.SecurityInitialHandler.handleRequest (SecurityInitialHandler.java:76) в io.undertow.server.handlers.PredicateHandler.handleRequest (PredicateHandler.java:43) в org.wildfly.curity.JACCContextIdHandler.handleRequest (JACCContextIdHandler.java:61) в io.undertow.server.handlers.PredicateHandler.handleRequest (PredicateHandler.java:43) в io.undertow.io.undertow.(ServletInitialHandler.java:80) в io.undertow.servlet.handlers.ServletInitialHandler $ 1.handleRequest (ServletInitialHandler.java:172) в io.undertow.server.Connectors.executeRootHandler (Connectors.java.er:.HttpServerExchange $ 1.выполнить (HttpServerExchange.java:774) в java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1142) в java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java.java6: 6: 6).run (Thread.java:748) Причина: org.springframework.transaction.InvalidIsolationLevelException: DefaultJpaDialect не поддерживает пользовательские уровни изоляции из-за ограничений в стандартном JPA.Конкретные меры могут быть реализованы в пользовательских вариантах JpaDialect.в org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction (DefaultJpaDialect.java:63) в org.springframework.orm.jpa.JpaTransactionManager.doBegin (JpaTransactionManager.java:380.ranschange.transgram.su) в org.spring(AbstractPlatformTransactionManager.java:377) в org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNeeded (TransactionAspectSupport.java:461) в org.springframework.transaction.interceptor.pport.WransInservice.Transaction.action.interceptor.TransactionInterceptor.invoke (TransactionInterceptor.java:96) в org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:179) в org.springframeworkk.213) на com.sun.proxy. $ Proxy419.getLastJobExecution (Неизвестный источник) на org.springframework.batch.core.launch.support.SimpleJobLauncher.run (SimpleJobLauncher.java:98) в com .... controllers.BatchController.batchTest (BatchController.java:42) в sun.reflect.NativeMethodAccessorImpl.invoke0 (собственный метод) в мотиве восстановления.invoke (NativeMethodAccessorImpl.java:62) на солнцеsupport.InvocableHandlerMethod.invokeAndHandle (ServletInvocableHandlerMethod.java:97) в org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod (RequestMappingHandlerAdapter.jworkqu.we..HandlerAdapter.handleInternal (RequestMappingHandlerAdapter.java:738)в org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle (AbstractHandlerMethodAdapter.java:85) в org.springframework.web.servlet.DispatcherServlet.doDispatch (DispatcherServlet.java:967) в org.springframework.web.servlet.DispatcherServlet.doService (DispatcherServlet.java:901) в org.springframework.web.servlet.FrameworkServlet.processRequest (FrameworkServlet.java:970) ... еще 71

1 Ответ

0 голосов
/ 11 июня 2019

Вы можете изменить уровень изоляции в JobRepositoryFactoryBean по умолчанию:

 @Bean
public JobRepository jobRepository() throws Exception {
    JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
    jobRepositoryFactoryBean.setDataSource(dataSource());
    jobRepositoryFactoryBean.setTransactionManager(transactionManager());
    jobRepositoryFactoryBean.setIsolationLevelForCreate("ISOLATION_DEFAULT");
    return jobRepositoryFactoryBean.getObject();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...