InfraNode with Java: HttpClient and OpenAPI Generator
Tutorial: fetch open data for German cities from Java, with the built-in java.net.http.HttpClient and Jackson or with a typed client that OpenAPI Generator builds from the official spec. No API key.
Option 1: HttpClient and Jackson
Since Java 11 the JDK ships java.net.http.HttpClient, which covers
HTTP. For the JSON, Jackson is the only dependency you need (Maven):
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.18.2</version>
</dependency>
Every response has the same envelope: the data under data, the
source status under meta. For a single record the values sit in
data.payload and the source credit in data.attribution.
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class Main {
private static final String BASE = "https://infranode.dev/api/v1";
private static final HttpClient HTTP = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
private static final ObjectMapper JSON = new ObjectMapper();
static JsonNode get(String path) throws Exception {
HttpRequest req = HttpRequest.newBuilder(URI.create(BASE + path))
.header("Accept", "application/json")
.timeout(Duration.ofSeconds(30))
.build();
HttpResponse<String> res = HTTP.send(req, HttpResponse.BodyHandlers.ofString());
if (res.statusCode() != 200) {
throw new IllegalStateException("HTTP " + res.statusCode() + ": " + res.body());
}
return JSON.readTree(res.body());
}
public static void main(String[] args) throws Exception {
JsonNode data = get("/cities/berlin/weather").path("data");
System.out.println(data.path("payload").path("temperature_c").asDouble() + " °C");
System.out.println("Source: " + data.path("attribution").path("text").asText());
JsonNode cities = get("/cities").path("data");
System.out.println(cities.size() + " cities");
}
}
Every record carries its own attribution (source and license URL).
The open data licenses require the credit, so show it to your users. The
available data types are listed in the data catalog.
Option 2: typed client via OpenAPI Generator
If you prefer classes over JsonNode, generate the client from the
official spec at
https://infranode.dev/openapi.json. With Docker
there is nothing to install locally:
docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli:v7.10.0 generate \
-i https://infranode.dev/openapi.json \
-g java --library native \
-o /local/infranode-client \
--api-package dev.infranode.api \
--model-package dev.infranode.model \
--invoker-package dev.infranode.client --library native builds on the JDK HttpClient and only pulls in
Jackson. Then install the client into your local Maven repository:
cd infranode-client
mvn install -DskipTests
Add the generated client through the coordinates in its pom.xml
(default: org.openapitools:openapi-java-client). Every data type
has its own method, e.g. getCityWeather,
getCityParking or getCityCharging:
import dev.infranode.api.CitiesApi;
import dev.infranode.client.ApiClient;
import dev.infranode.client.ApiException;
import dev.infranode.model.CanonicalRecord;
import dev.infranode.model.WeatherPayload;
public class Weather {
public static void main(String[] args) throws ApiException {
ApiClient client = new ApiClient();
client.updateBaseUri("https://infranode.dev");
CitiesApi cities = new CitiesApi(client);
CanonicalRecord rec = cities.getCityWeather("berlin").getData();
WeatherPayload w = rec.getPayload().getWeatherPayload();
System.out.println(w.getTemperatureC() + " °C");
System.out.println("Source: " + rec.getAttribution().getText());
// Errors (404 unknown city, 503 source down) arrive as ApiException
try {
cities.getCityWeather("essen");
} catch (ApiException e) {
System.out.println("HTTP " + e.getCode());
}
}
} payload is a union over all payload types, told apart by the
kind field. Get the matching type with its getter
(getWeatherPayload(), getParkingPayload(), ...) or
generically with getActualInstance().
Further reading
Endpoints and parameters: API reference. List endpoints support optional paging, see pagination. For AI agents there is the InfraNode MCP server.
Frequently asked questions
- Is there an official Java SDK?
- No, there is no dedicated Java package. The API is lean enough for the built-in HttpClient, and for typed classes OpenAPI Generator builds a complete client from https://infranode.dev/openapi.json.
- Do I need an API key?
- No. The InfraNode API is free and keyless. No key, no sign-up.
- Which Java version do I need?
- Java 11 or newer. java.net.http.HttpClient has been part of the JDK since Java 11, and the generated client targets Java 11 as well.
- Does this work with Kotlin or Spring?
- Yes. The generated Java client runs unchanged in Kotlin. OpenAPI Generator also has dedicated targets such as -g kotlin, or --library resttemplate and webclient for Spring.