Disappearing Exec Call

I am trying to run a session where one call depends on the result of another call. I have managed my way through many bugs to do with saving to Session, including a lot of compilation errors on trying to access session when the data didn’t exist yet, and then once data was saved successfully I had to remove special characters that were added (see def req5 in code below).

Anyway, now I have it compiling, but I don’t see my actual request getting built. I don’t see anything to do with it in the logs actually - no reference to Req5 as it appears in the request name, nor any part of the path that I’m querying (both these things appear in logs for all other requests).

Suppose the session variable I’m retrieving for req5 is saved via check(BodyString.saveAs()) in req2, my code looks something like this:

  def req5(sessionStr: String): HttpRequestBuilder = http(s"MyScenario - Req5")
    .get(s"/path/to/query/${fromJsonString[MyProto](sessionStr.replace("\"", "").replace("\\", "\"")).field}")

  setUp(
    scenario("MyScenario")
      .exec(
        exec(req1),
        exec(req2),
        exec(req3),
        exec(req4),
      )
      .exec { session =>
        req5(session("myString").as[String])
        session
      }
      .inject(injectionProfile)

I have also tried the following instead of chaining req5 after all the others:
exec(req2).exec { session => req5(session("myString").as[String]) session }
with exact same results - ‘successful’ test passing with all requests showing success, but no trace of req5

Note: if I change it it to the following, I get an error saying Session does not contain myString

 setUp(
    scenario("MyScenario")
      .exec(
        exec(req1)
        exec(req2)
        exec(req3)
        exec(req4)
        exec(req5(session("myString").as[String]))
        session
       }
      .inject(injectionProfile)

Any help is greatly appreciated.

Hi @WeinYopp,

Welcome aboard!

As stated in the first note box of the documentation:

The components of this DSL are mere definitions of the desired effect. They don’t generate the desired effect where you invoke them in your own code. Only when chained with other components so they are ultimately passed to the setUp, can the Gatling engine interpret them and produce the desired effect.

So, you can’t call this way.

For your use case, I assume you’ll need to set a session variable with your wanted value (or use transform when getting your "myString") and use that in a Gatling Expression Language

Something like:

  val req5: HttpRequestBuilder = http(s"MyScenario - Req5")
    .get("/path/to/query/#{myPath}")

  setUp(
    scenario("MyScenario")
      .exec(
        req1,
        req2,
        req3,
        req4,
      )
      .exec { session =>
        session.set("myPath", fromJsonString[MyProto](session("myString").as[String].replace("\"", "").replace("\\", "\"")).field)
      }
      .exec(req5)
      .inject(injectionProfile)

I hope this helps!

Cheers!

Thanks for the quick response. I was able to use this to successfully make 1 request based on 1 reply. However I was hoping for a bit more…

First of all, I noticed some limitations of the DSL that are not mentioned anywhere in docs:
a) I can’t use exec{ session => ... } with a request - it simply won’t run if you want to access session. This seems like it would be very good to have mentioned in docs because it caused me a lot of confusion.
b) I can’t do multiple things in a session without assigning the session to a var… I expected that I could do multiple sets in the same exec, and then return session, but it seems to only use the last one I put… or example I did

session.set("req2Field", req2.field)
session.set("req2Size", req2.size)

but only size was there in the next exec call. I figured out that I can do this instead:

var s = session
s = s.set("req2Field", req2.field)
s = s.set("req2Size", req2.size)
s

but that is a bit cumbersome to write every time - especially when the whole point is to get around writing exec{ session => ... } for each item I want to save.

and c) I cannot seem to write exec(req1, req2, ...) as you have - instead I’m finding I have to write exec(exec(req1), exec(req2), ...).

Secondly, I am still unsure if Gatling can fit my needs because I am hoping to be able to do one-response-to-many-requests flows with it. However this would rely on using a different identifier for each path interpolation, meaning I am currently trying to do the following:

    def req5s = (0 until req2Size).map(num =>
      http(s"StartScenario - GetAllEventsSchedForOrg$num")
        .get(
          s"/event/allData/status/${EventState.EVENT_STATE_SCHEDULED}/forOrg/#{orgId$num}"
        )
    )

setup(scnenario("name").exec(exec(req1), exec(req2),...).exec{session =>
  val req2Field = fromJsonString[Req2Proto](session("req2").as[String]).field
  req2Size = req2Field.size
  req2Field.zipWithIndex.foreach { case (item, index) =>
    s = s.set(s"req2field_$index", item)
  }
}.exec(req5s.map(exec)).inject(injectionProfile))

within an exec call. Note that req2Size is not retrieved from session but rather saved as a global var so I can write exec(...) instead of exec{session => ...}. The result of trying this is that the list req5s is totally ignored, and I am not sure why. I have also tried with req5s.map(exec): _*

Hi @WeinYopp,

As stated in my previous message, it is mentioned in the docs.
session => ... is the syntax to create a function. You can’t define in your own function.

Once again, it is written in the documentation: see the note box in Session API - Setting attributes

Do you know you can chain?

 .exec { session =>
    session.set("req2Field", req2.field)
      .set("req2Size", req2.size)
 }

Please open another topic to explain your use case if you do think so.
But, before, have you taken a look into the Gatling Academy?

And about using different path… you should use other structure elements

Cheers!

Thanks for all this! I did not know about chaining session commands - that is helpful. I will check out Gatling Academy too

I did some googling on my issue and ended up in this StackOverflow where I found a solution to my 1-reply-to-many-reqs requirement - foreach which can be used after exec. Unfortunately Academy did not help much with this, but at least I have found how to do it.