A JSR223 PreProcessor prepares data immediately before a JMeter sampler runs. It is useful when a request needs a value calculated at sample time, such as a signed payload, derived request body, timestamp, or variable that should be rebuilt for each virtual user iteration.
The preprocessor belongs under the sampler that needs the prepared value. JMeter runs it before taking that sample, and Groovy scripts can read and write JMeter variables through objects such as vars, props, ctx, and sampler.
A validation copy keeps script behavior visible before the logic moves into a larger load scenario. Cached Groovy scripts should call vars.get('name') and vars.put('name', value) instead of embedding direct ${name} replacements in the script text, because direct replacement can freeze the first substituted value in compiled script code.
Steps to add a JMeter JSR223 PreProcessor:
- Open a validation copy of the .jmx test plan in the JMeter GUI.
- Select the sampler that needs prepared request data.
- Add the preprocessor from Add → Pre Processors → JSR223 PreProcessor.
- Name the preprocessor for the value it prepares.
Name: Prepare order payload
- Set Language to groovy.
- Enable Cache compiled script if available for the inline Groovy script.
Use a script file or a unique script compilation cache key when the same script is reused in several places.
- Enter the Groovy script that prepares the sampler variable.
def orderId = vars.get('order_id') def payload = groovy.json.JsonOutput.toJson([orderId: orderId, status: 'ready']) vars.put('prepared_order_id', orderId) vars.put('prepared_payload', payload) log.info("Prepared payload for ${orderId}")
vars reads and writes variables for the current JMeter thread. Remove or reduce log.info calls after validation when the preprocessor runs for many users or loops.
- Use the prepared variable in the target sampler body or parameter.
Body Data: ${prepared_payload} - Save the validation copy of the test plan.
jsr223-preprocessor-demo.jmx
- Run a one-user non-GUI smoke test.
$ jmeter -n -t jsr223-preprocessor-demo.jmx -l jsr223-preprocessor-results.jtl -j jmeter.log Creating summariser <summary> Created the tree successfully using jsr223-preprocessor-demo.jmx Starting standalone test @ 2026 Jun 30 01:47:57 GMT Waiting for possible Shutdown/StopTestNow/HeapDump/ThreadDump message on port 4445 summary = 1 in 00:00:00 = 2.4/s Avg: 40 Min: 40 Max: 40 Err: 0 (0.00%) Tidying up ... ... end of run
- Check the result file for a successful sampler row.
$ cat jsr223-preprocessor-results.jtl timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect 1782784078215,40,POST prepared order,200,OK,Prepared request user 1-1,text,true,,48,0,1,1,null,0,0,0
- Check the prepared value that the sampler used.
$ cat jsr223-preprocessor.log prepared_order_id=A100 request_payload={"orderId":"A100","status":"ready"}In a GUI debug run, a Debug Sampler or View Results Tree request view can show the same variable or request body.
Related: How to add a Debug Sampler in JMeter - Remove validation-only debug output before increasing users, loops, or duration.
Per-sample log writes from a preprocessor can make jmeter.log grow quickly during a load test.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.