Populate data in map from response and use in subsequent http request

Hi all,

Can we store the data from the response into another data structure like a Map and then user that data for subsequent requests being made?

The idea is to populate the Map with key as the userNumber and value as the authKey and then retrieve that value based on the key passed to my method. Sharing a snippet of the code :

object APIs {

    var numbersVsUCID = new mutable.HashMap[String, String]()

    def newCall(phoneNumber: String, isSIP: Boolean): ChainBuilder = {
        exec(http(s"Start call : ${phoneNumber}")
        .get("outbound")
        .queryParam("api_key", "TOKEN")
        .queryParam("phone_no", phoneNumber)
        .queryParam("isSip", isSIP)
        .check(status.is(Config.success))
        .check(xpath("//message").saveAs("ucid")) //Extracted the id here
        .check(bodyString.saveAs("callStarted")))
        .exec(session => {
            numbersVsUCID.put(phoneNumber, session("ucid").as[String]) // If the phone number is 2020, the map would be HashMap("2020" -> "ZXCVBNMQWERTY")
            session
        })
    }

    def invite(phoneNumber: String, isSIP: Boolean): ChainBuilder = {
        exec(http(s"Invite : ${phoneNumber}")
        .get("Conference")
        .queryParam("api_key", "TOKEN")
        .queryParam("phoneno", phoneNumber)
        .queryParam("isSip", isSIP)
        .queryParam("ucid", "${ucid}")
        .check(status.is(Config.success))
        .check(jsonPath("$..ucid").saveAs("ucid"))) // Creates a new unique ID
        .exec(session => {
            numbersVsUCID.put(phoneNumber, session("ucid").as[String]) // If the number is 2022, the map would now be HashMap("2020" -> "ZXCVBNMQWERTY", "2022" -> "QWERTYZXCVBNM")
            session
        })
    }

    def disconnect(phoneNumber: String): ChainBuilder = {
        exec(http(s"Disconnect : ${phoneNumber}")
        .get("Disconnect")
        .queryParam("api_key", "TOKEN")
        .queryParam("ucid", numbersVsUCID.get(phoneNumber).get)) // Fetch the value from the map and use here
    }
}

class Test extends BaseSimulation {

    var callScn: ScenarioBuilder = scenario("Tests")
        .exec(APIs.newCall("2020", true))
        .pause(15 seconds, 30 seconds)
        .exec(OzonetelAPI.invite("2022", true))
        .pause(15 seconds, 30 seconds)
        .exec(OzonetelAPI.disconnect("2020"))
        .exec(OzonetelAPI.disconnect("2022"))

    setUp(
        callScn.inject(rampUsers("1") during ("1" seconds))
    ).protocols(Config.baseHttpConf)

}

One execution of the above code I always getting an invocation target exception as below :

java.util.NoSuchElementException: None.get
	at scala.None$.get(Option.scala:627)
	at scala.None$.get(Option.scala:626)
	at spr.objects.OzonetelAPI$.disconnect(APIs.scala:96)
	at spr.tests.CallControlsTest.<init>(Test.scala:23)
	... 10 common frames omitted
Wrapped by: java.lang.reflect.InvocationTargetException: null
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at io.gatling.app.Runner.run0(Runner.scala:62)
	at io.gatling.app.Runner.run(Runner.scala:49)
	at io.gatling.app.Gatling$.start(Gatling.scala:83)
	at io.gatling.app.Gatling$.fromArgs(Gatling.scala:45)
	at io.gatling.app.Gatling$.main(Gatling.scala:37)
	at io.gatling.app.Gatling.main(Gatling.scala)
Exception in thread "main" java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at io.gatling.app.Runner.run0(Runner.scala:62)
	at io.gatling.app.Runner.run(Runner.scala:49)
	at io.gatling.app.Gatling$.start(Gatling.scala:83)
	at io.gatling.app.Gatling$.fromArgs(Gatling.scala:45)
	at io.gatling.app.Gatling$.main(Gatling.scala:37)
	at io.gatling.app.Gatling.main(Gatling.scala)
Caused by: java.util.NoSuchElementException: None.get
	at scala.None$.get(Option.scala:627)
	at scala.None$.get(Option.scala:626)
	at spr.objects.APIs$.disconnect(OzonetelAPI.scala:96)
	at spr.tests.Test.<init>(CallControlsTest.scala:23)
	... 10 more

Can someone please point out what I might be doing wrong here?

Thanks in advance

numbersVsUCID.get(phoneNumber) returns an Option[String]
So, it may be None (no value).

If you get from a None you’ll have such error.
My understanding is that your numbersVsUCID map does not contain the wanted phone number (yet?)

Try with a doIf:

Try with a concurrent.Map as your calls may be on different threads.

But do you really need a global map? If the data are for a single user, they should go into the session (and yes, you can store any type of value in it, even if we strongly prefer immutable data).

Does that helps?

Cheers!