In JMeter's Java Request sampler, which interface must your class implement and when is each method called?
answer
- One interface, four methods
- Abstract base class saves writing three of them
- Setup happens later than most people think
- One method may never be called
basics
~10 sThe class must implement org.apache.jmeter.protocol.java.sampler.JavaSamplerClient. JMeter calls setupTest once before the first sample, runTest for every sample, teardownTest at the end, and getDefaultParameters to populate the sampler's argument table.
solid answer
~40 sThe Java Request sampler drives any class implementing `org.apache.jmeter.protocol.java.sampler.JavaSamplerClient`, and in practice you extend `AbstractJavaSamplerClient` rather than implementing the interface bare. Four methods make up the contract: `getDefaultParameters()` returns an `Arguments` object that seeds the sampler's parameter table in the GUI; `setupTest(JavaSamplerContext)` runs once, lazily, before that sampler instance takes its first sample; `runTest(JavaSamplerContext)` runs for every sample and must return a `SampleResult` you have timed with `sampleStart()`/`sampleEnd()` and marked with `setSuccessful()`; `teardownTest(JavaSamplerContext)` runs at the end. All parameters arrive as Strings. The Classname drop-down lists implementations JMeter found, and the shipped `JavaTest` and `SleepTest` examples are useful for shaking out a plan.
code
java · 49 linespackage com.example.jmeter.clients;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
public class PricingClient extends AbstractJavaSamplerClient {
private PricingSdk sdk;
@Override
public Arguments getDefaultParameters() {
Arguments args = new Arguments();
args.addArgument("endpoint", "https://pricing.internal/v2");
args.addArgument("sku", "${sku}");
return args;
}
@Override
public void setupTest(JavaSamplerContext context) {
sdk = PricingSdk.connect(context.getParameter("endpoint"));
}
@Override
public SampleResult runTest(JavaSamplerContext context) {
SampleResult result = new SampleResult();
result.setSampleLabel("quote");
result.sampleStart();
try {
String body = sdk.quote(context.getParameter("sku"));
result.setResponseData(body, "UTF-8");
result.setResponseCodeOK();
result.setSuccessful(true);
} catch (Exception e) {
result.setResponseCode("500");
result.setResponseMessage(e.toString());
result.setSuccessful(false);
} finally {
result.sampleEnd();
}
return result;
}
@Override
public void teardownTest(JavaSamplerContext context) {
sdk.close();
}
}go deeper
Recall the interface name and its four methods, and that you normally extend AbstractJavaSamplerClient rather than implementing JavaSamplerClient directly.
Explain the lifecycle: getDefaultParameters in the GUI, setupTest lazily before the first sample of a thread's instance, runTest per sample, teardownTest only when you override it.
Show what a correct runTest looks like under load - timing the right window, failing loudly, and keeping per-thread state out of shared fields.
Weigh the compiled hook against scripting for the team: a Java Request needs a build and a deployment for every change, which buys speed and reuse but adds a release cycle to test authoring.
The Java Request sampler is Apache JMeter's built-in escape hatch to compiled code: the way to make JMeter drive a client library, a proprietary protocol or an internal SDK without writing a full plugin with GUI classes, and without leaving the plan's timing, assertions and listeners behind. ## The contract Your class implements `org.apache.jmeter.protocol.java.sampler.JavaSamplerClient`, which declares exactly four methods: - **`Arguments getDefaultParameters()`** - the parameter names and default values the sampler's argument table is pre-filled with when someone picks your class in the GUI. It is documentation as much as configuration. - **`void setupTest(JavaSamplerContext context)`** - one-time preparation: build the client, open the connection pool, read a keystore. - **`SampleResult runTest(JavaSamplerContext context)`** - one sample. Everything a listener will show comes out of the `SampleResult` you return. - **`void teardownTest(JavaSamplerContext context)`** - one-time cleanup. Almost nobody implements the interface directly. `AbstractJavaSamplerClient` supplies no-op implementations plus a logger, so a real client overrides only what it needs. ## When each method actually runs This is the part candidates get wrong. `setupTest` is **not** called when the test starts; the sampler creates its client lazily and calls `setupTest` immediately before the first `runTest` on that instance. JMeter clones the test tree per thread, so each thread gets its own client object and its own `setupTest` call. `teardownTest` has a subtlety worth knowing: if a subclass of `AbstractJavaSamplerClient` does not override `teardownTest`, JMeter does not register the sampler for teardown at all and the inherited method is never called. The manual states this explicitly and gives the reason - it reduces JMeter's memory requirements. If you need cleanup, you must override the method; inheriting it is not enough. ## Writing runTest 1. Read what you need from the `JavaSamplerContext` - `getParameter(name)` and friends. Every argument arrives as a `String`, so parse and validate there. 2. Call `sampleStart()` on the `SampleResult`, do the work, call `sampleEnd()`. Anything outside that window is not measured. 3. Set `setSuccessful(true|false)`, a response code and a response message, and a sample label if you want something other than the element's name. 4. Never let an exception escape unrecorded - catch it, mark the result failed, and put the message in the response data so a listener can show it. A `runTest` that returns a result it never timed produces samples of zero elapsed time, which is a silent way to make a load test meaningless. ## How JMeter finds your class The Classname drop-down is populated by JMeter's combined lookup: implementations registered as Java services are loaded first, and then the jars on JMeter's component search path - `lib/ext` plus anything `search_paths` adds - are scanned for classes implementing `JavaSamplerClient`. Two examples ship with JMeter and always appear: `JavaTest`, useful because it lets you set values in almost every field of the result so assertions and extractors can be exercised, and `SleepTest`. If your class is missing from the list, the jar is in the wrong directory or the class is not public with a no-argument constructor; if it is in the list but errors, JMeter's log points at the `search_paths` and `plugin_dependency_paths` properties, which is usually a missing dependency rather than a missing plugin. ## Where it fits against the alternatives A Java Request is the right hook when the code is genuinely compiled and reusable: a protocol client, a signing routine that needs a real library, a workload driver you already own in Java. It costs a build and a deployment step for every change, which is its main disadvantage against JMeter's scripting elements. The JUnit Request sampler is the neighbouring hook and works differently: it scans for classes extending JUnit's `TestCase` rather than for a JMeter interface, takes no name/value parameters, and looks in `lib/junit`. Choose Java Request when you want parameters and a `SampleResult` you control; choose JUnit Request when you already have JUnit classes and want to drive them as-is.
- Why might teardownTest never run even though your class inherits it?JMeter checks whether `teardownTest` is declared by a class other than `AbstractJavaSamplerClient`. If the method comes straight from the abstract base, the sampler is not registered for teardown and the inherited no-op is never invoked. Override the method in your own class if you need the cleanup to happen.
- How does JMeter populate the Java Request Classname drop-down?It combines implementations registered as Java services with a scan of the component search path - `JMETER_HOME/lib/ext` plus any directories `search_paths` names - for classes implementing `JavaSamplerClient`. The shipped `JavaTest` and `SleepTest` examples always show up, which makes them a quick check that the lookup itself is working.
saying these in an interview costs you the question
- Thinks setupTest runs once for the whole test plan
- Returns a SampleResult without calling sampleStart and sampleEnd
- Assumes an inherited teardownTest is always called
- Expects typed parameters instead of Strings
- Lets exceptions escape runTest instead of marking the result failed