Skip to content

JPostman Tutorial Part 3: Access Token and Chained Requests

David Gofman edited this page Jun 8, 2026 · 4 revisions

Access Token and Chained Requests

Video tutorial: https://www.youtube.com/watch?v=u3Z9yjglmTs

Overview

In this tutorial, we go deeper into JPostman and review important features for real API test automation.

You will learn how JPostman handles immutable Request objects, how to resolve Postman environment placeholders, how to validate API responses with assertions, and how to chain REST API requests by passing an access token from one response into another request.

This tutorial continues from the previous setup where the Java Maven project already uses JPostman and the RestAssured executor.

What You Will Learn

By the end of this tutorial, you will know how to:

  • Understand why the JPostman Request object is immutable.
  • Build a resolved request using Postman environment values.
  • Compare unresolved and resolved requests.
  • Customize request URL, headers, auth, and body values with the request builder.
  • Store API execution results in an ApiResponse.
  • Assert the expected HTTP status code.
  • Use a Postman collection reference for cleaner code.
  • Rename variables for better readability.
  • Debug missing authorization values.
  • Extract an accessToken from one response.
  • Use the token in a second request.
  • Create a chained request flow.

Prerequisites

Before starting this tutorial, make sure you completed the previous tutorials:

  • Part 1: Java Maven project setup with jpostman-core.
  • Part 2: Execute REST API requests using jpostman-restassured.

You should already have:

  • A Maven test project.
  • Exported Postman collection JSON file.
  • Exported Postman environment JSON file.
  • JPostman dependencies configured.
  • A TestNG test class.
  • RestAssured executor working.

Part 1 Video

https://www.youtube.com/watch?v=UxFjeONEq60

Part 2 Video

https://www.youtube.com/watch?v=hwsDjBSxIRs

Step 1: Understand Request Immutability

JPostman Request objects are immutable.

This means the original request loaded from the exported Postman collection cannot be changed directly.

When you load a request from the collection, it keeps the same structure and placeholder values that came from Postman.

Example unresolved values may look like this:

{{base_url}}
{{username}}
{{password}}
{{accessToken}}

To apply environment values or custom changes, you must create a new resolved request using the request builder.

Step 2: Build a Resolved Request

JPostman uses the builder to resolve placeholders from the Postman environment.

Example:

Request resolvedRequest = req.builder().build(env);

This creates a new Request object with environment values applied.

The original request remains unchanged.

Step 3: Compare Original and Resolved Requests

To inspect the difference between the original request and the resolved request, print both:

req.print();

Request resolvedRequest = req.builder().build(env);
resolvedRequest.print();

When you run the test, the console shows that:

  • The original request still contains unresolved placeholders.
  • The resolved request replaces placeholders with values from the environment JSON file.

This helps confirm that JPostman does not mutate the original collection request.

Step 4: Review Request Builder Customization

The request builder can also manually customize request values before execution.

Common builder sections include:

url()
headers()
auth()
body()

Example:

Request resolvedRequest = req.builder()
        .url()
            .add("q", "hello+world")
            .map("base_url", "https://example.com")
            .end()
        .body()
            .set("username", "sam")
            .add("age", 21)
            .end(env.getParams())
        .build();

This example shows how to:

  • Add a URL query parameter.
  • Replace the {{base_url}} placeholder.
  • Replace an existing request body field.
  • Add a new request body field.
  • Resolve remaining body placeholders from the environment.
  • Build a new resolved Request.

After execution, the resolved request contains the updated URL and body values.

Step 5: Add Response Validation

A TestNG test can pass even when the API returns an error status code unless you add assertions.

For example, an API may return:

405 Method Not Allowed

The test runner may still mark the test as passed if no assertion fails.

To properly validate the API result, store the execution result and assert the expected status code.

Import ApiResponse:

import io.jpostman.ApiResponse;

Add a static import for TestNG assertEquals:

import static org.testng.Assert.assertEquals;

Execute the request and store the response:

ApiResponse res = RestAssuredExecutor.execute(resolvedRequest);

Assert the response status code:

assertEquals(res.statusCode(), 200, "Body Result: " + res.pretty() + "
");

Now the test fails correctly when the API does not return the expected status code.

The assertion message includes the server response body for debugging.

Step 6: Clean Up the Request Code

After confirming the assertion works, remove temporary hardcoded request customizations.

The cleaned-up request flow should:

  1. Get the request from the collection.
  2. Resolve it with the environment.
  3. Execute it.
  4. Assert the response status code.

Example:

Request req = cxt.getCollection()
        .getRequest("Login user and get tokens")
        .builder()
        .build(env);

ApiResponse res = RestAssuredExecutor.execute(req);

assertEquals(res.statusCode(), 200, "Body Result: " + res.pretty() + "
");

Step 7: Use a Collection Variable

Before selecting more requests, create a local reference to the Postman collection.

Import the JPostman Collection class:

import io.jpostman.Collection;

Create a local variable:

Collection col = cxt.getCollection();

This makes the code cleaner when calling multiple requests:

Request reqToken = col.getRequest("Login user and get tokens")
        .builder()
        .build(env);

Step 8: Organize and Rename Variables

For readability, rename variables based on the request purpose.

Example:

Request reqToken
ApiResponse resToken

These names make it clear that the request and response are related to the login or token API call.

When adding a second request, use names like:

Request reqUser
ApiResponse resUser

This keeps chained request code easier to read and maintain.

Step 9: Print Available Collection Requests

To view available requests from the loaded Postman collection, print the collection:

col.print();

Run the test and review the console output.

For this tutorial, the second API request is:

Get current auth user

Step 10: Add the Second Request

Reuse the same request execution pattern for the second request.

Example:

Request reqUser = col.getRequest("Get current auth user")
        .builder()
        .build(env);

ApiResponse resUser = RestAssuredExecutor.execute(reqUser);

assertEquals(resUser.statusCode(), 200, "Body Result: " + resUser.pretty() + "
");

At this stage, the second request may fail with:

401 Access Token is required

This means the request is missing an authorization token.

Step 11: Debug the Missing Access Token

To debug the authorization issue, print the unresolved and resolved versions of the second request.

Example:

col.getRequest("Get current auth user").print();

col.getRequest("Get current auth user")
        .builder()
        .build(env)
        .print();

The console output shows that the unresolved request expects an accessToken, but the resolved request still has an empty value.

This means the environment does not yet contain the access token needed for the second API call.

Step 12: Review the Token Response

Print the token response:

resToken.print();

The login request returns an accessToken in the response body.

This token can be used in the next request.

Step 13: Chain the Requests with OAuth2 Authorization

Instead of relying on a static environment value, extract the token from the first response and pass it into the second request.

Use the token response path:

resToken.path("accessToken")

Then configure the second request authorization with OAuth2:

ApiResponse resUser = RestAssuredExecutor
        .apply(reqUser)
        .auth()
        .oauth2(resToken.path("accessToken"))
        .response();

This creates a chained request flow:

  1. Execute the login request.
  2. Extract accessToken from the login response.
  3. Use that token in the next request.
  4. Execute the authenticated user request.

Complete Example Flow

Example test flow:

import static org.testng.Assert.assertEquals;

import org.testng.annotations.Test;

import io.jpostman.ApiResponse;
import io.jpostman.Collection;
import io.jpostman.Environment;
import io.jpostman.JPostman;
import io.jpostman.JPostman.Context;
import io.jpostman.Request;
import io.jpostman.restassured.RestAssuredExecutor;

public class DemoTest {

    @Test
    public void test1() throws Exception {

        Context cxt = JPostman
                .fromResources()
                .collection("DummyJSON.postman_collection.json")
                .environment("DummyJSON.postman_environment.json")
                .build();

        Environment env = cxt.getEnvironment();
        Collection col = cxt.getCollection();

        Request reqToken = col.getRequest("Login user and get tokens")
                .builder()
                .build(env);

        ApiResponse resToken = RestAssuredExecutor.execute(reqToken);

        assertEquals(resToken.statusCode(), 200, "Body Result: " + resToken.pretty() + "
");

        Request reqUser = col.getRequest("Get current auth user")
                .builder()
                .build(env);

        ApiResponse resUser = RestAssuredExecutor
                .apply(reqUser)
                .auth()
                .oauth2(resToken.path("accessToken"))
                .response();

        assertEquals(resUser.statusCode(), 200, "Body Result: " + resUser.pretty() + "
");
    }
}

Update the collection and environment file names if your exported files use different names.

What the Test Does

This test performs a simple chained API flow:

  1. Loads the Postman collection.
  2. Loads the Postman environment.
  3. Gets the login request from the collection.
  4. Resolves environment placeholders.
  5. Executes the login request.
  6. Validates that login returns status code 200.
  7. Extracts the accessToken from the login response.
  8. Gets the authenticated user request.
  9. Applies OAuth2 authorization using the extracted token.
  10. Executes the second request.
  11. Validates that the authenticated request returns status code 200.

Why Chained Requests Are Useful

Chained requests are common in API test automation.

They are useful when one request depends on data returned from another request.

Common examples include:

  • Login request returns an access token.
  • Create request returns an ID used by a get, update, or delete request.
  • Search request returns an object used in a follow-up request.
  • Authentication request returns session data used by later requests.

JPostman makes this easier by letting you reuse Postman requests while still controlling dynamic values from Java.

Summary

In this tutorial, we reviewed how JPostman keeps collection requests immutable, how to create resolved requests with environment values, and how to validate API responses with TestNG assertions.

We also created a chained request flow by extracting an accessToken from a login response and passing it into a second authenticated request using OAuth2 authorization.

In the next tutorial, we will review best practices for organizing multiple requests in TestNG.

Related Links

Clone this wiki locally