skip to content

Which JMeter element types come in a JSR223 variant?

level: juniorimportance: must knowfreq 70%

answer

  1. Same base class, different plan slots
  2. Count the slots a script can fill
  3. One is a sampler, one a timer
  4. Six variants in JMeter 6.0.0

basics

~20 s

Apache JMeter 6.0.0 ships six: JSR223 Sampler, JSR223 PreProcessor, JSR223 PostProcessor, JSR223 Assertion, JSR223 Timer and JSR223 Listener. All six extend one base class, so they share the same configuration fields and one process-wide compiled-script cache; each invocation still gets a fresh ScriptEngine from JMeter's single ScriptEngineManager.

solid answer

~40 s

JMeter exposes one JSR-223 scripting engine through six separate elements, each occupying a different slot in a test plan: **JSR223 Sampler**, **JSR223 PreProcessor**, **JSR223 PostProcessor**, **JSR223 Assertion**, **JSR223 Timer** and **JSR223 Listener**. All six extend the same `JSR223TestElement` base class, so the GUI is identical: `Language`, `Parameters`, a `Script File` field whose group is labelled *Script file (overrides script)*, the `Cache compiled script if available` checkbox, and the inline `Script` area. Leave `Language` blank and you get Groovy, the bundled default engine. What differs between the six is the slot each fills and what JMeter does with the value the script returns — the Timer parses it as a delay in milliseconds and the Sampler turns it into response data, while the PreProcessor, PostProcessor and Listener discard it.

go deeper

for a junior

Be able to name the JSR223 variants and say that the Language field falls back to Groovy. Knowing that a sampler produces its own result row while a pre-processor does not is enough here.

for a middle

Explain that all six extend one base class and share the same fields, and that only the Sampler and the Timer do anything with the value a script returns.

for a senior

Show that you choose the variant by the slot you need, and know where a script error becomes visible in the results and where it only reaches jmeter.log.

for a principal

Own the convention: which variants a team may use at all, what is allowed to live in a script, and how a script failure is made visible instead of being left in a log file nobody reads.

## One engine, six sockets Apache JMeter 6.0.0 bundles Groovy as its default JSR-223 engine and offers it through six test elements. Every one of them extends `org.apache.jmeter.util.JSR223TestElement`, which is why the configuration surface is identical in all six: - **Language** — the short name of a `ScriptEngine` on the classpath. The drop-down is built at startup from the engine factories JMeter can see, so it is not a fixed list; the manual notes that a language can be usable without appearing there if its jar is dropped into `lib/`. - **Parameters** — free text handed to the script. - **Script File** — a path. The GUI group is labelled *Script file (overrides script)* and that is literal: a non-empty path makes JMeter ignore the inline `Script` area entirely. A relative path resolves against the `user.dir` system property. - **Cache compiled script if available** — the compilation-cache switch. - **Script** — the inline source. Leave **Language** blank and the base class falls back to the string `groovy`. Name an engine JMeter cannot resolve and the element throws `Cannot find engine named: '<name>'`. ## What each variant is for | Element | Slot it fills | What JMeter does with the return value | |---|---|---| | JSR223 Sampler | a sampler, producing its own `SampleResult` | becomes the response data, unless the script already set one | | JSR223 PreProcessor | a pre-processor | discarded | | JSR223 PostProcessor | a post-processor | discarded | | JSR223 Assertion | an assertion, handed an `AssertionResult` to mark | discarded — you mark the `AssertionResult` instead | | JSR223 Timer | a timer | parsed with `Long.parseLong` and used as a delay in milliseconds | | JSR223 Listener | a sample listener | discarded | The Timer shows most sharply why the variants are not interchangeable. `JSR223Timer.delay()` calls `Long.parseLong` on the returned object's `toString()`; a `null` return logs *Script did not return a value* and yields `0`, and a non-numeric return raises a `NumberFormatException` that is logged and also yields `0`. The Sampler is the only variant that manufactures a result of its own. It labels the result with the element name, records the script text (or `File: <path>`) as the sampler data, and copies the script's return value into the response data if the script has not already set one. ## Where a script error surfaces The six do not agree on this, and the difference matters when you are reading a run afterwards: 1. **JSR223 Sampler** — a `ScriptException` or `IOException` is caught, the result is marked unsuccessful, the response code is set to `500` and the response message is the exception's text. 2. **JSR223 Assertion** — the `AssertionResult` is flagged as an error and carries the exception text as its failure message. 3. **JSR223 PreProcessor, PostProcessor and Listener** — the exception is only logged, as `Problem in JSR223 element named: '<name>'`, and the thread carries on. 4. **JSR223 Timer** — problems are logged and the delay collapses to zero. So a broken script inside a Sampler is loud, and the same broken script inside a PreProcessor is quiet. ## What one looks like in the plan file All six serialise to the same five properties; only the element name changes: ```xml <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="Sign request" enabled="true"> <stringProp name="cacheKey">true</stringProp> <stringProp name="filename"></stringProp> <stringProp name="parameters"></stringProp> <stringProp name="script">vars.put("nonce", UUID.randomUUID().toString())</stringProp> <stringProp name="scriptLanguage">groovy</stringProp> </JSR223PreProcessor> ``` ## Picking the right one Reach for the variant whose slot you actually need rather than defaulting to the Sampler. A signature that must exist before a request goes out belongs in a JSR223 PreProcessor attached to that request; a value that must be pulled out of a reply belongs in a JSR223 PostProcessor; a computed pause belongs in a JSR223 Timer, which is the only variant whose return value becomes a delay. Using a JSR223 Sampler for work that is not itself a request adds a result row you then have to explain, unless the script calls `SampleResult.setIgnore()` to keep it out of listeners and later processing.

  • In JMeter, what happens if a JSR223 element has both a Script File path and inline Script text?
    The file wins. `processFileOrScript` tests the file name first, and the GUI group is labelled *Script file (overrides script)*. The inline text is never evaluated. If the path is not an existing readable file the element throws a `ScriptException` naming the absolute path rather than quietly falling back to the inline script.
  • What does a JMeter JSR223 Timer do when its script returns something that is not a number?
    `JSR223Timer.delay()` calls `Long.parseLong` on the returned object's `toString()`. A `null` return logs *Script did not return a value* and produces a zero delay; a non-numeric value raises a `NumberFormatException` that is logged and also produces zero. Either way the thread does not pause and the run continues.

saying these in an interview costs you the question

  • Says JSR223 exists only as a sampler
  • Thinks each variant has its own scripting subsystem or its own set of configuration fields
  • Expects a PreProcessor's return value to be used
  • Assumes Script File is only a fallback for the inline script
  • Believes the Language field must always be filled in