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"
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>
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;
}
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) { }
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());
}
}
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();
}
}
This API gives you two simple endpoints:
GET /api/users/{count}
— returns N usersGET /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
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"
}
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
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
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)