Session API
Programmatically handle virtual users' data
Concept
Going stateful
In most load testing use cases, it’s important that the virtual users don’t play the same data. Otherwise, you might end up not testing your application but your caches.
Moreover, if you’re running an application on a Java Virtual Machine, the Just In Time compiler (JIT) will make impressive optimizations but your system will behave in a very different fashion than in your production environment.
Session
Session is a virtual user’s state.
Basically, it’s a Map<String, Object>
: a map with key Strings.
In Gatling, entries in this map are called Session attributes.
Action
.
Session
s are the messages that are passed along a scenario workflow.Injecting data
The first step is to inject state into the virtual users.
There’s 3 ways of doing that:
- using Feeders
- extracting data from responses and saving them, e.g. with Check’s saveAs
- programmatically with the Session API
Fetching data
Once you have injected data into your virtual users, you’ll naturally want to retrieve and use it.
There are 2 ways of implementing this:
- using Gatling’s Expression Language
- programmatically with the Session API
If Gatling complains that an attribute could not be found, check that:
- you don’t have a typo in a feeder file header
- you don’t have a typo in a Gatling EL expression
- your feed action is properly called (e.g. could be properly chained with other action because a dot is missing)
- the check that should have saved it actually failed
Session API
Setting attributes
// set one single attribute
Session newSession1 = session.set("key", "whateverValue");
// set multiple attributes
Session newSession2 = session.setAll(Map.of("key", "value"));
// remove one single attribute
Session newSession3 = session.remove("key");
// remove multiple attributes
Session newSession4 = session.removeAll("key1", "key2");
// remove all non Gatling internal attributes
Session newSession5 = session.reset();
// set one single attribute
const newSession1 = session.set("key", "whateverValue");
// set multiple attributes
const newSession2 = session.setAll({ "key": "value" });
// remove one single attribute
const newSession3 = session.remove("key");
// remove multiple attributes
const newSession4 = session.removeAll("key1", "key2");
// remove all non Gatling internal attributes
const newSession5 = session.reset();
// set one single attribute
val newSession1 = session.set("key", "whateverValue")
// set multiple attributes
val newSession2 = session.setAll(mapOf("key" to "value"))
// remove one single attribute
val newSession3 = session.remove("key")
// remove multiple attributes
val newSession4 = session.removeAll("key1", "key2")
// remove all non Gatling internal attributes
val newSession5 = session.reset()
// set one single attribute
val newSession1 = session.set("key", "whateverValue")
// set multiple attributes
val newSession2 = session.setAll(Map("key" -> "value"))
// remove one single attribute
val newSession3 = session.remove("key")
// remove multiple attributes
val newSession4 = session.removeAll("key1", "key2")
// remove all non Gatling internal attributes
val newSession5 = session.reset
Session
instances are immutable, meaning that methods such as set
return a new instance and leave the original instance unmodified!// wrong usage: result from Session#set is discarded
exec(session -> {
session.set("foo", "bar");
return session;
});
// correct usage
exec(session -> {
Session newSession = session.set("foo", "bar");
return newSession;
});
// wrong usage: result from Session#set is discarded
exec((session) => {
session.set("foo", "bar");
return session;
});
// correct usage
exec((session) => {
const newSession = session.set("foo", "bar");
return newSession;
});
// wrong usage: result from Session#set is discarded
exec { session ->
session.set("foo", "bar")
session
}
// correct usage
exec { session ->
val newSession = session.set("foo", "bar")
newSession
}
// wrong usage: result from Session#set is discarded
exec { session =>
session.set("foo", "bar")
session
}
// correct usage
exec { session =>
val newSession = session.set("foo", "bar")
newSession
}
Getting attributes
// check if an attribute is stored in the session
boolean contains = session.contains("key");
// get an attribute value and cast it
String string = session.getString("key");
// get an int attribute (will throw if it's null)
int primitiveInt = session.getInt("key");
// get an Integer attribute
Integer intWrapper = session.getIntegerWrapper("key");
// get a long attribute (will throw if it's null)
long primitiveLong = session.getLong("key");
// get a Long attribute
Long longWrapper = session.getLongWrapper("key");
// get a boolean attribute (will throw if it's null)
boolean primitiveBoolean = session.getBoolean("key");
// get a Boolean attribute
Boolean booleanWrapper = session.getBooleanWrapper("key");
// get a double attribute (will throw if it's null)
double primitiveDouble = session.getDouble("key");
// get a Double attribute
Double doubleWrapper = session.getDoubleWrapper("key");
// get an attribute value and cast it into a List
List<MyPojo> list = session.getList("key");
// get an attribute value and cast it into a Set
Set<MyPojo> set = session.getSet("key");
// get an attribute value and cast it into a Map
Map<String, MyPojo> map = session.getMap("key");
// get an attribute value and cast it
MyPojo myPojo = session.get("key");
// check if an attribute is stored in the session
const contains = session.contains("key");
// get an attribute value
const value = session.get("key");
// check if an attribute is stored in the session
val contains = session.contains("key")
// get an attribute value and cast it
val string = session.getString("key")
// get an Int attribute (will throw if it's null)
val primitiveInt = session.getInt("key")
// get an Int? attribute
val intWrapper = session.getIntegerWrapper("key")
// get a Long attribute (will throw if it's null)
val primitiveLong = session.getLong("key")
// get a Long? attribute
val longWrapper = session.getLongWrapper("key")
// get a Boolean attribute (will throw if it's null)
val primitiveBoolean = session.getBoolean("key")
// get a Boolean? attribute
val booleanWrapper = session.getBooleanWrapper("key")
// get a Double attribute (will throw if it's null)
val primitiveDouble = session.getDouble("key")
// get a Double? attribute
val doubleWrapper = session.getDoubleWrapper("key")
// get an attribute value and cast it into a List
val list: List<MyPojo> = session.getList("key")
// get an attribute value and cast it into a Set
val set: Set<MyPojo> = session.getSet("key")
// get an attribute value and cast it into a Map
val map: Map<String, MyPojo> = session.getMap("key")
// get an attribute value and cast it
val myPojoOrNull: MyPojo? = session.get("key")
// check if an attribute is stored in the session
val contains = session.contains("key")
// get an attribute value and convert it to the type parameter
// throws if key is undefined or actual type doesn't match
val string = session("key").as[String]
// get an attribute value and convert it to an Option of the type parameter
// throws if actual type doesn't match
val stringOpt: Option[String] = session("key").asOption[String]
// get an attribute value and convert it to a Validation of the type parameter
// never throws
val stringV: Validation[String] = session("key").validate[String]
Virtual user properties
// the unique id of this virtual user
long userId = session.userId();
// the name of the scenario this virtual user executes
String scenario = session.scenario();
// the groups this virtual user is currently in
List<String> groups = session.groups();
// the unique id of this virtual user
const userId = session.userId();
// the name of the scenario this virtual user executes
const scenario = session.scenario();
// the groups this virtual user is currently in
const groups = session.groups();
// the unique id of this virtual user
val userId = session.userId()
// the name of the scenario this virtual user executes
val scenario = session.scenario()
// the groups this virtual user is currently in
val groups = session.groups()
// the unique id of this virtual user
val userId = session.userId
// the name of the scenario this virtual user executes
val scenario = session.scenario
// the groups this virtual user is currently in
val groups = session.groups
Handling session state
// return true if the virtual user has experienced a failure before this point
boolean failed = session.isFailed();
// reset the state to success
// so that interrupt mechanisms such as exitHereIfFailed don't trigger
Session newSession1 = session.markAsSucceeded();
// force the state to failure
// so that interrupt mechanisms such as exitHereIfFailed do trigger
Session newSession2 = session.markAsFailed();
// return true if the virtual user has experienced a failure before this point
const failed = session.isFailed();
// reset the state to success
// so that interrupt mechanisms such as exitHereIfFailed don't trigger
const newSession1 = session.markAsSucceeded();
// force the state to failure
// so that interrupt mechanisms such as exitHereIfFailed do trigger
const newSession2 = session.markAsFailed();
// return true if the virtual user has experienced a failure before this point
val failed: Boolean = session.isFailed()
// reset the state to success
// so that interrupt mechanisms such as exitHereIfFailed don't trigger
val newSession1: Session = session.markAsSucceeded()
// force the state to failure
// so that interrupt mechanisms such as exitHereIfFailed do trigger
val newSession2: Session = session.markAsFailed()
// return true if the virtual user has experienced a failure before this point
val failed = session.isFailed
// reset the state to success
// so that interrupt mechanisms such as exitHereIfFailed don't trigger
val newSession1 = session.markAsSucceeded
// force the state to failure
// so that interrupt mechanisms such as exitHereIfFailed do trigger
val newSession2 = session.markAsFailed