Generate & pass a new unique JSON payload for each constant user

Hi all, dear community!

How to pass the unique JSON for each request for each user?

I realized that when creating an HTTP POST request and then executing it by the Gatling, the request is created once, and then spreads to users specified in the injection simulation.

For example:

var stringBody = getReceiptAsString(receipt);

exec(http("Send Request")
                .post(getUrl().concat(receiptSendRequest))
                .headers(new HeaderRequest().getHeaderWithAuth(token))
                .body(StringBody(stringBody))
                .check(status().is(200)));

Here

.body(StringBody(stringBody))

new unique JSON is always created and should be passed as a body for POST request. stringBody - is the variable in which JSON is written and converted to a string.

And here

getReceiptAsString(receipt);

we have the method which returns JSON as a string and has a simple STDOUT of json System.out.println(json) which was generated as a unique value.

And we have a configured Simulation as:

{
        setUp(new Scenario().getScenario().injectOpen(constantUsersPerSec(2).during(1)))
                .assertions(forAll().responseTime().max().between(200, 1000));
}

From this configuration, we have unique 2 users who will inject a request per 1 second for 1 second. So we will have only 2 executed requests.

I have added output logs as a TRACE and saw, that STDOUT was invoked only once and the request JSON body was the same for both 2 requests. How I can change it that I will have unique JSON for each request?

Many thanks!

Hi!

I’m not sure to understand your use case.

Two possibilities come to mind:

1. stringBody is generated independently from previous request of the current user.

You should want to read about feeder, to generate data.

2. stringBody is generated from a value in a previous request

You should store it in the session

As getReceiptAsString has an argument, I guess it is what your want.

  ScenarioBuilder scn = scenario("Scenario")
          .exec(http("Get Receipt ID").get(getUrl().concat("/receipt")).check(jsonPath(".id").saveAs("receipt")))
          .exec(session -> {
              String receipt = session.getString("receipt");
              String stringBody = getReceiptAsString(receipt);
              return session.set("stringBody", stringBody);
          })
          .exec(http("Send Request")
                  .post(getUrl().concat(receiptSendRequest))
                  .headers(new HeaderRequest().getHeaderWithAuth(token))
                  .body(StringBody("#{stringBody}"))
                  .check(status().is(200)));  

What do you think?

1 Like

@sbrevet Too complicated!!! You don’t need the intermediate Session set/get.

StringBody can either take a String (possibly containing some Gatling EL patterns) or a function.

ScenarioBuilder scn = scenario("Scenario")
.exec(
  http("Get Receipt ID")
    .get(getUrl() + "/receipt")
   .check(jsonPath(".id").saveAs("receipt"))
)
.exec(
  http("Send Request")
    .post(getUrl() + receiptSendRequest)
    .headers(new HeaderRequest().getHeaderWithAuth(token))
    .body(StringBody(session -> getReceiptAsString(session.getString("receipt")))
    .check(status().is(200))
);  

@slandelle , @sbrevet Thanks for your answers!

But, I have a situation where I don’t have a GET request before the POST. This is only POST which I have to pass a unique JSON for each user.

I try to understand how can I use session or feeders functionality.

Have you gone through the tutorials?
I don’t get where you’re struggling.

@slandelle , @sbrevet thank you very much for your support, I read the docs and in the end I got it like this one:

exec(
        session -> {
            return session.set("jsonPayload", getReceiptAsString(receipt));
        }
)
.exec(
    http("Send Receipts")
        .post(getUrl().concat(receiptSendRequest))
        .headers(new HeaderRequest().getHeaderWithAuth(token))
        .body(StringBody("#{jsonPayload}"))
        .check(status().is(200))
);

As I said, you can skip the intermediate storage and then EL fetch and directly pass a lambda to StringBody:

exec(
    http("Send Receipts")
        .post(getUrl().concat(receiptSendRequest))
        .headers(new HeaderRequest().getHeaderWithAuth(token))
        .body(StringBody(session -> getReceiptAsString(receipt)))
        .check(status().is(200))
);

Then, your receipt also get me concerned. It looks like it’s a global variable (ie shared with all virtual users). Is it really what you want?

1 Like

Yeah, you totally right.
But I have deleted sensitive code in the first execution section of lambda expressing.

session → { … }

I need to store specific values generated as payload files for each execution to pass them as the next code.
So for simple requests - yes, your solution is the best, it’s simple & without any overhead architecture.