HTTP requests not sent from Java using exec(session ->{})

This seems really simple and I have validated that the requests are never sent via Wireshark.
This DOES NOT send an HTTP request

.exec(
  session -> {
    try {
      http("Send [STORE]_CURRENT_STATE")
        .post("http://localhost:11640/messages")
        .headers(dashboardEventHeaders)
        .header("MESSAGE_TYPE", "#{storeId}_STORE_UPDATED")
        .body(StringBody(buildStoreUpdatedEvent()))
        .check(regex("Sent"))
        ;
      } catch (Exception e) {
        e.printStackTrace();
      }
      return session;
    }
  )
  .pause(TEN_SECONDS)
  .injectOpen(atOnceUsers(1))

No Exception is printed

This DOES (Identical except I have commented out the session)

.exec(
//  .session -> {
//    try {
        http("Send [STORE]_CURRENT_STATE")
          .post("http://localhost:11640/messages")
          .headers(dashboardEventHeaders)
          .header("MESSAGE_TYPE", "#{storeId}_STORE_UPDATED")
          .body(StringBody(buildStoreUpdatedEvent()))
          .check(regex("Sent"))
//        ;
//                                    } catch (Exception e) {
//                                        e.printStackTrace();
//                                    }
//                                    return session;
//                                }
  )
  .pause(TEN_SECONDS)
  .injectOpen(atOnceUsers(1))

Indeed, and it’s clearly stated that this doesn’t work in the documentation for exec:

Now if what you’re trying to achieve is to make it so that buildStoreUpdatedEvent() is called every time a request is generated:

.exec(
  http("Send [STORE]_CURRENT_STATE")
    .post("http://localhost:11640/messages")
    .headers(dashboardEventHeaders)
    .header("MESSAGE_TYPE", "#{storeId}_STORE_UPDATED")
    .body(StringBody(session -> buildStoreUpdatedEvent())) // <== pass a function here
    .check(regex("Sent"))
  )
  .pause(TEN_SECONDS)
  .injectOpen(atOnceUsers(1))

I guess I didn’t quite comprehend that comment correctly, this was part of a chain but probably not in the right way (need to get the execution model installed in my brain)
I worked around it in another way, but I like your solution better and will give that a try.
Thanks for the quick response !

I guess I didn’t quite comprehend that comment correctly, this was part of a chain but probably not in the right way (need to get the execution model installed in my brain)

We’d be very keen on having your feedback on how we could explain things better and improve our documentation. Also, there’s an “Edit this page on GitHub” at the bottom of each page to contribute documentation improvements.

Cheers

1 Like

So I think I am getting a better model in my head now and I want to confirm my understanding with you.
Because of the reactive architecture, execution and specification must remain separate.
The session holds a map of vars that must be accessed atomically, so mixing state change and execution doesn’t work.
So if you want to mutate anything during a run it must be done first via exec(s-> f(s)), then those values can be used in an action definition via “#{var}” replacements.
This makes it difficult to use object methods within a ActionBuilder without a lot of plumbing or am I missing something.

Still not getting something
Here sendDriverOnRun (Http Action to send to rest client) faults because startDriverDto is not found, that’s why I commented it out and replaced it with a debug print.

scenario("Drivers going on runs")
  .feed(driverFeeder)
  .exec(session -> buildDriverDto(session))
//  .exec(sendDriverOnRun()) 
  .exec(session -> {
    System.out.println("--- From Session ---");
    System.out.println(session.getString("startDriverDto"));
    System.out.println("------");
    return session;
  })
  .injectOpen(atOnceUsers(1));

private Session buildDriverDto(Session session) {
  DriverDto driver = session.get("driver");
  String s = buildDriverPayload(driver);
  session.set("startDriverDto",s);
  System.out.println("--- Driver DTO ---");
  System.out.println(s);
  System.out.println("-----");
 return session;
 }

Output from a run is

--- Driver DTO ---
{
  "driverId":123,
.....  JSON payload ...
  "sequence" : 1
}
-----
--- From Session ---
null
------

Just can’t see what I am doing wrong here

Because of the reactive architecture, execution and specification must remain separate.

Exactly

The session holds a map of vars that must be accessed atomically, so mixing state change and execution doesn’t work.

It’s more that functions are executed at runtime, way after the specification is built.

So if you want to mutate anything during a run it must be done first via exec(s-> f(s)), then those values can be used in an action definition via “#{var}” replacements.

That (first store, then fetch), or directly pass functions to individual methods.

This makes it difficult to use object methods within a ActionBuilder without a lot of plumbing or am I missing something.

Sorry, don’t understand what you mean here.

faults because startDriverDto is not found

Because Session is immutable (it’s the easiest way to deal with state in an asynchronous architecture, but something we’re considering changing for Gatling 4), see doc:

So;

private Session buildDriverDto(Session session) {
  DriverDto driver = session.get("driver");
  String s = buildDriverPayload(driver);
  Session newSession.set("startDriverDto",s);
  System.out.println("--- Driver DTO ---");
  System.out.println(s);
  System.out.println("-----");
 return newSession;
 }

or shorter:

private Session buildDriverDto(Session session) {
  return session.set("startDriverDto", buildDriverPayload(driver));
 }

Still, I don’t understand why you don’t directly build everything you need in sendDriverOnRun().

Im not building things directly because this test is getting complex (Maybe not the best one to start out with, but it means I have to learn fast) this has an init process, then concurrent scenarios of orders arriving, someone working a UI and drivers delivering orders so keeping the main script legible is important.
Also, at this point I am just trying to get it working before refactoring (probably today as I think I am pretty close) for a demo next Thursday
I didn’t see that section on the session, that explains a lot for me.
Expected an immutable to throw exceptions on a set(), instead of returning a new instance, thats more the builder pattern.

Probably a good idea for me to scan the docs and read those warning blocks carefully !

You have been very helpful, and so far I am pretty pleased with the product, thank you

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.