Java License Validation
This guide shows how to integrate Avalex license validation into your Java applications (desktop apps, plugins, microservices, or CLI tools) using the lightweight, zero-dependencyLicenseValidationClient class.
The LicenseValidationClient Class
Copy this self-contained class directly into your Java project. It uses standard Java standard library utilities (HttpURLConnection, MessageDigest, Pattern) and requires zero external dependencies.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LicenseValidationClient {
private static final String VALIDATE_PATH = "/licenses/validate";
private static final Pattern VALID_FIELD_PATTERN =
Pattern.compile("\"valid\"\\s*:\\s*(true|false)", Pattern.CASE_INSENSITIVE);
private LicenseValidationClient() {
}
public static boolean validate(String baseUrl, String licenseId, String productId, String hwid) throws IOException {
if (baseUrl == null || baseUrl.isEmpty()) {
throw new IllegalArgumentException("baseUrl is missing.");
}
if (licenseId == null || licenseId.isEmpty()) {
throw new IllegalArgumentException("licenseId is missing.");
}
if (productId == null || productId.isEmpty()) {
throw new IllegalArgumentException("productId is missing.");
}
if (hwid == null) {
hwid = "";
}
String normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
String jsonInputString = String.format(
"{\"licenseId\": \"%s\", \"productId\": \"%s\", \"hwid\": \"%s\"}",
escape(licenseId), escape(productId), escape(hwid)
);
URL url = new URL(normalizedBaseUrl + VALIDATE_PATH);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
conn.setRequestProperty("Accept", "application/json");
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}
int responseCode = conn.getResponseCode();
if (responseCode == 429) {
throw new RuntimeException("Rate limited by license server. Try again shortly.");
}
if (responseCode != 200) {
throw new RuntimeException("License server error. Response Code: " + responseCode
+ " : " + conn.getResponseMessage());
}
String body = readBody(conn.getInputStream());
Matcher m = VALID_FIELD_PATTERN.matcher(body);
if (!m.find()) {
throw new RuntimeException("Unexpected response from license server: " + body);
}
return Boolean.parseBoolean(m.group(1));
}
private static String readBody(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
}
return sb.toString();
}
private static String escape(String s) {
return s.replace("\\", "\\\\").replace("\"", "\\\"");
}
public static String getHWID() {
try {
String toEncrypt = System.getenv("COMPUTERNAME") + System.getProperty("user.name")
+ System.getenv("PROCESSOR_IDENTIFIER") + System.getenv("PROCESSOR_LEVEL");
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(toEncrypt.getBytes(StandardCharsets.UTF_8));
byte[] byteData = md.digest();
StringBuilder hexString = new StringBuilder();
for (byte aByteData : byteData) {
String hex = Integer.toHexString(0xff & aByteData);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (Exception e) {
e.printStackTrace();
return "Error";
}
}
}
How to Use the Client in Your Application
1. Simple Validation Call
To validate a license key at startup:String baseUrl = "https://license.yourdomain.com";
String licenseKey = "ABCD-EFGH-IJKL-MNOP";
String productId = "my-awesome-plugin";
String hwid = LicenseValidationClient.getHWID();
try {
boolean isValid = LicenseValidationClient.validate(baseUrl, licenseKey, productId, hwid);
if (isValid) {
System.out.println("License is valid! Starting application...");
// Start your application
} else {
System.err.println("License validation failed (invalid key, expired, or max activations reached).");
System.exit(1);
}
} catch (IOException e) {
System.err.println("Network error connecting to license server: " + e.getMessage());
} catch (RuntimeException e) {
System.err.println("Validation error: " + e.getMessage());
}
2. Full Application Lifecycle Example
Here is a complete, production-ready startup pattern that validates the license, handles rate limits (HTTP 429), and implements a local fallback grace period if the licensing server is temporarily unreachable:
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
public class MainApp {
private static final String BASE_URL = "https://license.yourdomain.com";
private static final String PRODUCT_ID = "my-desktop-tool";
private static final long GRACE_PERIOD_MILLIS = 48 * 60 * 60 * 1000L; // 48 Hours
public static void main(String[] args) {
String licenseKey = loadUserLicenseKey(); // e.g. from config.json or UI input
String hwid = LicenseValidationClient.getHWID();
try {
boolean valid = LicenseValidationClient.validate(BASE_URL, licenseKey, PRODUCT_ID, hwid);
if (valid) {
System.out.println("License verified successfully.");
updateLocalGraceTimestamp();
launchApp();
} else {
System.err.println("License is invalid or expired. Please purchase a license.");
System.exit(1);
}
} catch (RuntimeException | IOException ex) {
System.err.println("License server could not be reached: " + ex.getMessage());
if (isWithinGracePeriod()) {
System.out.println("Operating in offline grace period mode.");
launchApp();
} else {
System.err.println("Grace period expired. Internet connection required to verify license.");
System.exit(1);
}
}
}
private static void launchApp() {
System.out.println("Application initialized.");
}
private static String loadUserLicenseKey() {
return "ABCD-EFGH-IJKL-MNOP";
}
private static void updateLocalGraceTimestamp() {
// Persist System.currentTimeMillis() locally (encrypted if possible)
}
private static boolean isWithinGracePeriod() {
// Check if now - lastVerifiedTimestamp < GRACE_PERIOD_MILLIS
return false;
}
}
