fix: log errors happening while JMeter starts the test
Previously, the exceptions from TestStateListener.testStarted might
be unnoticed since the UI did not display them.
This change is a workaround to surface errors in common cases.
See https://github.com/apache/jmeter/issues/6174
diff --git a/src/components/src/main/java/org/apache/jmeter/timers/ConstantTimer.java b/src/components/src/main/java/org/apache/jmeter/timers/ConstantTimer.java
index 8d9790d..1b8b771 100644
--- a/src/components/src/main/java/org/apache/jmeter/timers/ConstantTimer.java
+++ b/src/components/src/main/java/org/apache/jmeter/timers/ConstantTimer.java
@@ -19,8 +19,6 @@
import java.io.Serializable;
-import org.apache.jmeter.engine.event.LoopIterationEvent;
-import org.apache.jmeter.engine.event.LoopIterationListener;
import org.apache.jmeter.testelement.AbstractTestElement;
import org.apache.jmeter.util.JMeterUtils;
diff --git a/src/core/src/main/java/org/apache/jmeter/engine/StandardJMeterEngine.java b/src/core/src/main/java/org/apache/jmeter/engine/StandardJMeterEngine.java
index 2aea222..a72602f 100644
--- a/src/core/src/main/java/org/apache/jmeter/engine/StandardJMeterEngine.java
+++ b/src/core/src/main/java/org/apache/jmeter/engine/StandardJMeterEngine.java
@@ -239,13 +239,21 @@
private void notifyTestListenersOfStart(SearchByClass<? extends TestStateListener> testListeners) {
for (TestStateListener tl : testListeners.getSearchResults()) {
- if (tl instanceof TestBean) {
- TestBeanHelper.prepare((TestElement) tl);
- }
- if (host == null) {
- tl.testStarted();
- } else {
- tl.testStarted(host);
+ try {
+ if (tl instanceof TestBean) {
+ TestBeanHelper.prepare((TestElement) tl);
+ }
+ if (host == null) {
+ tl.testStarted();
+ } else {
+ tl.testStarted(host);
+ }
+ } catch (Throwable e) {
+ // TODO: we should not be logging the exceptions multiple times, however, currently GUI does not
+ // monitor if the running test fails, so we log the exception for the users to see in the logs
+ log.error("Unable to execute testStarted({}) for test element {}", host, tl, e);
+ throw new IllegalStateException(
+ "Unable to execute testStarted(" + host + ") for test element " + tl, e);
}
}
}
diff --git a/src/core/src/main/java/org/apache/jmeter/testbeans/TestBeanHelper.java b/src/core/src/main/java/org/apache/jmeter/testbeans/TestBeanHelper.java
index 3c81ccc..1be2833 100644
--- a/src/core/src/main/java/org/apache/jmeter/testbeans/TestBeanHelper.java
+++ b/src/core/src/main/java/org/apache/jmeter/testbeans/TestBeanHelper.java
@@ -134,9 +134,25 @@
try {
for (CachedPropertyDescriptor desc : GOOD_PROPS.get(el.getClass())) {
// Obtain a value of the appropriate type for this property.
- JMeterProperty jprop = el.getProperty(desc.descriptor.getName());
Class<?> type = desc.propertyType;
- Object value = unwrapProperty(desc.descriptor, jprop, type);
+
+ JMeterProperty jprop;
+ Object value;
+ try {
+ jprop = el.getProperty(desc.descriptor.getName());
+ value = unwrapProperty(desc.descriptor, jprop, type);
+ } catch (OutOfMemoryError | StackOverflowError e) {
+ throw e;
+ } catch (Throwable e) {
+ String elementName;
+ try {
+ elementName = el.getName();
+ } catch(Throwable ignore) {
+ elementName = el.getClass().getName();
+ }
+ throw new IllegalStateException(
+ "Can't retrieve property '" + desc.descriptor.getName() + "' of element " + elementName, e);
+ }
if (log.isDebugEnabled()) {
log.debug("Setting {}={}", jprop.getName(), value);
diff --git a/src/functions/src/main/java/org/apache/jmeter/functions/TimeFunction.java b/src/functions/src/main/java/org/apache/jmeter/functions/TimeFunction.java
index f704985..95abd79 100644
--- a/src/functions/src/main/java/org/apache/jmeter/functions/TimeFunction.java
+++ b/src/functions/src/main/java/org/apache/jmeter/functions/TimeFunction.java
@@ -71,9 +71,14 @@
long div = Long.parseLong(fmt.substring(1)); // should never case NFE
return () -> Long.toString(System.currentTimeMillis() / div);
}
- DateTimeFormatter df = DateTimeFormatter
- .ofPattern(fmt)
- .withZone(ZoneId.systemDefault());
+ DateTimeFormatter df;
+ try {
+ df = DateTimeFormatter
+ .ofPattern(fmt)
+ .withZone(ZoneId.systemDefault());
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Unable to parse date format " + fmt, e);
+ }
if (isPossibleUsageOfUInFormat(df, fmt)) {
log.warn(
MessageFormat.format(