From c4adf6985da48be33d3b136637b3915109ca9183 Mon Sep 17 00:00:00 2001 From: Tarun Telang Date: Fri, 24 Apr 2026 20:25:33 +0530 Subject: [PATCH 01/10] Update pom.xml --- code/chapter04/catalog/pom.xml | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/code/chapter04/catalog/pom.xml b/code/chapter04/catalog/pom.xml index 1951188d..3e215a77 100644 --- a/code/chapter04/catalog/pom.xml +++ b/code/chapter04/catalog/pom.xml @@ -12,8 +12,8 @@ - 17 - 17 + 21 + 21 UTF-8 UTF-8 @@ -31,7 +31,7 @@ org.projectlombok lombok - 1.18.26 + 1.18.36 provided @@ -47,7 +47,7 @@ org.eclipse.microprofile microprofile - 6.1 + 7.1 pom provided @@ -119,6 +119,16 @@ ${project.artifactId} + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 21 + + + io.openliberty.tools @@ -167,4 +177,4 @@ - \ No newline at end of file + From 26917dc1bfb00f9751387c2942ac4eabf500b9a3 Mon Sep 17 00:00:00 2001 From: Tarun Telang Date: Fri, 24 Apr 2026 20:31:43 +0530 Subject: [PATCH 02/10] Create SecuredProductApplication.java Application class demonstrating security scheme definitions in MicroProfile OpenAPI 4.1. * This shows how to document multiple security mechanisms for your API. --- .../product/SecuredProductApplication.java | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/SecuredProductApplication.java diff --git a/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/SecuredProductApplication.java b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/SecuredProductApplication.java new file mode 100644 index 00000000..97f326d4 --- /dev/null +++ b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/SecuredProductApplication.java @@ -0,0 +1,87 @@ +package io.microprofile.tutorial.store.product; + +import org.eclipse.microprofile.openapi.annotations.OpenAPIDefinition; +import org.eclipse.microprofile.openapi.annotations.security.SecurityScheme; +import org.eclipse.microprofile.openapi.annotations.security.SecuritySchemes; +import org.eclipse.microprofile.openapi.annotations.enums.SecuritySchemeType; +import org.eclipse.microprofile.openapi.annotations.enums.SecuritySchemeIn; +import org.eclipse.microprofile.openapi.annotations.security.OAuthFlows; +import org.eclipse.microprofile.openapi.annotations.security.OAuthFlow; +import org.eclipse.microprofile.openapi.annotations.security.OAuthScope; +import org.eclipse.microprofile.openapi.annotations.info.Info; +import org.eclipse.microprofile.openapi.annotations.info.Contact; +import org.eclipse.microprofile.openapi.annotations.info.License; +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; + +/** + * Application class demonstrating security scheme definitions in MicroProfile OpenAPI 4.1. + * This shows how to document multiple security mechanisms for your API. + */ +@ApplicationPath("/api") +@OpenAPIDefinition( + info = @Info( + title = "Secured Product API", + version = "1.0.0", + description = "Product API with multiple security schemes demonstrating MicroProfile OpenAPI 4.1 capabilities", + contact = @Contact( + name = "API Support", + email = "support@example.com", + url = "https://example.com/support" + ), + license = @License( + name = "Apache 2.0", + url = "https://www.apache.org/licenses/LICENSE-2.0.html" + ) + ) +) +@SecuritySchemes({ + @SecurityScheme( + securitySchemeName = "apiKey", + type = SecuritySchemeType.APIKEY, + description = "API Key authentication - provide your API key in the X-API-Key header", + in = SecuritySchemeIn.HEADER, + apiKeyName = "X-API-Key" + ), + @SecurityScheme( + securitySchemeName = "bearerAuth", + type = SecuritySchemeType.HTTP, + description = "JWT Bearer token authentication - obtain token from /auth/login endpoint", + scheme = "bearer", + bearerFormat = "JWT" + ), + @SecurityScheme( + securitySchemeName = "oauth2", + type = SecuritySchemeType.OAUTH2, + description = "OAuth2 authentication with authorization code flow", + flows = @OAuthFlows( + authorizationCode = @OAuthFlow( + authorizationUrl = "https://example.com/oauth/authorize", + tokenUrl = "https://example.com/oauth/token", + refreshUrl = "https://example.com/oauth/refresh", + scopes = { + @OAuthScope( + name = "read:products", + description = "Read product information" + ), + @OAuthScope( + name = "write:products", + description = "Create and modify product information" + ), + @OAuthScope( + name = "delete:products", + description = "Delete product information" + ) + } + ) + ) + ), + @SecurityScheme( + securitySchemeName = "basicAuth", + type = SecuritySchemeType.HTTP, + description = "Basic HTTP authentication", + scheme = "basic" + ) +}) +public class SecuredProductApplication extends Application { +} From d58af57784aeb6af9e2d28154d8c22cb3d963f2e Mon Sep 17 00:00:00 2001 From: Tarun Telang Date: Fri, 24 Apr 2026 20:33:02 +0530 Subject: [PATCH 03/10] Create ExtensionFilter.java OpenAPI filter demonstrating the use of getExtension() and hasExtension() methods. * This filter is called for each element in the OpenAPI model tree. --- .../store/product/ExtensionFilter.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/ExtensionFilter.java diff --git a/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/ExtensionFilter.java b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/ExtensionFilter.java new file mode 100644 index 00000000..5b18761b --- /dev/null +++ b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/ExtensionFilter.java @@ -0,0 +1,34 @@ +package io.microprofile.tutorial.store.product; + +import org.eclipse.microprofile.openapi.OASFilter; +import org.eclipse.microprofile.openapi.models.Operation; + +/** + * OpenAPI filter demonstrating the use of getExtension() and hasExtension() methods. + * This filter is called for each element in the OpenAPI model tree. + */ +public class ExtensionFilter implements OASFilter { + + @Override + public Operation filterOperation(Operation operation) { + // Check if a custom extension exists using the new hasExtension method + if (operation.hasExtension("x-custom-timeout")) { + // Retrieve the extension value using the new getExtension method + Object timeout = operation.getExtension("x-custom-timeout"); + System.out.println("Custom timeout found: " + timeout); + + // Modify based on the extension + if (timeout != null && timeout instanceof Integer && (Integer) timeout > 30) { + operation.addExtension("x-requires-approval", true); + } + } + + // Check for rate limiting extension + if (operation.hasExtension("x-rate-limit")) { + Object rateLimit = operation.getExtension("x-rate-limit"); + System.out.println("Rate limit: " + rateLimit); + } + + return operation; + } +} From 6486ded802f29399d37426a6deac0ef9b00df3a3 Mon Sep 17 00:00:00 2001 From: Tarun Telang Date: Fri, 24 Apr 2026 20:34:08 +0530 Subject: [PATCH 04/10] Create CustomModelReader.java Custom OpenAPI model reader demonstrating jsonSchemaDialect support. * This reader is called once during application startup to build/enhance the OpenAPI model. --- .../store/product/CustomModelReader.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/CustomModelReader.java diff --git a/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/CustomModelReader.java b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/CustomModelReader.java new file mode 100644 index 00000000..12c05a9a --- /dev/null +++ b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/CustomModelReader.java @@ -0,0 +1,24 @@ +package io.microprofile.tutorial.store.product; + +import org.eclipse.microprofile.openapi.OASFactory; +import org.eclipse.microprofile.openapi.OASModelReader; +import org.eclipse.microprofile.openapi.models.OpenAPI; + +/** + * Custom OpenAPI model reader demonstrating jsonSchemaDialect support. + * This reader is called once during application startup to build/enhance the OpenAPI model. + */ +public class CustomModelReader implements OASModelReader { + + @Override + public OpenAPI buildModel() { + // Create an OpenAPI object with jsonSchemaDialect + return OASFactory.createOpenAPI() + .openapi("3.1.0") + .jsonSchemaDialect("https://spec.openapis.org/oas/3.1/dialect/base") + .info(OASFactory.createInfo() + .title("Product API") + .version("1.0.0") + .description("API for managing products with MicroProfile OpenAPI 4.1")); + } +} From fd36ec5fd7f60f1a545fdb42b742861e8f671429 Mon Sep 17 00:00:00 2001 From: Tarun Telang Date: Fri, 24 Apr 2026 20:37:04 +0530 Subject: [PATCH 05/10] Update ProductResource.java Adding `processProductAsync()` method demonstrating how to document asynchronous operations with callback URLs. --- .../product/resource/ProductResource.java | 117 +++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/resource/ProductResource.java b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/resource/ProductResource.java index b10f589b..e877f0f3 100644 --- a/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/resource/ProductResource.java +++ b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/resource/ProductResource.java @@ -5,8 +5,12 @@ import java.util.logging.Logger; import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.callbacks.Callback; +import org.eclipse.microprofile.openapi.annotations.callbacks.CallbackOperation; +import org.eclipse.microprofile.openapi.annotations.extensions.Extension; import org.eclipse.microprofile.openapi.annotations.media.Content; import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; import org.eclipse.microprofile.openapi.annotations.tags.Tag; @@ -159,4 +163,115 @@ public Response searchProducts( List results = productService.searchProducts(name, description, minPrice, maxPrice); return Response.ok(results).build(); } -} \ No newline at end of file + + // ===== New MicroProfile OpenAPI 4.1 Features Examples ===== + + @GET + @Path("/record/{id}") + @Produces(MediaType.APPLICATION_JSON) + @Operation( + summary = "Get product as Java Record", + description = "Returns product data using Java Record (MicroProfile OpenAPI 4.1 feature)", + extensions = { + @Extension(name = "x-custom-timeout", value = "60"), + @Extension(name = "x-rate-limit", value = "100") + } + ) + @APIResponse( + responseCode = "200", + description = "Product found", + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = io.microprofile.tutorial.store.product.entity.ProductRecord.class) + ) + ) + @APIResponse(responseCode = "404", description = "Product not found") + public Response getProductRecord(@PathParam("id") Long id) { + LOGGER.info("REST: Fetching product record with id: " + id); + Product product = productService.findProductById(id); + if (product != null) { + var record = io.microprofile.tutorial.store.product.entity.ProductRecord.fromProduct(product); + return Response.ok(record).build(); + } else { + return Response.status(Response.Status.NOT_FOUND).build(); + } + } + + @GET + @Path("/optional/{id}") + @Produces(MediaType.APPLICATION_JSON) + @Operation( + summary = "Get product with Optional fields", + description = "Returns product with Optional fields (MicroProfile OpenAPI 4.1 feature)" + ) + @APIResponse( + responseCode = "200", + description = "Product found", + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = io.microprofile.tutorial.store.product.entity.ProductWithOptional.class) + ) + ) + public Response getProductWithOptional(@PathParam("id") Long id) { + LOGGER.info("REST: Fetching product with optional fields, id: " + id); + Product product = productService.findProductById(id); + if (product != null) { + var productOptional = io.microprofile.tutorial.store.product.entity.ProductWithOptional.fromProduct(product); + return Response.ok(productOptional).build(); + } else { + return Response.status(Response.Status.NOT_FOUND).build(); + } + } + + @POST + @Path("/async-process") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation( + summary = "Process product asynchronously", + description = "Initiates async product processing and calls back when complete (MicroProfile OpenAPI 4.1 async feature)" + ) + @Callback( + name = "productProcessed", + callbackUrlExpression = "{$request.body#/callbackUrl}", + operations = { + @CallbackOperation( + method = "post", + summary = "Product processing completed", + requestBody = @RequestBody( + description = "Processing result", + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = io.microprofile.tutorial.store.product.entity.ProcessResult.class) + ) + ) + ) + } + ) + @APIResponse( + responseCode = "202", + description = "Processing initiated" + ) + @APIResponse( + responseCode = "400", + description = "Invalid request" + ) + public Response processProductAsync( + @RequestBody( + description = "Product and callback URL", + required = true, + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = io.microprofile.tutorial.store.product.entity.AsyncRequest.class) + ) + ) io.microprofile.tutorial.store.product.entity.AsyncRequest request + ) { + LOGGER.info("REST: Initiating async product processing"); + // In a real application, this would trigger async processing + // For demo purposes, we'll just return accepted + return Response.accepted() + .entity("{\"message\": \"Processing initiated\", \"requestId\": \"" + + java.util.UUID.randomUUID() + "\"}") + .build(); + } +} From 961f4b1c374850a1353702c4704b2d411355417e Mon Sep 17 00:00:00 2001 From: Tarun Telang Date: Fri, 24 Apr 2026 20:45:50 +0530 Subject: [PATCH 06/10] Create ProductRecord.java Product information as a Java Record * demonstrates MicroProfile OpenAPI 4.1 support for Java Records. --- .../store/product/entity/ProductRecord.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ProductRecord.java diff --git a/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ProductRecord.java b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ProductRecord.java new file mode 100644 index 00000000..c9ad6c66 --- /dev/null +++ b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ProductRecord.java @@ -0,0 +1,37 @@ +package io.microprofile.tutorial.store.product.entity; + +import org.eclipse.microprofile.openapi.annotations.media.Schema; + +/** + * Product information as a Java Record. + * Demonstrates MicroProfile OpenAPI 4.1 support for Java Records. + */ +@Schema(name = "ProductRecord", description = "Product information as a Java Record") +public record ProductRecord( + @Schema(description = "Product ID", example = "1") + Long id, + + @Schema(description = "Product name", example = "Laptop", required = true) + String name, + + @Schema(description = "Product description", example = "High-performance laptop") + String description, + + @Schema(description = "Product price", example = "999.99", required = true) + Double price +) { + /** + * Create a ProductRecord from a Product entity. + * + * @param product the product entity + * @return a new ProductRecord + */ + public static ProductRecord fromProduct(Product product) { + return new ProductRecord( + product.getId(), + product.getName(), + product.getDescription(), + product.getPrice() + ); + } +} From 124ed87d9276ff65a65352e753a33937eb2cca0c Mon Sep 17 00:00:00 2001 From: Tarun Telang Date: Fri, 24 Apr 2026 20:46:37 +0530 Subject: [PATCH 07/10] Create ProductWithOptional.java Product with optional fields. * Demonstrates MicroProfile OpenAPI 4.1 support for Optional types. --- .../product/entity/ProductWithOptional.java | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ProductWithOptional.java diff --git a/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ProductWithOptional.java b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ProductWithOptional.java new file mode 100644 index 00000000..19b6ea49 --- /dev/null +++ b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ProductWithOptional.java @@ -0,0 +1,90 @@ +package io.microprofile.tutorial.store.product.entity; + +import java.util.Optional; +import org.eclipse.microprofile.openapi.annotations.media.Schema; + +/** + * Product with optional fields. + * Demonstrates MicroProfile OpenAPI 4.1 support for Optional types. + */ +@Schema(description = "Product with optional fields") +public class ProductWithOptional { + + @Schema(description = "Product ID", required = true) + private Long id; + + @Schema(description = "Product name", required = true) + private String name; + + @Schema(description = "Optional product description") + private Optional description = Optional.empty(); + + @Schema(description = "Optional product category") + private Optional category = Optional.empty(); + + @Schema(description = "Product price", required = true) + private Double price; + + public ProductWithOptional() { + } + + public ProductWithOptional(Long id, String name, Double price) { + this.id = id; + this.name = name; + this.price = price; + } + + // Getters and setters + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Optional getDescription() { + return description; + } + + public void setDescription(Optional description) { + this.description = description; + } + + public Optional getCategory() { + return category; + } + + public void setCategory(Optional category) { + this.category = category; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + /** + * Create from a regular Product. + */ + public static ProductWithOptional fromProduct(Product product) { + ProductWithOptional p = new ProductWithOptional( + product.getId(), + product.getName(), + product.getPrice() + ); + p.setDescription(Optional.ofNullable(product.getDescription())); + return p; + } +} From a19647d9051182803c7ea8ecacd097524aecac66 Mon Sep 17 00:00:00 2001 From: Tarun Telang Date: Fri, 24 Apr 2026 20:47:39 +0530 Subject: [PATCH 08/10] Create AsyncRequest.java Request object for async product processing. --- .../store/product/entity/AsyncRequest.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/AsyncRequest.java diff --git a/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/AsyncRequest.java b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/AsyncRequest.java new file mode 100644 index 00000000..95e86171 --- /dev/null +++ b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/AsyncRequest.java @@ -0,0 +1,42 @@ +package io.microprofile.tutorial.store.product.entity; + +import org.eclipse.microprofile.openapi.annotations.media.Schema; + +/** + * Request object for async product processing. + */ +@Schema(description = "Async product processing request") +public class AsyncRequest { + + @Schema(description = "Product to process", required = true) + private Product product; + + @Schema(description = "Callback URL to notify when processing completes", + example = "https://example.com/callback", + required = true) + private String callbackUrl; + + public AsyncRequest() { + } + + public AsyncRequest(Product product, String callbackUrl) { + this.product = product; + this.callbackUrl = callbackUrl; + } + + public Product getProduct() { + return product; + } + + public void setProduct(Product product) { + this.product = product; + } + + public String getCallbackUrl() { + return callbackUrl; + } + + public void setCallbackUrl(String callbackUrl) { + this.callbackUrl = callbackUrl; + } +} From 80a07a356cfcdc98ce2cf46cf0ec2b92d3edddf0 Mon Sep 17 00:00:00 2001 From: Tarun Telang Date: Fri, 24 Apr 2026 20:48:23 +0530 Subject: [PATCH 09/10] Create ConditionalProduct.java Product with conditional validation. * Demonstrates the @DependentRequired annotation in MicroProfile OpenAPI 4.1. --- .../product/entity/ConditionalProduct.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ConditionalProduct.java diff --git a/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ConditionalProduct.java b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ConditionalProduct.java new file mode 100644 index 00000000..8ca1b1e7 --- /dev/null +++ b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ConditionalProduct.java @@ -0,0 +1,85 @@ +package io.microprofile.tutorial.store.product.entity; + +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.media.DependentRequired; + +/** + * Product with conditional validation. + * Demonstrates the @DependentRequired annotation in MicroProfile OpenAPI 4.1. + */ +@Schema( + description = "Product with conditional validation", + dependentRequired = { + @DependentRequired( + name = "discount", + requires = {"discountReason"} + ) + } +) +public class ConditionalProduct { + + @Schema(description = "Product ID", example = "1") + private Long id; + + @Schema(description = "Product name", example = "Laptop", required = true) + private String name; + + @Schema(description = "Product price", example = "999.99", required = true) + private Double price; + + @Schema(description = "Discount amount (requires discountReason if set)", example = "100.0") + private Double discount; + + @Schema(description = "Reason for discount", example = "Black Friday Sale") + private String discountReason; + + public ConditionalProduct() { + } + + public ConditionalProduct(Long id, String name, Double price) { + this.id = id; + this.name = name; + this.price = price; + } + + // Getters and setters + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + public Double getDiscount() { + return discount; + } + + public void setDiscount(Double discount) { + this.discount = discount; + } + + public String getDiscountReason() { + return discountReason; + } + + public void setDiscountReason(String discountReason) { + this.discountReason = discountReason; + } +} From 21febd9f6cacbc096354248eab533c5e74528d45 Mon Sep 17 00:00:00 2001 From: Tarun Telang Date: Fri, 24 Apr 2026 20:49:29 +0530 Subject: [PATCH 10/10] Create ProcessResult.java Result object for async product processing. --- .../store/product/entity/ProcessResult.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ProcessResult.java diff --git a/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ProcessResult.java b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ProcessResult.java new file mode 100644 index 00000000..1d9fedb6 --- /dev/null +++ b/code/chapter04/catalog/src/main/java/io/microprofile/tutorial/store/product/entity/ProcessResult.java @@ -0,0 +1,68 @@ +package io.microprofile.tutorial.store.product.entity; + +import org.eclipse.microprofile.openapi.annotations.media.Schema; + +/** + * Result object for async product processing. + */ +@Schema(description = "Result of async product processing") +public class ProcessResult { + + @Schema(description = "ID of the processed product", example = "123") + private Long productId; + + @Schema(description = "Processing status", + example = "COMPLETED", + enumeration = {"COMPLETED", "FAILED", "PENDING"}) + private String status; + + @Schema(description = "Processing message or error details", + example = "Product processed successfully") + private String message; + + @Schema(description = "Timestamp when processing completed", + example = "2025-01-31T16:00:00Z") + private String timestamp; + + public ProcessResult() { + } + + public ProcessResult(Long productId, String status, String message) { + this.productId = productId; + this.status = status; + this.message = message; + this.timestamp = java.time.Instant.now().toString(); + } + + public Long getProductId() { + return productId; + } + + public void setProductId(Long productId) { + this.productId = productId; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } +}