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:

  1. Open a validation copy of the .jmx test plan in the JMeter GUI.
  2. Select the sampler that needs prepared request data.
  3. Add the preprocessor from AddPre ProcessorsJSR223 PreProcessor.
  4. Name the preprocessor for the value it prepares.
    Name: Prepare order payload
  5. Set Language to groovy.
  6. 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.

  7. 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.

  8. Use the prepared variable in the target sampler body or parameter.
    Body Data:
    ${prepared_payload}
  9. Save the validation copy of the test plan.
    jsr223-preprocessor-demo.jmx
  10. 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
  11. 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
  12. 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

  13. 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.