DEV Community

Cover image for Generating Realistic Fake Data in Java with Quarkus, DataFaker & EasyRandom
Wallace Espindola
Wallace Espindola

Posted on

Generating Realistic Fake Data in Java with Quarkus, DataFaker & EasyRandom

Let’s be honest — your test data probably looks a little… robotic.
You know the drill: “John Doe”, “test@example.com”, “123 Main Street”.

It works, but it’s painfully obvious that it’s fake.

And if you’re demoing your API, seeding a database, or stress-testing your app, that kind of data just doesn’t cut it anymore.

The good news? With Quarkus, DataFaker, and EasyRandom, you can generate realistic, varied, and structured data — fast, elegant, and believable.

By the end of this article, you’ll have a Quarkus REST API that returns lifelike fake users — names, emails, phones, and addresses — all neatly timestamped.

Full code example here:
👉 github.com/wallaceespindola/fake-data-quarkus

Let’s dive in.


Why Fake Data Matters More Than Ever

If you’re a backend dev, you’ve probably needed mock data for one of these:

  • Testing APIs or UI components

  • Populating demo environments

  • Running performance or load tests

  • Anonymizing real data for staging environments

And sure, you could throw in “John Doe” again.
But what if you could generate realistic, localized names, addresses, and emails that feel like real-world data — and do it dynamically, in a fast Quarkus service?

That’s what we’re building.


The Stack

We’ll use:

  • Quarkus — the fast, lightweight Java framework for modern apps

  • DataFaker — for generating realistic values

  • EasyRandom — for filling entire objects automatically

  • Lombok — to cut boilerplate

  • OpenAPI + Swagger UI — for quick API testing


Project Setup

Generate a Quarkus project using the CLI or code.quarkus.io:

mvn io.quarkus.platform:quarkus-maven-plugin:3.12.1:create \
  -DprojectGroupId=com.example \
  -DprojectArtifactId=fake-data-quarkus \
  -DclassName="com.example.fakedata.UserResource" \
  -Dpath="/api/users"
Enter fullscreen mode Exit fullscreen mode

Then, add dependencies to your pom.xml:

<dependencies>
  <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-resteasy-reactive</artifactId>
  </dependency>
  <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-smallrye-openapi</artifactId>
  </dependency>
  <dependency>
    <groupId>net.datafaker</groupId>
    <artifactId>datafaker</artifactId>
    <version>2.2.2</version>
  </dependency>
  <dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-random-core</artifactId>
    <version>5.0.0</version>
  </dependency>
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
  </dependency>
  <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-junit5</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>
Enter fullscreen mode Exit fullscreen mode

The Domain

Let’s start small — our fake “User” object:

package com.example.fakedata.domain;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class User {
  private String id;
  private String fullName;
  private String email;
  private String phone;
  private String address;
}
Enter fullscreen mode Exit fullscreen mode

And a DTO version for API responses:

package com.example.fakedata.dto;

public record UserDto(String id, String fullName, String email, String phone, String address) { }
Enter fullscreen mode Exit fullscreen mode

We’re using Lombok for the model and a Java Record for the DTO to keep things clean.


The Data Generation Service

Here’s where we mix DataFaker and EasyRandom for maximum awesomeness:

package com.example.fakedata.service;

import com.example.fakedata.domain.User;
import jakarta.enterprise.context.ApplicationScoped;
import net.datafaker.Faker;
import org.jeasy.random.EasyRandom;
import org.jeasy.random.EasyRandomParameters;

import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@ApplicationScoped
public class DataGenService {

  private final Faker faker = new Faker(Locale.ENGLISH);
  private final EasyRandom easyRandom;

  public DataGenService() {
    EasyRandomParameters params = new EasyRandomParameters()
        .seed(System.currentTimeMillis())
        .stringLengthRange(5, 20);
    this.easyRandom = new EasyRandom(params);
  }

  public User randomUserViaDatafaker() {
    return User.builder()
        .id(UUID.randomUUID().toString())
        .fullName(faker.name().fullName())
        .email(faker.internet().emailAddress())
        .phone(faker.phoneNumber().cellPhone())
        .address(faker.address().fullAddress())
        .build();
  }

  public User randomUserViaEasyRandom() {
    User u = easyRandom.nextObject(User.class);
    if (u.getId() == null || u.getId().isBlank())
      u.setId(UUID.randomUUID().toString());
    u.setFullName(faker.name().fullName());
    u.setEmail(faker.internet().emailAddress());
    return u;
  }

  public List<User> manyUsers(int count, boolean useEasyRandom) {
    return IntStream.range(0, Math.max(0, count))
        .mapToObj(i -> useEasyRandom ? randomUserViaEasyRandom() : randomUserViaDatafaker())
        .collect(Collectors.toList());
  }
}
Enter fullscreen mode Exit fullscreen mode

Here’s the beauty of it:

  • DataFaker generates names, addresses, and emails that sound real.

  • EasyRandom handles the object creation for you.

Combine them, and you’ve got structured data that looks human.


The REST API

Now, let’s make it accessible with Quarkus RESTEasy Reactive.

package com.example.fakedata;

import com.example.fakedata.domain.User;
import com.example.fakedata.dto.UserDto;
import com.example.fakedata.service.DataGenService;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;

import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;

@Path("/api/users")
@Produces(MediaType.APPLICATION_JSON)
@Tag(name = "Users", description = "Generate fake users with DataFaker + EasyRandom")
public class UserResource {

  @Inject
  DataGenService service;

  record ApiResponse<T>(T data, Instant timestamp) {
    static <T> ApiResponse<T> of(T data) {
      return new ApiResponse<>(data, Instant.now());
    }
  }

  @GET
  @Path("/{count}")
  @Operation(summary = "Generate a list of fake users")
  public Response generateUsers(@PathParam("count") int count,
                                @QueryParam("easy") @DefaultValue("false") boolean easy) {
    List<UserDto> users = service.manyUsers(count, easy)
        .stream()
        .map(u -> new UserDto(u.getId(), u.getFullName(), u.getEmail(), u.getPhone(), u.getAddress()))
        .collect(Collectors.toList());
    return Response.ok(ApiResponse.of(users)).build();
  }

  @GET
  @Path("/one")
  @Operation(summary = "Generate one fake user")
  public Response oneUser() {
    User u = service.randomUserViaDatafaker();
    return Response.ok(ApiResponse.of(new UserDto(u.getId(), u.getFullName(), u.getEmail(), u.getPhone(), u.getAddress()))).build();
  }
}
Enter fullscreen mode Exit fullscreen mode

This API gives you two simple endpoints:

  • GET /api/users/{count} — returns N users

  • GET /api/users/one — returns a single fake user

Every response includes a timestamp, so you know exactly when it was generated.

Run It

Start Quarkus in dev mode:

./mvnw quarkus:dev
Enter fullscreen mode Exit fullscreen mode

Visit:

👉 http://localhost:8080/q/swagger-ui

Try:

GET /api/users/3

Sample output:

{
  "data": [
    {
      "id": "a8a5fbb3-47b6-4387-9827-8c9b8ac6e9dc",
      "fullName": "Rosa Bianchi",
      "email": "rosa.bianchi@example.it",
      "phone": "+39 349 123 4567",
      "address": "Via Roma 45, Milano"
    },
    {
      "id": "c48de9e7-92f4-4b15-8bcb-3c1b3a710c0c",
      "fullName": "James Holloway",
      "email": "james.holloway@demo.io",
      "phone": "+1 415 555 1829",
      "address": "77 Market Street, San Francisco"
    }
  ],
  "timestamp": "2025-10-06T18:45:33.982Z"
}
Enter fullscreen mode Exit fullscreen mode

Looks real enough to demo your next project, right?


Bonus: Built-In Swagger & OpenAPI

Quarkus comes with OpenAPI + Swagger UI ready to go.

No config hell, no dependencies to chase. Just hit /q/swagger-ui and explore your endpoints visually.

Want to tweak the OpenAPI path?

Just update application.properties:

quarkus.smallrye-openapi.path=/openapi
quarkus.swagger-ui.always-include=true
Enter fullscreen mode Exit fullscreen mode

Why This Combo Works

  • DataFaker brings authenticity — localized names, realistic emails, believable data.

  • EasyRandom handles complexity — fills entire objects without effort.

  • Quarkus ties it together with speed and simplicity — minimal setup, instant hot reloads, and small footprint.

You end up with a lightning-fast, production-like data generator that’s perfect for modern development.


Real Use Cases

  • Preloading a test database

  • Filling front-end prototypes with real-looking data

  • Stress-testing APIs with variety

  • Creating synthetic datasets for analytics

  • Replacing sensitive info in QA or sandbox environments


Going Native (Optional)

Want to go wild? Build it as a native binary using GraalVM:

./mvnw package -Pnative
./target/fake-data-quarkus-1.0.0-runner
Enter fullscreen mode Exit fullscreen mode

Startup time? Instant.
Memory footprint? Tiny.
Speed? Ridiculous.

Perfect for containers, CI pipelines, or quick mock environments.


Final Thoughts

Fake data doesn’t have to be boring.
With Quarkus, DataFaker, and EasyRandom, you can generate realistic, rich, and structured data that makes your applications — and demos — feel alive.

This setup is fast, modern, and ready to use for everything from testing to production seeding.

So next time you’re building or testing an API, forget “John Doe”.
Give your fake data a little soul.


Need more tech insights?

Check out my GitHub, LinkedIn, and SpeakerDeck.

Support my work: Buy Me A Coffee

Top comments (0)