Skip to content

Commit 0b4cfb7

Browse files
TRUNK-6243: Add a new runtime property to determine if app is running in development or production mode
1 parent 37e529c commit 0b4cfb7

File tree

4 files changed

+122
-0
lines changed

4 files changed

+122
-0
lines changed

api/src/main/java/org/openmrs/util/OpenmrsConstants.java

+7
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,13 @@ public static final Collection<String> AUTO_ROLES() {
558558
public static final String ENCRYPTION_KEY_RUNTIME_PROPERTY = "encryption.key";
559559

560560
public static final String ENCRYPTION_KEY_DEFAULT = "dTfyELRrAICGDwzjHDjuhw==";
561+
562+
/**
563+
* Runtime property that will tell the system if app is running in development or production mode.
564+
*/
565+
public static final String DEVELOPMENT_MODE_RUNTIME_PROPERTY = "development.mode";
566+
567+
public static final String DEVELOPMENT_MODE_DEFAULT = "true";
561568

562569
/**
563570
* Global property name for the visit type(s) to automatically close

api/src/main/java/org/openmrs/util/OpenmrsUtil.java

+65
Original file line numberDiff line numberDiff line change
@@ -1946,6 +1946,71 @@ public static String shortenedStackTrace(String stackTrace) {
19461946
return StringUtils.join(results, "\n");
19471947
}
19481948

1949+
/**
1950+
* Convert a stack trace into a formatted message version for easier viewing In production mode, instead of a page
1951+
* with stack traces. In development mode, we should continue to have stack traces.
1952+
*
1953+
* @param stackTrace original stack trace from an error
1954+
* @return formatted stack trace message
1955+
* <strong>Should</strong> return null if stackTrace is null
1956+
* <strong>Should</strong> return the Error and the Cause
1957+
* @since 2.8
1958+
*/
1959+
public static String formattedStackTrace(String stackTrace) {
1960+
if (stackTrace == null) {
1961+
return null;
1962+
}
1963+
1964+
// If not in dev mode, convert a stack trace into a formatted message version
1965+
String props = Context.getRuntimeProperties().getProperty(OpenmrsConstants.DEVELOPMENT_MODE_RUNTIME_PROPERTY);
1966+
if (StringUtils.equals(props, "false")) {
1967+
// Pattern to match the first exception and first "Caused by"
1968+
Pattern pattern = Pattern.compile("(?m)^(([\\w.$]+Exception|Error|Throwable): .*)|"
1969+
+ "(Caused by: [\\w.$]+(Exception|Error|Throwable): .*)");
1970+
1971+
Matcher matcher = pattern.matcher(stackTrace);
1972+
StringBuilder result = new StringBuilder();
1973+
boolean foundFirst = false;
1974+
boolean foundCause = false;
1975+
1976+
while (matcher.find()) {
1977+
String line = matcher.group().trim();
1978+
if (!foundFirst) {
1979+
if (isExceptionLine(line)) {
1980+
result.append(detectExceptionType(line)).append(": ").append(line);
1981+
}
1982+
foundFirst = true;
1983+
} else if (line.startsWith("Caused by:")) {
1984+
result.append("\n").append(line);
1985+
foundCause = true;
1986+
}
1987+
1988+
if (foundCause) {
1989+
break;
1990+
}
1991+
}
1992+
1993+
return result.toString();
1994+
} else {
1995+
return stackTrace;
1996+
}
1997+
}
1998+
1999+
private static boolean isExceptionLine(String line) {
2000+
return line.matches("([\\w$]+\\.)*[\\w$]+(Exception|Error|Throwable): .*");
2001+
}
2002+
2003+
private static String detectExceptionType(String line) {
2004+
if (line.contains(".hl7")) {
2005+
return "Error (HL7)";
2006+
} else if (line.contains("org.springframework.")) {
2007+
return "Error (Spring)";
2008+
} else if (line.contains("java.") || line.contains("javax.")) {
2009+
return "Error (Java)";
2010+
}
2011+
return "Error";
2012+
}
2013+
19492014
/**
19502015
* <pre>
19512016
* Finds and loads the runtime properties file for a specific OpenMRS application.

api/src/test/java/org/openmrs/util/OpenmrsUtilTest.java

+48
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,54 @@ public void shortenedStackTrace_shouldRemoveSpringframeworkAndReflectionRelatedL
672672
assertEquals(expected, OpenmrsUtil.shortenedStackTrace(test), "stack trace was not shortened properly");
673673
}
674674

675+
/**
676+
* @see OpenmrsUtil#formattedStackTrace(String)
677+
*/
678+
@Test
679+
public void formattedStackTrace_shouldReturnTheErrorAndCauseAfterFormattingIfNotInDevMode() {
680+
Properties props = Context.getRuntimeProperties();
681+
props.setProperty(OpenmrsConstants.DEVELOPMENT_MODE_RUNTIME_PROPERTY, "false");
682+
Context.setRuntimeProperties(props);
683+
684+
String test = "ca.uhn.hl7v2.HL7Exception: Error while processing HL7 message: ORU_R01\n"
685+
+ "\tat org.openmrs.hl7.impl.HL7ServiceImpl.processHL7Message(HL7ServiceImpl.java:752)\n"
686+
+ "Caused by: ca.uhn.hl7v2.app.ApplicationException: ca.uhn.hl7v2.HL7Exception: Could not resolve patient by identifier\n"
687+
+ "\tat org.openmrs.hl7.handler.ORUR01Handler.processMessage(ORUR01Handler.java:132)\n"
688+
+ "Caused by: ca.uhn.hl7v2.HL7Exception: Could not resolve patient by identifier\n"
689+
+ "\tat org.openmrs.hl7.handler.ORUR01Handler.getPatientByIdentifier(ORUR01Handler.java:998)";
690+
691+
String expected = "Error (HL7): ca.uhn.hl7v2.HL7Exception: Error while processing HL7 message: ORU_R01\n"
692+
+ "Caused by: ca.uhn.hl7v2.app.ApplicationException: ca.uhn.hl7v2.HL7Exception: Could not resolve patient by identifier";
693+
694+
assertEquals(expected, OpenmrsUtil.formattedStackTrace(test), "stack trace was not formatted properly");
695+
}
696+
697+
/**
698+
* @see OpenmrsUtil#formattedStackTrace(String)
699+
*/
700+
@Test
701+
public void formattedStackTrace_shouldReturnTheUnFormattedStackTraceIfInDevMode() {
702+
Properties props = Context.getRuntimeProperties();
703+
props.setProperty(OpenmrsConstants.DEVELOPMENT_MODE_RUNTIME_PROPERTY, "true");
704+
Context.setRuntimeProperties(props);
705+
706+
String test = "ca.uhn.hl7v2.HL7Exception: Error while processing HL7 message: ORU_R01\n"
707+
+ "\tat org.openmrs.hl7.impl.HL7ServiceImpl.processHL7Message(HL7ServiceImpl.java:752)\n"
708+
+ "Caused by: ca.uhn.hl7v2.app.ApplicationException: ca.uhn.hl7v2.HL7Exception: Could not resolve patient by identifier\n"
709+
+ "\tat org.openmrs.hl7.handler.ORUR01Handler.processMessage(ORUR01Handler.java:132)\n"
710+
+ "Caused by: ca.uhn.hl7v2.HL7Exception: Could not resolve patient by identifier\n"
711+
+ "\tat org.openmrs.hl7.handler.ORUR01Handler.getPatientByIdentifier(ORUR01Handler.java:998)";
712+
713+
String expected = "ca.uhn.hl7v2.HL7Exception: Error while processing HL7 message: ORU_R01\n"
714+
+ "\tat org.openmrs.hl7.impl.HL7ServiceImpl.processHL7Message(HL7ServiceImpl.java:752)\n"
715+
+ "Caused by: ca.uhn.hl7v2.app.ApplicationException: ca.uhn.hl7v2.HL7Exception: Could not resolve patient by identifier\n"
716+
+ "\tat org.openmrs.hl7.handler.ORUR01Handler.processMessage(ORUR01Handler.java:132)\n"
717+
+ "Caused by: ca.uhn.hl7v2.HL7Exception: Could not resolve patient by identifier\n"
718+
+ "\tat org.openmrs.hl7.handler.ORUR01Handler.getPatientByIdentifier(ORUR01Handler.java:998)";
719+
720+
assertEquals(expected, OpenmrsUtil.formattedStackTrace(test), "stack trace was not returned properly");
721+
}
722+
675723
/**
676724
* @see OpenmrsUtil#shortenedStackTrace(String)
677725
*/

web/src/main/java/org/openmrs/web/filter/initialization/InitializationFilter.java

+2
Original file line numberDiff line numberDiff line change
@@ -1533,6 +1533,8 @@ public void run() {
15331533
new String(base64.encode(Security.generateNewInitVector()), StandardCharsets.UTF_8));
15341534
runtimeProperties.put(OpenmrsConstants.ENCRYPTION_KEY_RUNTIME_PROPERTY,
15351535
new String(base64.encode(Security.generateNewSecretKey()), StandardCharsets.UTF_8));
1536+
runtimeProperties.put(OpenmrsConstants.DEVELOPMENT_MODE_RUNTIME_PROPERTY,
1537+
OpenmrsConstants.DEVELOPMENT_MODE_DEFAULT);
15361538

15371539
Properties properties = Context.getRuntimeProperties();
15381540
properties.putAll(runtimeProperties);

0 commit comments

Comments
 (0)