Command Palette
Search for a command to run...
Java
Enterprise Java SDK with thread safety and connection pooling
Installation & Setup
Required dependencies and setup for Java development
Java & Maven Setup
# Install Java 11 or higher
# On Ubuntu/Debian
sudo apt-get update
sudo apt-get install openjdk-11-jdk maven
brew install openjdk@11 maven
choco install openjdk11 maven
mvn archetype:generate -DgroupId=com.example -DartifactId=leakzero-client -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
cd leakzero-client
export LEAKZERO_API_KEY=your_api_key_here
mvn compile exec:java -Dexec.mainClass="BasicUsage"pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>leakzero-client</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.11.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.8</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
</plugin>
</plugins>
</build>
</project>Dockerfile
FROM openjdk:11-jre-slim
# Install Maven
RUN apt-get update && \
apt-get install -y maven && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline -B
COPY src ./src
CMD ["mvn", "exec:java", "-Dexec.mainClass=BasicUsage"]Java Version: This example requires Java 11+ for modern features like var keyword and enhanced HTTP client. Uses OkHttp for HTTP and Jackson for JSON processing.
Quick Start Example
Simple example to get you started with Java
BasicUsage.java
import java.util.*;
public class BasicUsage {
public static void main(String[] args) {
try {
LeakZeroClient client = new LeakZeroClient(System.getenv("LEAKZERO_API_KEY"));
SearchOptions options = new SearchOptions("email", "[email protected]");
options.setRowLimit(100);
SearchResult result = client.regularSearch(options);
System.out.printf("Found %d records%n", result.getTotalResults());
System.out.printf("Cost: $%.6f%n", result.getCost());
result.getData().stream().limit(5).forEach(record -> {
String breach = (String) record.getOrDefault("breach_name", "Unknown");
String date = (String) record.getOrDefault("breach_date", "Unknown");
System.out.printf("Breach: %s, Date: %s%n", breach, date);
});
Map<String, Object> analysis = client.analyzeBreaches(result);
System.out.printf("\nUnique breaches: %s%n", analysis.get("unique_breaches"));
client.close();
} catch (Exception e) {
System.err.printf("Search failed: %s%n", e.getMessage());
}
}
}Production ReadyComplete Java Implementation
Full-featured client with thread safety, connection pooling, and enterprise features
LeakZeroClient.java
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;
public class SearchOptions {
private String field;
private String value;
private String option = "exact";
private int rowLimit = 1000;
private Map<String, Object> autoExport;
public SearchOptions(String field, String value) {
this.field = field;
this.value = value;
}
public String getField() { return field; }
public void setField(String field) { this.field = field; }
public String getValue() { return value; }
public void setValue(String value) { this.value = value; }
public String getOption() { return option; }
public void setOption(String option) { this.option = option; }
public int getRowLimit() { return rowLimit; }
public void setRowLimit(int rowLimit) { this.rowLimit = Math.min(rowLimit, 10000); }
public Map<String, Object> getAutoExport() { return autoExport; }
public void setAutoExport(Map<String, Object> autoExport) { this.autoExport = autoExport; }
public Map<String, Object> toMap() {
Map<String, Object> map = new HashMap<>();
map.put("field", field);
map.put("value", value);
map.put("option", option);
map.put("rowLimit", rowLimit);
if (autoExport != null) {
map.put("autoExport", autoExport);
}
return map;
}
}
public class SearchResult {
private List<Map<String, Object>> data = new ArrayList<>();
private int totalResults = 0;
private double cost = 0.0;
private String requestId = "";
private int processingTime = 0;
private Map<String, Object> analysis = new HashMap<>();
public List<Map<String, Object>> getData() { return data; }
public void setData(List<Map<String, Object>> data) { this.data = data; }
public void addRecord(Map<String, Object> record) { this.data.add(record); }
public int getTotalResults() { return totalResults; }
public void setTotalResults(int totalResults) { this.totalResults = totalResults; }
public double getCost() { return cost; }
public void setCost(double cost) { this.cost = cost; }
public String getRequestId() { return requestId; }
public void setRequestId(String requestId) { this.requestId = requestId; }
public int getProcessingTime() { return processingTime; }
public void setProcessingTime(int processingTime) { this.processingTime = processingTime; }
public Map<String, Object> getAnalysis() { return analysis; }
public void setAnalysis(Map<String, Object> analysis) { this.analysis = analysis; }
public int size() { return data.size(); }
public boolean isEmpty() { return data.isEmpty(); }
}
public class BalanceResponse {
@JsonProperty("balance")
private double balance = 0.0;
@JsonProperty("currency")
private String currency = "USD";
@JsonProperty("lastUsage")
private String lastUsage = "";
public BalanceResponse() {}
public BalanceResponse(double balance, String currency, String lastUsage) {
this.balance = balance;
this.currency = currency;
this.lastUsage = lastUsage;
}
public double getBalance() { return balance; }
public void setBalance(double balance) { this.balance = balance; }
public String getCurrency() { return currency; }
public void setCurrency(String currency) { this.currency = currency; }
public String getLastUsage() { return lastUsage; }
public void setLastUsage(String lastUsage) { this.lastUsage = lastUsage; }
}
public class UsageStats {
@JsonProperty("totalRequests")
private int totalRequests = 0;
@JsonProperty("totalCost")
private double totalCost = 0.0;
@JsonProperty("requestsToday")
private int requestsToday = 0;
@JsonProperty("costToday")
private double costToday = 0.0;
@JsonProperty("requestsThisWeek")
private int requestsThisWeek = 0;
@JsonProperty("costThisWeek")
private double costThisWeek = 0.0;
public int getTotalRequests() { return totalRequests; }
public void setTotalRequests(int totalRequests) { this.totalRequests = totalRequests; }
public double getTotalCost() { return totalCost; }
public void setTotalCost(double totalCost) { this.totalCost = totalCost; }
public int getRequestsToday() { return requestsToday; }
public void setRequestsToday(int requestsToday) { this.requestsToday = requestsToday; }
public double getCostToday() { return costToday; }
public void setCostToday(double costToday) { this.costToday = costToday; }
public int getRequestsThisWeek() { return requestsThisWeek; }
public void setRequestsThisWeek(int requestsThisWeek) { this.requestsThisWeek = requestsThisWeek; }
public double getCostThisWeek() { return costThisWeek; }
public void setCostThisWeek(double costThisWeek) { this.costThisWeek = costThisWeek; }
}
public class ApiException extends Exception {
private final String errorCode;
private final int statusCode;
public ApiException(String errorCode, String message, int statusCode) {
super(String.format("API Error [%d]: %s - %s", statusCode, errorCode, message));
this.errorCode = errorCode;
this.statusCode = statusCode;
}
public String getErrorCode() { return errorCode; }
public int getStatusCode() { return statusCode; }
}
public class LeakZeroClient {
private static final Logger logger = LoggerFactory.getLogger(LeakZeroClient.class);
private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
private final String apiKey;
private final String baseUrl;
private final OkHttpClient httpClient;
private final ObjectMapper objectMapper;
private final int maxRetries;
public LeakZeroClient(String apiKey) {
this(apiKey, "https://api.leakzero.io/api/v1", 3, 120);
}
public LeakZeroClient(String apiKey, String baseUrl, int maxRetries, int timeoutSeconds) {
if (apiKey == null || apiKey.trim().isEmpty()) {
throw new IllegalArgumentException("API key is required");
}
this.apiKey = apiKey;
this.baseUrl = baseUrl.replaceAll("/$", "");
this.maxRetries = maxRetries;
this.objectMapper = new ObjectMapper();
this.httpClient = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(timeoutSeconds, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES))
.retryOnConnectionFailure(true)
.build();
}
private Headers generateHeaders() {
return new Headers.Builder()
.add("x-api-key", apiKey)
.add("x-timestamp", Instant.now().toString())
.add("x-request-id", generateRequestId())
.add("Content-Type", "application/json")
.add("User-Agent", "LeakZero-Java-SDK/1.0.0")
.build();
}
private String generateRequestId() {
return "req_" + System.currentTimeMillis() / 1000 + "_" +
UUID.randomUUID().toString().substring(0, 8);
}
private Response makeRequestWithRetry(String method, String endpoint, Object payload)
throws ApiException, IOException {
String url = baseUrl + endpoint;
Headers headers = generateHeaders();
RequestBody body = null;
if (payload != null) {
String json = objectMapper.writeValueAsString(payload);
body = RequestBody.create(json, JSON);
}
Request request = new Request.Builder()
.url(url)
.headers(headers)
.method(method, body)
.build();
for (int attempt = 0; attempt <= maxRetries; attempt++) {
try {
Response response = httpClient.newCall(request).execute();
if (response.code() == 429) {
String retryAfterHeader = response.header("Retry-After");
int retryAfter = retryAfterHeader != null ?
Math.min(Integer.parseInt(retryAfterHeader), 30) : 5;
logger.warn("Rate limited. Waiting {}s", retryAfter);
response.close();
try {
Thread.sleep(retryAfter * 1000L);
continue;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Request interrupted", e);
}
}
if (response.code() >= 400) {
String responseBody = response.body() != null ? response.body().string() : "";
try {
JsonNode errorNode = objectMapper.readTree(responseBody);
String errorCode = errorNode.has("error") ?
errorNode.get("error").asText() : "HTTP_ERROR";
String errorMessage = errorNode.has("message") ?
errorNode.get("message").asText() : "HTTP " + response.code();
response.close();
throw new ApiException(errorCode, errorMessage, response.code());
} catch (Exception e) {
response.close();
throw new ApiException("HTTP_ERROR", "HTTP " + response.code(), response.code());
}
}
logger.info("API Request successful: {} {}", method, endpoint);
return response;
} catch (ApiException e) {
if (attempt == maxRetries) {
throw e;
}
logger.warn("Request attempt {} failed: {}", attempt + 1, e.getMessage());
try {
Thread.sleep((attempt + 1) * 1000L);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Request interrupted", ie);
}
}
}
throw new RuntimeException("Max retries exceeded");
}
public BalanceResponse getBalance() throws ApiException, IOException {
try (Response response = makeRequestWithRetry("GET", "/public/balance", null)) {
String responseBody = response.body().string();
return objectMapper.readValue(responseBody, BalanceResponse.class);
} catch (Exception e) {
logger.error("Failed to get balance: {}", e.getMessage());
throw e;
}
}
public SearchResult regularSearch(SearchOptions options) throws ApiException, IOException {
options.setRowLimit(Math.min(options.getRowLimit(), 10000));
try {
logger.info("Searching for {}: {}", options.getField(), options.getValue());
try (Response response = makeRequestWithRetry("POST", "/public/search/regular", options.toMap())) {
SearchResult result = new SearchResult();
String rowsReturned = response.header("x-rows-returned");
result.setTotalResults(rowsReturned != null ? Integer.parseInt(rowsReturned) : 0);
String charge = response.header("x-charge");
result.setCost(charge != null ? Integer.parseInt(charge) / 1_000_000_000.0 : 0.0);
result.setRequestId(response.header("x-request-id", ""));
String processingTime = response.header("x-processing-time");
result.setProcessingTime(processingTime != null ? Integer.parseInt(processingTime) : 0);
String responseBody = response.body().string();
JsonNode jsonNode = objectMapper.readTree(responseBody);
if (jsonNode.has("data") && jsonNode.get("data").isArray()) {
for (JsonNode recordNode : jsonNode.get("data")) {
Map<String, Object> record = objectMapper.convertValue(recordNode, Map.class);
result.addRecord(record);
}
}
logger.info("Found {} records (Cost: {:.6f})", result.getTotalResults(), result.getCost());
return result;
} catch (Exception e) {
logger.error("Regular search failed: {}", e.getMessage());
throw e;
}
}
}Enterprise Ready: Connection pooling, thread safety, and resource management
Modern Java: Streams, CompletableFuture, and lambda expressions
High Performance: OkHttp with connection pooling and async operations
Key Features
Core Features
- • Strong typing with generics and annotations
- • Thread-safe operations with concurrent collections
- • Automatic retry with exponential backoff
- • Rate limit handling with intelligent delays
- • Comprehensive exception handling
Performance Features
- • OkHttp with connection pooling
- • CompletableFuture for async operations
- • Stream API for efficient data processing
- • Jackson for high-performance JSON parsing
- • Resource management with try-with-resources
Best Practices:
- • Always use environment variables for API keys
- • Implement proper exception handling in production
- • Use CompletableFuture for concurrent operations
- • Monitor your API usage and balance regularly
- • Close resources properly with try-with-resources