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

openmrs / openmrs-core / 29845974054

21 Jul 2026 03:51PM UTC coverage: 66.106% (-0.004%) from 66.11%
29845974054

push

github

web-flow
TRUNK-6713: Switch to saner DaemonThread protection scheme (#6361)

60 of 90 new or added lines in 6 files covered. (66.67%)

6 existing lines in 4 files now uncovered.

24347 of 36830 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.
NEW
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 {
NEW
60
                                Listener.startOpenmrs(servletContext);
×
NEW
61
                        } catch (ServletException e) {
×
NEW
62
                                throw new ModuleException("Unable to start OpenMRS. Error thrown was: " + e.getMessage(), e);
×
NEW
63
                        }
×
NEW
64
                }, callerKey);
×
65

66
                try {
NEW
67
                        startup.get();
×
UNCOV
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.
NEW
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