diff --git a/README.md b/README.md
index 8843e9f..5295f78 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,21 @@
# Welcome to the Licensing Project!
[](https://github.com/bsayli/licensing/actions/workflows/build.yml)
-[](https://github.com/bsayli/licensing/releases/latest)
+[](https://github.com/bsayli/licensing/releases/latest)
[](https://codecov.io/gh/bsayli/licensing)
+
[](https://openjdk.org/projects/jdk/21/)
[](https://spring.io/projects/spring-boot)
+[](https://github.com/blueprint-platform/openapi-generics)
+[](https://openapi-generator.tech/)
+
[](https://www.keycloak.org/)
[](https://redis.io/)
-[](https://maven.apache.org/)
-[](https://www.docker.com/)
[](https://github.com/ben-manes/caffeine)
[](https://jwt.io/)
+
+[](https://maven.apache.org/)
+[](https://www.docker.com/)
[](LICENSE)
@@ -66,6 +71,7 @@ This project provides a **complete licensing framework** for applications, combi
## Subprojects
+* **licensing-api-contract**: Shared API response contract (`ApiResponse`, `ApiError`) reused by service, client, SDK, and CLI modules.
* **license-generator**: Java project for license key generation, encryption, and cryptographic tooling.
* **licensing-service**: Spring Boot application that issues and validates license tokens.
* **licensing-service-sdk**: Spring Boot application acting as a client SDK (with caching & detached signature) for integrating licensing capabilities into external apps.
@@ -136,7 +142,7 @@ licensing-service-sdk-cli | INFO Message: License is valid
cd licensing/licensing-service-sdk-cli
mvn clean package
cd target
-java -jar licensing-service-sdk-cli-1.0.1.jar -s crm -v 1.5.0 -i "crm~macbook~00:2A:8D:BE:F1:56" -k "BSAYLI."
+java -jar licensing-service-sdk-cli-1.0.5.jar -s crm -v 1.5.0 -i "crm~macbook~00:2A:8D:BE:F1:56" -k "BSAYLI."
```
---
@@ -183,9 +189,10 @@ If you found this project useful, please consider giving it a star ⭐ on GitHub
## Related Modules (Quick View)
-| Module | Purpose | Documentation |
-| ----------------------------- | ------------------------------------------ | ---------------------------------------------------------- |
-| **licensing-service** | REST API for issuing and validating tokens | [README](licensing-service/README.md) |
-| **licensing-service-sdk** | Client SDK for integration | [README](licensing-service-sdk/README.md) |
-| **licensing-service-sdk-cli** | CLI demo client | [README](licensing-service-sdk-cli/README.md) |
-| **license-generator** | Key & signature tooling | [README](license-generator/README.md) |
\ No newline at end of file
+| Module | Purpose | Documentation |
+|-------------------------------|-------------------------------------------------------------|-----------------------------------------------|
+| **licensing-service** | REST API for issuing and validating tokens | [README](licensing-service/README.md) |
+| **licensing-service-sdk** | Client SDK for integration | [README](licensing-service-sdk/README.md) |
+| **licensing-service-sdk-cli** | CLI demo client | [README](licensing-service-sdk-cli/README.md) |
+| **licensing-api-contract** | Shared API response contract (`ApiResponse`, `ApiError`) | [README](licensing-api-contract/README.md) |
+| **license-generator** | Key and signature tooling | [README](license-generator/README.md) |
\ No newline at end of file
diff --git a/docker-compose/client/docker-compose.yml b/docker-compose/client/docker-compose.yml
index c4c1597..61ee77f 100644
--- a/docker-compose/client/docker-compose.yml
+++ b/docker-compose/client/docker-compose.yml
@@ -5,7 +5,7 @@ networks:
services:
licensing-service-sdk-cli:
build: ./../../licensing-service-sdk-cli
- image: licensing-service-sdk-cli:1.0.1
+ image: licensing-service-sdk-cli:1.0.5
container_name: licensing-service-sdk-cli
networks:
- license_network
@@ -14,5 +14,5 @@ services:
INSTANCE_ID: "licensing-service~demo~00:11:22:33:44:55"
SERVICE_ID: "crm"
SERVICE_VERSION: "1.5.0"
- LICENSE_KEY: "BSAYLI~X66e_qYlfPxWiIaN2ahPb9tQFyqjMuTih06LCytzjZ0~0aT6lLTZGkO1zHHPHFDzwF7zPiZLRLWSl06HSVQO5z+NqtzzcFCUkkVFuqHTYKcAcI9037sQQQSfBQakQDUoCA=="
+ LICENSE_KEY: "BSAYLI.AQA3-gCQ66DQsfC0LwnAO8DTjKgad7DhPaOtCf7WG2bFUoK9pmScIhhCf2S-D0j8g4jC7nlFrLDpuM0ezEoDQc79SizxxEIUGN9YUhTNBW7iRQ"
restart: "no"
\ No newline at end of file
diff --git a/docker-compose/server/docker-compose.yml b/docker-compose/server/docker-compose.yml
index aae31b1..c930bb8 100644
--- a/docker-compose/server/docker-compose.yml
+++ b/docker-compose/server/docker-compose.yml
@@ -51,8 +51,9 @@ services:
restart: unless-stopped
licensing-service:
- build: ./../../licensing-service
- image: licensing-service:1.0.1
+ build:
+ context: ./../..
+ dockerfile: licensing-service/Dockerfile
container_name: licensing-service
networks: [ license_network ]
depends_on:
@@ -80,7 +81,7 @@ services:
build:
context: ./../..
dockerfile: licensing-service-sdk/Dockerfile
- image: licensing-service-sdk:1.0.1
+ image: licensing-service-sdk:1.0.5
container_name: licensing-service-sdk
networks: [ license_network ]
depends_on:
diff --git a/license-generator/README.md b/license-generator/README.md
index 70fc107..79e6a15 100644
--- a/license-generator/README.md
+++ b/license-generator/README.md
@@ -3,8 +3,8 @@
[](https://github.com/bsayli/licensing/actions/workflows/build.yml)
[](https://openjdk.org/projects/jdk/21/)
[](https://github.com/jwtk/jjwt)
-[](https://www.bouncycastle.org/)
-[](https://github.com/FasterXML/jackson)
+[](https://www.bouncycastle.org/)
+[](https://github.com/FasterXML/jackson)
[](../LICENSE)
Tools and libraries for generating cryptographic keys, constructing license strings, creating **detached Ed25519
diff --git a/license-generator/pom.xml b/license-generator/pom.xml
index 2ad3b22..dff383c 100644
--- a/license-generator/pom.xml
+++ b/license-generator/pom.xml
@@ -6,19 +6,19 @@
io.github.bsayli
license-generator
- 1.0.4
+ 1.0.5
21
UTF-8
UTF-8
0.12.7
- 1.81
- 2.19.2
- 1.5.18
+ 1.84
+ 2.21.3
+ 1.5.32
2.0.17
5.13.4
- 0.8.13
+ 0.8.14
1.2.1
3.14.0
3.5.4
diff --git a/licensing-api-contract/README.md b/licensing-api-contract/README.md
new file mode 100644
index 0000000..6581250
--- /dev/null
+++ b/licensing-api-contract/README.md
@@ -0,0 +1,73 @@
+# Licensing API Contract
+
+Shared API contract types used by the licensing modules.
+
+This module contains the response envelope used by `licensing-service`, `licensing-service-client`, `licensing-service-sdk` and `licensing-service-sdk-cli` to ensure a consistent API contract across all layers.
+
+```java
+ApiResponse
+ApiError
+```
+
+## Purpose
+
+`licensing-api-contract` keeps the API response shape in one place so server and client modules use the same contract instead of redefining response wrappers independently.
+
+It is also used as a BYOE (Bring Your Own Envelope) example for `openapi-generics`: generated client response wrappers extend the existing `ApiResponse` type instead of generating a new envelope model.
+
+Example generated client wrapper:
+
+```java
+public class ApiResponseLicenseAccessResponse
+ extends ApiResponse {
+}
+```
+
+## Contract Shape
+
+`ApiResponse` represents the standard licensing API envelope:
+
+```json
+{
+ "status": 200,
+ "message": "License is valid",
+ "data": {},
+ "errors": []
+}
+```
+
+Fields:
+
+| Field | Type | Description |
+| --------- | ---------------- | ----------------------------------------------- |
+| `status` | `int` | HTTP-style status code returned in the envelope |
+| `message` | `String` | Human-readable response message |
+| `data` | `T` | Typed response payload |
+| `errors` | `List` | Structured error details |
+
+## BYOE Requirements
+
+Because generated wrappers extend `ApiResponse`, the envelope is intentionally subclass-friendly:
+
+* public no-argument constructor
+* public getters and setters
+* generic payload accessor through `getData()` / `setData(T data)`
+
+This keeps the envelope compatible with generated client wrappers while preserving the original API contract.
+
+## Module Coordinates
+
+```xml
+
+ io.github.bsayli
+ licensing-api-contract
+ 1.0.5
+
+```
+
+## See Also
+
+* [`licensing-service`](../licensing-service/README.md) — REST API that returns `ApiResponse`
+* [`licensing-service-client`](../licensing-service-client/README.md) — generated client using the shared envelope
+* [`licensing-service-sdk`](../licensing-service-sdk/README.md) — SDK layer built on top of the generated client
+* [`licensing-service-sdk-cli`](../licensing-service-sdk-cli/README.md) — command-line client demo
diff --git a/licensing-api-contract/pom.xml b/licensing-api-contract/pom.xml
new file mode 100644
index 0000000..8e30efd
--- /dev/null
+++ b/licensing-api-contract/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+
+ io.github.bsayli
+ licensing-api-contract
+ 1.0.5
+ jar
+
+ licensing-api-contract
+ API contract types used by the licensing service.
+
+
+ UTF-8
+ UTF-8
+
+ 21
+ 3.15.0
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ ${maven.compiler.release}
+ ${project.build.sourceEncoding}
+
+
+
+
+
\ No newline at end of file
diff --git a/licensing-service/src/main/java/io/github/bsayli/licensing/common/api/ApiError.java b/licensing-api-contract/src/main/java/io/github/bsayli/licensing/contract/api/ApiError.java
similarity index 55%
rename from licensing-service/src/main/java/io/github/bsayli/licensing/common/api/ApiError.java
rename to licensing-api-contract/src/main/java/io/github/bsayli/licensing/contract/api/ApiError.java
index 3a09fd1..11e62c4 100644
--- a/licensing-service/src/main/java/io/github/bsayli/licensing/common/api/ApiError.java
+++ b/licensing-api-contract/src/main/java/io/github/bsayli/licensing/contract/api/ApiError.java
@@ -1,3 +1,3 @@
-package io.github.bsayli.licensing.common.api;
+package io.github.bsayli.licensing.contract.api;
public record ApiError(String errorCode, String message) {}
diff --git a/licensing-api-contract/src/main/java/io/github/bsayli/licensing/contract/api/ApiResponse.java b/licensing-api-contract/src/main/java/io/github/bsayli/licensing/contract/api/ApiResponse.java
new file mode 100644
index 0000000..1dfe301
--- /dev/null
+++ b/licensing-api-contract/src/main/java/io/github/bsayli/licensing/contract/api/ApiResponse.java
@@ -0,0 +1,100 @@
+package io.github.bsayli.licensing.contract.api;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+public class ApiResponse {
+
+ private int status;
+ private String message;
+ private T data;
+ private List errors = Collections.emptyList();
+
+ public ApiResponse() {}
+
+ public ApiResponse(int status, String message, T data, List errors) {
+ this.status = status;
+ this.message = message;
+ this.data = data;
+ this.errors = errors != null ? errors : Collections.emptyList();
+ }
+
+ public static ApiResponse ok(T data) {
+ return new ApiResponse<>(200, "OK", data, Collections.emptyList());
+ }
+
+ public static ApiResponse of(int status, String message, T data) {
+ return new ApiResponse<>(status, message, data, Collections.emptyList());
+ }
+
+ public static ApiResponse error(int status, String message) {
+ return new ApiResponse<>(status, message, null, Collections.emptyList());
+ }
+
+ public static ApiResponse error(int status, String message, List errors) {
+ return new ApiResponse<>(status, message, null, errors);
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ public void setStatus(int status) {
+ this.status = status;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public T getData() {
+ return data;
+ }
+
+ public void setData(T data) {
+ this.data = data;
+ }
+
+ public List getErrors() {
+ return errors;
+ }
+
+ public void setErrors(List errors) {
+ this.errors = errors != null ? errors : Collections.emptyList();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ApiResponse> that)) return false;
+ return status == that.status
+ && Objects.equals(message, that.message)
+ && Objects.equals(data, that.data)
+ && Objects.equals(errors, that.errors);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(status, message, data, errors);
+ }
+
+ @Override
+ public String toString() {
+ return "ApiResponse{"
+ + "status="
+ + status
+ + ", message='"
+ + message
+ + '\''
+ + ", data="
+ + data
+ + ", errors="
+ + errors
+ + '}';
+ }
+}
diff --git a/licensing-service-client/README.md b/licensing-service-client/README.md
index 1174b93..e924443 100644
--- a/licensing-service-client/README.md
+++ b/licensing-service-client/README.md
@@ -2,7 +2,9 @@
[](https://github.com/bsayli/licensing/actions/workflows/build.yml)
[](https://openjdk.org/projects/jdk/21/)
-[](https://openapi-generator.tech/)
+[](https://openapi-generator.tech/)
+[](https://github.com/blueprint-platform/openapi-generics)
+[](https://spring.io/projects/spring-boot)
[](https://maven.apache.org/)
[](../LICENSE)
@@ -34,7 +36,7 @@ Add to your service's `pom.xml`:
io.github.bsayli
licensing-service-client
- 0.1.0
+ 1.0.5
```
@@ -132,7 +134,7 @@ mvn clean package
Produces:
```
-target/licensing-service-client-0.1.0.jar
+target/licensing-service-client-1.0.5.jar
```
---
diff --git a/licensing-service-client/pom.xml b/licensing-service-client/pom.xml
index a662462..b8962f0 100644
--- a/licensing-service-client/pom.xml
+++ b/licensing-service-client/pom.xml
@@ -4,10 +4,17 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
+
+ io.github.blueprint-platform
+ openapi-generics-java-codegen-parent
+ 1.0.2
+
+
+
io.github.bsayli
licensing-service-client
- 1.0.4
-
+ 1.0.5
+
licensing-service-client
Generated client for licensing-service using generics-aware OpenAPI templates
jar
@@ -16,20 +23,31 @@
UTF-8
UTF-8
21
- 7.15.0
- 3.13.0
- 3.6.0
- 3.5.5
- 3.0.2
- 2.1.1
- 5.13.4
- 5.1.0
- 5.5
- 3.5.3
- 0.8.13
+ 3.5.14
+ 7.22.0
+ 1.0.5
+ 3.1.1
+ 3.0.0
+ 5.3.2
+ 5.5.2
+ 2.0.17
+ 1.5.32
+
+ 3.15.0
+ 3.5.5
+ 3.5.5
+ 0.8.14
+
+
+
+ io.github.bsayli
+ licensing-api-contract
+ ${licensing-api-contract.version}
+
+
org.springframework.boot
spring-boot-starter-web
@@ -64,6 +82,19 @@
${httpclient5.version}
+
+ org.slf4j
+ slf4j-api
+ ${slf4j-api.version}
+
+
+
+ ch.qos.logback
+ logback-classic
+ ${logback.version}
+ test
+
+
org.springframework.boot
spring-boot-starter-test
@@ -84,67 +115,64 @@
src/main/resources
- **/*.yaml
openapi-templates/**
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ resolve-mockito-agent
+
+ properties
+
+
+
+
+
org.openapitools
openapi-generator-maven-plugin
- ${openapi.generator.version}
generate-client
+ generate-sources
generate
+ java-generics-contract
${project.basedir}/src/main/resources/licensing-service-api-docs.yaml
- java
+
restclient
-
+
io.github.bsayli.licensing.client.generated.api
io.github.bsayli.licensing.client.generated.dto
io.github.bsayli.licensing.client.generated.invoker
- ${project.basedir}/src/main/resources/openapi-templates
-
- true
- false
- false
- false
- false
true
- true
jackson
- java8
- true
false
- src/gen/java
-
-
-
-
-
- org.codehaus.mojo
- build-helper-maven-plugin
- ${build.helper.plugin.version}
-
-
- add-generated-sources
- generate-sources
-
- add-source
-
-
-
- ${project.build.directory}/generated-sources/openapi/src/gen/java
-
+
+
+ openapi-generics.envelope=io.github.bsayli.licensing.contract.api.ApiResponse
+
+
+
+ true
+ false
+
+ false
+ false
+ false
+ false
@@ -153,10 +181,10 @@
org.apache.maven.plugins
maven-compiler-plugin
- ${maven.compiler.plugin.version}
+ ${maven-compiler-plugin.version}
${java.version}
- UTF-8
+ ${project.build.sourceEncoding}
@@ -165,10 +193,34 @@
maven-surefire-plugin
${maven-surefire-plugin.version}
- false
+ @{argLine} -javaagent:${org.mockito:mockito-core:jar}
+
+ **/*Test.java
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+ ${maven-failsafe-plugin.version}
+
+
+ default
+
+ integration-test
+ verify
+
+
+ @{argLine} -javaagent:${org.mockito:mockito-core:jar}
+
+ **/*IT.java
+
+
+
+
+
+
org.jacoco
jacoco-maven-plugin
@@ -180,6 +232,12 @@
prepare-agent
+
+ prepare-agent-integration
+
+ prepare-agent-integration
+
+
report
verify
@@ -187,9 +245,15 @@
report
+
+ report-integration
+ verify
+
+ report-integration
+
+
-
\ No newline at end of file
diff --git a/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/adapter/LicensingServiceClientAdapter.java b/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/adapter/LicensingServiceClientAdapter.java
index bf6ecaf..1f31551 100644
--- a/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/adapter/LicensingServiceClientAdapter.java
+++ b/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/adapter/LicensingServiceClientAdapter.java
@@ -1,14 +1,14 @@
package io.github.bsayli.licensing.client.adapter;
-import io.github.bsayli.licensing.client.common.contract.ApiClientResponse;
import io.github.bsayli.licensing.client.generated.dto.IssueAccessRequest;
import io.github.bsayli.licensing.client.generated.dto.LicenseAccessResponse;
import io.github.bsayli.licensing.client.generated.dto.ValidateAccessRequest;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
public interface LicensingServiceClientAdapter {
- ApiClientResponse issueAccess(IssueAccessRequest request);
+ ApiResponse issueAccess(IssueAccessRequest request);
- ApiClientResponse validateAccess(
+ ApiResponse validateAccess(
String licenseToken, ValidateAccessRequest request);
}
diff --git a/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/adapter/impl/LicensingServiceClientAdapterImpl.java b/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/adapter/impl/LicensingServiceClientAdapterImpl.java
index 70b891a..850acf0 100644
--- a/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/adapter/impl/LicensingServiceClientAdapterImpl.java
+++ b/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/adapter/impl/LicensingServiceClientAdapterImpl.java
@@ -1,12 +1,12 @@
package io.github.bsayli.licensing.client.adapter.impl;
import io.github.bsayli.licensing.client.adapter.LicensingServiceClientAdapter;
-import io.github.bsayli.licensing.client.common.contract.ApiClientResponse;
import io.github.bsayli.licensing.client.common.core.ApiClientExecutor;
import io.github.bsayli.licensing.client.generated.api.LicenseControllerApi;
import io.github.bsayli.licensing.client.generated.dto.IssueAccessRequest;
import io.github.bsayli.licensing.client.generated.dto.LicenseAccessResponse;
import io.github.bsayli.licensing.client.generated.dto.ValidateAccessRequest;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import org.springframework.stereotype.Service;
@Service
@@ -21,13 +21,13 @@ public LicensingServiceClientAdapterImpl(LicenseControllerApi api, ApiClientExec
}
@Override
- public ApiClientResponse issueAccess(IssueAccessRequest request) {
+ public ApiResponse issueAccess(IssueAccessRequest request) {
return executor.handle(
"issueAccess", LicenseAccessResponse.class, () -> api.createAccess(request));
}
@Override
- public ApiClientResponse validateAccess(
+ public ApiResponse validateAccess(
String licenseToken, ValidateAccessRequest request) {
return executor.handle(
"validateAccess",
diff --git a/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/contract/ApiClientError.java b/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/contract/ApiClientError.java
deleted file mode 100644
index 74abb81..0000000
--- a/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/contract/ApiClientError.java
+++ /dev/null
@@ -1,3 +0,0 @@
-package io.github.bsayli.licensing.client.common.contract;
-
-public record ApiClientError(String errorCode, String message) {}
diff --git a/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/contract/ApiClientResponse.java b/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/contract/ApiClientResponse.java
deleted file mode 100644
index bb34561..0000000
--- a/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/contract/ApiClientResponse.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package io.github.bsayli.licensing.client.common.contract;
-
-import java.util.List;
-import java.util.Objects;
-
-public class ApiClientResponse {
-
- private Integer status;
- private String statusText;
- private String message;
- private List errors;
- private T data;
-
- public ApiClientResponse() {}
-
- public ApiClientResponse(
- Integer status, String statusText, String message, List errors, T data) {
- this.status = status;
- this.statusText = statusText;
- this.message = message;
- this.errors = errors;
- this.data = data;
- }
-
- public static ApiClientResponse from(
- Integer status, String statusText, String message, List errors, T data) {
- return new ApiClientResponse<>(status, statusText, message, errors, data);
- }
-
- public Integer getStatus() {
- return status;
- }
-
- public void setStatus(Integer status) {
- this.status = status;
- }
-
- public String getStatusText() {
- return statusText;
- }
-
- public void setStatusText(String statusText) {
- this.statusText = statusText;
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public List getErrors() {
- return errors;
- }
-
- public void setErrors(List errors) {
- this.errors = errors;
- }
-
- public T getData() {
- return data;
- }
-
- public void setData(T data) {
- this.data = data;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof ApiClientResponse> that)) return false;
- return Objects.equals(status, that.status)
- && Objects.equals(statusText, that.statusText)
- && Objects.equals(message, that.message)
- && Objects.equals(errors, that.errors)
- && Objects.equals(data, that.data);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(status, statusText, message, errors, data);
- }
-
- @Override
- public String toString() {
- return "ApiClientResponse{"
- + "status="
- + status
- + ", statusText='"
- + statusText
- + '\''
- + ", message='"
- + message
- + '\''
- + ", errors="
- + errors
- + ", data="
- + data
- + '}';
- }
-}
diff --git a/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/core/ApiClientExecutor.java b/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/core/ApiClientExecutor.java
index b79c47a..2ec60ec 100644
--- a/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/core/ApiClientExecutor.java
+++ b/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/core/ApiClientExecutor.java
@@ -1,6 +1,6 @@
package io.github.bsayli.licensing.client.common.core;
-import io.github.bsayli.licensing.client.common.contract.ApiClientResponse;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import java.util.function.Supplier;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpStatusCodeException;
@@ -14,8 +14,8 @@ public ApiClientExecutor(ResponseParser responseParser) {
this.responseParser = responseParser;
}
- public ApiClientResponse handle(
- String operation, Class clazz, Supplier> supplier) {
+ public ApiResponse handle(
+ String operation, Class clazz, Supplier> supplier) {
try {
return supplier.get();
} catch (HttpStatusCodeException e) {
diff --git a/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/core/ResponseParser.java b/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/core/ResponseParser.java
index 27c13cf..acbce80 100644
--- a/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/core/ResponseParser.java
+++ b/licensing-service-client/src/main/java/io/github/bsayli/licensing/client/common/core/ResponseParser.java
@@ -1,8 +1,8 @@
package io.github.bsayli.licensing.client.common.core;
import com.fasterxml.jackson.databind.ObjectMapper;
-import io.github.bsayli.licensing.client.common.contract.ApiClientResponse;
import io.github.bsayli.licensing.client.common.exception.ApiClientException;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import java.util.Optional;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
@@ -20,7 +20,7 @@ public ResponseParser(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
- public ApiClientResponse parseOrThrow(
+ public ApiResponse parseOrThrow(
String operation, HttpStatusCodeException e, Class targetClass) {
String responseBody = e.getResponseBodyAsString();
@@ -43,7 +43,7 @@ public ApiClientResponse parseOrThrow(
responseBody,
objectMapper
.getTypeFactory()
- .constructParametricType(ApiClientResponse.class, targetClass));
+ .constructParametricType(ApiResponse.class, targetClass));
} catch (Exception ex) {
throw new ApiClientException(
"[" + operation + "] Failed to parse JSON error response",
diff --git a/licensing-service-client/src/main/resources/licensing-service-api-docs.yaml b/licensing-service-client/src/main/resources/licensing-service-api-docs.yaml
index 8bbae5d..40ecadf 100644
--- a/licensing-service-client/src/main/resources/licensing-service-api-docs.yaml
+++ b/licensing-service-client/src/main/resources/licensing-service-api-docs.yaml
@@ -2,12 +2,12 @@ openapi: 3.1.0
info:
title: Licensing Service API
description: Licensing Service type-safe generic API responses with OpenAPI
- version: 1.0.1
+ version: 1.0.5
servers:
- url: http://localhost:8081/licensing-service
description: Licensing Service URL
security:
- - basicAuth: [ ]
+ - basicAuth: []
paths:
/v1/licenses/access:
post:
@@ -96,13 +96,21 @@ components:
type: string
message:
type: string
+ x-ignore-model: true
ApiResponseLicenseAccessResponse:
- allOf:
- - $ref: "#/components/schemas/ApiResponse"
- - type: object
- properties:
- data:
- $ref: "#/components/schemas/LicenseAccessResponse"
+ type: object
+ properties:
+ status:
+ type: integer
+ format: int32
+ message:
+ type: string
+ data:
+ $ref: "#/components/schemas/LicenseAccessResponse"
+ errors:
+ type: array
+ items:
+ $ref: "#/components/schemas/ApiError"
x-api-wrapper: true
x-api-wrapper-datatype: LicenseAccessResponse
LicenseAccessResponse:
@@ -144,42 +152,6 @@ components:
- serviceId
- serviceVersion
- signature
- ApiResponse:
- type: object
- properties:
- status:
- type: integer
- format: int32
- message:
- type: string
- errors:
- type: array
- items:
- type: object
- properties:
- errorCode:
- type: string
- message:
- type: string
- ApiResponseVoid:
- type: object
- properties:
- status:
- type: integer
- format: int32
- message:
- type: string
- data:
- type: object
- errors:
- type: array
- items:
- type: object
- properties:
- errorCode:
- type: string
- message:
- type: string
securitySchemes:
basicAuth:
type: http
diff --git a/licensing-service-client/src/main/resources/openapi-templates/api_wrapper.mustache b/licensing-service-client/src/main/resources/openapi-templates/api_wrapper.mustache
deleted file mode 100644
index f5cea39..0000000
--- a/licensing-service-client/src/main/resources/openapi-templates/api_wrapper.mustache
+++ /dev/null
@@ -1,3 +0,0 @@
-public class {{classname}}
- extends io.github.bsayli.licensing.client.common.contract.ApiClientResponse<{{vendorExtensions.x-api-wrapper-datatype}}> {
-}
\ No newline at end of file
diff --git a/licensing-service-client/src/main/resources/openapi-templates/model.mustache b/licensing-service-client/src/main/resources/openapi-templates/model.mustache
deleted file mode 100644
index 6383fc6..0000000
--- a/licensing-service-client/src/main/resources/openapi-templates/model.mustache
+++ /dev/null
@@ -1,88 +0,0 @@
-{{>licenseInfo}}
-
-package {{package}};
-
-{{#useReflectionEqualsHashCode}}
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
-{{/useReflectionEqualsHashCode}}
-import java.util.Objects;
-import java.util.Arrays;
-{{#imports}}
-import {{import}};
-{{/imports}}
-{{#serializableModel}}
-import java.io.Serializable;
-{{/serializableModel}}
-{{#jackson}}
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import com.fasterxml.jackson.annotation.JsonTypeName;
-{{#withXml}}
-import com.fasterxml.jackson.dataformat.xml.annotation.*;
-{{/withXml}}
-{{#vendorExtensions.x-has-readonly-properties}}
-import com.fasterxml.jackson.annotation.JsonCreator;
-{{/vendorExtensions.x-has-readonly-properties}}
-{{/jackson}}
-{{#withXml}}
-import {{javaxPackage}}.xml.bind.annotation.*;
-import {{javaxPackage}}.xml.bind.annotation.adapters.*;
-import io.github.threetenjaxb.core.*;
-{{/withXml}}
-{{#jsonb}}
-import java.lang.reflect.Type;
-import {{javaxPackage}}.json.bind.annotation.JsonbTypeDeserializer;
-import {{javaxPackage}}.json.bind.annotation.JsonbTypeSerializer;
-import {{javaxPackage}}.json.bind.serializer.DeserializationContext;
-import {{javaxPackage}}.json.bind.serializer.JsonbDeserializer;
-import {{javaxPackage}}.json.bind.serializer.JsonbSerializer;
-import {{javaxPackage}}.json.bind.serializer.SerializationContext;
-import {{javaxPackage}}.json.stream.JsonGenerator;
-import {{javaxPackage}}.json.stream.JsonParser;
-import {{javaxPackage}}.json.bind.annotation.JsonbProperty;
-{{#vendorExtensions.x-has-readonly-properties}}
-import {{javaxPackage}}.json.bind.annotation.JsonbCreator;
-{{/vendorExtensions.x-has-readonly-properties}}
-{{/jsonb}}
-{{#parcelableModel}}
-import android.os.Parcelable;
-import android.os.Parcel;
-{{/parcelableModel}}
-{{#useBeanValidation}}
-import {{javaxPackage}}.validation.constraints.*;
-import {{javaxPackage}}.validation.Valid;
-{{/useBeanValidation}}
-{{#performBeanValidation}}
-import org.hibernate.validator.constraints.*;
-{{/performBeanValidation}}
-{{#supportUrlQuery}}
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.StringJoiner;
-{{/supportUrlQuery}}
-
-{{#models}}
-{{#model}}
-
-{{#vendorExtensions.x-api-wrapper}}
- {{>api_wrapper}}
-{{/vendorExtensions.x-api-wrapper}}
-
-{{^vendorExtensions.x-api-wrapper}}
- {{#isEnum}}
- {{>modelEnum}}
- {{/isEnum}}
-
- {{^isEnum}}
- {{#vendorExtensions.x-is-one-of-interface}}
- {{>oneof_interface}}
- {{/vendorExtensions.x-is-one-of-interface}}
-
- {{^vendorExtensions.x-is-one-of-interface}}
- {{>pojo}}
- {{/vendorExtensions.x-is-one-of-interface}}
- {{/isEnum}}
-{{/vendorExtensions.x-api-wrapper}}
-
-{{/model}}
-{{/models}}
\ No newline at end of file
diff --git a/licensing-service-client/src/main/resources/openapi-templates/modelEnum.mustache b/licensing-service-client/src/main/resources/openapi-templates/modelEnum.mustache
deleted file mode 100644
index 90cd7f8..0000000
--- a/licensing-service-client/src/main/resources/openapi-templates/modelEnum.mustache
+++ /dev/null
@@ -1,120 +0,0 @@
-{{#jackson}}
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonValue;
-{{/jackson}}
-{{#gson}}
-import java.io.IOException;
-import com.google.gson.TypeAdapter;
-import com.google.gson.annotations.JsonAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-{{/gson}}
-{{#isUri}}
-import java.net.URI;
-{{/isUri}}
-
-/**
- * {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}
- */
-{{#gson}}
-@JsonAdapter({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class)
-{{/gson}}
-{{#jsonb}}
-@JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class)
-@JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class)
-{{/jsonb}}
-{{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}{{#vendorExtensions.x-implements}}{{#-first}} implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
- {{#allowableValues}}{{#enumVars}}
- {{#enumDescription}}
- /**
- * {{.}}
- */
- {{/enumDescription}}
- {{#withXml}}
- @XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}})
- {{/withXml}}
- {{{name}}}({{{value}}}){{^-last}},
- {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
-
- private {{{dataType}}} value;
-
- {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) {
- this.value = value;
- }
-
-{{#jackson}}
- @JsonValue
-{{/jackson}}
- public {{{dataType}}} getValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return String.valueOf(value);
- }
-
-{{#jackson}}
- @JsonCreator
-{{/jackson}}
- public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) {
- for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
- if (b.value.{{^isString}}equals{{/isString}}{{#isString}}{{#useEnumCaseInsensitive}}equalsIgnoreCase{{/useEnumCaseInsensitive}}{{^useEnumCaseInsensitive}}equals{{/useEnumCaseInsensitive}}{{/isString}}(value)) {
- return b;
- }
- }
- {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}{{#enumUnknownDefaultCase}}{{#allowableValues}}{{#enumVars}}{{#-last}}return {{{name}}};{{/-last}}{{/enumVars}}{{/allowableValues}}{{/enumUnknownDefaultCase}}{{^enumUnknownDefaultCase}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/enumUnknownDefaultCase}}{{/isNullable}}
- }
-{{#gson}}
-
- public static class Adapter extends TypeAdapter<{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> {
- @Override
- public void write(final JsonWriter jsonWriter, final {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException {
- jsonWriter.value(enumeration.getValue(){{#isUri}}.toASCIIString(){{/isUri}});
- }
-
- @Override
- public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
- {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}}{{#isUri}}URI.create({{/isUri}}jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{#isUri}}nextString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
- return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
- }
- }
-{{/gson}}
-{{#jsonb}}
-
- public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> {
- @Override
- public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) {
- for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
- if (String.valueOf(b.value).equals(parser.getString())) {
- return b;
- }
- }
- {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}}
- }
- }
-
- public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> {
- @Override
- public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) {
- generator.write(obj.value);
- }
- }
-{{/jsonb}}
-{{#supportUrlQuery}}
-
- /**
- * Convert the instance into URL query string.
- *
- * @param prefix prefix of the query string
- * @return URL query string
- */
- public String toUrlQueryString(String prefix) {
- if (prefix == null) {
- prefix = "";
- }
-
- return String.format("%s=%s", prefix, this.toString());
- }
-{{/supportUrlQuery}}
-}
diff --git a/licensing-service-client/src/main/resources/openapi-templates/oneof_interface.mustache b/licensing-service-client/src/main/resources/openapi-templates/oneof_interface.mustache
deleted file mode 100644
index eadcb26..0000000
--- a/licensing-service-client/src/main/resources/openapi-templates/oneof_interface.mustache
+++ /dev/null
@@ -1,6 +0,0 @@
-{{>additionalOneOfTypeAnnotations}}{{>generatedAnnotation}}{{>typeInfoAnnotation}}{{>xmlAnnotation}}
-public {{>sealed}}interface {{classname}} {{#vendorExtensions.x-implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}}{{>permits}}{
- {{#discriminator}}
- public {{propertyType}} {{propertyGetter}}();
- {{/discriminator}}
-}
diff --git a/licensing-service-client/src/main/resources/openapi-templates/pojo.mustache b/licensing-service-client/src/main/resources/openapi-templates/pojo.mustache
deleted file mode 100644
index 25974f2..0000000
--- a/licensing-service-client/src/main/resources/openapi-templates/pojo.mustache
+++ /dev/null
@@ -1,624 +0,0 @@
-/**
- * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}}
- * @deprecated{{/isDeprecated}}
- */{{#isDeprecated}}
-@Deprecated{{/isDeprecated}}
-{{#swagger1AnnotationLibrary}}
-{{#description}}
-@ApiModel(description = "{{{.}}}")
-{{/description}}
-{{/swagger1AnnotationLibrary}}
-{{#swagger2AnnotationLibrary}}
-{{#description}}
-@Schema(description = "{{{.}}}")
-{{/description}}
-{{/swagger2AnnotationLibrary}}
-{{#jackson}}
-@JsonPropertyOrder({
-{{#vars}}
- {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}}
-{{/vars}}
-})
-{{#isClassnameSanitized}}
-{{^hasDiscriminatorWithNonEmptyMapping}}
-@JsonTypeName("{{name}}")
-{{/hasDiscriminatorWithNonEmptyMapping}}
-{{/isClassnameSanitized}}
-{{/jackson}}
-{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}
-{{#vendorExtensions.x-class-extra-annotation}}
-{{{vendorExtensions.x-class-extra-annotation}}}
-{{/vendorExtensions.x-class-extra-annotation}}
-public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{
-{{#serializableModel}}
- private static final long serialVersionUID = 1L;
-
-{{/serializableModel}}
- {{#vars}}
- {{#isEnum}}
- {{^isContainer}}
-{{>modelInnerEnum}}
-
- {{/isContainer}}
- {{#isContainer}}
- {{#mostInnerItems}}
-{{>modelInnerEnum}}
-
- {{/mostInnerItems}}
- {{/isContainer}}
- {{/isEnum}}
- {{#gson}}
- public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}";
- {{/gson}}
- {{#jackson}}
- public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}";
- {{/jackson}}
- {{#withXml}}
- @Xml{{#isXmlAttribute}}Attribute{{/isXmlAttribute}}{{^isXmlAttribute}}Element{{/isXmlAttribute}}(name = "{{items.xmlName}}{{^items.xmlName}}{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}{{/items.xmlName}}"{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}})
- {{#isXmlWrapped}}
- @XmlElementWrapper(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}"{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}})
- {{/isXmlWrapped}}
- {{^isXmlAttribute}}
- {{#isDateTime}}
- @XmlJavaTypeAdapter(OffsetDateTimeXmlAdapter.class)
- {{/isDateTime}}
- {{/isXmlAttribute}}
- {{/withXml}}
- {{#gson}}
- @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}})
- {{/gson}}
- {{^isDiscriminator}}
- {{>nullable_var_annotations}}{{! prevent indent}}
- {{/isDiscriminator}}
- {{#isDiscriminator}}
- // The discriminator does not have Nullability-annotation since it is added during serialization by the @JsonTypeName annotation
- {{/isDiscriminator}}
- {{#vendorExtensions.x-field-extra-annotation}}
- {{{vendorExtensions.x-field-extra-annotation}}}
- {{/vendorExtensions.x-field-extra-annotation}}
- {{#vendorExtensions.x-is-jackson-optional-nullable}}
- {{#isContainer}}
- {{#hasChildren}}protected{{/hasChildren}}{{^hasChildren}}private{{/hasChildren}} JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined();
- {{/isContainer}}
- {{^isContainer}}
- {{#hasChildren}}protected{{/hasChildren}}{{^hasChildren}}private{{/hasChildren}} JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
- {{/isContainer}}
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
- {{^vendorExtensions.x-is-jackson-optional-nullable}}
- {{#isContainer}}
- {{#hasChildren}}protected{{/hasChildren}}{{^hasChildren}}private{{/hasChildren}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
- {{/isContainer}}
- {{^isContainer}}
- {{#hasChildren}}protected{{/hasChildren}}{{^hasChildren}}private{{/hasChildren}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
- {{/isContainer}}
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
-
- {{/vars}}
- public {{classname}}() {
- {{#parent}}
- {{#parcelableModel}}
- super();{{/parcelableModel}}
- {{/parent}}
- {{#gson}}
- {{#discriminator}}
- {{#discriminator.isEnum}}
- this.{{{discriminatorName}}} = this.getClass().getSimpleName();
- {{/discriminator.isEnum}}
- {{/discriminator}}
- {{/gson}}
- }
- {{#vendorExtensions.x-has-readonly-properties}}
- {{^withXml}}
- /**
- * Constructor with only readonly parameters{{#generateConstructorWithAllArgs}}{{^vendorExtensions.x-java-all-args-constructor}} and all parameters{{/vendorExtensions.x-java-all-args-constructor}}{{/generateConstructorWithAllArgs}}
- */
- {{#jsonb}}@JsonbCreator{{/jsonb}}{{#jackson}}@JsonCreator{{/jackson}}
- public {{classname}}(
- {{#readOnlyVars}}
- {{#jsonb}}@JsonbProperty(value = "{{baseName}}"{{^required}}, nullable = true{{/required}}){{/jsonb}}{{#jackson}}@JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}){{/jackson}} {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}}
- {{/readOnlyVars}}
- ) {
- this();
- {{#readOnlyVars}}
- this.{{name}} = {{#vendorExtensions.x-is-jackson-optional-nullable}}{{name}} == null ? JsonNullable.<{{{datatypeWithEnum}}}>undefined() : JsonNullable.of({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{name}}{{/vendorExtensions.x-is-jackson-optional-nullable}};
- {{/readOnlyVars}}
- }
- {{/withXml}}
- {{/vendorExtensions.x-has-readonly-properties}}
-{{#vendorExtensions.x-java-all-args-constructor}}
-
- /**
- * Constructor with all args parameters
- */
- public {{classname}}({{#vendorExtensions.x-java-all-args-constructor-vars}}{{#jsonb}}@JsonbProperty(value = "{{baseName}}"{{^required}}, nullable = true{{/required}}){{/jsonb}}{{#jackson}}@JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}){{/jackson}} {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-java-all-args-constructor-vars}}) {
-{{#parent}}
- super({{#parentVars}}{{name}}{{^-last}}, {{/-last}}{{/parentVars}});
-{{/parent}}
- {{#vars}}
- this.{{name}} = {{#vendorExtensions.x-is-jackson-optional-nullable}}{{name}} == null ? JsonNullable.<{{{datatypeWithEnum}}}>undefined() : JsonNullable.of({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{name}}{{/vendorExtensions.x-is-jackson-optional-nullable}};
-{{/vars}}
- }
-{{/vendorExtensions.x-java-all-args-constructor}}
-
-{{#vars}}
- {{^isReadOnly}}
- public {{classname}} {{name}}({{>nullable_var_annotations}} {{{datatypeWithEnum}}} {{name}}) {
- {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}}
- {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}}
- return this;
- }
- {{#isArray}}
-
- public {{classname}} add{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
- {{#vendorExtensions.x-is-jackson-optional-nullable}}
- if (this.{{name}} == null || !this.{{name}}.isPresent()) {
- this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}});
- }
- try {
- this.{{name}}.get().add({{name}}Item);
- } catch (java.util.NoSuchElementException e) {
- // this can never happen, as we make sure above that the value is present
- }
- return this;
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
- {{^vendorExtensions.x-is-jackson-optional-nullable}}
- if (this.{{name}} == null) {
- this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}};
- }
- this.{{name}}.add({{name}}Item);
- return this;
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
- }
- {{/isArray}}
- {{#isMap}}
-
- public {{classname}} put{{nameInPascalCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
- {{#vendorExtensions.x-is-jackson-optional-nullable}}
- if (this.{{name}} == null || !this.{{name}}.isPresent()) {
- this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}});
- }
- try {
- this.{{name}}.get().put(key, {{name}}Item);
- } catch (java.util.NoSuchElementException e) {
- // this can never happen, as we make sure above that the value is present
- }
- return this;
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
- {{^vendorExtensions.x-is-jackson-optional-nullable}}
- {{^required}}
- if (this.{{name}} == null) {
- this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}};
- }
- {{/required}}
- this.{{name}}.put(key, {{name}}Item);
- return this;
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
- }
- {{/isMap}}
-
- {{/isReadOnly}}
- /**
- {{#description}}
- * {{.}}
- {{/description}}
- {{^description}}
- * Get {{name}}
- {{/description}}
- {{#minimum}}
- * minimum: {{.}}
- {{/minimum}}
- {{#maximum}}
- * maximum: {{.}}
- {{/maximum}}
- * @return {{name}}
- {{#deprecated}}
- * @deprecated
- {{/deprecated}}
- */
-{{#deprecated}}
- @Deprecated
-{{/deprecated}}
- {{>nullable_var_annotations}}{{! prevent indent}}
-{{#jsonb}}
- @JsonbProperty("{{baseName}}")
-{{/jsonb}}
-{{#useBeanValidation}}
-{{>beanValidation}}
-
-{{/useBeanValidation}}
-{{#swagger1AnnotationLibrary}}
- @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
-{{/swagger1AnnotationLibrary}}
-{{#swagger2AnnotationLibrary}}
- @Schema({{#example}}example = "{{{.}}}", {{/example}}requiredMode = {{#required}}Schema.RequiredMode.REQUIRED{{/required}}{{^required}}Schema.RequiredMode.NOT_REQUIRED{{/required}}, description = "{{{description}}}")
-{{/swagger2AnnotationLibrary}}
-{{#vendorExtensions.x-extra-annotation}}
- {{{vendorExtensions.x-extra-annotation}}}
-{{/vendorExtensions.x-extra-annotation}}
-{{#vendorExtensions.x-is-jackson-optional-nullable}}
- {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}}
- @JsonIgnore
-{{/vendorExtensions.x-is-jackson-optional-nullable}}
-{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}}
- public {{{datatypeWithEnum}}} {{getter}}() {
- {{#vendorExtensions.x-is-jackson-optional-nullable}}
- {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}}
- if ({{name}} == null) {
- {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
- }
- {{/isReadOnly}}
- return {{name}}.orElse(null);
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
- {{^vendorExtensions.x-is-jackson-optional-nullable}}
- return {{name}};
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
- }
-
- {{#vendorExtensions.x-is-jackson-optional-nullable}}
-{{> jackson_annotations}}
-
- public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() {
- return {{name}};
- }
- {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}}
- @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}})
- {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) {
- {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}}
- this.{{name}} = {{name}};
- }
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
-
- {{^isReadOnly}}
-{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}}
-{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{>nullable_var_annotations}} {{{datatypeWithEnum}}} {{name}}) {
- {{#vendorExtensions.x-is-jackson-optional-nullable}}
- this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
- {{^vendorExtensions.x-is-jackson-optional-nullable}}
- this.{{name}} = {{name}};
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
- }
- {{/isReadOnly}}
-
- {{/vars}}
- {{#parent}}
- {{#readWriteVars}}
- {{#isOverridden}}
- @Override
- public {{classname}} {{name}}({{>nullable_var_annotations}} {{{datatypeWithEnum}}} {{name}}) {
- {{#vendorExtensions.x-is-jackson-optional-nullable}}
- this.{{setter}}(JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}));
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
- {{^vendorExtensions.x-is-jackson-optional-nullable}}
- this.{{setter}}({{name}});
- {{/vendorExtensions.x-is-jackson-optional-nullable}}
- return this;
- }
-
- {{/isOverridden}}
- {{/readWriteVars}}
- {{/parent}}
- @Override
- public boolean equals(Object o) {
- {{#useReflectionEqualsHashCode}}
- return EqualsBuilder.reflectionEquals(this, o, false, null, true);
- {{/useReflectionEqualsHashCode}}
- {{^useReflectionEqualsHashCode}}
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }{{#hasVars}}
- {{classname}} {{classVarName}} = ({{classname}}) o;
- return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} &&
- {{/-last}}{{/vars}}{{#parent}} &&
- super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}}
- return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}}
- {{/useReflectionEqualsHashCode}}
- }{{#vendorExtensions.x-jackson-optional-nullable-helpers}}
-
- private static boolean equalsNullable(JsonNullable a, JsonNullable b) {
- return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get()));
- }{{/vendorExtensions.x-jackson-optional-nullable-helpers}}
-
- @Override
- public int hashCode() {
- {{#useReflectionEqualsHashCode}}
- return HashCodeBuilder.reflectionHashCode(this);
- {{/useReflectionEqualsHashCode}}
- {{^useReflectionEqualsHashCode}}
- return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}});
- {{/useReflectionEqualsHashCode}}
- }{{#vendorExtensions.x-jackson-optional-nullable-helpers}}
-
- private static int hashCodeNullable(JsonNullable a) {
- if (a == null) {
- return 1;
- }
- return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31;
- }{{/vendorExtensions.x-jackson-optional-nullable-helpers}}
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("class {{classname}} {\n");
- {{#parent}}
- sb.append(" ").append(toIndentedString(super.toString())).append("\n");
- {{/parent}}
- {{#vars}}
- sb.append(" {{name}}: ").append({{#isPassword}}"*"{{/isPassword}}{{^isPassword}}toIndentedString({{name}}){{/isPassword}}).append("\n");
- {{/vars}}
- sb.append("}");
- return sb.toString();
- }
-
- /**
- * Convert the given object to string with each line indented by 4 spaces
- * (except the first line).
- */
- private{{#jsonb}} static{{/jsonb}} String toIndentedString(Object o) {
- if (o == null) {
- return "null";
- }
- return o.toString().replace("\n", "\n ");
- }
-{{#supportUrlQuery}}
-
- /**
- * Convert the instance into URL query string.
- *
- * @return URL query string
- */
- public String toUrlQueryString() {
- return toUrlQueryString(null);
- }
-
- /**
- * Convert the instance into URL query string.
- *
- * @param prefix prefix of the query string
- * @return URL query string
- */
- public String toUrlQueryString(String prefix) {
- String suffix = "";
- String containerSuffix = "";
- String containerPrefix = "";
- if (prefix == null) {
- // style=form, explode=true, e.g. /pet?name=cat&type=manx
- prefix = "";
- } else {
- // deepObject style e.g. /pet?id[name]=cat&id[type]=manx
- prefix = prefix + "[";
- suffix = "]";
- containerSuffix = "]";
- containerPrefix = "[";
- }
-
- StringJoiner joiner = new StringJoiner("&");
-
- {{#allVars}}
- // add `{{baseName}}` to the URL query string
- {{#isArray}}
- {{#items.isPrimitiveType}}
- {{#uniqueItems}}
- if ({{getter}}() != null) {
- int i = 0;
- for ({{{items.datatypeWithEnum}}} _item : {{getter}}()) {
- try {
- joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
- "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix),
- URLEncoder.encode(String.valueOf(_item), "UTF-8").replaceAll("\\+", "%20")));
- } catch (UnsupportedEncodingException e) {
- // Should never happen, UTF-8 is always supported
- throw new RuntimeException(e);
- }
- }
- i++;
- }
- {{/uniqueItems}}
- {{^uniqueItems}}
- if ({{getter}}() != null) {
- for (int i = 0; i < {{getter}}().size(); i++) {
- try {
- joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
- "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix),
- URLEncoder.encode(String.valueOf({{getter}}().get(i)), "UTF-8").replaceAll("\\+", "%20")));
- } catch (UnsupportedEncodingException e) {
- // Should never happen, UTF-8 is always supported
- throw new RuntimeException(e);
- }
- }
- }
- {{/uniqueItems}}
- {{/items.isPrimitiveType}}
- {{^items.isPrimitiveType}}
- {{#items.isModel}}
- {{#uniqueItems}}
- if ({{getter}}() != null) {
- int i = 0;
- for ({{{items.dataType}}} _item : {{getter}}()) {
- if (_item != null) {
- joiner.add(_item.toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix,
- "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix))));
- }
- }
- i++;
- }
- {{/uniqueItems}}
- {{^uniqueItems}}
- if ({{getter}}() != null) {
- for (int i = 0; i < {{getter}}().size(); i++) {
- if ({{getter}}().get(i) != null) {
- joiner.add({{getter}}().get(i).toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix,
- "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix))));
- }
- }
- }
- {{/uniqueItems}}
- {{/items.isModel}}
- {{^items.isModel}}
- {{#uniqueItems}}
- if ({{getter}}() != null) {
- int i = 0;
- for ({{{items.dataType}}} _item : {{getter}}()) {
- if (_item != null) {
- try {
- joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
- "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix),
- URLEncoder.encode(String.valueOf(_item), "UTF-8").replaceAll("\\+", "%20")));
- } catch (UnsupportedEncodingException e) {
- // Should never happen, UTF-8 is always supported
- throw new RuntimeException(e);
- }
- }
- i++;
- }
- }
- {{/uniqueItems}}
- {{^uniqueItems}}
- if ({{getter}}() != null) {
- for (int i = 0; i < {{getter}}().size(); i++) {
- if ({{getter}}().get(i) != null) {
- try {
- joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
- "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix),
- URLEncoder.encode(String.valueOf({{getter}}().get(i)), "UTF-8").replaceAll("\\+", "%20")));
- } catch (UnsupportedEncodingException e) {
- // Should never happen, UTF-8 is always supported
- throw new RuntimeException(e);
- }
- }
- }
- }
- {{/uniqueItems}}
- {{/items.isModel}}
- {{/items.isPrimitiveType}}
- {{/isArray}}
- {{^isArray}}
- {{#isMap}}
- {{^items.isModel}}
- if ({{getter}}() != null) {
- for (String _key : {{getter}}().keySet()) {
- try {
- joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
- "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix),
- {{getter}}().get(_key), URLEncoder.encode(String.valueOf({{getter}}().get(_key)), "UTF-8").replaceAll("\\+", "%20")));
- } catch (UnsupportedEncodingException e) {
- // Should never happen, UTF-8 is always supported
- throw new RuntimeException(e);
- }
- }
- }
- {{/items.isModel}}
- {{#items.isModel}}
- if ({{getter}}() != null) {
- for (String _key : {{getter}}().keySet()) {
- if ({{getter}}().get(_key) != null) {
- joiner.add({{getter}}().get(_key).toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix,
- "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix))));
- }
- }
- }
- {{/items.isModel}}
- {{/isMap}}
- {{^isMap}}
- {{#isPrimitiveType}}
- if ({{getter}}() != null) {
- try {
- joiner.add(String.format("%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), "UTF-8").replaceAll("\\+", "%20")));
- } catch (UnsupportedEncodingException e) {
- // Should never happen, UTF-8 is always supported
- throw new RuntimeException(e);
- }
- }
- {{/isPrimitiveType}}
- {{^isPrimitiveType}}
- {{#isModel}}
- if ({{getter}}() != null) {
- joiner.add({{getter}}().toUrlQueryString(prefix + "{{{baseName}}}" + suffix));
- }
- {{/isModel}}
- {{^isModel}}
- if ({{getter}}() != null) {
- try {
- joiner.add(String.format("%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), "UTF-8").replaceAll("\\+", "%20")));
- } catch (UnsupportedEncodingException e) {
- // Should never happen, UTF-8 is always supported
- throw new RuntimeException(e);
- }
- }
- {{/isModel}}
- {{/isPrimitiveType}}
- {{/isMap}}
- {{/isArray}}
-
- {{/allVars}}
- return joiner.toString();
- }
-{{/supportUrlQuery}}
-{{#parcelableModel}}
-
- public void writeToParcel(Parcel out, int flags) {
-{{#model}}
-{{#isArray}}
- out.writeList(this);
-{{/isArray}}
-{{^isArray}}
-{{#parent}}
- super.writeToParcel(out, flags);
-{{/parent}}
-{{#vars}}
- out.writeValue({{name}});
-{{/vars}}
-{{/isArray}}
-{{/model}}
- }
-
- {{classname}}(Parcel in) {
-{{#isArray}}
- in.readTypedList(this, {{arrayModelType}}.CREATOR);
-{{/isArray}}
-{{^isArray}}
-{{#parent}}
- super(in);
-{{/parent}}
-{{#vars}}
-{{#isPrimitiveType}}
- {{name}} = ({{{datatypeWithEnum}}})in.readValue(null);
-{{/isPrimitiveType}}
-{{^isPrimitiveType}}
- {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader());
-{{/isPrimitiveType}}
-{{/vars}}
-{{/isArray}}
- }
-
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() {
- public {{classname}} createFromParcel(Parcel in) {
-{{#model}}
-{{#isArray}}
- {{classname}} result = new {{classname}}();
- result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader()));
- return result;
-{{/isArray}}
-{{^isArray}}
- return new {{classname}}(in);
-{{/isArray}}
-{{/model}}
- }
- public {{classname}}[] newArray(int size) {
- return new {{classname}}[size];
- }
- };
-{{/parcelableModel}}
-{{#generateBuilders}}
-
- {{>javaBuilder}}{{! prevent indent}}
-{{/generateBuilders}}
-
-}
diff --git a/licensing-service-client/src/main/resources/openapi-templates/sealed.mustache b/licensing-service-client/src/main/resources/openapi-templates/sealed.mustache
deleted file mode 100644
index 8e5076b..0000000
--- a/licensing-service-client/src/main/resources/openapi-templates/sealed.mustache
+++ /dev/null
@@ -1 +0,0 @@
-{{#useSealedOneOfInterfaces}}{{#vendorExtensions.x-is-one-of-interface}}{{#permits.0}}sealed {{/permits.0}}{{/vendorExtensions.x-is-one-of-interface}}{{^permits.0}}{{#vendorExtensions.x-implements}}final {{/vendorExtensions.x-implements}}{{/permits.0}}{{/useSealedOneOfInterfaces}}
\ No newline at end of file
diff --git a/licensing-service-client/src/test/java/io/github/bsayli/licensing/client/adapter/LicensingServiceClientAdapterIT.java b/licensing-service-client/src/test/java/io/github/bsayli/licensing/client/adapter/LicensingServiceClientAdapterIT.java
index bca201c..ea34e0f 100644
--- a/licensing-service-client/src/test/java/io/github/bsayli/licensing/client/adapter/LicensingServiceClientAdapterIT.java
+++ b/licensing-service-client/src/test/java/io/github/bsayli/licensing/client/adapter/LicensingServiceClientAdapterIT.java
@@ -5,12 +5,12 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.bsayli.licensing.client.adapter.config.LicensingServiceApiClientConfig;
import io.github.bsayli.licensing.client.adapter.impl.LicensingServiceClientAdapterImpl;
-import io.github.bsayli.licensing.client.common.contract.ApiClientResponse;
import io.github.bsayli.licensing.client.common.core.ApiClientExecutor;
import io.github.bsayli.licensing.client.common.core.ResponseParser;
import io.github.bsayli.licensing.client.generated.dto.IssueAccessRequest;
import io.github.bsayli.licensing.client.generated.dto.LicenseAccessResponse;
import io.github.bsayli.licensing.client.generated.dto.ValidateAccessRequest;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
@@ -76,7 +76,7 @@ void issueAccess_shouldReturn200_andMappedBody() throws Exception {
.licenseKey("BSAYLI~RND~ENC")
.signature("BASE64SIG");
- ApiClientResponse resp = adapter.issueAccess(req);
+ ApiResponse resp = adapter.issueAccess(req);
assertNotNull(resp);
assertEquals(200, resp.getStatus());
@@ -120,7 +120,7 @@ void validateAccess_shouldReturn200_andMappedBody_andSendHeader() throws Excepti
.signature("BASE64SIG");
String jwt = "jwt-123";
- ApiClientResponse resp = adapter.validateAccess(jwt, req);
+ ApiResponse resp = adapter.validateAccess(jwt, req);
assertNotNull(resp);
assertEquals(200, resp.getStatus());
diff --git a/licensing-service-sdk-cli/Dockerfile b/licensing-service-sdk-cli/Dockerfile
index 40b8a9a..c94f0f9 100644
--- a/licensing-service-sdk-cli/Dockerfile
+++ b/licensing-service-sdk-cli/Dockerfile
@@ -20,9 +20,9 @@ RUN apt-get update && \
LABEL org.opencontainers.image.title="licensing-service-sdk-cli" \
org.opencontainers.image.description="CLI for Licensing Service SDK" \
- org.opencontainers.image.version="1.0.1" \
+ org.opencontainers.image.version="1.0.5" \
org.opencontainers.image.source="https://github.com/bsayli/licensing" \
- org.opencontainers.image.licenses="Apache-2.0"
+ org.opencontainers.image.licenses="MIT"
COPY --from=builder --chown=appuser:appuser /app/target/*.jar /app/licensing-service-sdk-cli.jar
diff --git a/licensing-service-sdk-cli/README.md b/licensing-service-sdk-cli/README.md
index dd43c4d..e581d2a 100644
--- a/licensing-service-sdk-cli/README.md
+++ b/licensing-service-sdk-cli/README.md
@@ -64,7 +64,7 @@ Default values can also be injected from environment variables:
## Example
```bash
-java -jar target/licensing-service-sdk-cli-1.0.1.jar \
+java -jar target/licensing-service-sdk-cli-1.0.5.jar \
-k 'BSAYLI.AQA3-gCQ66DQsfC0LwnAO8DTjKgad7DhPaOtCf7WG2bFUoK9pmScIhhCf2S-D0j8g4jC7nlFrLDpuM0ezEoDQc79SizxxEIUGN9YUhTNBW7iRQ' \
-s crm \
-v 1.5.0 \
diff --git a/licensing-service-sdk-cli/pom.xml b/licensing-service-sdk-cli/pom.xml
index 2101679..ea74551 100644
--- a/licensing-service-sdk-cli/pom.xml
+++ b/licensing-service-sdk-cli/pom.xml
@@ -4,32 +4,39 @@
4.0.0
io.github.bsayli
licensing-service-sdk-cli
- 1.0.4
+ ${licensing-api-contract.version}
licensing-service-sdk-cli
Licensing Service Sdk Cli
+ UTF-8
+ UTF-8
21
4.7.6
5.5
- 2.19.2
+ 2.21.3
2.0.17
- 1.5.18
- UTF-8
- UTF-8
+ 1.5.32
5.13.4
3.5.3
- 0.8.13
- 3.5.5
- 3.14.0
+ 0.8.14
+ 3.5.14
+ 3.15.0
5.19.0
5.2.0
5.19.0
+ 1.0.5
+
+ io.github.bsayli
+ licensing-api-contract
+ ${licensing-api-contract.version}
+
+
info.picocli
picocli
diff --git a/licensing-service-sdk-cli/src/main/java/io/github/bsayli/licensing/sdk/cli/model/ApiError.java b/licensing-service-sdk-cli/src/main/java/io/github/bsayli/licensing/sdk/cli/model/ApiError.java
deleted file mode 100644
index e76bdfe..0000000
--- a/licensing-service-sdk-cli/src/main/java/io/github/bsayli/licensing/sdk/cli/model/ApiError.java
+++ /dev/null
@@ -1,3 +0,0 @@
-package io.github.bsayli.licensing.sdk.cli.model;
-
-public record ApiError(String errorCode, String message) {}
diff --git a/licensing-service-sdk-cli/src/main/java/io/github/bsayli/licensing/sdk/cli/model/ApiResponse.java b/licensing-service-sdk-cli/src/main/java/io/github/bsayli/licensing/sdk/cli/model/ApiResponse.java
deleted file mode 100644
index e0a6666..0000000
--- a/licensing-service-sdk-cli/src/main/java/io/github/bsayli/licensing/sdk/cli/model/ApiResponse.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package io.github.bsayli.licensing.sdk.cli.model;
-
-import java.util.List;
-
-public record ApiResponse(int status, String message, T data, List errors) {}
diff --git a/licensing-service-sdk-cli/src/main/java/io/github/bsayli/licensing/sdk/cli/service/impl/LicenseSdkClientServiceImpl.java b/licensing-service-sdk-cli/src/main/java/io/github/bsayli/licensing/sdk/cli/service/impl/LicenseSdkClientServiceImpl.java
index dabf251..860721a 100644
--- a/licensing-service-sdk-cli/src/main/java/io/github/bsayli/licensing/sdk/cli/service/impl/LicenseSdkClientServiceImpl.java
+++ b/licensing-service-sdk-cli/src/main/java/io/github/bsayli/licensing/sdk/cli/service/impl/LicenseSdkClientServiceImpl.java
@@ -1,7 +1,7 @@
package io.github.bsayli.licensing.sdk.cli.service.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
-import io.github.bsayli.licensing.sdk.cli.model.ApiResponse;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import io.github.bsayli.licensing.sdk.cli.model.LicenseAccessRequest;
import io.github.bsayli.licensing.sdk.cli.model.LicenseSdkClientProperties;
import io.github.bsayli.licensing.sdk.cli.model.LicenseToken;
@@ -121,21 +121,22 @@ private ApiResponse parseApiResponseLicenseToken(String json) {
}
private boolean isSuccess(ApiResponse api) {
- return api.status() == 200 && api.data() != null && api.data().licenseToken() != null;
+ return api.getStatus() == 200 && api.getData() != null && api.getData().licenseToken() != null;
}
private void logSuccess(ApiResponse api) {
log.info("License validated successfully.");
- log.info("Token: {}", api.data().licenseToken());
- if (api.message() != null && !api.message().isBlank()) {
- log.info("Message: {}", api.message());
+ log.info("Token: {}", api.getData().licenseToken());
+ if (api.getMessage() != null && !api.getMessage().isBlank()) {
+ log.info("Message: {}", api.getMessage());
}
}
private void logFailure(ApiResponse api) {
- log.error("License validation failed. status={}, message={}", api.status(), api.message());
- if (api.errors() != null) {
- api.errors()
+ log.error(
+ "License validation failed. status={}, message={}", api.getStatus(), api.getMessage());
+ if (api.getErrors() != null) {
+ api.getErrors()
.forEach(err -> log.error("errorCode={}, message={}", err.errorCode(), err.message()));
}
}
diff --git a/licensing-service-sdk/Dockerfile b/licensing-service-sdk/Dockerfile
index 1fd11c5..429245e 100644
--- a/licensing-service-sdk/Dockerfile
+++ b/licensing-service-sdk/Dockerfile
@@ -1,9 +1,14 @@
FROM maven:3.9.11-eclipse-temurin-21-noble AS builder
WORKDIR /build
+COPY licensing-api-contract/pom.xml licensing-api-contract/pom.xml
COPY licensing-service-client/pom.xml licensing-service-client/pom.xml
COPY licensing-service-sdk/pom.xml licensing-service-sdk/pom.xml
+COPY licensing-api-contract/ licensing-api-contract/
+RUN --mount=type=cache,target=/root/.m2 \
+ mvn -q -DskipTests -f licensing-api-contract/pom.xml install
+
RUN --mount=type=cache,target=/root/.m2 \
mvn -q -DskipTests -f licensing-service-client/pom.xml dependency:go-offline
@@ -29,7 +34,7 @@ RUN apt-get update && \
LABEL org.opencontainers.image.title="licensing-service-sdk" \
org.opencontainers.image.description="Licensing Service SDK (Spring Boot)" \
- org.opencontainers.image.version="1.0.1" \
+ org.opencontainers.image.version="1.0.5" \
org.opencontainers.image.source="https://github.com/bsayli/licensing" \
org.opencontainers.image.licenses="MIT"
diff --git a/licensing-service-sdk/pom.xml b/licensing-service-sdk/pom.xml
index 08147b0..d87998c 100644
--- a/licensing-service-sdk/pom.xml
+++ b/licensing-service-sdk/pom.xml
@@ -6,12 +6,12 @@
org.springframework.boot
spring-boot-starter-parent
- 3.5.5
+ 3.5.14
io.github.bsayli
licensing-service-sdk
- 1.0.4
+ 1.0.5
licensing-service-sdk
Licensing Service SDK App
@@ -20,10 +20,10 @@
UTF-8
UTF-8
21
- 2.8.13
- 3.18.0
- 1.0.4
- 0.8.13
+ 2.8.17
+ 3.20.0
+ 1.0.5
+ 0.8.14
diff --git a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/api/controller/LicenseController.java b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/api/controller/LicenseController.java
index aac028a..6056740 100644
--- a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/api/controller/LicenseController.java
+++ b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/api/controller/LicenseController.java
@@ -1,8 +1,8 @@
package io.github.bsayli.licensing.sdk.api.controller;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import io.github.bsayli.licensing.sdk.api.dto.LicenseAccessRequest;
import io.github.bsayli.licensing.sdk.api.dto.LicenseToken;
-import io.github.bsayli.licensing.sdk.common.api.ApiResponse;
import io.github.bsayli.licensing.sdk.common.i18n.LocalizedMessageResolver;
import io.github.bsayli.licensing.sdk.service.LicenseOrchestrationService;
import jakarta.validation.Valid;
@@ -32,6 +32,7 @@ public ResponseEntity> getLicenseToken(
LicenseToken token = licenseService.getLicenseToken(request);
String msg = messageResolver.getMessage("license.validation.success");
- return ResponseEntity.status(HttpStatus.OK).body(ApiResponse.of(HttpStatus.OK, msg, token));
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(ApiResponse.of(HttpStatus.OK.value(), msg, token));
}
}
diff --git a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/api/exception/LicenseControllerAdvice.java b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/api/exception/LicenseControllerAdvice.java
index dcaa4e9..64cab6b 100644
--- a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/api/exception/LicenseControllerAdvice.java
+++ b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/api/exception/LicenseControllerAdvice.java
@@ -1,7 +1,7 @@
package io.github.bsayli.licensing.sdk.api.exception;
-import io.github.bsayli.licensing.sdk.common.api.ApiError;
-import io.github.bsayli.licensing.sdk.common.api.ApiResponse;
+import io.github.bsayli.licensing.contract.api.ApiError;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import io.github.bsayli.licensing.sdk.common.exception.LicensingSdkHttpTransportException;
import io.github.bsayli.licensing.sdk.common.exception.LicensingSdkRemoteServiceException;
import io.github.bsayli.licensing.sdk.common.i18n.LocalizedMessageResolver;
@@ -41,7 +41,7 @@ public ResponseEntity> handleMethodArgNotValid(
}
String topMsg = messages.getMessage("request.validation.failed");
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
- .body(ApiResponse.error(HttpStatus.BAD_REQUEST, topMsg, errors));
+ .body(ApiResponse.error(HttpStatus.BAD_REQUEST.value(), topMsg, errors));
}
@ExceptionHandler(ConstraintViolationException.class)
@@ -56,13 +56,13 @@ public ResponseEntity> handleConstraintViolation(
}
String topMsg = messages.getMessage("request.validation.failed");
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
- .body(ApiResponse.error(HttpStatus.BAD_REQUEST, topMsg, errors));
+ .body(ApiResponse.error(HttpStatus.BAD_REQUEST.value(), topMsg, errors));
}
@ExceptionHandler(LicensingSdkRemoteServiceException.class)
public ResponseEntity> handleRemoteError(
LicensingSdkRemoteServiceException ex) {
- HttpStatus http =
+ HttpStatus httpStatus =
Objects.requireNonNullElse(ex.getHttpStatus(), HttpStatus.INTERNAL_SERVER_ERROR);
String top =
@@ -83,26 +83,26 @@ public ResponseEntity> handleRemoteError(
errs = List.of();
}
- return ResponseEntity.status(http).body(ApiResponse.error(http, top, errs));
+ return ResponseEntity.status(httpStatus).body(ApiResponse.error(httpStatus.value(), top, errs));
}
@ExceptionHandler(LicensingSdkHttpTransportException.class)
public ResponseEntity> handleTransportError(
LicensingSdkHttpTransportException ex) {
log.error("Transport/parse error when calling licensing-service", ex);
- HttpStatus http = HttpStatus.BAD_GATEWAY;
+ HttpStatus httpStatus = HttpStatus.BAD_GATEWAY;
String top = messages.getMessage("license.validation.error");
List errs = List.of(new ApiError("TRANSPORT_ERROR", top));
- return ResponseEntity.status(http).body(ApiResponse.error(http, top, errs));
+ return ResponseEntity.status(httpStatus).body(ApiResponse.error(httpStatus.value(), top, errs));
}
@ExceptionHandler(Exception.class)
public ResponseEntity> handleGeneric(Exception ex) {
log.error("Unexpected error in SDK API layer", ex);
- HttpStatus http = HttpStatus.INTERNAL_SERVER_ERROR;
+ HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
String top = messages.getMessage("license.validation.error");
List errs = List.of(new ApiError("INTERNAL_SERVER_ERROR", top));
- return ResponseEntity.status(http).body(ApiResponse.error(http, top, errs));
+ return ResponseEntity.status(httpStatus).body(ApiResponse.error(httpStatus.value(), top, errs));
}
private String resolveStrict(String keyOrText, Object... args) {
diff --git a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/api/ApiError.java b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/api/ApiError.java
deleted file mode 100644
index fa1f1d3..0000000
--- a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/api/ApiError.java
+++ /dev/null
@@ -1,3 +0,0 @@
-package io.github.bsayli.licensing.sdk.common.api;
-
-public record ApiError(String errorCode, String message) {}
diff --git a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/api/ApiResponse.java b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/api/ApiResponse.java
deleted file mode 100644
index dc4cce0..0000000
--- a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/api/ApiResponse.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package io.github.bsayli.licensing.sdk.common.api;
-
-import java.util.Collections;
-import java.util.List;
-import org.springframework.http.HttpStatus;
-
-public record ApiResponse(int status, String message, T data, List errors) {
- public static ApiResponse ok(T data) {
- return new ApiResponse<>(HttpStatus.OK.value(), "OK", data, Collections.emptyList());
- }
-
- public static ApiResponse of(HttpStatus status, String message, T data) {
- return new ApiResponse<>(status.value(), message, data, Collections.emptyList());
- }
-
- public static ApiResponse error(HttpStatus status, String message) {
- return new ApiResponse<>(status.value(), message, null, Collections.emptyList());
- }
-
- public static ApiResponse error(HttpStatus status, String message, List errors) {
- return new ApiResponse<>(
- status.value(), message, null, errors != null ? errors : Collections.emptyList());
- }
-}
diff --git a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/openapi/ApiResponseSchemaFactory.java b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/openapi/ApiResponseSchemaFactory.java
deleted file mode 100644
index b53204a..0000000
--- a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/openapi/ApiResponseSchemaFactory.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.github.bsayli.licensing.sdk.common.openapi;
-
-import static io.github.bsayli.licensing.sdk.common.openapi.OpenApiSchemas.*;
-
-import io.swagger.v3.oas.models.media.ComposedSchema;
-import io.swagger.v3.oas.models.media.ObjectSchema;
-import io.swagger.v3.oas.models.media.Schema;
-import java.util.List;
-
-public final class ApiResponseSchemaFactory {
- private ApiResponseSchemaFactory() {}
-
- public static Schema> createComposedWrapper(String dataRefName) {
- var schema = new ComposedSchema();
- schema.setAllOf(
- List.of(
- new Schema<>().$ref("#/components/schemas/" + SCHEMA_API_RESPONSE),
- new ObjectSchema()
- .addProperty(
- PROP_DATA, new Schema<>().$ref("#/components/schemas/" + dataRefName))));
- schema.addExtension(EXT_API_WRAPPER, true);
- schema.addExtension(EXT_API_WRAPPER_DATATYPE, dataRefName);
- return schema;
- }
-}
diff --git a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/openapi/OpenApiSchemas.java b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/openapi/OpenApiSchemas.java
deleted file mode 100644
index a542b1f..0000000
--- a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/openapi/OpenApiSchemas.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.github.bsayli.licensing.sdk.common.openapi;
-
-public final class OpenApiSchemas {
- // Common property keys
- public static final String PROP_STATUS = "status";
- public static final String PROP_MESSAGE = "message";
- public static final String PROP_ERRORS = "errors";
- public static final String PROP_ERROR_CODE = "errorCode";
- public static final String PROP_DATA = "data";
- // Base envelopes
- public static final String SCHEMA_API_RESPONSE = "ApiResponse";
- public static final String SCHEMA_API_RESPONSE_VOID = "ApiResponseVoid";
- // Vendor extensions
- public static final String EXT_API_WRAPPER = "x-api-wrapper";
- public static final String EXT_API_WRAPPER_DATATYPE = "x-api-wrapper-datatype";
-
- private OpenApiSchemas() {}
-}
diff --git a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/openapi/SwaggerResponseCustomizer.java b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/openapi/SwaggerResponseCustomizer.java
deleted file mode 100644
index a287dad..0000000
--- a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/common/openapi/SwaggerResponseCustomizer.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package io.github.bsayli.licensing.sdk.common.openapi;
-
-import static io.github.bsayli.licensing.sdk.common.openapi.OpenApiSchemas.*;
-
-import io.swagger.v3.oas.models.media.ArraySchema;
-import io.swagger.v3.oas.models.media.IntegerSchema;
-import io.swagger.v3.oas.models.media.ObjectSchema;
-import io.swagger.v3.oas.models.media.StringSchema;
-import org.springdoc.core.customizers.OpenApiCustomizer;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class SwaggerResponseCustomizer {
-
- @Bean
- public OpenApiCustomizer responseEnvelopeSchemas() {
- return openApi -> {
- if (!openApi.getComponents().getSchemas().containsKey(SCHEMA_API_RESPONSE)) {
- openApi
- .getComponents()
- .addSchemas(
- SCHEMA_API_RESPONSE,
- new ObjectSchema()
- .addProperty(PROP_STATUS, new IntegerSchema().format("int32"))
- .addProperty(PROP_MESSAGE, new StringSchema())
- .addProperty(
- PROP_ERRORS,
- new ArraySchema()
- .items(
- new ObjectSchema()
- .addProperty(PROP_ERROR_CODE, new StringSchema())
- .addProperty(PROP_MESSAGE, new StringSchema()))));
- }
-
- if (!openApi.getComponents().getSchemas().containsKey(SCHEMA_API_RESPONSE_VOID)) {
- openApi
- .getComponents()
- .addSchemas(
- SCHEMA_API_RESPONSE_VOID,
- new ObjectSchema()
- .addProperty(PROP_STATUS, new IntegerSchema().format("int32"))
- .addProperty(PROP_MESSAGE, new StringSchema())
- .addProperty(PROP_DATA, new ObjectSchema())
- .addProperty(
- PROP_ERRORS,
- new ArraySchema()
- .items(
- new ObjectSchema()
- .addProperty(PROP_ERROR_CODE, new StringSchema())
- .addProperty(PROP_MESSAGE, new StringSchema()))));
- }
- };
- }
-}
diff --git a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/client/LicenseServiceClient.java b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/client/LicenseServiceClient.java
index 223c207..2707827 100644
--- a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/client/LicenseServiceClient.java
+++ b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/client/LicenseServiceClient.java
@@ -1,12 +1,12 @@
package io.github.bsayli.licensing.sdk.service.client;
-import io.github.bsayli.licensing.client.common.contract.ApiClientResponse;
import io.github.bsayli.licensing.client.generated.dto.IssueAccessRequest;
import io.github.bsayli.licensing.client.generated.dto.LicenseAccessResponse;
import io.github.bsayli.licensing.client.generated.dto.ValidateAccessRequest;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
public interface LicenseServiceClient {
- ApiClientResponse issueAccess(IssueAccessRequest req);
+ ApiResponse issueAccess(IssueAccessRequest req);
- ApiClientResponse validateAccess(String token, ValidateAccessRequest req);
+ ApiResponse validateAccess(String token, ValidateAccessRequest req);
}
diff --git a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/client/impl/LicenseServiceClientImpl.java b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/client/impl/LicenseServiceClientImpl.java
index 4ad00e0..df0494d 100644
--- a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/client/impl/LicenseServiceClientImpl.java
+++ b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/client/impl/LicenseServiceClientImpl.java
@@ -1,10 +1,10 @@
package io.github.bsayli.licensing.sdk.service.client.impl;
import io.github.bsayli.licensing.client.adapter.LicensingServiceClientAdapter;
-import io.github.bsayli.licensing.client.common.contract.ApiClientResponse;
import io.github.bsayli.licensing.client.generated.dto.IssueAccessRequest;
import io.github.bsayli.licensing.client.generated.dto.LicenseAccessResponse;
import io.github.bsayli.licensing.client.generated.dto.ValidateAccessRequest;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import io.github.bsayli.licensing.sdk.service.client.LicenseServiceClient;
import org.springframework.stereotype.Service;
@@ -18,12 +18,12 @@ public LicenseServiceClientImpl(LicensingServiceClientAdapter adapter) {
}
@Override
- public ApiClientResponse issueAccess(IssueAccessRequest req) {
+ public ApiResponse issueAccess(IssueAccessRequest req) {
return adapter.issueAccess(req);
}
@Override
- public ApiClientResponse validateAccess(
+ public ApiResponse validateAccess(
String token, ValidateAccessRequest req) {
return adapter.validateAccess(token, req);
}
diff --git a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/handler/LicenseResponseHandler.java b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/handler/LicenseResponseHandler.java
index 279e114..2abf6fc 100644
--- a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/handler/LicenseResponseHandler.java
+++ b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/handler/LicenseResponseHandler.java
@@ -1,7 +1,7 @@
package io.github.bsayli.licensing.sdk.service.handler;
-import io.github.bsayli.licensing.client.common.contract.ApiClientResponse;
import io.github.bsayli.licensing.client.generated.dto.LicenseAccessResponse;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import io.github.bsayli.licensing.sdk.common.exception.LicensingSdkRemoteServiceException;
import io.github.bsayli.licensing.sdk.common.i18n.LocalizedMessageResolver;
import java.util.List;
@@ -27,16 +27,16 @@ public LicenseResponseHandler(LocalizedMessageResolver messages) {
this.messages = messages;
}
- private void requireOk(ApiClientResponse resp) {
+ private void requireOk(ApiResponse resp) {
if (isOk(resp)) return;
throw buildRemoteException(resp);
}
- private boolean isOk(ApiClientResponse resp) {
- return resp != null && resp.getStatus() != null && resp.getStatus() == HTTP_OK;
+ private boolean isOk(ApiResponse resp) {
+ return resp != null && resp.getStatus() == HTTP_OK;
}
- public String extractTokenOrThrow(ApiClientResponse resp) {
+ public String extractTokenOrThrow(ApiResponse resp) {
requireOk(resp);
String token = safeToken(resp);
if (token == null) {
@@ -49,19 +49,19 @@ public String extractTokenOrThrow(ApiClientResponse resp)
return token;
}
- public String extractTokenIfPresentOrThrow(ApiClientResponse resp) {
+ public String extractTokenIfPresentOrThrow(ApiResponse resp) {
requireOk(resp);
return safeToken(resp);
}
- private String safeToken(ApiClientResponse resp) {
+ private String safeToken(ApiResponse resp) {
var data = resp.getData();
if (data == null) return null;
String t = data.getLicenseToken();
return (t == null || t.isBlank()) ? null : t;
}
- private LicensingSdkRemoteServiceException buildRemoteException(ApiClientResponse resp) {
+ private LicensingSdkRemoteServiceException buildRemoteException(ApiResponse resp) {
HttpStatus status = resolveStatus(resp);
String top = resolveTopMessage(resp);
String errorCode = resolveErrorCode(resp);
@@ -69,18 +69,18 @@ private LicensingSdkRemoteServiceException buildRemoteException(ApiClientRes
return new LicensingSdkRemoteServiceException(status, errorCode, top, details);
}
- private HttpStatus resolveStatus(ApiClientResponse resp) {
- if (resp == null || resp.getStatus() == null) return HttpStatus.INTERNAL_SERVER_ERROR;
+ private HttpStatus resolveStatus(ApiResponse resp) {
+ if (resp == null) return HttpStatus.INTERNAL_SERVER_ERROR;
return HttpStatus.valueOf(resp.getStatus());
}
- private String resolveTopMessage(ApiClientResponse resp) {
+ private String resolveTopMessage(ApiResponse resp) {
if (resp == null) return messages.getMessage(KEY_TOP_REMOTE_FAILED);
String msg = resp.getMessage();
return (msg == null || msg.isBlank()) ? messages.getMessage(KEY_TOP_REMOTE_FAILED) : msg;
}
- private String resolveErrorCode(ApiClientResponse resp) {
+ private String resolveErrorCode(ApiResponse resp) {
if (resp == null || resp.getErrors() == null || resp.getErrors().isEmpty()) {
return CODE_REMOTE_ERROR;
}
@@ -89,7 +89,7 @@ private String resolveErrorCode(ApiClientResponse resp) {
return (code == null || code.isBlank()) ? CODE_REMOTE_ERROR : code;
}
- private List resolveDetails(ApiClientResponse resp) {
+ private List resolveDetails(ApiResponse resp) {
if (resp == null || resp.getErrors() == null || resp.getErrors().isEmpty()) {
return List.of(messages.getMessage(KEY_DETAIL_NO_PAYLOAD));
}
diff --git a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/impl/LicenseOrchestrationServiceImpl.java b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/impl/LicenseOrchestrationServiceImpl.java
index d60674d..12a068d 100644
--- a/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/impl/LicenseOrchestrationServiceImpl.java
+++ b/licensing-service-sdk/src/main/java/io/github/bsayli/licensing/sdk/service/impl/LicenseOrchestrationServiceImpl.java
@@ -1,10 +1,10 @@
package io.github.bsayli.licensing.sdk.service.impl;
-import io.github.bsayli.licensing.client.common.contract.ApiClientResponse;
import io.github.bsayli.licensing.client.common.exception.ApiClientException;
import io.github.bsayli.licensing.client.generated.dto.IssueAccessRequest;
import io.github.bsayli.licensing.client.generated.dto.LicenseAccessResponse;
import io.github.bsayli.licensing.client.generated.dto.ValidateAccessRequest;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import io.github.bsayli.licensing.sdk.api.dto.LicenseAccessRequest;
import io.github.bsayli.licensing.sdk.api.dto.LicenseToken;
import io.github.bsayli.licensing.sdk.common.exception.LicensingSdkHttpTransportException;
@@ -77,7 +77,7 @@ private String validateThenMaybeRefreshOrReissue(
validateReq.setSignature(signatureGenerator.generateForValidate(cachedToken, validateReq));
- ApiClientResponse vResp =
+ ApiResponse vResp =
licenseServiceClient.validateAccess(cachedToken, validateReq);
try {
@@ -107,7 +107,7 @@ private String issueAndCacheToken(LicenseAccessRequest request, String clientId)
String signature = signatureGenerator.generateForIssue(issueReq);
issueReq.setSignature(signature);
- ApiClientResponse resp = licenseServiceClient.issueAccess(issueReq);
+ ApiResponse resp = licenseServiceClient.issueAccess(issueReq);
String token = responseHandler.extractTokenOrThrow(resp);
licenseTokenCacheService.put(clientId, token);
diff --git a/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/api/controller/LicenseControllerTest.java b/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/api/controller/LicenseControllerTest.java
index 71da194..e4d5305 100644
--- a/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/api/controller/LicenseControllerTest.java
+++ b/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/api/controller/LicenseControllerTest.java
@@ -3,9 +3,9 @@
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import io.github.bsayli.licensing.sdk.api.dto.LicenseAccessRequest;
import io.github.bsayli.licensing.sdk.api.dto.LicenseToken;
-import io.github.bsayli.licensing.sdk.common.api.ApiResponse;
import io.github.bsayli.licensing.sdk.common.i18n.LocalizedMessageResolver;
import io.github.bsayli.licensing.sdk.service.LicenseOrchestrationService;
import org.junit.jupiter.api.DisplayName;
@@ -47,11 +47,11 @@ void getLicenseToken_ok() {
assertEquals(HttpStatus.OK, resp.getStatusCode());
assertNotNull(resp.getBody());
- assertEquals(200, resp.getBody().status());
- assertEquals("License is valid", resp.getBody().message());
- assertNotNull(resp.getBody().data());
- assertEquals("jwt-abc.def.ghi", resp.getBody().data().licenseToken());
- assertTrue(resp.getBody().errors().isEmpty());
+ assertEquals(200, resp.getBody().getStatus());
+ assertEquals("License is valid", resp.getBody().getMessage());
+ assertNotNull(resp.getBody().getData());
+ assertEquals("jwt-abc.def.ghi", resp.getBody().getData().licenseToken());
+ assertTrue(resp.getBody().getErrors().isEmpty());
verify(licenseService).getLicenseToken(req);
verify(messageResolver).getMessage("license.validation.success");
diff --git a/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/generator/impl/SignatureGeneratorImplTest.java b/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/generator/impl/SignatureGeneratorImplTest.java
index 9c0c933..d413146 100644
--- a/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/generator/impl/SignatureGeneratorImplTest.java
+++ b/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/generator/impl/SignatureGeneratorImplTest.java
@@ -102,6 +102,28 @@ void generateForValidate_verifiable() throws Exception {
assertTrue(verifyWithPublic(kp, expectedJson, sigBytes));
}
+ @Test
+ @DisplayName("Generate Postman signature for validate access request")
+ void generatePostmanSignatureForValidate() {
+ String privateKey = "MC4CAQAwBQYDK2VwBCIEIMmR+qdAZ/vAWUKt0ZNlL+CCyqaRScTpAq52WtOmyg8E";
+
+ String licenseToken =
+ "eyJhbGciOiJFZERTQSJ9.eyJzdWIiOiJ2X1VfR0l6VnEzdlBxQmtTcjZXWTZWZU1TMjQ0QURwcnlXNlFpYjYyZGcwIiwibGljZW5zZVN0YXR1cyI6IkFDVElWRSIsImxpY2Vuc2VUaWVyIjoiUHJvZmVzc2lvbmFsIiwibWVzc2FnZSI6IllvdXIgbGljZW5zZSBpcyBhY3RpdmUiLCJpYXQiOjE3NzkxOTg3NzEsImV4cCI6MTc3OTIwNDI1Mn0.Hhx10GUBhuDLcrVk7f563BFir5bqcDN4Wt6vV8a37pEQiYm8eQU1K9fGpQKx_1mWCt4xfg28w_WeraVXs7ZaBA";
+
+ SignatureGenerator gen = new SignatureGeneratorImpl(privateKey);
+
+ ValidateAccessRequest request =
+ new ValidateAccessRequest()
+ .serviceId("crm")
+ .serviceVersion("1.5.0")
+ .instanceId("licensing-service~demo~00:11:22:33:44:55")
+ .checksum("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8a5");
+
+ String signature = gen.generateForValidate(licenseToken, request);
+
+ System.out.println("signature = " + signature);
+ }
+
@Test
@DisplayName("generateForValidate(null, ...) -> NullPointerException")
void generateForValidate_nullToken() throws Exception {
diff --git a/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/service/client/impl/LicenseServiceClientImplTest.java b/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/service/client/impl/LicenseServiceClientImplTest.java
index be75264..d3cc4c9 100644
--- a/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/service/client/impl/LicenseServiceClientImplTest.java
+++ b/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/service/client/impl/LicenseServiceClientImplTest.java
@@ -1,13 +1,14 @@
package io.github.bsayli.licensing.sdk.service.client.impl;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.Mockito.*;
import io.github.bsayli.licensing.client.adapter.LicensingServiceClientAdapter;
-import io.github.bsayli.licensing.client.common.contract.ApiClientResponse;
import io.github.bsayli.licensing.client.generated.dto.IssueAccessRequest;
import io.github.bsayli.licensing.client.generated.dto.LicenseAccessResponse;
import io.github.bsayli.licensing.client.generated.dto.ValidateAccessRequest;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
@@ -37,10 +38,10 @@ void issueAccess_delegates() {
.checksum("chk")
.licenseKey("LK_xxx");
@SuppressWarnings("unchecked")
- ApiClientResponse expected = mock(ApiClientResponse.class);
+ ApiResponse expected = mock(ApiResponse.class);
when(adapter.issueAccess(any(IssueAccessRequest.class))).thenReturn(expected);
- ApiClientResponse actual = client.issueAccess(req);
+ ApiResponse actual = client.issueAccess(req);
assertSame(expected, actual);
ArgumentCaptor captor = ArgumentCaptor.forClass(IssueAccessRequest.class);
@@ -49,11 +50,11 @@ void issueAccess_delegates() {
verify(adapter, times(1)).issueAccess(any(IssueAccessRequest.class));
verifyNoMoreInteractions(adapter);
- org.junit.jupiter.api.Assertions.assertEquals("crm", passed.getServiceId());
- org.junit.jupiter.api.Assertions.assertEquals("1.2.3", passed.getServiceVersion());
- org.junit.jupiter.api.Assertions.assertEquals("inst-1", passed.getInstanceId());
- org.junit.jupiter.api.Assertions.assertEquals("chk", passed.getChecksum());
- org.junit.jupiter.api.Assertions.assertEquals("LK_xxx", passed.getLicenseKey());
+ assertEquals("crm", passed.getServiceId());
+ assertEquals("1.2.3", passed.getServiceVersion());
+ assertEquals("inst-1", passed.getInstanceId());
+ assertEquals("chk", passed.getChecksum());
+ assertEquals("LK_xxx", passed.getLicenseKey());
}
@Test
@@ -67,11 +68,11 @@ void validateAccess_delegates() {
.instanceId("inst-1")
.checksum("chk");
@SuppressWarnings("unchecked")
- ApiClientResponse expected = mock(ApiClientResponse.class);
+ ApiResponse expected = mock(ApiResponse.class);
when(adapter.validateAccess(anyString(), any(ValidateAccessRequest.class)))
.thenReturn(expected);
- ApiClientResponse actual = client.validateAccess(token, req);
+ ApiResponse actual = client.validateAccess(token, req);
assertSame(expected, actual);
ArgumentCaptor tokenCap = ArgumentCaptor.forClass(String.class);
@@ -80,11 +81,11 @@ void validateAccess_delegates() {
verify(adapter).validateAccess(tokenCap.capture(), reqCap.capture());
verify(adapter, times(1)).validateAccess(anyString(), any(ValidateAccessRequest.class));
verifyNoMoreInteractions(adapter);
- org.junit.jupiter.api.Assertions.assertEquals("jwt-token", tokenCap.getValue());
+ assertEquals("jwt-token", tokenCap.getValue());
ValidateAccessRequest passed = reqCap.getValue();
- org.junit.jupiter.api.Assertions.assertEquals("crm", passed.getServiceId());
- org.junit.jupiter.api.Assertions.assertEquals("1.2.3", passed.getServiceVersion());
- org.junit.jupiter.api.Assertions.assertEquals("inst-1", passed.getInstanceId());
- org.junit.jupiter.api.Assertions.assertEquals("chk", passed.getChecksum());
+ assertEquals("crm", passed.getServiceId());
+ assertEquals("1.2.3", passed.getServiceVersion());
+ assertEquals("inst-1", passed.getInstanceId());
+ assertEquals("chk", passed.getChecksum());
}
}
diff --git a/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/service/handler/LicenseResponseHandlerTest.java b/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/service/handler/LicenseResponseHandlerTest.java
index 9ec6744..009f535 100644
--- a/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/service/handler/LicenseResponseHandlerTest.java
+++ b/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/service/handler/LicenseResponseHandlerTest.java
@@ -3,8 +3,8 @@
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
-import io.github.bsayli.licensing.client.common.contract.ApiClientResponse;
import io.github.bsayli.licensing.client.generated.dto.LicenseAccessResponse;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import io.github.bsayli.licensing.sdk.common.exception.LicensingSdkRemoteServiceException;
import io.github.bsayli.licensing.sdk.common.i18n.LocalizedMessageResolver;
import java.util.List;
@@ -29,7 +29,7 @@ class LicenseResponseHandlerTest {
@DisplayName("extractTokenOrThrow -> OK + token")
void extractTokenOrThrow_ok_withToken() {
@SuppressWarnings("unchecked")
- ApiClientResponse resp = mock(ApiClientResponse.class);
+ ApiResponse resp = mock(ApiResponse.class);
when(resp.getStatus()).thenReturn(HttpStatus.OK.value());
LicenseAccessResponse data = mock(LicenseAccessResponse.class);
when(resp.getData()).thenReturn(data);
@@ -47,7 +47,7 @@ void extractTokenOrThrow_ok_emptyToken_throws() {
when(messages.getMessage("sdk.remote.empty.token.detail")).thenReturn("detail");
@SuppressWarnings("unchecked")
- ApiClientResponse resp = mock(ApiClientResponse.class);
+ ApiResponse resp = mock(ApiResponse.class);
when(resp.getStatus()).thenReturn(HttpStatus.OK.value());
LicenseAccessResponse data = mock(LicenseAccessResponse.class);
when(resp.getData()).thenReturn(data);
@@ -67,7 +67,7 @@ void extractTokenOrThrow_ok_emptyToken_throws() {
@DisplayName("extractTokenIfPresentOrThrow -> OK + no data -> null")
void extractTokenIfPresentOrThrow_ok_noData_returnsNull() {
@SuppressWarnings("unchecked")
- ApiClientResponse resp = mock(ApiClientResponse.class);
+ ApiResponse resp = mock(ApiResponse.class);
when(resp.getStatus()).thenReturn(HttpStatus.OK.value());
when(resp.getData()).thenReturn(null);
@@ -83,7 +83,7 @@ void nonOk_throwsRemoteServiceException() {
when(messages.getMessage("sdk.remote.no.payload")).thenReturn("no-payload");
@SuppressWarnings("unchecked")
- ApiClientResponse resp = mock(ApiClientResponse.class);
+ ApiResponse resp = mock(ApiResponse.class);
when(resp.getStatus()).thenReturn(HttpStatus.BAD_REQUEST.value());
when(resp.getMessage()).thenReturn(null);
when(resp.getErrors()).thenReturn(null);
diff --git a/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/service/impl/LicenseOrchestrationServiceImplTest.java b/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/service/impl/LicenseOrchestrationServiceImplTest.java
index ba4f16d..6a0aa3b 100644
--- a/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/service/impl/LicenseOrchestrationServiceImplTest.java
+++ b/licensing-service-sdk/src/test/java/io/github/bsayli/licensing/sdk/service/impl/LicenseOrchestrationServiceImplTest.java
@@ -3,11 +3,11 @@
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
-import io.github.bsayli.licensing.client.common.contract.ApiClientResponse;
import io.github.bsayli.licensing.client.common.exception.ApiClientException;
import io.github.bsayli.licensing.client.generated.dto.IssueAccessRequest;
import io.github.bsayli.licensing.client.generated.dto.LicenseAccessResponse;
import io.github.bsayli.licensing.client.generated.dto.ValidateAccessRequest;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import io.github.bsayli.licensing.sdk.api.dto.LicenseAccessRequest;
import io.github.bsayli.licensing.sdk.api.dto.LicenseToken;
import io.github.bsayli.licensing.sdk.common.exception.LicensingSdkHttpTransportException;
@@ -61,7 +61,7 @@ void cacheMiss_issueAndCache() {
when(cache.get("cid")).thenReturn(null);
when(signatureGenerator.generateForIssue(any(IssueAccessRequest.class))).thenReturn("sig");
@SuppressWarnings("unchecked")
- ApiClientResponse resp = mock(ApiClientResponse.class);
+ ApiResponse resp = mock(ApiResponse.class);
when(licenseServiceClient.issueAccess(any(IssueAccessRequest.class))).thenReturn(resp);
when(responseHandler.extractTokenOrThrow(resp)).thenReturn("jwt-1");
@@ -86,7 +86,7 @@ void cacheHit_validate_active_noRefresh() {
when(signatureGenerator.generateForValidate(eq("jwt-old"), any(ValidateAccessRequest.class)))
.thenReturn("vsig");
@SuppressWarnings("unchecked")
- ApiClientResponse vResp = mock(ApiClientResponse.class);
+ ApiResponse vResp = mock(ApiResponse.class);
when(licenseServiceClient.validateAccess(eq("jwt-old"), any(ValidateAccessRequest.class)))
.thenReturn(vResp);
when(responseHandler.extractTokenIfPresentOrThrow(vResp)).thenReturn(null);
@@ -110,7 +110,7 @@ void cacheHit_validate_refreshed() {
when(signatureGenerator.generateForValidate(eq("jwt-old"), any(ValidateAccessRequest.class)))
.thenReturn("vsig");
@SuppressWarnings("unchecked")
- ApiClientResponse vResp = mock(ApiClientResponse.class);
+ ApiResponse vResp = mock(ApiResponse.class);
when(licenseServiceClient.validateAccess(eq("jwt-old"), any(ValidateAccessRequest.class)))
.thenReturn(vResp);
when(responseHandler.extractTokenIfPresentOrThrow(vResp)).thenReturn("jwt-new");
@@ -130,7 +130,7 @@ void cacheHit_validate_tooOld_fallbackIssue() {
eq("jwt-very-old"), any(ValidateAccessRequest.class)))
.thenReturn("vsig");
@SuppressWarnings("unchecked")
- ApiClientResponse vResp = mock(ApiClientResponse.class);
+ ApiResponse vResp = mock(ApiResponse.class);
when(licenseServiceClient.validateAccess(eq("jwt-very-old"), any(ValidateAccessRequest.class)))
.thenReturn(vResp);
LicensingSdkRemoteServiceException tooOld =
@@ -139,7 +139,7 @@ void cacheHit_validate_tooOld_fallbackIssue() {
when(responseHandler.extractTokenIfPresentOrThrow(vResp)).thenThrow(tooOld);
@SuppressWarnings("unchecked")
- ApiClientResponse iResp = mock(ApiClientResponse.class);
+ ApiResponse iResp = mock(ApiResponse.class);
when(signatureGenerator.generateForIssue(any(IssueAccessRequest.class))).thenReturn("sig");
when(licenseServiceClient.issueAccess(any(IssueAccessRequest.class))).thenReturn(iResp);
when(responseHandler.extractTokenOrThrow(iResp)).thenReturn("jwt-new");
diff --git a/licensing-service/Dockerfile b/licensing-service/Dockerfile
index fbff5f4..768479e 100644
--- a/licensing-service/Dockerfile
+++ b/licensing-service/Dockerfile
@@ -1,9 +1,18 @@
FROM maven:3.9.11-eclipse-temurin-21-noble AS builder
-WORKDIR /app
-COPY pom.xml .
+WORKDIR /build
+
+# Install shared contract module into the local Maven repository
+COPY licensing-api-contract/ licensing-api-contract/
+RUN --mount=type=cache,target=/root/.m2 \
+ mvn -q -DskipTests -f licensing-api-contract/pom.xml install
+
+# Build licensing-service
+WORKDIR /build/licensing-service
+COPY licensing-service/pom.xml .
RUN --mount=type=cache,target=/root/.m2 \
mvn -q -DskipTests dependency:go-offline
-COPY src ./src
+
+COPY licensing-service/src ./src
RUN --mount=type=cache,target=/root/.m2 \
mvn -q -T 2C -DskipTests --no-transfer-progress clean package && \
java -Djarmode=layertools -jar target/*.jar extract
@@ -23,14 +32,14 @@ RUN apt-get update && \
LABEL org.opencontainers.image.title="licensing-service" \
org.opencontainers.image.description="Licensing Service (Spring Boot, EdDSA, Caffeine, Keycloak)" \
- org.opencontainers.image.version="1.0.1" \
+ org.opencontainers.image.version="1.0.5" \
org.opencontainers.image.source="https://github.com/bsayli/licensing" \
org.opencontainers.image.licenses="MIT"
-COPY --from=builder --chown=appuser:appuser /app/dependencies/ ./
-COPY --from=builder --chown=appuser:appuser /app/snapshot-dependencies/ ./
-COPY --from=builder --chown=appuser:appuser /app/spring-boot-loader/ ./
-COPY --from=builder --chown=appuser:appuser /app/application/ ./
+COPY --from=builder --chown=appuser:appuser /build/licensing-service/dependencies/ ./
+COPY --from=builder --chown=appuser:appuser /build/licensing-service/snapshot-dependencies/ ./
+COPY --from=builder --chown=appuser:appuser /build/licensing-service/spring-boot-loader/ ./
+COPY --from=builder --chown=appuser:appuser /build/licensing-service/application/ ./
USER appuser
diff --git a/licensing-service/README.md b/licensing-service/README.md
index b235c45..2a09eef 100644
--- a/licensing-service/README.md
+++ b/licensing-service/README.md
@@ -6,6 +6,7 @@
[](https://www.keycloak.org/)
[](https://redis.io/)
[](https://www.openapis.org/)
+[](https://github.com/blueprint-platform/openapi-generics)
[](https://www.docker.com/)
[](../LICENSE)
@@ -315,7 +316,7 @@ mvn clean package
```bash
mvn spring-boot:run
# or
-java -jar target/licensing-service-1.0.1.jar
+java -jar target/licensing-service-1.0.5.jar
```
### With Docker Compose (from repo root)
diff --git a/licensing-service/pom.xml b/licensing-service/pom.xml
index bc6ad38..34f3d50 100644
--- a/licensing-service/pom.xml
+++ b/licensing-service/pom.xml
@@ -6,12 +6,12 @@
org.springframework.boot
spring-boot-starter-parent
- 3.5.5
+ 3.5.14
io.github.bsayli
licensing-service
- 1.0.4
+ 1.0.5
licensing-service
Licensing Service App
@@ -19,9 +19,11 @@
UTF-8
UTF-8
21
+ 1.0.2
+ 2.8.17
+ 1.0.5
0.12.7
- 1.81
- 2.8.13
+ 1.84
3.18.0
2.12.1
0.8.13
@@ -30,6 +32,19 @@
6.0.0
+
+
+ io.github.blueprint-platform
+ openapi-generics-server-starter
+ ${openapi-generics-server-starter.version}
+
+
+
+ io.github.bsayli
+ licensing-api-contract
+ ${licensing-api-contract.version}
+
+
org.springframework.boot
spring-boot-starter-security
diff --git a/licensing-service/src/main/java/io/github/bsayli/licensing/api/controller/LicenseController.java b/licensing-service/src/main/java/io/github/bsayli/licensing/api/controller/LicenseController.java
index 18c43d3..027e94a 100644
--- a/licensing-service/src/main/java/io/github/bsayli/licensing/api/controller/LicenseController.java
+++ b/licensing-service/src/main/java/io/github/bsayli/licensing/api/controller/LicenseController.java
@@ -4,8 +4,8 @@
import io.github.bsayli.licensing.api.dto.LicenseAccessResponse;
import io.github.bsayli.licensing.api.dto.ValidateAccessRequest;
import io.github.bsayli.licensing.api.validation.annotations.ValidLicenseToken;
-import io.github.bsayli.licensing.common.api.ApiResponse;
import io.github.bsayli.licensing.common.i18n.LocalizedMessageResolver;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import io.github.bsayli.licensing.service.LicenseOrchestrationService;
import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
@@ -32,7 +32,8 @@ public ResponseEntity> createAccess(
@Valid @RequestBody IssueAccessRequest request) {
var result = service.issueAccess(request);
String msg = messageResolver.getMessage("license.validation.success");
- return ResponseEntity.status(HttpStatus.OK).body(ApiResponse.of(HttpStatus.OK, msg, result));
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(ApiResponse.of(HttpStatus.OK.value(), msg, result));
}
@PostMapping("/access/validate")
@@ -42,6 +43,7 @@ public ResponseEntity> validateAccess(
var result = service.validateAccess(request, licenseToken);
String msg = messageResolver.getMessage("license.validation.success");
- return ResponseEntity.status(HttpStatus.OK).body(ApiResponse.of(HttpStatus.OK, msg, result));
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(ApiResponse.of(HttpStatus.OK.value(), msg, result));
}
}
diff --git a/licensing-service/src/main/java/io/github/bsayli/licensing/api/exception/LicenseControllerAdvice.java b/licensing-service/src/main/java/io/github/bsayli/licensing/api/exception/LicenseControllerAdvice.java
index ce42a11..4f72fd0 100644
--- a/licensing-service/src/main/java/io/github/bsayli/licensing/api/exception/LicenseControllerAdvice.java
+++ b/licensing-service/src/main/java/io/github/bsayli/licensing/api/exception/LicenseControllerAdvice.java
@@ -1,10 +1,10 @@
package io.github.bsayli.licensing.api.exception;
-import io.github.bsayli.licensing.common.api.ApiError;
-import io.github.bsayli.licensing.common.api.ApiResponse;
import io.github.bsayli.licensing.common.exception.ServiceErrorCode;
import io.github.bsayli.licensing.common.exception.ServiceException;
import io.github.bsayli.licensing.common.i18n.LocalizedMessageResolver;
+import io.github.bsayli.licensing.contract.api.ApiError;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import io.github.bsayli.licensing.repository.exception.RepositoryException;
import io.github.bsayli.licensing.service.user.exception.UserOperationException;
import jakarta.validation.ConstraintViolation;
@@ -51,7 +51,7 @@ public ResponseEntity> handleMethodArgNotValid(
String topMsg = messageResolver.getMessage("request.validation.failed");
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
- .body(ApiResponse.error(HttpStatus.BAD_REQUEST, topMsg, errors));
+ .body(ApiResponse.error(HttpStatus.BAD_REQUEST.value(), topMsg, errors));
}
@ExceptionHandler(ConstraintViolationException.class)
@@ -74,7 +74,7 @@ public ResponseEntity> handleConstraintViolation(
String topMsg = messageResolver.getMessage("request.validation.failed");
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
- .body(ApiResponse.error(HttpStatus.BAD_REQUEST, topMsg, errors));
+ .body(ApiResponse.error(HttpStatus.BAD_REQUEST.value(), topMsg, errors));
}
@ExceptionHandler(MissingServletRequestParameterException.class)
@@ -88,7 +88,7 @@ public ResponseEntity> handleMissingParameter(
String msg = messageResolver.getMessage("request.param.missing", ex.getParameterName());
List errors = List.of(new ApiError(ServiceErrorCode.MISSING_PARAMETER.name(), msg));
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
- .body(ApiResponse.error(HttpStatus.BAD_REQUEST, msg, errors));
+ .body(ApiResponse.error(HttpStatus.BAD_REQUEST.value(), msg, errors));
}
@ExceptionHandler(MissingRequestHeaderException.class)
@@ -98,18 +98,18 @@ public ResponseEntity> handleMissingHeader(MissingRequestHeade
String msg = messageResolver.getMessage("request.header.missing", ex.getHeaderName());
List errors = List.of(new ApiError(ServiceErrorCode.MISSING_PARAMETER.name(), msg));
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
- .body(ApiResponse.error(HttpStatus.BAD_REQUEST, msg, errors));
+ .body(ApiResponse.error(HttpStatus.BAD_REQUEST.value(), msg, errors));
}
@ExceptionHandler(ServiceException.class)
public ResponseEntity> handleServiceException(ServiceException ex) {
ServiceErrorCode code = ex.getCode();
- HttpStatus http = code.httpStatus();
+ HttpStatus httpStatus = code.httpStatus();
- var logger = http.is5xxServerError() ? log.atError() : log.atWarn();
+ var logger = httpStatus.is5xxServerError() ? log.atError() : log.atWarn();
logger
.setCause(ex)
- .addArgument(http.value())
+ .addArgument(httpStatus.value())
.addArgument(code)
.addArgument(ex.getMessageKey())
.log("Service exception. statusCode={}, code={}, messageKey={} ");
@@ -118,23 +118,23 @@ public ResponseEntity> handleServiceException(ServiceException
String top = messageResolver.getMessage("license.validation.failed");
ApiResponse body =
- ApiResponse.error(http, top, List.of(new ApiError(code.name(), detail)));
- return ResponseEntity.status(http).body(body);
+ ApiResponse.error(httpStatus.value(), top, List.of(new ApiError(code.name(), detail)));
+ return ResponseEntity.status(httpStatus).body(body);
}
@ExceptionHandler(RepositoryException.class)
public ResponseEntity> handleRepositoryException(RepositoryException ex) {
- HttpStatus http =
+ HttpStatus httpStatus =
switch (ex.getErrorCode()) {
case USER_NOT_FOUND -> HttpStatus.NOT_FOUND;
case USER_ATTRIBUTE_MISSING, USER_ATTRIBUTE_INVALID_FORMAT ->
HttpStatus.INTERNAL_SERVER_ERROR;
};
- var logger = http.is5xxServerError() ? log.atError() : log.atWarn();
+ var logger = httpStatus.is5xxServerError() ? log.atError() : log.atWarn();
logger
.setCause(ex)
- .addArgument(http.value())
+ .addArgument(httpStatus.value())
.addArgument(ex.getErrorCode())
.addArgument(ex.getMessageKey())
.log("Repository exception handled. statusCode={}, errorCode={}, messageKey={} ");
@@ -143,22 +143,23 @@ public ResponseEntity> handleRepositoryException(RepositoryExc
String top = messageResolver.getMessage("repository.operation.failed");
ApiResponse body =
- ApiResponse.error(http, top, List.of(new ApiError(ex.getErrorCode().name(), detail)));
- return ResponseEntity.status(http).body(body);
+ ApiResponse.error(
+ httpStatus.value(), top, List.of(new ApiError(ex.getErrorCode().name(), detail)));
+ return ResponseEntity.status(httpStatus).body(body);
}
@ExceptionHandler(UserOperationException.class)
public ResponseEntity> handleUserOperationException(UserOperationException ex) {
- HttpStatus http =
+ HttpStatus httpStatus =
switch (ex.getErrorCode()) {
case ALREADY_PROCESSING -> HttpStatus.CONFLICT;
case MAX_RETRY_ATTEMPTS_EXCEEDED -> HttpStatus.TOO_MANY_REQUESTS;
};
- var logger = http.is5xxServerError() ? log.atError() : log.atWarn();
+ var logger = httpStatus.is5xxServerError() ? log.atError() : log.atWarn();
logger
.setCause(ex)
- .addArgument(http.value())
+ .addArgument(httpStatus.value())
.addArgument(ex.getErrorCode())
.addArgument(ex.getMessageKey())
.log("User operation exception handled. statusCode={}, errorCode={}, messageKey={} ");
@@ -167,8 +168,9 @@ public ResponseEntity> handleUserOperationException(UserOperat
String top = messageResolver.getMessage("user.operation.failed");
ApiResponse body =
- ApiResponse.error(http, top, List.of(new ApiError(ex.getErrorCode().name(), detail)));
- return ResponseEntity.status(http).body(body);
+ ApiResponse.error(
+ httpStatus.value(), top, List.of(new ApiError(ex.getErrorCode().name(), detail)));
+ return ResponseEntity.status(httpStatus).body(body);
}
@ExceptionHandler(Exception.class)
@@ -179,7 +181,7 @@ public ResponseEntity> handleGenericException(Exception ex) {
List errors =
List.of(new ApiError(ServiceErrorCode.INTERNAL_SERVER_ERROR.name(), msg));
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
- .body(ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR, msg, errors));
+ .body(ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), msg, errors));
}
private String resolveStrict(String keyOrText, Object... args) {
diff --git a/licensing-service/src/main/java/io/github/bsayli/licensing/api/openapi/SwaggerLicensingResponseCustomizer.java b/licensing-service/src/main/java/io/github/bsayli/licensing/api/openapi/SwaggerLicensingResponseCustomizer.java
deleted file mode 100644
index 68cb349..0000000
--- a/licensing-service/src/main/java/io/github/bsayli/licensing/api/openapi/SwaggerLicensingResponseCustomizer.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package io.github.bsayli.licensing.api.openapi;
-
-import static io.github.bsayli.licensing.common.openapi.OpenApiSchemas.SCHEMA_API_RESPONSE;
-
-import io.github.bsayli.licensing.api.dto.LicenseAccessResponse;
-import io.github.bsayli.licensing.common.openapi.ApiResponseSchemaFactory;
-import org.springdoc.core.customizers.OpenApiCustomizer;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class SwaggerLicensingResponseCustomizer {
-
- private static final String REF_LICENSE_VALIDATION_RESPONSE =
- LicenseAccessResponse.class.getSimpleName();
-
- private static String apiResponseWrapperNameFor(String ref) {
- return SCHEMA_API_RESPONSE + ref;
- }
-
- @Bean
- public OpenApiCustomizer licensingWrappers() {
- return openApi ->
- openApi
- .getComponents()
- .addSchemas(
- apiResponseWrapperNameFor(REF_LICENSE_VALIDATION_RESPONSE),
- ApiResponseSchemaFactory.createComposedWrapper(REF_LICENSE_VALIDATION_RESPONSE));
- }
-}
diff --git a/licensing-service/src/main/java/io/github/bsayli/licensing/common/api/ApiResponse.java b/licensing-service/src/main/java/io/github/bsayli/licensing/common/api/ApiResponse.java
deleted file mode 100644
index 46f04e7..0000000
--- a/licensing-service/src/main/java/io/github/bsayli/licensing/common/api/ApiResponse.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package io.github.bsayli.licensing.common.api;
-
-import java.util.Collections;
-import java.util.List;
-import org.springframework.http.HttpStatus;
-
-public record ApiResponse(int status, String message, T data, List errors) {
- public static ApiResponse ok(T data) {
- return new ApiResponse<>(HttpStatus.OK.value(), "OK", data, Collections.emptyList());
- }
-
- public static ApiResponse of(HttpStatus status, String message, T data) {
- return new ApiResponse<>(status.value(), message, data, Collections.emptyList());
- }
-
- public static ApiResponse error(HttpStatus status, String message) {
- return new ApiResponse<>(status.value(), message, null, Collections.emptyList());
- }
-
- public static ApiResponse error(HttpStatus status, String message, List errors) {
- return new ApiResponse<>(
- status.value(), message, null, errors != null ? errors : Collections.emptyList());
- }
-}
diff --git a/licensing-service/src/main/java/io/github/bsayli/licensing/common/openapi/ApiResponseSchemaFactory.java b/licensing-service/src/main/java/io/github/bsayli/licensing/common/openapi/ApiResponseSchemaFactory.java
deleted file mode 100644
index 7bf4d0e..0000000
--- a/licensing-service/src/main/java/io/github/bsayli/licensing/common/openapi/ApiResponseSchemaFactory.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.github.bsayli.licensing.common.openapi;
-
-import static io.github.bsayli.licensing.common.openapi.OpenApiSchemas.*;
-
-import io.swagger.v3.oas.models.media.ComposedSchema;
-import io.swagger.v3.oas.models.media.ObjectSchema;
-import io.swagger.v3.oas.models.media.Schema;
-import java.util.List;
-
-public final class ApiResponseSchemaFactory {
- private ApiResponseSchemaFactory() {}
-
- public static Schema> createComposedWrapper(String dataRefName) {
- var schema = new ComposedSchema();
- schema.setAllOf(
- List.of(
- new Schema<>().$ref("#/components/schemas/" + SCHEMA_API_RESPONSE),
- new ObjectSchema()
- .addProperty(
- PROP_DATA, new Schema<>().$ref("#/components/schemas/" + dataRefName))));
- schema.addExtension(EXT_API_WRAPPER, true);
- schema.addExtension(EXT_API_WRAPPER_DATATYPE, dataRefName);
- return schema;
- }
-}
diff --git a/licensing-service/src/main/java/io/github/bsayli/licensing/common/openapi/OpenApiSchemas.java b/licensing-service/src/main/java/io/github/bsayli/licensing/common/openapi/OpenApiSchemas.java
deleted file mode 100644
index 4a071e6..0000000
--- a/licensing-service/src/main/java/io/github/bsayli/licensing/common/openapi/OpenApiSchemas.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.github.bsayli.licensing.common.openapi;
-
-public final class OpenApiSchemas {
- // Common property keys
- public static final String PROP_STATUS = "status";
- public static final String PROP_MESSAGE = "message";
- public static final String PROP_ERRORS = "errors";
- public static final String PROP_ERROR_CODE = "errorCode";
- public static final String PROP_DATA = "data";
- // Base envelopes
- public static final String SCHEMA_API_RESPONSE = "ApiResponse";
- public static final String SCHEMA_API_RESPONSE_VOID = "ApiResponseVoid";
- // Vendor extensions
- public static final String EXT_API_WRAPPER = "x-api-wrapper";
- public static final String EXT_API_WRAPPER_DATATYPE = "x-api-wrapper-datatype";
-
- private OpenApiSchemas() {}
-}
diff --git a/licensing-service/src/main/java/io/github/bsayli/licensing/common/openapi/SwaggerResponseCustomizer.java b/licensing-service/src/main/java/io/github/bsayli/licensing/common/openapi/SwaggerResponseCustomizer.java
deleted file mode 100644
index 87f2961..0000000
--- a/licensing-service/src/main/java/io/github/bsayli/licensing/common/openapi/SwaggerResponseCustomizer.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package io.github.bsayli.licensing.common.openapi;
-
-import static io.github.bsayli.licensing.common.openapi.OpenApiSchemas.*;
-
-import io.swagger.v3.oas.models.media.ArraySchema;
-import io.swagger.v3.oas.models.media.IntegerSchema;
-import io.swagger.v3.oas.models.media.ObjectSchema;
-import io.swagger.v3.oas.models.media.StringSchema;
-import org.springdoc.core.customizers.OpenApiCustomizer;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class SwaggerResponseCustomizer {
-
- @Bean
- public OpenApiCustomizer responseEnvelopeSchemas() {
- return openApi -> {
- if (!openApi.getComponents().getSchemas().containsKey(SCHEMA_API_RESPONSE)) {
- openApi
- .getComponents()
- .addSchemas(
- SCHEMA_API_RESPONSE,
- new ObjectSchema()
- .addProperty(PROP_STATUS, new IntegerSchema().format("int32"))
- .addProperty(PROP_MESSAGE, new StringSchema())
- .addProperty(
- PROP_ERRORS,
- new ArraySchema()
- .items(
- new ObjectSchema()
- .addProperty(PROP_ERROR_CODE, new StringSchema())
- .addProperty(PROP_MESSAGE, new StringSchema()))));
- }
-
- if (!openApi.getComponents().getSchemas().containsKey(SCHEMA_API_RESPONSE_VOID)) {
- openApi
- .getComponents()
- .addSchemas(
- SCHEMA_API_RESPONSE_VOID,
- new ObjectSchema()
- .addProperty(PROP_STATUS, new IntegerSchema().format("int32"))
- .addProperty(PROP_MESSAGE, new StringSchema())
- .addProperty(PROP_DATA, new ObjectSchema())
- .addProperty(
- PROP_ERRORS,
- new ArraySchema()
- .items(
- new ObjectSchema()
- .addProperty(PROP_ERROR_CODE, new StringSchema())
- .addProperty(PROP_MESSAGE, new StringSchema()))));
- }
- };
- }
-}
diff --git a/licensing-service/src/main/resources/application.yml b/licensing-service/src/main/resources/application.yml
index fa0089f..36b9ad5 100644
--- a/licensing-service/src/main/resources/application.yml
+++ b/licensing-service/src/main/resources/application.yml
@@ -59,6 +59,8 @@ logging:
org.springframework.web: INFO
org.springframework.security: INFO
io.github.bsayli.licensing: DEBUG
+ io.github.blueprintplatform: DEBUG
+
licensing:
api:
@@ -72,6 +74,10 @@ app:
version: @project.version@
base-url: "http://localhost:${server.port}${server.servlet.context-path:}"
+openapi-generics:
+ envelope:
+ type: io.github.bsayli.licensing.contract.api.ApiResponse
+
license:
jwt:
private:
diff --git a/licensing-service/src/test/java/io/github/bsayli/licensing/api/controller/LicenseControllerTest.java b/licensing-service/src/test/java/io/github/bsayli/licensing/api/controller/LicenseControllerTest.java
index 18f7f72..edddf0e 100644
--- a/licensing-service/src/test/java/io/github/bsayli/licensing/api/controller/LicenseControllerTest.java
+++ b/licensing-service/src/test/java/io/github/bsayli/licensing/api/controller/LicenseControllerTest.java
@@ -6,8 +6,8 @@
import io.github.bsayli.licensing.api.dto.IssueAccessRequest;
import io.github.bsayli.licensing.api.dto.LicenseAccessResponse;
import io.github.bsayli.licensing.api.dto.ValidateAccessRequest;
-import io.github.bsayli.licensing.common.api.ApiResponse;
import io.github.bsayli.licensing.common.i18n.LocalizedMessageResolver;
+import io.github.bsayli.licensing.contract.api.ApiResponse;
import io.github.bsayli.licensing.service.LicenseOrchestrationService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
@@ -43,11 +43,11 @@ void createAccess() {
assertEquals(HttpStatus.OK, resp.getStatusCode());
assertNotNull(resp.getBody());
- assertEquals(200, resp.getBody().status());
- assertEquals("License is valid", resp.getBody().message());
- assertNotNull(resp.getBody().data());
- assertEquals("jwt-token", resp.getBody().data().licenseToken());
- assertTrue(resp.getBody().errors().isEmpty());
+ assertEquals(200, resp.getBody().getStatus());
+ assertEquals("License is valid", resp.getBody().getMessage());
+ assertNotNull(resp.getBody().getData());
+ assertEquals("jwt-token", resp.getBody().getData().licenseToken());
+ assertTrue(resp.getBody().getErrors().isEmpty());
verify(service).issueAccess(req);
verify(messageResolver).getMessage("license.validation.success");
@@ -68,11 +68,11 @@ void validateToken_shouldReturnOkWithRefreshedAccess() {
assertEquals(HttpStatus.OK, resp.getStatusCode());
assertNotNull(resp.getBody());
- assertEquals(200, resp.getBody().status());
- assertEquals("License is valid", resp.getBody().message());
- assertNotNull(resp.getBody().data());
- assertEquals("new-jwt", resp.getBody().data().licenseToken());
- assertTrue(resp.getBody().errors().isEmpty());
+ assertEquals(200, resp.getBody().getStatus());
+ assertEquals("License is valid", resp.getBody().getMessage());
+ assertNotNull(resp.getBody().getData());
+ assertEquals("new-jwt", resp.getBody().getData().licenseToken());
+ assertTrue(resp.getBody().getErrors().isEmpty());
verify(service).validateAccess(req, token);
verify(messageResolver).getMessage("license.validation.success");
@@ -93,12 +93,12 @@ void validateAccess_shouldReturnOkActive() {
assertEquals(HttpStatus.OK, resp.getStatusCode());
assertNotNull(resp.getBody());
- assertEquals("License is valid", resp.getBody().message());
- assertNotNull(resp.getBody().data());
- assertNull(resp.getBody().data().licenseToken());
+ assertEquals("License is valid", resp.getBody().getMessage());
+ assertNotNull(resp.getBody().getData());
+ assertNull(resp.getBody().getData().licenseToken());
verify(service).validateAccess(req, token);
verify(messageResolver).getMessage("license.validation.success");
verifyNoMoreInteractions(service, messageResolver);
}
-}
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index e80b277..8ef821a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
io.github.bsayli
licensing-aggregator
- 1.0.4
+ 1.0.5
pom
licensing (aggregator)
@@ -16,7 +16,7 @@
HEAD
- 0.8.13
+ 0.8.14
@@ -28,6 +28,7 @@
+ licensing-api-contract
license-generator
licensing-service
licensing-service-client