• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

openmrs / openmrs-core / 29373009385

14 Jul 2026 10:26PM UTC coverage: 63.842% (+0.03%) from 63.813%
29373009385

push

github

web-flow
TRUNK-6516: Fix outbox/broker issues found in events/CDC sign-off (#6298) (#6313)

Backport of #6298 to 2.9.x, adapted to the 2.9.x platform (javax
persistence / Hibernate 5 / Spring 5). Addresses findings 1, 2, 4, 5, 7
from the sign-off issue.

- Finding 1: OutboxEventRegistry now owns the scheduler lifecycle. It
  triggers OutboxTaskSchedulerInitializer.schedule()/deleteScheduledTasks()
  after scanning listener beans, guaranteeing the poller only starts once
  listeners are known. OutboxTaskSchedulerInitializer no longer implements
  SmartInitializingSingleton and no longer references OutboxEventRegistry.
- Finding 2: Use Context.loadClass() instead of Class.forName() in
  OutboxPollingTaskHandler so module-defined event types resolve.
- Finding 4: Change outbox_event.payload and completed_listeners from TEXT
  to MEDIUMTEXT in the update changelog and align the OutboxEvent entity
  columnDefinition. HibernateAdministrationDAO now treats LONGTEXT and
  MEDIUMTEXT columns as unbounded so ValidateUtil accepts large payloads.
- Finding 5: BrokerEventListenerFactory rejects wildcard/raw
  BrokerIncomingEvent at registration time instead of dead-lettering.
- Finding 7: Document on OpenmrsServiceEventAdvice that a synchronous
  @EventListener exception aborting the service call is intentional.

The 2.9.x liquibase schema-only snapshot does not exist yet, so only the
update changelog carries the MEDIUMTEXT change. Context.java javadoc link
updated to OutboxTaskSchedulerInitializer#schedule().

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

19 of 27 new or added lines in 5 files covered. (70.37%)

15 existing lines in 5 files now uncovered.

24113 of 37770 relevant lines covered (63.84%)

0.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.16
/api/src/main/java/org/openmrs/event/outbox/tasks/OutboxTaskSchedulerInitializer.java
1
/**
2
 * This Source Code Form is subject to the terms of the Mozilla Public License,
3
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
4
 * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5
 * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6
 *
7
 * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8
 * graphic logo is a trademark of OpenMRS Inc.
9
 */
10
package org.openmrs.event.outbox.tasks;
11

12
import org.openmrs.api.context.Context;
13
import org.openmrs.scheduler.SchedulerService;
14
import org.openmrs.util.PrivilegeConstants;
15
import org.springframework.stereotype.Component;
16

17
import java.time.Duration;
18

19
/**
20
 * Owns the lifecycle of the outbox scheduler tasks. Scheduling is triggered by
21
 * {@link org.openmrs.event.outbox.OutboxEventRegistry} once it has scanned for
22
 * {@link org.openmrs.event.outbox.OutboxEventListener} beans, so that the poller only starts when
23
 * at least one listener is present.
24
 *
25
 * @since 2.9.0
26
 */
27
@Component
28
public class OutboxTaskSchedulerInitializer {
29

30
        public static final String OUTBOX_POLLER_TASK_NAME = "Transactional Outbox Poller";
31
        public static final String OUTBOX_POLLER_TASK_UUID = "bc2739ac-5bf3-4ecd-8e11-d383d53695bb";
32
        public static final String OUTBOX_CLEANUP_TASK_NAME = "Transactional Outbox Cleanup";
33
        public static final String OUTBOX_CLEANUP_TASK_UUID = "a0c11918-0aba-46bf-a7c6-7b0cc47e7323";
34

35
        private final SchedulerService schedulerService;
36

37
        public OutboxTaskSchedulerInitializer(SchedulerService schedulerService) {
1✔
38
                this.schedulerService = schedulerService;
1✔
39
        }
1✔
40

41
        public void schedule() {
42
                try {
43
                        if (!Context.isSessionOpen()) {
1✔
44
                                Context.openSession();
1✔
45
                        }
46
                        Context.addProxyPrivilege(PrivilegeConstants.MANAGE_SCHEDULER);
1✔
47

48
                        // Schedule the outbox polling task to run recurrently in the background
49
                        schedulerService.scheduleRecurrently(
1✔
50
                                OUTBOX_POLLER_TASK_UUID,
51
                                new OutboxPollingTaskData(),
52
                                Duration.ofSeconds(15),
1✔
53
                                OUTBOX_POLLER_TASK_NAME
54
                        );
55

56
                        // Schedule the outbox cleanup task to run recurrently (e.g., every day)
57
                        schedulerService.scheduleRecurrently(
1✔
58
                                OUTBOX_CLEANUP_TASK_UUID,
59
                                new OutboxCleanupTaskData(),
60
                                Duration.ofDays(1),
1✔
61
                                OUTBOX_CLEANUP_TASK_NAME
62
                        );
63
                } finally {
64
                        Context.removeProxyPrivilege(PrivilegeConstants.MANAGE_SCHEDULER);
1✔
65
                }
66
        }
1✔
67

68
        public void deleteScheduledTasks() {
69
                try {
NEW
70
                        if (!Context.isSessionOpen()) {
×
NEW
71
                                Context.openSession();
×
72
                        }
NEW
73
                        Context.addProxyPrivilege(PrivilegeConstants.MANAGE_SCHEDULER);
×
74

NEW
75
                        schedulerService.deleteRecurringTask(OUTBOX_POLLER_TASK_UUID);
×
NEW
76
                        schedulerService.deleteRecurringTask(OUTBOX_CLEANUP_TASK_UUID);
×
77
                } finally {
UNCOV
78
                        Context.removeProxyPrivilege(PrivilegeConstants.MANAGE_SCHEDULER);
×
79
                }
UNCOV
80
        }
×
81
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc