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.
Name: Prepare order payload
Use a script file or a unique script compilation cache key when the same script is reused in several places.
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.
Body Data:
${prepared_payload}
jsr223-preprocessor-demo.jmx
$ 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
$ 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
$ 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
Per-sample log writes from a preprocessor can make jmeter.log grow quickly during a load test.