skip to content

In Gatling, how do you tell a check to extract an Int rather than a String, and why does ofType not compile in a Java, Kotlin or JavaScript simulation?

level: middleimportance: nice to knowfreq 30%

answer

  1. Everything extracts String by default
  2. Scala has one generic method
  3. The Java family has named methods
  4. ofInt, ofNode, captureGroups
  5. bodyStream and ofNode are JVM-only

basics

~20 s

ofType is the Scala spelling only. The Java API, which Kotlin and the JavaScript/TypeScript SDK also use, exposes a family of named methods instead: ofInt(), ofString(), ofBoolean(), ofLong(), ofDouble(), ofList(), ofMap(), ofObject(), and ofNode() for css.

solid answer

~40 s

By default `jsonPath`, `jmesPath` and `css` extract **Strings** — non-String JSON values get serialised back into JSON text. To get a typed value you add one more step. In **Scala** that step is generic: `jsonPath("$.foo").ofType[Int]`, `css("a", "href").ofType[Node]`, `regex("a(.*)b(.*)c").ofType[(String, String)]`. In the **Java API** — and therefore in Kotlin and the JavaScript/TypeScript SDK — there is no public `ofType`; you call the named method for the type instead: `ofInt()`, `ofString()`, `ofBoolean()`, `ofLong()`, `ofDouble()`, `ofList()`, `ofMap()`, `ofObject()`, `ofNode()` for `css`, and `captureGroups(n)` for a multi-group regex. Two of these have no JS/TS equivalent at all: the JavaScript/TypeScript samples render `css(...).ofNode()` and the whole `bodyStream` check type as `NOT SUPPORTED`.

code

java · 21 lines
java
import io.gatling.javaapi.core.*;
import io.gatling.javaapi.http.*;
import static io.gatling.javaapi.core.CoreDsl.*;
import static io.gatling.javaapi.http.HttpDsl.*;

public class TypedExtractionSimulation extends Simulation {

  ScenarioBuilder scn = scenario("Order")
    .exec(http("Fetch order")
      .get("/orders/42")
      // default extraction is String; ask for a type explicitly
      .check(jsonPath("$.quantity").ofInt().gt(0))
      .check(jsonPath("$.paid").ofBoolean().is(true))
      .check(jsonPath("$.lines").ofList().saveAs("lines"))
      // a regex with two capture groups needs captureGroups(2)
      .check(regex("order (\\d+) for (\\w+)").captureGroups(2).saveAs("pair")));

  {
    setUp(scn.injectOpen(atOnceUsers(1)));
  }
}

go deeper

for a junior

Be ready to say that path checks extract Strings by default and that asking for another type is an extra step in the chain.

for a middle

Explain that ofType is Scala-only and that the Java API, Kotlin and the JavaScript SDK use named methods such as ofInt, ofNode and captureGroups.

for a senior

Point out that the JavaScript and TypeScript SDK lacks bodyStream and css ofNode entirely, so a JVM check cannot always be ported straight across.

for a principal

Own whether a mixed-language suite is worth the cost, given that the JavaScript SDK is a subset of the JVM check surface.

Every path-style check in Gatling extracts a **String** unless you say otherwise. For `jsonPath` and `jmesPath` the reference is explicit that non-String values are *serialised back into JSON* rather than handed over as numbers or booleans, and that the check will then **fail** if the actual value does not match the type you declare. Declaring the type is a step of its own, and it is spelled differently depending on which SDK you are in. ## Scala: one generic method ```scala .check( jsonPath("$.foo").ofType[Int], jsonPath("$.foo").ofType[Seq[Any]], css("article.more a", "href").ofType[Node], regex("foo(.*)bar(.*)baz").ofType[(String, String)] ) ``` Scala's `ofType[T]` is one method parameterised by the target type. For `regex` it also serves as the multi-capture-group form, taking a tuple of up to eight Strings. ## Java, Kotlin, JavaScript and TypeScript: a family of named methods There is **no public `ofType` in the Java API**. The builder interfaces declare a named method per type: | what you want | Java / Kotlin / JS / TS | Scala | |---|---|---| | String | `ofString()` | `ofType[String]` | | Boolean | `ofBoolean()` | `ofType[Boolean]` | | Int / Long / Double | `ofInt()` / `ofLong()` / `ofDouble()` | `ofType[Int]` etc. | | JSON array | `ofList()` | `ofType[Seq[Any]]` | | JSON object | `ofMap()` | `ofType[Map[String, Any]]` | | any JSON value | `ofObject()` | `ofType[Any]` | | a DOM node from `css` | `ofNode()` | `ofType[Node]` | | several regex capture groups | `captureGroups(n)` | `ofType[(String, String)]` | Because Kotlin and the JavaScript/TypeScript SDK both sit on the Java API rather than on the Scala core, they use the Java column. This is the same split that gives Scala a single `inject` while the other four languages call `injectOpen`/`injectClosed` — the boundary is Java API versus Scala core, not "Java versus everyone else". ## Two gaps that are JVM-only The JavaScript/TypeScript SDK is a subset, and the documentation marks the gaps by rendering the sample region as the literal text `NOT SUPPORTED`. Two of those gaps land squarely on this pipeline: 1. **`css(...).ofNode()`** — the `css-ofType` sample region renders as `NOT SUPPORTED` in the TypeScript sample file. You can select nodes with `css` in JS/TS and read their text or an attribute; you cannot ask for the DOM node object itself. 2. **`bodyStream`** — the whole check type renders as `NOT SUPPORTED` in the same file. The JVM SDKs use it to `transform` the raw `InputStream` before processing — decoding a Base64 body, for example — and JS/TS has no equivalent. Everything else on the typed-extraction step, including `ofInt()` and `captureGroups(n)`, is present in JS/TS. ## Where the step sits in the chain Typed extraction attaches to the **check-type** end of the chain, before or as part of extraction; the rest of the pipeline is unchanged. `jsonPath("$.qty").ofInt().gt(0)` is check type, typed extraction, implicit `find()`, then the `gt` validation. Getting the type wrong does not fail at compile time — it fails at run time, because the check cannot coerce the actual value and reports a failure like any other. ## Two spellings to keep straight * `ofType` in a Java, Kotlin or JS/TS simulation does not compile — the method is `protected` on the default implementations and exists only as the bridge to the Scala core. * The documentation's sample *region* is named `css-ofType` and `jsonPath-ofType` in **all** language tabs, because the region name is shared across the files. The name of the region is not the name of the method in four of the five languages. ## And the Kotlin reserved words Once you have your typed value the validation step follows, and in Kotlin two of its methods collide with language keywords: `is` is written `shouldBe` and `in` is written `within`. So a typed check reads `jsonPath("$.qty").ofInt().shouldBe(3)` in Kotlin against `jsonPath("$.qty").ofInt().is(3)` in Java.

  • What does a `jsonPath` check extract if you declare no type at all?
    A String. Non-String JSON values are serialised back into JSON text, so a number arrives as its textual form and an object arrives as a JSON string. Declaring a type with `ofInt()` or `ofType[Int]` also makes the check fail if the actual value is not of that type.
  • Which two parts of the check pipeline are missing from the JavaScript and TypeScript SDK?
    The `bodyStream` check type and `css(...).ofNode()`. Both render as the literal text `NOT SUPPORTED` in the TypeScript sample files, so a reader of the Java tab alone never learns they are absent. Everything else on the pipeline, including `ofInt()` and `captureGroups(n)`, is present.
  • How do you capture two groups from one regular expression?
    In Java, Kotlin and JS/TS use `regex(pattern).captureGroups(2)`, which yields a list of Strings. In Scala use `regex(pattern).ofType[(String, String)]`, which yields a tuple; the tuple form supports up to eight groups. With no such step a regex extracts zero or one group as a String.

saying these in an interview costs you the question

  • Writing ofType in a Java, Kotlin or JavaScript simulation
  • Assuming jsonPath hands back a number without a type step
  • Believing the JavaScript SDK matches the JVM check surface exactly
  • Confusing the doc region name css-ofType with a real Java method