JMeter Groovy Scripting: Beyond the GUI
How to use JSR223 Groovy scripting in JMeter for custom logic that the built-in components can't express, with practical examples.
JMeter’s GUI components cover most common needs, but custom logic — complex data transformation, conditional behavior beyond what an If Controller expresses cleanly, or integrating with an external system — eventually needs real code. The JSR223 Sampler/PreProcessor/PostProcessor elements, scripted in Groovy, are the standard way to do this.
Why Groovy over BeanShell or the legacy Java element
JMeter historically supported BeanShell for scripting; JSR223 with Groovy is faster (Groovy scripts can be compiled and cached, unlike interpreted BeanShell) and is the currently recommended approach for any new custom scripting. Avoid BeanShell for new scripts unless you have a specific compatibility reason.
Where JSR223 elements fit
- JSR223 PreProcessor — runs before a sampler executes; useful for computing a value the sampler needs (a signed request hash, a dynamically constructed payload).
- JSR223 PostProcessor — runs after a sampler’s response arrives; useful for custom extraction logic beyond what the built-in extractors support, or for custom validation logic.
- JSR223 Sampler — a standalone sampler running arbitrary Groovy, useful for steps that aren’t really HTTP requests at all (computing a value, calling a local library, talking to a system JMeter has no native sampler for).
A practical example: HMAC-signed requests
Some APIs require a request signature computed from the request body and a secret key. A JSR223 PreProcessor can compute this signature in a few lines of Groovy and store it as a JMeter variable for the HTTP sampler to include as a header — something no built-in component handles directly:
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
def secret = vars.get("apiSecret")
def payload = vars.get("requestBody")
def mac = Mac.getInstance("HmacSHA256")
mac.init(new SecretKeySpec(secret.bytes, "HmacSHA256"))
def signature = mac.doFinal(payload.bytes).encodeHex().toString()
vars.put("requestSignature", signature)
Accessing JMeter context from Groovy
Inside a JSR223 element, vars (JMeter variables), props (JMeter properties), log (JMeter’s logger), and prev (the previous sample result, in PostProcessors) are all available without extra imports — covering most of what scripts need to read/write test state or inspect the last response.
Performance consideration
JSR223 with Groovy, using “compiled” mode (cache the compiled script rather than re-parsing it every iteration — the default behavior when a script is provided directly rather than via an external file reference that changes), is fast enough for most uses. Very hot-path scripts running on every single sample, at very high iteration counts, are worth benchmarking standalone if they involve anything non-trivial (cryptography, large string processing) since they do add real CPU cost to the load generator itself.
When not to reach for Groovy
If a built-in component (Extractor, Assertion, Controller) already does what you need, prefer it — it’s more maintainable for the next person reading the test plan, and avoids accumulating scattered custom code across a script that’s otherwise GUI-configured.
Takeaway: JSR223 Groovy is the escape hatch for the genuinely custom 10% of logic a load test sometimes needs — reach for it specifically when a built-in component can’t express what you need, not as a default scripting style.
Comments are powered by Giscus (GitHub Discussions). Enable them by
configuring GISCUS in src/consts.ts — see
giscus.app.