08 — Session and Variables
Each virtual user has its own Session — a key/value store that persists for the lifetime of that user's scenario run. It is the primary way to pass data between steps.
Reading session values
In EL expressions (inside strings)
// #{key} is resolved at runtime against the current user's session
http("Get user").get("/users/#{userId}")
http("Auth").header("Authorization", "Bearer #{token}")
In Java lambdas
// session -> session.getString("key")
exec(session -> {
String token = session.getString("authToken");
int userId = session.getInt("userId");
long count = session.getLong("count");
boolean active = session.getBoolean("isActive");
List<Object> ids = session.getList("itemIds");
return session;
})
In Kotlin lambdas
exec { session ->
val token = session.getString("authToken")
val userId = session.getInt("userId")
session
}
Writing session values
From a check (most common)
http("Login").post("/login")
.check(jsonPath("$.token").saveAs("authToken"))
.check(jsonPath("$.userId").ofInt().saveAs("userId"))
From a lambda (programmatic)
// Java
exec(session -> session.set("retryCount", 0))
exec(session -> session.set("retryCount", session.getInt("retryCount") + 1))
// Kotlin
exec { session -> session.set("retryCount", 0) }
Setting multiple values at once
// Java
exec(session -> session
.set("startTime", System.currentTimeMillis())
.set("env", "staging")
)
Removing session values
Checking session state
// Use in doIf, asLongAs, etc.
doIf(session -> session.contains("authToken")).on(
exec(http("Protected").get("/protected")
.header("Authorization", "Bearer #{authToken}"))
)
doIf(session -> !session.isFailed()).on(
exec(http("Proceed").post("/next"))
)
Session failure
A session is marked as failed when a mandatory check fails. Subsequent steps still run (unless you use exitBlockOnFail or exitHereIfFailed).
// Stop the scenario for this user if the session is failed
exec(http("Critical").post("/start").check(status().is(200)))
.exitHereIfFailed()
.exec(http("Next step").get("/next"))
Practical patterns
Pattern 1 — Login once, reuse token
// Java
ScenarioBuilder scn = scenario("Authenticated scenario")
.exec(
http("Login").post("/auth/token")
.formParam("grant_type", "password")
.formParam("username", "#{username}")
.formParam("password", "#{password}")
.check(status().is(200))
.check(jsonPath("$.access_token").saveAs("accessToken"))
)
.exec(
http("Get orders").get("/orders")
.header("Authorization", "Bearer #{accessToken}")
)
.exec(
http("Get profile").get("/profile")
.header("Authorization", "Bearer #{accessToken}")
);
// Kotlin
val scn = scenario("Authenticated scenario")
.exec(
http("Login").post("/auth/token")
.formParam("grant_type", "password")
.formParam("username", "#{username}")
.formParam("password", "#{password}")
.check(status().`is`(200))
.check(jsonPath("$.access_token").saveAs("accessToken"))
)
.exec(
http("Get orders").get("/orders")
.header("Authorization", "Bearer #{accessToken}")
)
Pattern 2 — Computed values
// Java
exec(session -> {
long now = System.currentTimeMillis();
String correlationId = "load-" + now + "-" + session.userId();
return session
.set("timestamp", now)
.set("correlationId", correlationId);
})
.exec(http("Request with correlation ID").get("/api")
.header("X-Correlation-Id", "#{correlationId}"))
// Kotlin
exec { session ->
val now = System.currentTimeMillis()
val correlationId = "load-$now-${session.userId()}"
session
.set("timestamp", now)
.set("correlationId", correlationId)
}
.exec(
http("Request with correlation ID").get("/api")
.header("X-Correlation-Id", "#{correlationId}")
)
Pattern 3 — Counter / pagination
// Java
exec(session -> session.set("page", 0))
.asLongAs(session -> session.getInt("page") < 5).on(
exec(http("Page #{page}").get("/items?page=#{page}"))
.exec(session -> session.set("page", session.getInt("page") + 1))
.pause(500, TimeUnit.MILLISECONDS)
)
Pattern 4 — Conditional auth header
// Only add auth header when token is present
http("Request").get("/resource")
.header("Authorization", session ->
session.contains("accessToken")
? "Bearer " + session.getString("accessToken")
: null
)
Session attributes set by Gatling automatically
| Key | Type | Description |
|---|---|---|
gatling.userId |
Long | Unique ID for each virtual user |
Access via session.userId().