skip to content

Session Values

Where every value a virtual user sends or checks actually comes from: records fed in from a file or a database, and values pulled back out of a response into that user's Session.

on this pageshow

explore

questions

23

In Gatling, what are the six ordered steps of a check, and which of them does Gatling supply for you when you leave them out?

level: juniorimportance: must knowfreq 68%

answer

  1. A check is an ordered chain
  2. Six steps, two have defaults
  3. Implicit find, implicit exists
  4. find() means find(0), zero-based
  5. saveAs and name are never implied

basics

~20 s

A Gatling check is an ordered chain of six steps: pick a check type, extract an occurrence, transform it, validate it, name it, save it. Only two are supplied when omitted: an implicit find() and an implicit exists().

solid answer

~40 s

Gatling reads a check as six chained steps: the **check type** (`jsonPath`, `regex`, `status` …), the **extraction** (`find`, `find(n)`, `findAll`, `count`), an optional **transform**, the **validation** (`is`, `not`, `exists`, `in` …), an optional **name**, and an optional **saveAs**. Two of those have defaults. If you write no extraction step, Gatling inserts `find()`, which is identical to `find(0)` — the first occurrence. If you write no validation step, Gatling inserts `exists()`. So `jsonPath("$.orderId")` alone already means “the first `$.orderId` must be present, or the request is KO”. Transform, `name(...)` and `saveAs(...)` have **no** default: leave `saveAs` off and nothing reaches the Session, even though the check still passes or fails.

code

java · 19 lines
java
import io.gatling.javaapi.core.*;
import io.gatling.javaapi.http.*;
import static io.gatling.javaapi.core.CoreDsl.*;
import static io.gatling.javaapi.http.HttpDsl.*;

public class CheckStepsSimulation extends Simulation {

  ScenarioBuilder scn = scenario("Checkout")
    .exec(http("Place order")
      .post("/orders")
      .check(status().is(201))
      // these two lines declare exactly the same check
      .check(jsonPath("$.orderId"))
      .check(jsonPath("$.orderId").find(0).exists()));

  {
    setUp(scn.injectOpen(atOnceUsers(1)));
  }
}

go deeper

for a junior

Be ready to list the six steps in order and to say which two Gatling inserts for you: find() and exists().

for a middle

Explain that the chain is a Find to Validate to Final type ladder of immutable builders, and that find() resolves to find(0).

for a senior

Show how an auto-generated failure message such as jsonPath($.orderId).find.exists reveals the steps that were never written.

for a principal

Own the convention for when a capture-only check should carry optional() rather than inherit the implicit exists().

A Gatling **check** looks like one method call but is really an ordered chain. Gatling's own reference lists the six steps in this order: defining the check type, extracting, transforming, validating, naming, saving. Reading a check left to right is reading that chain, and most surprises come from the two steps Gatling silently inserts when you skip them. ## The six steps 1. **Check type** — what part of the exchange you are looking at. Generic types such as `responseTimeInMillis`, `bodyString`, `bodyBytes`, `bodyLength`, `bodyStream`, `substring`, `regex`, `css`, `xpath`, `jsonPath` and `jmesPath` are statics on **`CoreDsl`**. HTTP adds its own on **`HttpDsl`**: `status`, `header`, `headerRegex`, `currentLocation`. Importing the wrong one is the most common compile failure here. 2. **Extraction** — which occurrence you want: `find()`, `find(n)`, `findAll()`, `findRandom()`, `count()`. 3. **Transformation** — optional: `transform`, `transformWithSession`, `withDefault`, `transformOption`. 4. **Validation** — the condition: `is`, `not`, `isNull`, `notNull`, `exists`, `notExists`, `in`, `optional`, `validate`. 5. **Naming** — optional `name(...)`, a **static String only**, used in the failure message. 6. **Saving** — optional `saveAs(key)`, also a **static String only**, which writes the value into the virtual user's Session. ## What Gatling fills in | step | left out means | |---|---| | extraction | Gatling inserts `find()`, which is **identical to `find(0)`** — the first or only occurrence | | validation | Gatling inserts `exists()` — fails the check if nothing was captured | | transform | nothing happens; there is no default transform | | name | the failure message is auto-generated from the extractor and validator | | saveAs | **nothing is written to the Session**, even on a passing check | So `substring("expected")` is exactly `substring("expected").find().exists()`, and `jsonPath("$.foo")`, `jsonPath("$.foo").find()` and `jsonPath("$.foo").find(0)` are three spellings of one check. `find(n)` is a **zero-based** rank, so `find(1)` is the second occurrence. ## The mechanism differs by SDK, the behaviour does not * In the **Java API** — which Kotlin and the JavaScript/TypeScript SDK also sit on — the default implementations delegate. `Find.Default.saveAs(key)` calls `find().saveAs(key)`, and `Validate.Default.saveAs(key)` calls `exists().saveAs(key)`. The skipped steps are inserted by the class hierarchy itself. * In **Scala**, three implicit conversions in `io.gatling.core.check.CheckSupport` do the same job: one turns a `Find` into a `Validate` by calling `.find`, one turns a `Validate` into a `Final` by calling `.exists`, and one does both. They arrive with `import io.gatling.core.Predef._`; without that import a Scala check that omits a step will not compile. Either way the ladder is `Find` -> `Validate` -> `Final`, and each rung returns a **new immutable builder**. ## Reading the defaults back out of a failure When a check fails and you have not called `name(...)`, Gatling builds the name as `extractorName.arity.validatorName`. A `jsonPath("$.orderId")` that matched nothing therefore fails with a message beginning `jsonPath($.orderId).find.exists` — the error message literally spells out the two steps you did not write. `arity` renders as `find`, `find(2)`, `findAll`, `count` or `findRandom` depending on the extraction step, so the message also tells you which occurrence was searched. ## The two omissions that bite * **`saveAs` is not implied by extracting.** A check that extracts, passes validation and never calls `saveAs` leaves the Session untouched. Capturing a value and asserting on a value are the same chain, separated only by that last call. Both `saveAs(key)` and `name(n)` take a **static String only**, so neither can be computed per virtual user. * **`exists` is implied.** Writing `jsonPath("$.token")` purely to capture a token also asserts it is present, so a response without it marks the request KO. If you want a genuinely optional capture, say so with `optional()` — it never fails, and when nothing matched, the later steps including `saveAs` do not fire, so an existing Session value is neither overwritten nor removed. `withDefault(value)` is the other escape, supplying a fallback so the remaining steps still run. ## The order the steps run in is not the order you wrote the checks in The six steps run in order **within one check**, but the checks on a single response are another matter. Gatling walks the whole list even after one of them fails, reports only the **first** failure, and still applies the `saveAs` of every check that passed — so a KO request can legitimately have written Session attributes. For HTTP it also sorts the checks by scope before running them: URL, then status, then header, then body, then time, regardless of the order they appear in your source. That is why a 500 carrying a JSON error payload reports the status failure rather than the body failure. One more consequence of the same machinery: when more than one check is attached to a response, Gatling allocates a **prepared cache** — but it is keyed by the check's `Preparer` **object**, so only checks handed the same preparer share the work. `regex`, `substring` and `bodyString` sit on one shared string preparer, and every `xpath` check on one shared DOM parse, so those are prepared once. It does **not** help `jsonPath`, `jmesPath` or `css`: their materializers are built per check and allocate a fresh preparer, so two `jsonPath` checks on one response parse the JSON body **twice**. ## Where the check types come from Getting the imports right is part of getting the first step right. In Java the preamble is four lines, two per DSL family, because the package wildcard supplies the **types** and no static import can: ```java import io.gatling.javaapi.core.*; import static io.gatling.javaapi.core.CoreDsl.*; import io.gatling.javaapi.http.*; import static io.gatling.javaapi.http.HttpDsl.*; ``` Kotlin writes the same four without the `static` keyword, which it does not have. Scala replaces all four with `import io.gatling.core.Predef._` and `import io.gatling.http.Predef._` — and those are also what bring the implicit conversions above into scope.

  • Does an extraction step on its own put the captured value into the Session?
    No. Saving is a separate, optional step. A check that extracts and validates but never calls `saveAs(key)` leaves the Session untouched — it only decides whether the request is OK or KO. `saveAs` also takes a static String key, so the name cannot be computed at runtime.
  • What is the difference between leaving the validation step off and writing `optional()`?
    Leaving it off inserts `exists()`, so a missing value fails the check and marks the request KO. `optional()` always succeeds; when nothing matched, the remaining steps do not run, so `saveAs` writes nothing and any value already under that key is neither replaced nor removed.
  • Is `find(1)` the first or the second occurrence?
    The second. `find(n)` takes a zero-based rank, so `find(0)` is the first and is what the parameterless `find()` — and therefore an omitted extraction step — resolves to.

It reads like a sentence with two words you may leave unsaid: skip them and Gatling still hears "the first one" and "it must be there".

saying these in an interview costs you the question

  • Thinking extracting a value also stores it in the Session without saveAs
  • Believing an omitted validation step means the check can never fail
  • Treating find(n) as a one-based occurrence rank
  • Assuming transform still runs when the extraction captured nothing
open as a page

In a Gatling simulation, which placeholder syntax reads a value back out of the Session, and what does a request URL still written with `${}` actually send?

level: juniorimportance: must knowfreq 74%

basics

~10 s

Gatling interpolates only the #{attributeName} placeholder. The older ${...} form was removed in Gatling 3.11.0 and is no longer interpreted, so a URL containing it is sent to the server as literal characters.

open as a page

In a Gatling simulation, which built-in feeders read a character-separated file, and where must the file sit for csv("credentials.csv") to resolve?

level: juniorimportance: must knowfreq 70%

basics

~10 s

Gatling ships csv, tsv, ssv and separatedValues for delimited files, plus jsonFile, jsonUrl and sitemap. The path is resolved from your classpath root: src/main/resources or src/test/resources on the JVM, resources in the JavaScript SDK.

open as a page

In Gatling, which four record-consumption strategies can you set on a feeder, and which one applies if you set none?

level: juniorimportance: must knowfreq 68%

basics

~20 s

Gatling feeders take exactly four strategies: queue, random, shuffle and circular. Queue is the default. Queue and shuffle hand out each record once and stop the run when the stock empties; random and circular reuse records and never run out.

open as a page

In a Gatling simulation, how do you capture an order id from a JSON response body and send it on the next request, and what happens to both requests if the id is missing?

level: middleimportance: must knowfreq 74%

basics

~20 s

Attach a check to the first request: jsonPath("$.orderId").saveAs("orderId"), then read it back with the placeholder #{orderId} in the next request's URL or body. If the id is missing, the implicit exists() fails, nothing is saved, and both requests are KO.

open as a page

Which values can a Gatling Expression Language string produce on its own with no Session attribute behind it, and how many values does `#{randomUuid()}` yield when it appears twice in one URL?

level: middleimportance: must knowfreq 52%

basics

~20 s

Gatling EL ships generator functions that need no Session attribute: currentTimeMillis(), currentDate(pattern), randomUuid(), randomSecureUuid(), randomInt(), randomLong(), randomDouble() and randomAlphanumeric(). Each occurrence is evaluated separately, so two randomUuid() calls in one URL give two different ids.

open as a page

A Gatling simulation declares csv("src/main/resources/credentials.csv") and dies before a single virtual user starts, although the file is exactly there. Why?

level: middleimportance: must knowfreq 55%

basics

~10 s

Gatling resolves a feeder path against the classpath, not the project tree, and specifically refuses paths starting src/main/resources/, src/test/resources/ or src/gatling/resources/. Use credentials.csv. The check runs while the Simulation constructor evaluates csv().

open as a page

In a Gatling simulation whose scenario feeds from `csv("credentials.csv")` with no strategy method called on it, what happens when more virtual users reach that feed step than the file has rows?

level: middleimportance: must knowfreq 58%

basics

~20 s

The default queue strategy hands out each row once, so the first virtual user to find the feeder empty stops the whole load generator. Gatling ends the run as a crash reading 'feeder is now empty', not a failed request.

open as a page

In Gatling, which check types can return more than one occurrence, and what happens when you call findAll or count on one that cannot?

level: middleimportance: should knowfreq 46%

basics

~20 s

Multi-occurrence check types such as regex, css, xpath, jsonPath, substring and header return a MultipleFind builder that offers find(n), findAll, findRandom and count. Single-value types such as status, jmesPath, currentLocation, responseTimeInMillis and bodyString do not, so those calls fail to compile.

open as a page

In Gatling's Expression Language, what do `#{ids(0)}`, `#{order.total}` and `#{ids.size()}` each read, and what may appear inside the index parentheses?

level: middleimportance: should knowfreq 42%

basics

~20 s

#{ids(0)} takes an element by index, #{order.total} takes a key or field, and #{ids.size()} gives a collection's length. The index may be a literal, a negative offset from the end, or the name of another Session attribute.

open as a page

In Gatling 3.15, what happened to the `eager` and `batch` feeder loading modes, and what now decides how a file-backed feeder is loaded?

level: middleimportance: should knowfreq 20%

basics

~20 s

Gatling 3.15 dropped both methods outright, so calls to them no longer compile. Loading is now automatic for the line-based file sources such as CSV: the file's size is compared against a megabyte threshold setting, 100 by default, and larger files are streamed rather than held in memory. JSON feeder files are always loaded whole.

open as a page

When a Gatling check fails, what does the default error message contain, and how do name(...) and logActualValueInError(false) change it?

level: seniorimportance: should knowfreq 36%

basics

~20 s

With no name declared, Gatling builds the message from the extractor, the extraction arity and the validator, then appends the validator's own outcome — for example jsonPath($.orderId).find.exists, found nothing. name(...) replaces that prefix; logActualValueInError(false), added in 3.15, flattens the value-interpolating validators to failed.

open as a page

In a Gatling Java simulation, why does `queryParam("lat", Integer.parseInt("#{lat}"))` not work, and what do you pass instead when the value needs real computation?

level: seniorimportance: should knowfreq 36%

basics

~10 s

Only Gatling's own SDK methods interpolate placeholders. Integer.parseInt runs first, on the literal placeholder characters, and throws. When a parameter needs computing, pass a function of the Session instead of a placeholder string.

open as a page

A Gatling login simulation feeds from a 200,000-row credentials CSV. Does Gatling hold every row in heap, and what decides?

level: seniorimportance: should knowfreq 36%

basics

~20 s

It depends on file size. Gatling compares the uncompressed file length against gatling.core.feederAdaptiveLoadModeThreshold, 100 MB by default: below it the whole file is parsed into memory, above it records are read from disk as users consume them.

open as a page

A Gatling simulation calls csv("credentials.csv").readRecords() only to size its injection profile. What does that cost, and what should it call instead?

level: seniorimportance: should knowfreq 30%

basics

~20 s

readRecords builds the feeder and drains it into a list, so the file is parsed once for the sizing call and again when the run starts. recordsCount counts lines without constructing records, and is the call for sizing.

open as a page

A Gatling run stopped eight minutes into a planned thirty with 'Feeder csv(credentials.csv) crashed: feeder is now empty' — what outputs does that run leave you, and how do you size the file so the next one finishes?

level: seniorimportance: should knowfreq 40%

basics

~20 s

That run leaves its raw log but no HTML report and no assertion verdict, because a crash stops it first. Size the file from feed step executions - arrival rate times duration times feeds per user - and add headroom.

open as a page

In a Gatling suite, a response field is present on only some responses — how would you decide between a plain check, checkIf, optional() and withDefault for it?

level: principalimportance: should knowfreq 32%

basics

~20 s

Decide by what absence means. If absence is a defect, leave the implicit exists() in place. If you know in advance when the field should be there, gate the check with checkIf. If absence is legitimate, use optional() to capture without failing, or withDefault to substitute a value.

open as a page

A Gatling login simulation needs 200,000 distinct credentials per run. Would you ship them as a CSV, read them with jdbcFeeder, or serve them from Redis?

level: principalimportance: should knowfreq 32%

basics

~20 s

Default to the CSV. It is the only one of the three available in all five SDKs, it costs the running system nothing, and it ships with the artifact. Use the others only when the data cannot be a file.

open as a page

Across a Gatling suite, how would you decide which of the four feeder consumption strategies each data file gets, and what can those four not express?

level: principalimportance: should knowfreq 33%

basics

~20 s

Decide from the data, not the scenario: records carrying an identity get a consuming strategy and a stock sized to the run; everything else gets circular or random. The four cannot express reuse with uniqueness, or lending a record back.

open as a page

In Gatling, how do you tell a check to extract an Int rather than a String, and why does ofType not compile in a Java, Kotlin or JavaScript simulation?

level: middleimportance: nice to knowfreq 30%

basics

~20 s

ofType is the Scala spelling only. The Java API, which Kotlin and the JavaScript/TypeScript SDK also use, exposes a family of named methods instead: ofInt(), ofString(), ofBoolean(), ofLong(), ofDouble(), ofList(), ofMap(), ofObject(), and ofNode() for css.

open as a page

In Gatling's JavaScript and TypeScript SDK, which feeders and feeder methods from the JVM SDKs are missing?

level: middleimportance: nice to knowfreq 28%

basics

~20 s

jdbcFeeder, redisFeeder in all four command forms, readRecords and the custom-iterator feeder are documented as not supported in the JavaScript and TypeScript SDK. The file and in-memory feeders, unzip, shard, transform and recordsCount all are.

open as a page

In a Gatling simulation, what does `feed(feeder, 2)` put into the virtual user's Session, and what happens if only one record is left?

level: middleimportance: nice to knowfreq 24%

basics

~20 s

It takes two records in one step and merges them by key, so each source column becomes one Session attribute holding a two-element list that you read by index. If fewer than two records remain, Gatling stops the load generator.

open as a page

In Gatling's Expression Language, which forms turn an absent or null Session attribute into a value instead of failing the request, and what does each one produce?

level: seniorimportance: nice to knowfreq 26%

basics

~10 s

A bare placeholder on a missing attribute fails, so Gatling never builds the request. #{x.exists()} and #{x.isUndefined()} return booleans instead of failing, and #{x.jsonStringify()} rescues a null value but not an absent one.

open as a page