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

openmrs / openmrs-core / 36456271610

28 Sep 2026 04:53PM UTC coverage: 66.105% (+1.2%) from 64.906%
36456271610

push

github

ibacher
Clear leaked outbox rows before OutboxEventServiceTest tests (#6596)

Global property saves committed by earlier tests in the shared context
are persisted as outbox events via TestTransactionalEventAggregator.
When more than 100 are pending, getProcessingAndPendingEvents (ordered
by id, limit 100) no longer returns the test's own events, so the test
failed whenever the module tests ran before it, as on Linux CI.


Claude-Session: https://claude.ai/code/session_015sv8E9mrTQK5LBCaS5zqCn

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

25547 of 38646 relevant lines covered (66.11%)

0.66 hits per line

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

50.0
/web/src/main/java/org/openmrs/web/WebDaemon.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.web;
11

12
import javax.servlet.ServletContext;
13
import javax.servlet.ServletException;
14

15
import org.openmrs.api.APIException;
16
import org.openmrs.api.context.Daemon;
17
import org.openmrs.module.ModuleException;
18
import org.openmrs.util.DatabaseUpdateException;
19
import org.openmrs.util.InputRequiredException;
20

21
import java.util.concurrent.ExecutionException;
22
import java.util.concurrent.Future;
23

24
/**
25
 * This class provides {@link Daemon} functionality in a web context.
26
 * 
27
 * @since 1.9
28
 */
29
public final class WebDaemon {
30
        
31
        /**
32
         * The capability that proves to {@link Daemon} that this class is allowed to act with daemon
33
         * permissions.
34
         */
35
        private static volatile Daemon.CallerKey daemonCallerKey;
36
        
37
        private WebDaemon() {
38
        };
39
        
40
        /**
41
         * Start openmrs in a new thread that is authenticated as the daemon user.
42
         * 
43
         * @param servletContext the servlet context.
44
         */
45
        public static void startOpenmrs(final ServletContext servletContext) throws DatabaseUpdateException, InputRequiredException {
46

47
                Daemon.CallerKey callerKey = daemonCallerKey();
1 ✔
48
                if (callerKey == null) {
1 ✔
49
                        // Daemon distributes the key to WebDaemon reflectively during its initialization. If we get
50
                        // here without one, that hand-off failed; surface the real cause rather than letting the
51
                        // authorization check below fail with a misleading "unauthorized caller" message.
52
                        throw new APIException("Unable to start OpenMRS: WebDaemon was not granted a Daemon caller key. "
×
53
                                + "Check the logs for an earlier error about providing the DaemonCallerKey to WebDaemon.");
54
                }
55

56
                // Startup runs on the servlet container's thread, which is not a daemon thread, so use the
57
                // CallerKey-authorized overload to launch the work on a daemon thread.
58
                Future<?> startup = Daemon.runNewDaemonTask(() -> {
1 ✔
59
                        try {
60
                                Listener.startOpenmrs(servletContext);
×
61
                        } catch (ServletException e) {
×
62
                                throw new ModuleException("Unable to start OpenMRS. Error thrown was: " + e.getMessage(), e);
×
63
                        }
×
64
                }, callerKey);
×
65

66
                try {
67
                        startup.get();
×
68
                } catch (InterruptedException  ignored) {
×
69
                } catch (ExecutionException e) {
1 ✔
70
                        Throwable cause = e.getCause();
1 ✔
71
                        if (cause instanceof DatabaseUpdateException) {
1 ✔
72
                                throw (DatabaseUpdateException) cause;
×
73
                        } else if (cause instanceof InputRequiredException) {
1 ✔
74
                                throw (InputRequiredException) cause;
×
75
                        } else if (!(cause instanceof ModuleException)) {
1 ✔
76
                                throw new ModuleException("Unable to start OpenMRS. Error thrown was: " + cause.getMessage(), cause);
1 ✔
77
                        }  else {
78
                                throw (ModuleException) cause;
×
79
                        }
80
                }
×
81
        }
×
82
        
83
        /**
84
         * Receives the {@link Daemon} caller key. Called only by {@link Daemon} during its initialization.
85
         *
86
         * @param callerKey the caller key issued by {@link Daemon}
87
         * @since 3.0.0, 2.9.0, 2.8.9
88
         */
89
        public static void setDaemonCallerKey(Daemon.CallerKey callerKey) {
90
                if (callerKey != null && daemonCallerKey == null) {
1 ✔
91
                        daemonCallerKey = callerKey;
1 ✔
92
                }
93
        }
1 ✔
94
        
95
        private static Daemon.CallerKey daemonCallerKey() {
96
                if (daemonCallerKey == null) {
1 ✔
97
                        // Guarantee Daemon has initialized and therefore handed us the key, regardless of the order in
98
                        // which the two classes were first loaded.
99
                        Daemon.ensureInitialized();
×
100
                }
101
                return daemonCallerKey;
1 ✔
102
        }
103
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc