Overview
Recently, I built a lightweight RESTful API using only Java — no Spring Boot, no frameworks, just the standard Java libraries.
The goal was to create a simple /me endpoint that returns my profile information along with a dynamic cat fact fetched from an external API called Cat Facts API (https://catfact.ninja/fact).
This task validated my ability to:
- Consume third-party APIs
- Format JSON responses
- Return dynamic data from a Java HTTP server
- Handle errors and timeouts gracefully
🧩 The Task
The requirements were clear:
✅ Create a GET endpoint at /me
✅ Return JSON data with this structure:
{
"status": "success",
"user": {
"email": "get2adeshola@gmail.com",
"name": "Adeshola Adetona",
"stack": "Java"
},
"timestamp": "2025-10-18T12:34:56.789Z",
"fact": "A random cat fact"
}
Fetch a fresh random fact from Cat Facts API on every request
Handle API failure gracefully
Ensure Content-Type: application/json
Tools & Stack
Language: Java 17
Libraries: None (used com.sun.net.httpserver.HttpServer)
IDE: IntelliJ IDEA
Version Control: Git + GitHub
Testing Tool: cURL / Browser
🧱 Implementation Steps
Step 1 — Create a Simple HTTP Server
Instead of using Spring Boot, I used Java’s built-in HTTP server:
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
server.createContext("/me", new ProfileHandler());
server.setExecutor(null);
server.start();
System.out.println("Server started on port 8080");
This created a lightweight server that listens for requests on port 8080.
Step 2 — Define the Handler
The handler processes /me requests, fetches a random cat fact, and builds the JSON response:
public void handle(HttpExchange exchange) throws IOException {
if ("GET".equals(exchange.getRequestMethod())) {
String fact = fetchCatFact();
String response = buildResponse(fact);
exchange.getResponseHeaders().set("Content-Type", "application/json");
exchange.sendResponseHeaders(200, response.getBytes().length);
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
Step 3 — Fetching the Cat Fact
I connected to the public Cat Facts API using HttpURLConnection:
private static String fetchCatFact() {
try {
URL url = new URL("https://catfact.ninja/fact");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(3000);
conn.setReadTimeout(3000);
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String json = reader.lines().collect(Collectors.joining());
reader.close();
return new JSONObject(json).getString("fact");
} catch (Exception e) {
return "Could not fetch cat fact at this time.";
}
}
This ensures:
Each request gets a new cat fact
If the API fails, a fallback message appears instead
Step 4 — Generate the JSON Response
private static String buildResponse(String fact) {
JSONObject response = new JSONObject();
response.put("status", "success");
JSONObject user = new JSONObject();
user.put("email", "get2adeshola@gmail.com");
user.put("name", "Adeshola Adetona");
user.put("stack", "Java");
response.put("user", user);
response.put("timestamp", Instant.now().toString());
response.put("fact", fact);
return response.toString();
}
Testing the API
I ran the server locally with:
java ProfileServer
Then tested it using:
Output:
{
"status": "success",
"user": {
"email": "get2adeshola@gmail.com",
"name": "Adeshola Adetona",
"stack": "Java"
},
"timestamp": "2025-10-18T14:22:07.231Z",
"fact": "Cats sleep for 70% of their lives."
}
This task taught me:
How to serve APIs without frameworks
I now understand how Spring Boot simplifies low-level operations.
HTTP fundamentals : handling connections, status codes, and headers manually.
Resilience : implementing fallback responses for third-party API failures.
Clean JSON formatting and working with timestamps in ISO 8601.
Version control workflow : initializing a repo, committing, and pushing to GitHub.
Repository
https://github.com/Tonathe3rd/Dynamic-Profile-Endpoint-HNG
API can be found in the Railway app here: https://dynamic-profile-endpoint-hng-production.up.railway.app/me
Conclusion
Building this project from scratch reminded me that even without frameworks, Java remains powerful for web development, it just requires a little more setup.
This exercise sharpened my understanding of how HTTP servers, JSON, and APIs work under the hood.
Author
Adeshola Adetona
get2adeshola@gmail.com
Backend Stack: Java
Cat Fact Enthusiast
Top comments (0)