Client integration
beanguard-client is a Spring Boot library you add to your own application so it fetches, decrypts, and enforces the content of a licence issued by your beanguard-server.
Want to see this working before wiring it into your own app? beanguard-demo is a runnable example — fetches a licence, shows its status, and can refresh, extend, or transfer it.
Maven dependency
<dependency>
<groupId>dev.beanguard</groupId>
<artifactId>beanguard-client</artifactId>
<version>0.1.5</version>
</dependency>
beanguard-client registers itself as a Spring Boot autoconfiguration — it requires no additional @Enable* annotation in your application.
Implementing BeanGuardConfiguration
All server connection configuration and your application's licence identity come from a single bean implementing BeanGuardConfiguration:
package com.example.myapp.licence;
import dev.beanguard.client.config.BeanGuardConfiguration;
import dev.beanguard.client.config.LicenceKeys;
import dev.beanguard.client.config.ServerConfig;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class MyBeanGuardConfiguration implements BeanGuardConfiguration {
@Override
public ServerConfig getServerConfig() {
return new ServerConfig(
"https://api.beanguard.dev",
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...", // LICENCE_PUBLIC_KEY from the admin panel
"dGhpcyBpcyBhIHNlY3JldCBrZXkgZm9yIEFFUy0yNTY=" // LICENCE_SECRET_KEY from the admin panel
);
}
@Override
public Optional<LicenceKeys> getLicenceKeys() {
return Optional.of(new LicenceKeys(
"11111111-1111-1111-1111-111111111111", // licence key
"my-licence-secret" // licence secret
));
}
@Override
public Optional<String> loadLicence() {
// load the last saved licence, e.g. from a file or your application's database
return Optional.empty();
}
@Override
public void saveLicence(String licence) {
// save the received licence so it survives a restart without a server connection
}
}
getServerConfig()— yourbeanguard-serveraddress, the RSA public key (LICENCE_PUBLIC_KEY), and the AES secret (LICENCE_SECRET_KEY) generated in the admin panel, Settings → Cryptographic keys tab.getLicenceKeys()— the key and secret of your customer's specific licence. ReturnOptional.empty()if no licence has been assigned yet.loadLicence()/saveLicence()— a local cache of the last received licence, so the application keeps working even without a momentary connection to the server.
Don't put this class in the dev.beanguard.* package. If you want to
protect the keys with ProGuard against decompilation, see Protecting keys
with ProGuard.
Reading licence status
When BeanGuardConfiguration is present in the context, the autoconfiguration registers a LicenceRegistry — the licence is fetched on application startup and refreshed every hour:
import dev.beanguard.client.registries.LicenceRegistry;
import dev.beanguard.client.registries.LicenceStatus;
import org.springframework.stereotype.Component;
@Component
class LicenceBanner {
private final LicenceRegistry licenceRegistry;
LicenceBanner(LicenceRegistry licenceRegistry) {
this.licenceRegistry = licenceRegistry;
}
boolean isLicenceValid() {
return licenceRegistry.getStatus() == LicenceStatus.LOADED;
}
}
LicenceStatus takes the values NOT_LOADED, MISSING_KEY, WRONG_KEY, WRONG_SECRET, EXPIRED, LOADED — use them, for instance, to show a "licence expired" banner in your application.
Transferring a licence to another machine
To move an existing licence to a new machine (a reinstall, or a lost secret), use the BeanGuardServer bean. The flow has two steps:
import dev.beanguard.api.models.licence.LicenceTransferInitResponse;
import dev.beanguard.api.models.licence.LicenceTransferStatusResponse;
import dev.beanguard.client.server.BeanGuardServer;
// 1. Start the transfer - the server emails a confirmation link to the licence owner.
LicenceTransferInitResponse init = beanGuardServer.initiateLicenceTransfer(licenceKey);
// Keep init.transferToken() and init.expiresAt() until the transfer completes.
// 2. Poll until the owner opens the link.
LicenceTransferStatusResponse status = beanGuardServer.getLicenceTransferStatus(init.transferToken());
switch (status.status()) {
case "CONFIRMED" -> {
// status.secret() is the new secret - store it with the licence key,
// then call licenceRegistry.refreshLicence().
}
case "EXPIRED" -> { /* start over with initiateLicenceTransfer */ }
default -> { /* PENDING - check again later */ }
}
The transfer is confirmed by the licence owner, not by the machine that started it: the confirmation link goes only to the email on the licence, and transferToken can only be used to poll. The first poll after the owner confirmed rotates the licence secret and returns it; the secret can be collected once, so store it immediately (a later poll returns an error). The previous secret keeps working until then. Initiating a transfer for an unknown key, or within TRANSFER_INIT_COOLDOWN_SECONDS of the previous request, looks like success but sends no email, so polling that token reports an error.
Both methods throw BeanGuardServerException when the server rejects the request (for example an unknown licence key or transfer token). Storing the pending transfer and the new secret is up to your application, since BeanGuardConfiguration only reads the licence keys - see beanguard-demo for a working example.
Method-level annotations enforce the limits and features from the licence — see Licensing annotations.
