当前位置: 首页 > 知识库问答 >
问题:

QuartzDeadlineManager(调度程序)无意中替换了已配置的TransactionManager

夏青青
2023-03-14

Axon文档在描述EventSchedulerDeadlineManager之间的细微差别以及在哪些场景中必须使用每一个方面有些缺陷。在一次试用中,我尝试使用EventScheduler,这是实现的少数Saga之一。我意识到它不会在聚合上触发@eventsourcinghandler,所以我被迫更改为deadlineManager。(提示:这可以在文档中更好地描述)

现在,第一个挑战是在没有任何洞察力的情况下配置DeadlineManager。下面是我完成的最后一段代码:

@Configuration
public class AxonConfiguration {
    @Bean
    public DeadlineManager deadlineManager(
        final Scheduler scheduler,
        // Disregard "Could not autowire. No beans of 'AxonConfiguration' type found." complain from IntelliJ.
        // This class is an @Configuration, which is a @Component by itself.
        final org.axonframework.spring.config.AxonConfiguration configuration,
        final TransactionManager transactionManager,
        final Serializer serializer
    ) {
        return QuartzDeadlineManager.builder()
            .scheduler(scheduler)
            .serializer(serializer)
            .scopeAwareProvider(new ConfigurationScopeAwareProvider(configuration))
            .transactionManager(transactionManager)
            .build();
    }
}

正如您可能看到的,当使用一个信誉良好的IDE时,它会抱怨AxonConfiguration不是Bean,因此您必须永远忍受警告。

@Slf4j
@Saga
public class MySaga {
    static final Long DELAY_INITIALIZE = 60L;
    static final String INITIALIZE_DEADLINE_NAME = "MyInitialize";

    @Autowired
    private transient DeadlineManager deadlineManager;

    @Autowired
    private transient CommandGateway commandGateway;

    private String scheduleName;
    private String scheduleId;

    @StartSaga
    @SagaEventHandler(associationProperty = "correlationId")
    protected void on(final ScheduleEvent event, @Timestamp final Instant eventInstant) {
        final Instant timerInitialize = eventInstant.plus(Duration.ofSeconds(DELAY_INITIALIZE));

        this.scheduleName = INITIALIZE_DEADLINE_NAME;
        this.scheduleId = this.deadlineManager.schedule(
            timerInitialize,
            INITIALIZE_DEADLINE_NAME,
            InitializeEvent.builder()
                .id(event.getId())
                .build()
        );
    }

    @DeadlineHandler(deadlineName = INITIALIZE_DEADLINE_NAME)
    protected void onDeadline(final InitializeEvent command) {
        this.commandGateway.send(command);
    }

    // ...
}

但是,在执行我的代码时,我不断地得到以下异常:

2020-05-28 03:26:13.001 ERROR 1 --- [eduler_Worker-1] o.a.deadline.quartz.DeadlineJob          : Exception occurred during processing a deadline job which will be retried [com.eblock.simulcast.bidding_engine_axon.auction_event.command.InitializeAuctionEvent]

javax.persistence.TransactionRequiredException: Executing an update/delete query
    at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:413) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1608) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:409) ~[spring-orm-5.2.6.RELEASE.jar!/:5.2.6.RELEASE]
    at com.sun.proxy.$Proxy175.executeUpdate(Unknown Source) ~[na:na]
    at org.axonframework.modelling.saga.repository.jpa.JpaSagaStore.updateSaga(JpaSagaStore.java:272) ~[axon-modelling-4.3.3.jar!/:4.3.3]
    at org.axonframework.modelling.saga.repository.AnnotatedSagaRepository.updateSaga(AnnotatedSagaRepository.java:208) ~[axon-modelling-4.3.3.jar!/:4.3.3]
    at org.axonframework.modelling.saga.repository.AnnotatedSagaRepository.commit(AnnotatedSagaRepository.java:174) ~[axon-modelling-4.3.3.jar!/:4.3.3]
    at org.axonframework.modelling.saga.repository.AnnotatedSagaRepository.lambda$doLoad$2(AnnotatedSagaRepository.java:121) ~[axon-modelling-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.MessageProcessingContext.notifyHandlers(MessageProcessingContext.java:71) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.DefaultUnitOfWork.notifyHandlers(DefaultUnitOfWork.java:106) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.AbstractUnitOfWork.changePhase(AbstractUnitOfWork.java:222) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.AbstractUnitOfWork.commitAsRoot(AbstractUnitOfWork.java:83) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.AbstractUnitOfWork.commit(AbstractUnitOfWork.java:71) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.DefaultUnitOfWork.executeWithResult(DefaultUnitOfWork.java:92) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.UnitOfWork.executeWithResult(UnitOfWork.java:328) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.deadline.quartz.DeadlineJob.execute(DeadlineJob.java:134) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.3.2.jar!/:na]
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) ~[quartz-2.3.2.jar!/:na]

2020-05-28 03:26:13.001  INFO 1 --- [eduler_Worker-1] org.quartz.core.JobRunShell              : Job InitializeAuctionEvent.deadline-7e5d9eec-2c7d-4312-9dde-acb9a56abc6b threw a JobExecutionException: 

org.quartz.JobExecutionException: javax.persistence.TransactionRequiredException: Executing an update/delete query
    at org.axonframework.deadline.quartz.DeadlineJob.execute(DeadlineJob.java:143) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.3.2.jar!/:na]
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) ~[quartz-2.3.2.jar!/:na]
Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query
    at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:413) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1608) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:409) ~[spring-orm-5.2.6.RELEASE.jar!/:5.2.6.RELEASE]
    at com.sun.proxy.$Proxy175.executeUpdate(Unknown Source) ~[na:na]
    at org.axonframework.modelling.saga.repository.jpa.JpaSagaStore.updateSaga(JpaSagaStore.java:272) ~[axon-modelling-4.3.3.jar!/:4.3.3]
    at org.axonframework.modelling.saga.repository.AnnotatedSagaRepository.updateSaga(AnnotatedSagaRepository.java:208) ~[axon-modelling-4.3.3.jar!/:4.3.3]
    at org.axonframework.modelling.saga.repository.AnnotatedSagaRepository.commit(AnnotatedSagaRepository.java:174) ~[axon-modelling-4.3.3.jar!/:4.3.3]
    at org.axonframework.modelling.saga.repository.AnnotatedSagaRepository.lambda$doLoad$2(AnnotatedSagaRepository.java:121) ~[axon-modelling-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.MessageProcessingContext.notifyHandlers(MessageProcessingContext.java:71) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.DefaultUnitOfWork.notifyHandlers(DefaultUnitOfWork.java:106) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.AbstractUnitOfWork.changePhase(AbstractUnitOfWork.java:222) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.AbstractUnitOfWork.commitAsRoot(AbstractUnitOfWork.java:83) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.AbstractUnitOfWork.commit(AbstractUnitOfWork.java:71) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.DefaultUnitOfWork.executeWithResult(DefaultUnitOfWork.java:92) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.messaging.unitofwork.UnitOfWork.executeWithResult(UnitOfWork.java:328) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    at org.axonframework.deadline.quartz.DeadlineJob.execute(DeadlineJob.java:134) ~[axon-messaging-4.3.3.jar!/:4.3.3]
    ... 2 common frames omitted

我决定进行调试,并花几个小时试图缩小问题的范围。我意识到在我的代码库之外(可能是Axon魔术),stdScheduler.getContext().get(deadlinejob.transaction_manager_key)被重写。

下面是两张突出这个问题的截图:

有人经历过这种情况吗?是如何减轻的?现在,我正在遍历所有Axon代码,试图了解实例在哪里被交换。

谢谢,

共有1个答案

云曦之
2023-03-14

我最终解决了这个问题。在我的AxonConfiguration类中,EventScheduler的方法留在那里,以防我们在不久的将来不得不恢复或使用该调度程序。EventScheduler定义如下:

    @Bean
    public QuartzEventSchedulerFactoryBean eventScheduler() {
        return new QuartzEventSchedulerFactoryBean();
    }

由于QuartzEventScheduler是由FactoryBean创建的,因此它从ApplicationContext中提取StdScheduler,并重新分配相关变量。由于我没有自定义的TransactionManager,因此将默认值(NOTransactionManager)分配给QuartzEventScheduler,然后更改QuartzScheduler上下文,从而导致此问题。

为了解决这个问题,我将Bean扩展为以下内容:

    @Bean
    public QuartzEventSchedulerFactoryBean eventScheduler(
        final ApplicationContext applicationContext,
        @Qualifier("eventStore") final EventBus eventBus,
        final Scheduler scheduler,
        final PlatformTransactionManager transactionManager
    ) {
        final QuartzEventSchedulerFactoryBean factoryBean = new QuartzEventSchedulerFactoryBean();

        factoryBean.setApplicationContext(applicationContext);
        factoryBean.setEventBus(eventBus);
        factoryBean.setScheduler(scheduler);
        factoryBean.setTransactionManager(transactionManager);
        factoryBean.setTransactionDefinition(new DefaultTransactionDefinition());

        return factoryBean;
    }

QuartzEventScheduler(FactoryBean)需要基础PlatformTransactionManager,并创建一个新的SpringTransactionManager来分配。如果他们保持与QuartzDeadlineManager相同的方法,直接使用autowired的TransactionManager,而不是在内部处理实例化(并替换axon-spring-autoconfigure创建的实例化),那么会容易得多。

 类似资料:
  • 问题内容: 我正在尝试为我的项目需求实现简单的调度程序,我的项目正在使用。到目前为止,我浏览了Adobe网站并尝试实现所提供的示例,但是没有一个示例可以更新我的文件。 因此,根据这个,它应该工作 依赖 我是否需要进行其他任何更改才能使调度程序正常工作?请建议缺少的内容。 问题答案: 以下解决方案按要求工作,这里处理了三种情况 with :每分钟执行一次作业 with :每3分钟执行一次作业 wit

  • 相关: 我觉得我错过了什么?

  • 问题内容: 我正在尝试构建一个React应用,但是当我执行命令时它给了我以下错误: 我正在使用MacOS High Sierra。我尝试使用以下命令将NPM_TOKEN设置为环境变量: 但这不起作用。问题是什么? 问题答案: 第一个可能的解决方案: 简单的解决方案:(删除.npmrc文件) 第二种可能的解决方案: 但是,如果您不想删除文件,则只需删除文件中的这一行代码即可。 代码行:(删除此代码)

  • 我们在Tomcat 6上有一个Spring 3 Web应用程序,它通过(主要用于每天晚上运行的作业)使用了几个计划服务。现在看来,有时(很少,也许是两个月左右一次)调度程序线程会停止工作,因此在接下来的晚上不会执行任何作业。在我们的日志文件中没有异常或日志条目。 有人知道为什么会发生这种情况吗?或者如何获得关于这个问题的更多信息? 有没有办法在应用程序中检测到这种情况并重新启动调度程序? 目前,我

  • 在我的工作中,我们设置了任务调度程序,定期启动java程序来读取邮件。该任务计划每分钟运行一次,它调用启动java程序的. bat文件。 现在问题来了。大约一个月一次,jave.exe过程不能正常结束,所以下一分钟当它试图运行时,我得到: 任务计划程序无法启动用户“NT 颁发机构\系统”的“\XXX 作业”任务。其他数据:错误值:2147750687。 然后我每分钟都会收到这条消息,直到我从任务管

  • 这些是什么,我们应该如何配置它们,以查看它们如何影响应用程序性能? 谢谢!