Skip to content

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

exec(session -> session.remove("tempValue"))
exec(session -> session.removeAll("key1", "key2"))

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