diff --git a/docker-compose.yml b/docker-compose.yml
index de621ce9..498e49bd 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -237,6 +237,11 @@ services:
KAFKA__BOOTSTRAPSERVERS: "redpanda:9092"
KAFKA__SCHEMAREGISTRY: "http://redpanda:8082"
KAFKA__GROUPID: "stickerlandia-user-management"
+ healthcheck:
+ test: ["CMD", "curl", "-f", "http://localhost:8080/api/users/v1/health"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
labels:
- "traefik.enable=true"
- "traefik.http.routers.user-management.rule=PathPrefix(`/api/users`)"
diff --git a/sticker-award/README.md b/sticker-award/README.md
index 72875e13..d7f00433 100644
--- a/sticker-award/README.md
+++ b/sticker-award/README.md
@@ -60,3 +60,86 @@ The API returns standard HTTP status codes and follows the RFC 7807 Problem Deta
Full API documentation is available in OpenAPI format:
- Synchronous API: [api.yaml](./docs/api.yaml)
- Asynchronous API: [async_api.json](./docs/async_api.json)
+
+## Building and Running
+
+### Prerequisites
+- Java 21+
+- Maven 3.8+
+
+### Development
+
+Run in development mode:
+```bash
+./mvnw compile quarkus:dev
+```
+
+### Testing
+
+Run tests:
+```bash
+./mvnw test
+```
+
+Run integration tests:
+```bash
+./mvnw verify
+```
+
+## Code Quality
+
+This project enforces high code quality through multiple static analysis tools:
+
+### Error Prone
+
+This project uses Error Prone to catch common Java programming mistakes at compile time.
+
+**Error Prone Integration:**
+- Runs automatically during compilation (`./mvnw compile`)
+- Catches bugs like incorrect Date usage, unused variables, and charset issues
+- Configured in the Maven compiler plugin
+- Uses Error Prone version 2.38.0
+
+**Common Error Prone checks include:**
+- `JavaUtilDate` - Flags usage of legacy `java.util.Date` API
+- `UnusedVariable` - Detects unused fields and variables
+- `DefaultCharset` - Warns about implicit charset usage in string operations
+
+### Checkstyle
+
+This project uses Checkstyle to enforce coding standards based on the Google Java Style Guide.
+
+**Run Checkstyle validation:**
+```bash
+# Check code style (runs automatically during build)
+./mvnw validate
+
+# Run only Checkstyle check
+./mvnw checkstyle:check
+
+# Generate Checkstyle report (creates HTML report at target/reports/checkstyle.html)
+./mvnw checkstyle:checkstyle
+```
+
+### Spotless (Code Formatting)
+
+This project uses Spotless with Google Java Format to automatically fix code style issues.
+
+**Format your code:**
+```bash
+# Check if code formatting is correct
+./mvnw spotless:check
+
+# Automatically fix code formatting issues
+./mvnw spotless:apply
+
+# Format and then validate with Checkstyle
+./mvnw spotless:apply validate
+```
+
+**Checkstyle Configuration:**
+- Configuration file: `checkstyle.xml`
+- Suppressions file: `checkstyle-suppressions.xml`
+- Based on Google Java Style Guide (modified for 4-space indentation)
+- Enforces 4-space indentation, 100-character line limit
+- Checks import ordering, Javadoc completeness, and naming conventions
diff --git a/sticker-award/checkstyle-suppressions.xml b/sticker-award/checkstyle-suppressions.xml
new file mode 100644
index 00000000..edc89ad7
--- /dev/null
+++ b/sticker-award/checkstyle-suppressions.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sticker-award/checkstyle.xml b/sticker-award/checkstyle.xml
new file mode 100644
index 00000000..a3e18f79
--- /dev/null
+++ b/sticker-award/checkstyle.xml
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sticker-award/pom.xml b/sticker-award/pom.xml
index cdb700da..2fe9dfe3 100644
--- a/sticker-award/pom.xml
+++ b/sticker-award/pom.xml
@@ -3,7 +3,7 @@
4.0.0
org.acme
sticker-award
- 1.0.0-SNAPSHOT
+ 1.0.2-SNAPSHOT
3.14.0
@@ -15,6 +15,10 @@
3.22.1
true
3.5.2
+ 10.18.2
+ 3.5.0
+ 2.43.0
+ 2.38.0
@@ -138,10 +142,39 @@
+ org.apache.maven.plugins
maven-compiler-plugin
- ${compiler-plugin.version}
+ 3.11.0
- true
+ UTF-8
+ true
+
+ -XDcompilePolicy=simple
+ --should-stop=ifError=FLOW
+ -Xplugin:ErrorProne
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
+ -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
+ -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
+
+
+
+ com.google.errorprone
+ error_prone_core
+ ${error-prone.version}
+
+
+
@@ -173,6 +206,70 @@
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ ${checkstyle-plugin.version}
+
+ checkstyle.xml
+ true
+ true
+ true
+ warning
+ false
+ true
+
+
+
+ com.puppycrawl.tools
+ checkstyle
+ ${checkstyle.version}
+
+
+
+
+ validate
+ validate
+
+ check
+
+
+
+
+
+
+ com.diffplug.spotless
+ spotless-maven-plugin
+ ${spotless-plugin.version}
+
+
+
+
+ 1.19.2
+
+
+
+
+
+
+
+
+ src/main/java/**/*.java
+ src/test/java/**/*.java
+
+
+
+
+
+
+ check
+
+
+
+
diff --git a/sticker-award/src/main/docker/Dockerfile.jvmlocal b/sticker-award/src/main/docker/Dockerfile.jvmlocal
index 52553b95..84191c55 100644
--- a/sticker-award/src/main/docker/Dockerfile.jvmlocal
+++ b/sticker-award/src/main/docker/Dockerfile.jvmlocal
@@ -22,6 +22,7 @@ WORKDIR /build
# The context needs to be the root of the sticker-award directory, not the Dockerfile location
COPY pom.xml .
+COPY checkstyle.xml .
COPY src ./src
# Make sure mvnw is executable and then build
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/StickerAwardRepository.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/StickerAwardRepository.java
index 7f53c74f..808e90a3 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/StickerAwardRepository.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/StickerAwardRepository.java
@@ -2,47 +2,64 @@
import com.datadoghq.stickerlandia.stickeraward.award.dto.AssignStickerRequest;
import com.datadoghq.stickerlandia.stickeraward.award.dto.AssignStickerResponse;
-import com.datadoghq.stickerlandia.stickeraward.award.dto.StickerAssignmentDTO;
-import com.datadoghq.stickerlandia.stickeraward.award.dto.RemoveStickerFromUserResponse;
import com.datadoghq.stickerlandia.stickeraward.award.dto.GetUserStickersResponse;
-import com.datadoghq.stickerlandia.stickeraward.sticker.entity.Sticker;
+import com.datadoghq.stickerlandia.stickeraward.award.dto.RemoveStickerFromUserResponse;
+import com.datadoghq.stickerlandia.stickeraward.award.dto.StickerAssignmentDTO;
import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
+import com.datadoghq.stickerlandia.stickeraward.sticker.entity.Sticker;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
-
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
+/** Repository class for managing sticker award operations. */
@ApplicationScoped
public class StickerAwardRepository {
+ /**
+ * Gets all sticker assignments for a specific user.
+ *
+ * @param userId the ID of the user
+ * @return response containing user's sticker assignments
+ */
public GetUserStickersResponse getUserStickers(String userId) {
List assignments = StickerAssignment.findActiveByUserId(userId);
- List stickerAssignmentDTOS = assignments.stream()
- .map(assignment -> {
- Sticker sticker = assignment.getSticker();
- StickerAssignmentDTO dto = new StickerAssignmentDTO();
- dto.setStickerId(sticker.getStickerId());
- dto.setName(sticker.getName());
- dto.setDescription(sticker.getDescription());
- dto.setImageUrl(sticker.getImageUrl());
- dto.setAssignedAt(Date.from(assignment.getAssignedAt()));
- return dto;
- })
- .collect(Collectors.toList());
+ List stickerAssignmentDtos =
+ assignments.stream()
+ .map(
+ assignment -> {
+ Sticker sticker = assignment.getSticker();
+ StickerAssignmentDTO dto = new StickerAssignmentDTO();
+ dto.setStickerId(sticker.getStickerId());
+ dto.setName(sticker.getName());
+ dto.setDescription(sticker.getDescription());
+ dto.setImageUrl(sticker.getImageUrl());
+ dto.setAssignedAt(Date.from(assignment.getAssignedAt()));
+ return dto;
+ })
+ .collect(Collectors.toList());
GetUserStickersResponse response = new GetUserStickersResponse();
response.setUserId(userId);
- response.setStickers(stickerAssignmentDTOS);
+ response.setStickers(stickerAssignmentDtos);
return response;
}
+ /**
+ * Assigns a sticker to a user.
+ *
+ * @param userId the ID of the user
+ * @param stickerId the ID of the sticker
+ * @param request the assignment request
+ * @return response containing assignment details, or null if assignment failed
+ */
@Transactional
- public AssignStickerResponse assignStickerToUser(String userId, String stickerId, AssignStickerRequest request) {
+ public AssignStickerResponse assignStickerToUser(
+ String userId, String stickerId, AssignStickerRequest request) {
// Find the sticker to assign
Sticker sticker = Sticker.findById(stickerId);
if (sticker == null) {
@@ -50,7 +67,8 @@ public AssignStickerResponse assignStickerToUser(String userId, String stickerId
}
// Check if user already has this sticker
- StickerAssignment existingAssignment = StickerAssignment.findActiveByUserAndSticker(userId, stickerId);
+ StickerAssignment existingAssignment =
+ StickerAssignment.findActiveByUserAndSticker(userId, stickerId);
if (existingAssignment != null) {
throw new IllegalStateException("User already has this sticker assigned");
}
@@ -72,10 +90,18 @@ public AssignStickerResponse assignStickerToUser(String userId, String stickerId
return response;
}
+ /**
+ * Removes a sticker assignment from a user.
+ *
+ * @param userId the ID of the user
+ * @param stickerId the ID of the sticker to remove
+ * @return response containing removal details, or null if removal failed
+ */
@Transactional
public RemoveStickerFromUserResponse removeStickerFromUser(String userId, String stickerId) {
// Find the active assignment
- StickerAssignment assignment = StickerAssignment.findActiveByUserAndSticker(userId, stickerId);
+ StickerAssignment assignment =
+ StickerAssignment.findActiveByUserAndSticker(userId, stickerId);
if (assignment == null) {
return null; // Assignment not found
}
@@ -92,4 +118,4 @@ public RemoveStickerFromUserResponse removeStickerFromUser(String userId, String
return response;
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/StickerAwardResource.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/StickerAwardResource.java
index d792e13e..ce6e78a9 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/StickerAwardResource.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/StickerAwardResource.java
@@ -2,9 +2,8 @@
import com.datadoghq.stickerlandia.stickeraward.award.dto.AssignStickerRequest;
import com.datadoghq.stickerlandia.stickeraward.award.dto.AssignStickerResponse;
-import com.datadoghq.stickerlandia.stickeraward.award.dto.StickerAssignmentDTO;
-import com.datadoghq.stickerlandia.stickeraward.award.dto.RemoveStickerFromUserResponse;
import com.datadoghq.stickerlandia.stickeraward.award.dto.GetUserStickersResponse;
+import com.datadoghq.stickerlandia.stickeraward.award.dto.RemoveStickerFromUserResponse;
import com.datadoghq.stickerlandia.stickeraward.award.messaging.StickerAwardEventPublisher;
import io.smallrye.common.constraint.NotNull;
import jakarta.inject.Inject;
@@ -16,43 +15,48 @@
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.openapi.annotations.Operation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Path("/api")
+/** REST resource for managing sticker awards and assignments. */
+@Path("/api/award/v1/users")
public class StickerAwardResource {
-
- private static final Logger log = LoggerFactory.getLogger(StickerAwardResource.class);
-
- @Inject
- StickerAwardEventPublisher eventPublisher;
- @Inject
- StickerAwardRepository stickerAwardRepository;
+ @Inject StickerAwardEventPublisher eventPublisher;
- @Operation(description = "Get stickers assigned to a user (access controlled based on caller identity)")
- @Path("/award/v1/users/{userId}/stickers")
+ @Inject StickerAwardRepository stickerAwardRepository;
+
+ @Operation(
+ description =
+ "Get stickers assigned to a user (access controlled based on caller identity)")
+ @Path("/{userId}/stickers")
@GET
@Produces("application/json")
public GetUserStickersResponse getUserStickers(@PathParam("userId") String userId) {
return stickerAwardRepository.getUserStickers(userId);
}
- @Operation(description = "Assign a new sticker to a user (access controlled based on caller identity)")
- @Path("/award/v1/users/{userId}/stickers")
+ /**
+ * Assigns a sticker to a user.
+ *
+ * @param userId the ID of the user to assign the sticker to
+ * @param request the assignment request containing sticker details
+ * @return response containing assignment details
+ */
@POST
- @Produces("application/json")
- @Consumes("application/json")
+ @Path("/{userId}/stickers")
+ @Operation(summary = "Assign a sticker to a user")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
@Transactional
- public Response assignStickerToUser(@PathParam("userId") String userId,
- @NotNull AssignStickerRequest data) {
+ public Response assignStickerToUser(
+ @PathParam("userId") String userId, @NotNull AssignStickerRequest request) {
try {
- String stickerId = data.getStickerId();
- AssignStickerResponse response = stickerAwardRepository.assignStickerToUser(userId, stickerId, data);
+ String stickerId = request.getStickerId();
+ AssignStickerResponse response =
+ stickerAwardRepository.assignStickerToUser(userId, stickerId, request);
if (response == null) {
return Response.status(Response.Status.BAD_REQUEST).build();
}
@@ -60,29 +64,36 @@ public Response assignStickerToUser(@PathParam("userId") String userId,
// Publish events - Note: We'll need to modify event publisher to work with DTOs
// For now, skip event publishing until we refactor the event publisher
// try {
- // log.info("Publishing sticker assignment events for userId={}, stickerId={}", userId, stickerId);
+ // log.info("Publishing sticker assignment events for userId={}, stickerId={}",
+ // userId, stickerId);
// eventPublisher.publishStickerAssigned(...);
// } catch (Exception e) {
// log.error("Failed to publish sticker assignment events", e);
// }
- return Response.status(Response.Status.CREATED)
- .entity(response)
- .build();
+ return Response.status(Response.Status.CREATED).entity(response).build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.CONFLICT).build();
}
}
- @Operation(description = "Remove a sticker assignment from a user (access controlled based on caller identity)")
- @Path("/award/v1/users/{userId}/stickers/{stickerId}")
+ /**
+ * Removes a sticker assignment from a user.
+ *
+ * @param userId the ID of the user
+ * @param stickerId the ID of the sticker to remove
+ * @return response indicating the removal result
+ */
@DELETE
- @Produces("application/json")
+ @Path("/{userId}/stickers/{stickerId}")
+ @Operation(summary = "Remove a sticker assignment from a user")
+ @Produces(MediaType.APPLICATION_JSON)
@Transactional
- public Response removeStickerFromUser(@PathParam("userId") String userId,
- @PathParam("stickerId") String stickerId) {
+ public Response removeStickerFromUser(
+ @PathParam("userId") String userId, @PathParam("stickerId") String stickerId) {
- RemoveStickerFromUserResponse response = stickerAwardRepository.removeStickerFromUser(userId, stickerId);
+ RemoveStickerFromUserResponse response =
+ stickerAwardRepository.removeStickerFromUser(userId, stickerId);
if (response == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
@@ -90,7 +101,8 @@ public Response removeStickerFromUser(@PathParam("userId") String userId,
// Publish events - Note: We'll need to modify event publisher to work with DTOs
// For now, skip event publishing until we refactor the event publisher
// try {
- // log.info("Publishing sticker removal event for userId={}, stickerId={}", userId, stickerId);
+ // log.info("Publishing sticker removal event for userId={}, stickerId={}", userId,
+ // stickerId);
// eventPublisher.publishStickerRemoved(...);
// } catch (Exception e) {
// log.error("Failed to publish sticker removal event", e);
@@ -98,4 +110,4 @@ public Response removeStickerFromUser(@PathParam("userId") String userId,
return Response.ok(response).build();
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/AssignStickerRequest.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/AssignStickerRequest.java
index 7b0f7509..c131e001 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/AssignStickerRequest.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/AssignStickerRequest.java
@@ -1,44 +1,29 @@
-
package com.datadoghq.stickerlandia.stickeraward.award.dto;
-import javax.annotation.processing.Generated;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import javax.annotation.processing.Generated;
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "stickerId",
- "reason"
-})
+@JsonPropertyOrder({"stickerId", "reason"})
@Generated("jsonschema2pojo")
public class AssignStickerRequest {
- /**
- *
- * (Required)
- *
- */
+ /** (Required). */
@JsonProperty("stickerId")
private String stickerId;
+
@JsonProperty("reason")
private String reason;
- /**
- *
- * (Required)
- *
- */
+ /** (Required). */
@JsonProperty("stickerId")
public String getStickerId() {
return stickerId;
}
- /**
- *
- * (Required)
- *
- */
+ /** (Required). */
@JsonProperty("stickerId")
public void setStickerId(String stickerId) {
this.stickerId = stickerId;
@@ -53,5 +38,4 @@ public String getReason() {
public void setReason(String reason) {
this.reason = reason;
}
-
}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/AssignStickerResponse.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/AssignStickerResponse.java
index 469950d3..295ff3d7 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/AssignStickerResponse.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/AssignStickerResponse.java
@@ -1,27 +1,27 @@
-
package com.datadoghq.stickerlandia.stickeraward.award.dto;
-import java.util.Date;
-import javax.annotation.processing.Generated;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import java.util.Date;
+import javax.annotation.processing.Generated;
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "userId",
- "stickerId",
- "assignedAt"
-})
+@JsonPropertyOrder({"userId", "stickerId", "assignedAt"})
@Generated("jsonschema2pojo")
public class AssignStickerResponse {
@JsonProperty("userId")
private String userId;
+
@JsonProperty("stickerId")
private String stickerId;
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
+
+ @JsonFormat(
+ shape = JsonFormat.Shape.STRING,
+ pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'",
+ timezone = "UTC")
@JsonProperty("assignedAt")
private Date assignedAt;
@@ -54,5 +54,4 @@ public Date getAssignedAt() {
public void setAssignedAt(Date assignedAt) {
this.assignedAt = assignedAt;
}
-
}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/GetUserStickersResponse.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/GetUserStickersResponse.java
index bb784e71..e1fb9d05 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/GetUserStickersResponse.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/GetUserStickersResponse.java
@@ -1,23 +1,20 @@
-
package com.datadoghq.stickerlandia.stickeraward.award.dto;
-import java.util.ArrayList;
-import java.util.List;
-import javax.annotation.processing.Generated;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import java.util.ArrayList;
+import java.util.List;
+import javax.annotation.processing.Generated;
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "userId",
- "stickers"
-})
+@JsonPropertyOrder({"userId", "stickers"})
@Generated("jsonschema2pojo")
public class GetUserStickersResponse {
@JsonProperty("userId")
private String userId;
+
@JsonProperty("stickers")
private List stickers = new ArrayList();
@@ -40,5 +37,4 @@ public List getStickers() {
public void setStickers(List stickers) {
this.stickers = stickers;
}
-
}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/RemoveStickerFromUserResponse.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/RemoveStickerFromUserResponse.java
index 386638c9..3ce0df18 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/RemoveStickerFromUserResponse.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/RemoveStickerFromUserResponse.java
@@ -1,27 +1,27 @@
-
package com.datadoghq.stickerlandia.stickeraward.award.dto;
-import java.util.Date;
-import javax.annotation.processing.Generated;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import java.util.Date;
+import javax.annotation.processing.Generated;
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "userId",
- "stickerId",
- "removedAt"
-})
+@JsonPropertyOrder({"userId", "stickerId", "removedAt"})
@Generated("jsonschema2pojo")
public class RemoveStickerFromUserResponse {
@JsonProperty("userId")
private String userId;
+
@JsonProperty("stickerId")
private String stickerId;
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
+
+ @JsonFormat(
+ shape = JsonFormat.Shape.STRING,
+ pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'",
+ timezone = "UTC")
@JsonProperty("removedAt")
private Date removedAt;
@@ -54,5 +54,4 @@ public Date getRemovedAt() {
public void setRemovedAt(Date removedAt) {
this.removedAt = removedAt;
}
-
}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/StickerAssignmentDTO.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/StickerAssignmentDTO.java
index 3da0889b..5efa1cd8 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/StickerAssignmentDTO.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/StickerAssignmentDTO.java
@@ -1,33 +1,33 @@
-
package com.datadoghq.stickerlandia.stickeraward.award.dto;
-import java.util.Date;
-import javax.annotation.processing.Generated;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import java.util.Date;
+import javax.annotation.processing.Generated;
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "stickerId",
- "name",
- "description",
- "imageUrl",
- "assignedAt"
-})
+@JsonPropertyOrder({"stickerId", "name", "description", "imageUrl", "assignedAt"})
@Generated("jsonschema2pojo")
public class StickerAssignmentDTO {
@JsonProperty("stickerId")
private String stickerId;
+
@JsonProperty("name")
private String name;
+
@JsonProperty("description")
private String description;
+
@JsonProperty("imageUrl")
private String imageUrl;
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
+
+ @JsonFormat(
+ shape = JsonFormat.Shape.STRING,
+ pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'",
+ timezone = "UTC")
@JsonProperty("assignedAt")
private Date assignedAt;
@@ -80,5 +80,4 @@ public Date getAssignedAt() {
public void setAssignedAt(Date assignedAt) {
this.assignedAt = assignedAt;
}
-
}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/UserAssignmentDTO.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/UserAssignmentDTO.java
index 343546ce..8de0c179 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/UserAssignmentDTO.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/dto/UserAssignmentDTO.java
@@ -1,24 +1,26 @@
package com.datadoghq.stickerlandia.stickeraward.award.dto;
-import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import java.util.Date;
+/** DTO representing a user assignment with details about when and why a sticker was assigned. */
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "userId",
- "assignedAt",
- "reason"
-})
+@JsonPropertyOrder({"userId", "assignedAt", "reason"})
public class UserAssignmentDTO {
@JsonProperty("userId")
private String userId;
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
+
+ @JsonFormat(
+ shape = JsonFormat.Shape.STRING,
+ pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'",
+ timezone = "UTC")
@JsonProperty("assignedAt")
private Date assignedAt;
+
@JsonProperty("reason")
private String reason;
@@ -51,5 +53,4 @@ public String getReason() {
public void setReason(String reason) {
this.reason = reason;
}
-
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/entity/StickerAssignment.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/entity/StickerAssignment.java
index 0a3bd5c6..c1e5ae34 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/entity/StickerAssignment.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/entity/StickerAssignment.java
@@ -12,13 +12,14 @@
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
-
import java.time.Instant;
import java.util.List;
+/** Entity representing the assignment of a sticker to a user. */
@Entity
-@Table(name = "sticker_assignments",
- uniqueConstraints = @UniqueConstraint(columnNames = {"user_id", "sticker_id"}))
+@Table(
+ name = "sticker_assignments",
+ uniqueConstraints = @UniqueConstraint(columnNames = {"user_id", "sticker_id"}))
public class StickerAssignment extends PanacheEntityBase {
@Id
@@ -43,10 +44,15 @@ public class StickerAssignment extends PanacheEntityBase {
private String reason;
// Default constructor for JPA
- public StickerAssignment() {
- }
-
- // Constructor with fields
+ public StickerAssignment() {}
+
+ /**
+ * Constructor with fields for creating a new sticker assignment.
+ *
+ * @param userId the ID of the user
+ * @param sticker the sticker to assign
+ * @param reason the reason for the assignment
+ */
public StickerAssignment(String userId, Sticker sticker, String reason) {
this.userId = userId;
this.sticker = sticker;
@@ -104,17 +110,38 @@ public void setReason(String reason) {
}
// Helper methods
+ /**
+ * Checks if this assignment is currently active (not removed).
+ *
+ * @return true if the assignment is active, false otherwise
+ */
public boolean isActive() {
return removedAt == null;
}
// Repository methods
+ /**
+ * Finds all active sticker assignments for a specific user.
+ *
+ * @param userId the ID of the user
+ * @return list of active sticker assignments
+ */
public static List findActiveByUserId(String userId) {
return list("userId = ?1 AND removedAt IS NULL", userId);
}
+ /**
+ * Finds an active sticker assignment for a specific user and sticker.
+ *
+ * @param userId the ID of the user
+ * @param stickerId the ID of the sticker
+ * @return the active assignment, or null if not found
+ */
public static StickerAssignment findActiveByUserAndSticker(String userId, String stickerId) {
- return find("userId = ?1 AND sticker.stickerId = ?2 AND removedAt IS NULL", userId, stickerId)
+ return find(
+ "userId = ?1 AND sticker.stickerId = ?2 AND removedAt IS NULL",
+ userId,
+ stickerId)
.firstResult();
}
@@ -125,4 +152,4 @@ public static List findActiveByStickerId(String stickerId) {
public static long countActiveByStickerId(String stickerId) {
return count("sticker.stickerId = ?1 AND removedAt IS NULL", stickerId);
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/messaging/StickerAwardEventPublisher.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/messaging/StickerAwardEventPublisher.java
index 81c692a6..9e10804e 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/messaging/StickerAwardEventPublisher.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/award/messaging/StickerAwardEventPublisher.java
@@ -1,92 +1,98 @@
package com.datadoghq.stickerlandia.stickeraward.award.messaging;
+import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
+import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerAssignedToUserEvent;
+import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerClaimedEvent;
+import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerRemovedFromUserEvent;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
-
import org.eclipse.microprofile.reactive.messaging.Channel;
import org.eclipse.microprofile.reactive.messaging.Emitter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
-import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerAssignedToUserEvent;
-import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerClaimedEvent;
-import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerRemovedFromUserEvent;
-
-/**
- * Service responsible for publishing sticker-related events to Kafka topics.
- */
+/** Service responsible for publishing sticker-related events to Kafka topics. */
@ApplicationScoped
public class StickerAwardEventPublisher {
-
+
private static final Logger log = LoggerFactory.getLogger(StickerAwardEventPublisher.class);
-
+
@Inject
@Channel("stickers-assigned")
Emitter stickerAssignedEmitter;
-
+
@Inject
@Channel("stickers-removed")
Emitter stickerRemovedEmitter;
-
+
@Inject
@Channel("stickers-claimed")
Emitter stickerClaimedEmitter;
-
+
/**
* Publishes a sticker assigned event when a sticker is assigned to a user.
- *
+ *
* @param assignment The sticker assignment entity
*/
public void publishStickerAssigned(StickerAssignment assignment) {
try {
- StickerAssignedToUserEvent event = StickerAssignedToUserEvent.fromAssignment(assignment);
- log.info("Publishing sticker assigned event: userId={}, stickerId={}",
- event.getAccountId(), event.getStickerId());
+ StickerAssignedToUserEvent event =
+ StickerAssignedToUserEvent.fromAssignment(assignment);
+ log.info(
+ "Publishing sticker assigned event: userId={}, stickerId={}",
+ event.getAccountId(),
+ event.getStickerId());
stickerAssignedEmitter.send(event);
-
+
// Also publish sticker claimed event for the user management service
publishStickerClaimed(assignment);
} catch (Exception e) {
log.error("Error publishing sticker assigned event", e);
}
}
-
+
/**
* Publishes a sticker removed event when a sticker is removed from a user.
- *
+ *
* @param assignment The sticker assignment entity with removed status
*/
public void publishStickerRemoved(StickerAssignment assignment) {
if (assignment.getRemovedAt() == null) {
- log.warn("Cannot publish removal event for active assignment: userId={}, stickerId={}",
- assignment.getUserId(), assignment.getSticker().getStickerId());
+ log.warn(
+ "Cannot publish removal event for active assignment: userId={}, stickerId={}",
+ assignment.getUserId(),
+ assignment.getSticker().getStickerId());
return;
}
-
+
try {
- StickerRemovedFromUserEvent event = StickerRemovedFromUserEvent.fromAssignment(assignment);
- log.info("Publishing sticker removed event: userId={}, stickerId={}",
- event.getAccountId(), event.getStickerId());
+ StickerRemovedFromUserEvent event =
+ StickerRemovedFromUserEvent.fromAssignment(assignment);
+ log.info(
+ "Publishing sticker removed event: userId={}, stickerId={}",
+ event.getAccountId(),
+ event.getStickerId());
stickerRemovedEmitter.send(event);
} catch (Exception e) {
log.error("Error publishing sticker removed event", e);
}
}
-
+
/**
* Publishes a sticker claimed event for the user management service to update claim count.
- *
+ *
* @param assignment The sticker assignment entity
*/
private void publishStickerClaimed(StickerAssignment assignment) {
try {
StickerClaimedEvent event = StickerClaimedEvent.fromAssignment(assignment);
- log.info("Publishing sticker claimed event: userId={}, stickerId={}",
- event.getAccountId(), event.getStickerId());
+ log.info(
+ "Publishing sticker claimed event: userId={}, stickerId={}",
+ event.getAccountId(),
+ event.getStickerId());
stickerClaimedEmitter.send(event);
} catch (Exception e) {
log.error("Error publishing sticker claimed event", e);
}
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/dto/PagedResponse.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/dto/PagedResponse.java
index 33dfc96c..1b00e98f 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/dto/PagedResponse.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/dto/PagedResponse.java
@@ -4,115 +4,124 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import java.util.List;
+/**
+ * Generic DTO for paginated responses.
+ *
+ * @param the type of items in the response
+ */
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "page",
- "size",
- "total",
- "totalPages"
-})
-public class PagedResponse {
-
- /**
- * Current page number (0-based)
- *
- */
+@JsonPropertyOrder({"data", "page", "size", "total", "totalPages", "hasNext", "hasPrevious"})
+public class PagedResponse {
+
+ /** The current page number. */
@JsonProperty("page")
@JsonPropertyDescription("Current page number (0-based)")
private Integer page;
- /**
- * Number of items per page
- *
- */
+
+ /** The page size. */
@JsonProperty("size")
@JsonPropertyDescription("Number of items per page")
private Integer size;
- /**
- * Total number of items
- *
- */
+
+ /** The total number of items. */
@JsonProperty("total")
@JsonPropertyDescription("Total number of items")
private Integer total;
- /**
- * Total number of pages
- *
- */
+
+ /** The total number of pages. */
@JsonProperty("totalPages")
@JsonPropertyDescription("Total number of pages")
private Integer totalPages;
- /**
- * Current page number (0-based)
- *
- */
+ /** Whether there is a next page. */
+ @JsonProperty("hasNext")
+ public Boolean getHasNext() {
+ return null;
+ }
+
+ /** Whether there is a previous page. */
+ @JsonProperty("hasPrevious")
+ public Boolean getHasPrevious() {
+ return null;
+ }
+
+ /** The list of items in this page. */
+ @JsonProperty("data")
+ public List getData() {
+ return null;
+ }
+
+ /** The first item index on this page. */
+ @JsonProperty("first")
+ public Integer getFirst() {
+ return null;
+ }
+
+ /** The last item index on this page. */
+ @JsonProperty("last")
+ public Integer getLast() {
+ return null;
+ }
+
+ /** Whether this is the first page. */
+ @JsonProperty("isFirst")
+ public Boolean getIsFirst() {
+ return null;
+ }
+
+ /** Whether this is the last page. */
+ @JsonProperty("isLast")
+ public Boolean getIsLast() {
+ return null;
+ }
+
+ /** Current page number (0-based). */
@JsonProperty("page")
public Integer getPage() {
return page;
}
- /**
- * Current page number (0-based)
- *
- */
+ /** Current page number (0-based). */
@JsonProperty("page")
public void setPage(Integer page) {
this.page = page;
}
- /**
- * Number of items per page
- *
- */
+ /** Number of items per page. */
@JsonProperty("size")
public Integer getSize() {
return size;
}
- /**
- * Number of items per page
- *
- */
+ /** Number of items per page. */
@JsonProperty("size")
public void setSize(Integer size) {
this.size = size;
}
- /**
- * Total number of items
- *
- */
+ /** Total number of items. */
@JsonProperty("total")
public Integer getTotal() {
return total;
}
- /**
- * Total number of items
- *
- */
+ /** Total number of items. */
@JsonProperty("total")
public void setTotal(Integer total) {
this.total = total;
}
- /**
- * Total number of pages
- *
- */
+ /** Total number of pages. */
@JsonProperty("totalPages")
public Integer getTotalPages() {
return totalPages;
}
- /**
- * Total number of pages
- *
- */
+ /** Total number of pages. */
@JsonProperty("totalPages")
public void setTotalPages(Integer totalPages) {
this.totalPages = totalPages;
}
-
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/DomainEvent.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/DomainEvent.java
index 2c465697..141a6b82 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/DomainEvent.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/DomainEvent.java
@@ -1,32 +1,29 @@
package com.datadoghq.stickerlandia.stickeraward.common.events;
-/**
- * Base abstract class for all domain events.
- * This class should be extended by all event types.
- */
+/** Base abstract class for all domain events. This class should be extended by all event types. */
public abstract class DomainEvent {
-
+
private String eventName;
private String eventVersion;
-
+
protected DomainEvent(String eventName, String eventVersion) {
this.eventName = eventName;
this.eventVersion = eventVersion;
}
-
+
public String getEventName() {
return eventName;
}
-
+
public void setEventName(String eventName) {
this.eventName = eventName;
}
-
+
public String getEventVersion() {
return eventVersion;
}
-
+
public void setEventVersion(String eventVersion) {
this.eventVersion = eventVersion;
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/in/CertificationCompletedEvent.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/in/CertificationCompletedEvent.java
index e4c2594e..38bebf24 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/in/CertificationCompletedEvent.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/in/CertificationCompletedEvent.java
@@ -3,36 +3,36 @@
import java.time.Instant;
/**
- * Event received when a certification is completed.
- * Subscribed from the 'certifications.certificationCompleted.v1' topic.
+ * Event received when a certification is completed. Subscribed from the
+ * 'certifications.certificationCompleted.v1' topic.
*/
public class CertificationCompletedEvent {
-
+
private String accountId;
private String certificationId;
private Instant completedAt;
-
+
public String getAccountId() {
return accountId;
}
-
+
public void setAccountId(String accountId) {
this.accountId = accountId;
}
-
+
public String getCertificationId() {
return certificationId;
}
-
+
public void setCertificationId(String certificationId) {
this.certificationId = certificationId;
}
-
+
public Instant getCompletedAt() {
return completedAt;
}
-
+
public void setCompletedAt(Instant completedAt) {
this.completedAt = completedAt;
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/out/StickerAssignedToUserEvent.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/out/StickerAssignedToUserEvent.java
index aacdd100..6e7fbd47 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/out/StickerAssignedToUserEvent.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/out/StickerAssignedToUserEvent.java
@@ -1,33 +1,31 @@
package com.datadoghq.stickerlandia.stickeraward.common.events.out;
-import java.time.Instant;
-
import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
import com.datadoghq.stickerlandia.stickeraward.common.events.DomainEvent;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.time.Instant;
/**
- * Event published when a sticker is assigned to a user.
- * Published to the 'stickers.stickerAssignedToUser.v1' topic.
+ * Event published when a sticker is assigned to a user. Published to the
+ * 'stickers.stickerAssignedToUser.v1' topic.
*/
public class StickerAssignedToUserEvent extends DomainEvent {
-
+
private static final String EVENT_NAME = "StickerAssignedToUser";
private static final String EVENT_VERSION = "v1";
-
+
private String accountId;
private String stickerId;
private Instant assignedAt;
-
- /**
- * Default constructor for serialization frameworks
- */
+
+ /** Default constructor for serialization frameworks. */
public StickerAssignedToUserEvent() {
super(EVENT_NAME, EVENT_VERSION);
}
-
+
/**
- * Create a new event from a sticker assignment entity
- *
+ * Create a new event from a sticker assignment entity.
+ *
* @param assignment The sticker assignment entity
* @return A new event instance
*/
@@ -38,28 +36,36 @@ public static StickerAssignedToUserEvent fromAssignment(StickerAssignment assign
event.setAssignedAt(assignment.getAssignedAt());
return event;
}
-
- public String getAccountId() {
+
+ /** The ID of the user who was assigned the sticker. */
+ @JsonProperty("userId")
+ public String getUserId() {
return accountId;
}
-
+
public void setAccountId(String accountId) {
this.accountId = accountId;
}
-
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ /** The ID of the sticker that was assigned. */
+ @JsonProperty("stickerId")
public String getStickerId() {
return stickerId;
}
-
+
public void setStickerId(String stickerId) {
this.stickerId = stickerId;
}
-
+
public Instant getAssignedAt() {
return assignedAt;
}
-
+
public void setAssignedAt(Instant assignedAt) {
this.assignedAt = assignedAt;
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/out/StickerClaimedEvent.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/out/StickerClaimedEvent.java
index a40e9d1e..393e2fee 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/out/StickerClaimedEvent.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/out/StickerClaimedEvent.java
@@ -2,29 +2,27 @@
import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
import com.datadoghq.stickerlandia.stickeraward.common.events.DomainEvent;
+import com.fasterxml.jackson.annotation.JsonProperty;
/**
- * Event published when a user claims a sticker.
- * Published to the 'users.stickerClaimed.v1' topic.
+ * Event published when a user claims a sticker. Published to the 'users.stickerClaimed.v1' topic.
*/
public class StickerClaimedEvent extends DomainEvent {
-
+
private static final String EVENT_NAME = "StickerClaimed";
private static final String EVENT_VERSION = "v1";
-
+
private String accountId;
private String stickerId;
-
- /**
- * Default constructor for serialization frameworks
- */
+
+ /** Default constructor for serialization frameworks. */
public StickerClaimedEvent() {
super(EVENT_NAME, EVENT_VERSION);
}
-
+
/**
- * Create a new event from a sticker assignment entity
- *
+ * Create a new event from a sticker assignment entity.
+ *
* @param assignment The sticker assignment entity
* @return A new event instance
*/
@@ -34,20 +32,28 @@ public static StickerClaimedEvent fromAssignment(StickerAssignment assignment) {
event.setStickerId(assignment.getSticker().getStickerId());
return event;
}
-
- public String getAccountId() {
+
+ /** The ID of the user who claimed the sticker. */
+ @JsonProperty("userId")
+ public String getUserId() {
return accountId;
}
-
+
public void setAccountId(String accountId) {
this.accountId = accountId;
}
-
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ /** The ID of the sticker that was claimed. */
+ @JsonProperty("stickerId")
public String getStickerId() {
return stickerId;
}
-
+
public void setStickerId(String stickerId) {
this.stickerId = stickerId;
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/out/StickerRemovedFromUserEvent.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/out/StickerRemovedFromUserEvent.java
index 0fbff82c..b939b139 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/out/StickerRemovedFromUserEvent.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/common/events/out/StickerRemovedFromUserEvent.java
@@ -1,69 +1,76 @@
package com.datadoghq.stickerlandia.stickeraward.common.events.out;
-import java.time.Instant;
-
import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
import com.datadoghq.stickerlandia.stickeraward.common.events.DomainEvent;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.time.Instant;
/**
- * Event published when a sticker is removed from a user.
- * Published to the 'stickers.stickerRemovedFromUser.v1' topic.
+ * Event published when a sticker is removed from a user. Published to the
+ * 'stickers.stickerRemovedFromUser.v1' topic.
*/
public class StickerRemovedFromUserEvent extends DomainEvent {
-
+
private static final String EVENT_NAME = "StickerRemovedFromUser";
private static final String EVENT_VERSION = "v1";
-
+
private String accountId;
private String stickerId;
private Instant removedAt;
-
- /**
- * Default constructor for serialization frameworks
- */
+
+ /** Default constructor for serialization frameworks. */
public StickerRemovedFromUserEvent() {
super(EVENT_NAME, EVENT_VERSION);
}
-
+
/**
- * Create a new event from a sticker assignment entity
- *
+ * Create a new event from a sticker assignment entity.
+ *
* @param assignment The sticker assignment entity with removed status
* @return A new event instance
*/
public static StickerRemovedFromUserEvent fromAssignment(StickerAssignment assignment) {
if (assignment.getRemovedAt() == null) {
- throw new IllegalArgumentException("Cannot create removal event from active assignment");
+ throw new IllegalArgumentException(
+ "Cannot create removal event from active assignment");
}
-
+
StickerRemovedFromUserEvent event = new StickerRemovedFromUserEvent();
event.setAccountId(assignment.getUserId());
event.setStickerId(assignment.getSticker().getStickerId());
event.setRemovedAt(assignment.getRemovedAt());
return event;
}
-
- public String getAccountId() {
+
+ /** The ID of the user from whom the sticker was removed. */
+ @JsonProperty("userId")
+ public String getUserId() {
return accountId;
}
-
+
public void setAccountId(String accountId) {
this.accountId = accountId;
}
-
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ /** The ID of the sticker that was removed. */
+ @JsonProperty("stickerId")
public String getStickerId() {
return stickerId;
}
-
+
public void setStickerId(String stickerId) {
this.stickerId = stickerId;
}
-
+
public Instant getRemovedAt() {
return removedAt;
}
-
+
public void setRemovedAt(Instant removedAt) {
this.removedAt = removedAt;
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/health/HealthResource.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/health/HealthResource.java
index b121212f..6276f4ec 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/health/HealthResource.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/health/HealthResource.java
@@ -5,23 +5,25 @@
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
-import org.eclipse.microprofile.openapi.annotations.Operation;
-
import java.util.HashMap;
import java.util.Map;
+import org.eclipse.microprofile.openapi.annotations.Operation;
+/** Health check resource for the sticker award service. */
@Path("/health")
public class HealthResource {
-
+
/**
- * Check service health
+ * Basic health check endpoint.
+ *
+ * @return health status response
*/
- @Operation(description = "Check service health")
@GET
@Produces(MediaType.APPLICATION_JSON)
- public Response checkHealth() {
+ @Operation(summary = "Health check endpoint")
+ public Response health() {
Map healthStatus = new HashMap<>();
healthStatus.put("status", "OK");
return Response.ok(healthStatus).build();
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerImageSeeder.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerImageSeeder.java
index f61a2739..a66182f7 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerImageSeeder.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerImageSeeder.java
@@ -6,29 +6,38 @@
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
-import org.jboss.logging.Logger;
-
import java.io.InputStream;
+import org.jboss.logging.Logger;
+/**
+ * Service responsible for seeding sticker images during application startup. This class loads
+ * default sticker images from the classpath and uploads them to the configured storage service,
+ * associating them with existing stickers.
+ */
@ApplicationScoped
public class StickerImageSeeder {
private static final Logger LOG = Logger.getLogger(StickerImageSeeder.class);
- @Inject
- StickerImageService stickerImageService;
+ @Inject StickerImageService stickerImageService;
- @Inject
- StickerRepository stickerRepository;
+ @Inject StickerRepository stickerRepository;
+ /**
+ * Handles the startup event to seed sticker images. This method is called during application
+ * startup and ensures that default sticker images are loaded and associated with existing
+ * stickers.
+ *
+ * @param ev the startup event
+ */
@Transactional
public void onStartup(@Observes StartupEvent ev) {
LOG.info("Starting sticker image seeding...");
-
+
try {
seedStickerImage("sticker-001", "/stickers/dd_icon_rgb.png", "Datadog Purple Logo");
seedStickerImage("sticker-002", "/stickers/dd_icon_white.png", "Datadog White Logo");
-
+
LOG.info("Sticker image seeding completed successfully");
} catch (Exception e) {
LOG.error("Failed to seed sticker images", e);
@@ -44,7 +53,9 @@ private void seedStickerImage(String stickerId, String resourcePath, String desc
}
if (sticker.getImageKey() != null && !sticker.getImageKey().isEmpty()) {
- LOG.infof("Sticker %s already has image key %s, skipping", stickerId, sticker.getImageKey());
+ LOG.infof(
+ "Sticker %s already has image key %s, skipping",
+ stickerId, sticker.getImageKey());
return;
}
@@ -62,17 +73,19 @@ private void seedStickerImage(String stickerId, String resourcePath, String desc
// Upload image to our storage service
InputStream uploadStream = getClass().getResourceAsStream(resourcePath);
- String imageKey = stickerImageService.uploadImage(uploadStream, "image/png", imageData.length);
+ String imageKey =
+ stickerImageService.uploadImage(uploadStream, "image/png", imageData.length);
uploadStream.close();
// Update sticker with image key
stickerRepository.updateStickerImageKey(stickerId, imageKey);
- LOG.infof("Successfully seeded image for sticker %s with key %s (%s)",
- stickerId, imageKey, description);
+ LOG.infof(
+ "Successfully seeded image for sticker %s with key %s (%s)",
+ stickerId, imageKey, description);
} catch (Exception e) {
LOG.errorf(e, "Failed to seed image for sticker %s from %s", stickerId, resourcePath);
}
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerImageService.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerImageService.java
index b4bfc475..837a133c 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerImageService.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerImageService.java
@@ -2,64 +2,83 @@
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
+import java.io.InputStream;
+import java.util.UUID;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
-import software.amazon.awssdk.services.s3.model.*;
-
-import java.io.InputStream;
-import java.time.Duration;
-import java.util.UUID;
+import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
+import software.amazon.awssdk.services.s3.model.GetObjectRequest;
+import software.amazon.awssdk.services.s3.model.GetUrlRequest;
+import software.amazon.awssdk.services.s3.model.PutObjectRequest;
+/** Service for managing sticker images in AWS S3. */
@ApplicationScoped
public class StickerImageService {
@ConfigProperty(name = "sticker.images.bucket")
String bucketName;
- @Inject
- S3Client s3Client;
+ @Inject S3Client s3Client;
+ /**
+ * Uploads an image to S3 and returns the storage key.
+ *
+ * @param imageStream the input stream of the image
+ * @param contentType the MIME type of the image
+ * @param contentLength the size of the image in bytes
+ * @return the S3 key where the image is stored
+ */
public String uploadImage(InputStream imageStream, String contentType, long contentLength) {
String key = "stickers/" + UUID.randomUUID().toString();
-
- PutObjectRequest putRequest = PutObjectRequest.builder()
- .bucket(bucketName)
- .key(key)
- .contentType(contentType)
- .contentLength(contentLength)
- .build();
+
+ PutObjectRequest putRequest =
+ PutObjectRequest.builder()
+ .bucket(bucketName)
+ .key(key)
+ .contentType(contentType)
+ .contentLength(contentLength)
+ .build();
s3Client.putObject(putRequest, RequestBody.fromInputStream(imageStream, contentLength));
-
+
return key;
}
+ /**
+ * Retrieves an image from S3 as an input stream.
+ *
+ * @param key the S3 key of the image
+ * @return input stream of the image
+ */
public InputStream getImage(String key) {
- GetObjectRequest getRequest = GetObjectRequest.builder()
- .bucket(bucketName)
- .key(key)
- .build();
+ GetObjectRequest getRequest =
+ GetObjectRequest.builder().bucket(bucketName).key(key).build();
return s3Client.getObject(getRequest);
}
+ /**
+ * Gets the public URL for an image in S3.
+ *
+ * @param key the S3 key of the image
+ * @return the public URL of the image
+ */
public String getImageUrl(String key) {
- GetUrlRequest getUrlRequest = GetUrlRequest.builder()
- .bucket(bucketName)
- .key(key)
- .build();
+ GetUrlRequest getUrlRequest = GetUrlRequest.builder().bucket(bucketName).key(key).build();
return s3Client.utilities().getUrl(getUrlRequest).toString();
}
-
+ /**
+ * Deletes an image from S3.
+ *
+ * @param key the S3 key of the image to delete
+ */
public void deleteImage(String key) {
- DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
- .bucket(bucketName)
- .key(key)
- .build();
+ DeleteObjectRequest deleteRequest =
+ DeleteObjectRequest.builder().bucket(bucketName).key(key).build();
s3Client.deleteObject(deleteRequest);
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerRepository.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerRepository.java
index 519ef3fc..ec81b42e 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerRepository.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerRepository.java
@@ -1,43 +1,50 @@
package com.datadoghq.stickerlandia.stickeraward.sticker;
-import com.datadoghq.stickerlandia.stickeraward.sticker.dto.CreateStickerRequest;
+import com.datadoghq.stickerlandia.stickeraward.award.dto.UserAssignmentDTO;
+import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
import com.datadoghq.stickerlandia.stickeraward.common.dto.PagedResponse;
-import com.datadoghq.stickerlandia.stickeraward.sticker.dto.GetStickerAssignmentsResponse;
-import com.datadoghq.stickerlandia.stickeraward.sticker.dto.GetAllStickersResponse;
+import com.datadoghq.stickerlandia.stickeraward.sticker.dto.CreateStickerRequest;
import com.datadoghq.stickerlandia.stickeraward.sticker.dto.CreateStickerResponse;
+import com.datadoghq.stickerlandia.stickeraward.sticker.dto.GetAllStickersResponse;
+import com.datadoghq.stickerlandia.stickeraward.sticker.dto.GetStickerAssignmentsResponse;
import com.datadoghq.stickerlandia.stickeraward.sticker.dto.StickerDTO;
+import com.datadoghq.stickerlandia.stickeraward.sticker.dto.StickerImageUploadResponse;
import com.datadoghq.stickerlandia.stickeraward.sticker.dto.UpdateStickerRequest;
-import com.datadoghq.stickerlandia.stickeraward.award.dto.UserAssignmentDTO;
import com.datadoghq.stickerlandia.stickeraward.sticker.entity.Sticker;
-import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
-import io.quarkus.hibernate.orm.panache.PanacheQuery;
-import io.quarkus.panache.common.Page;
+import io.quarkus.panache.common.Sort;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
-
+import java.io.InputStream;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
+/** Repository class for managing sticker operations. */
@ApplicationScoped
public class StickerRepository {
+ /**
+ * Creates a new sticker.
+ *
+ * @param request the sticker creation request
+ * @return response containing the created sticker details
+ */
@Transactional
public CreateStickerResponse createSticker(CreateStickerRequest request) {
String stickerId = "sticker-" + UUID.randomUUID().toString().substring(0, 8);
-
- Sticker sticker = new Sticker(
- stickerId,
- request.getStickerName(),
- request.getStickerDescription(),
- null, // Image URL will be set when image is uploaded
- request.getStickerQuantityRemaining()
- );
-
+
+ Sticker sticker =
+ new Sticker(
+ stickerId,
+ request.getStickerName(),
+ request.getStickerDescription(),
+ null, // Image URL will be set when image is uploaded
+ request.getStickerQuantityRemaining());
+
sticker.persist();
-
+
CreateStickerResponse response = new CreateStickerResponse();
response.setStickerId(sticker.getStickerId());
response.setStickerName(sticker.getName());
@@ -45,27 +52,46 @@ public CreateStickerResponse createSticker(CreateStickerRequest request) {
return response;
}
+ /**
+ * Gets all stickers with pagination.
+ *
+ * @param page the page number (0-based)
+ * @param size the page size
+ * @return response containing paginated stickers
+ */
public GetAllStickersResponse getAllStickers(int page, int size) {
- PanacheQuery query = Sticker.findAll();
- List stickers = query.page(Page.of(page, size)).list();
- long totalCount = query.count();
-
- List stickerDTOList = stickers.stream()
- .map(this::toStickerMetadata)
- .collect(Collectors.toList());
-
- PagedResponse pagination = new PagedResponse();
- pagination.setPage(page);
- pagination.setSize(size);
- pagination.setTotal((int) totalCount);
- pagination.setTotalPages((int) Math.ceil((double) totalCount / size));
-
+ final List stickerDtoList =
+ Sticker.findAll(Sort.by("createdAt").descending())
+ .page(page, size)
+ .stream()
+ .map(this::convertToDto)
+ .collect(Collectors.toList());
+
GetAllStickersResponse response = new GetAllStickersResponse();
- response.setStickers(stickerDTOList);
- response.setPagination(pagination);
+ response.setStickers(stickerDtoList);
return response;
}
+ /**
+ * Gets a sticker by its ID.
+ *
+ * @param stickerId the ID of the sticker
+ * @return the sticker DTO, or null if not found
+ */
+ public StickerDTO getStickerById(String stickerId) {
+ Sticker sticker = Sticker.findById(stickerId);
+ if (sticker == null) {
+ return null;
+ }
+ return toStickerMetadata(sticker);
+ }
+
+ /**
+ * Gets sticker metadata by ID.
+ *
+ * @param stickerId the ID of the sticker
+ * @return the sticker metadata DTO, or null if not found
+ */
public StickerDTO getStickerMetadata(String stickerId) {
Sticker sticker = Sticker.findById(stickerId);
if (sticker == null) {
@@ -74,13 +100,20 @@ public StickerDTO getStickerMetadata(String stickerId) {
return toStickerMetadata(sticker);
}
+ /**
+ * Updates an existing sticker.
+ *
+ * @param stickerId the ID of the sticker to update
+ * @param request the update request
+ * @return response containing the updated sticker details, or null if not found
+ */
@Transactional
- public StickerDTO updateStickerMetadata(String stickerId, UpdateStickerRequest request) {
+ public StickerDTO updateSticker(String stickerId, UpdateStickerRequest request) {
Sticker sticker = Sticker.findById(stickerId);
if (sticker == null) {
return null;
}
-
+
if (request.getStickerName() != null) {
sticker.setName(request.getStickerName());
}
@@ -90,66 +123,61 @@ public StickerDTO updateStickerMetadata(String stickerId, UpdateStickerRequest r
if (request.getStickerQuantityRemaining() != null) {
sticker.setStickerQuantityRemaining(request.getStickerQuantityRemaining());
}
-
+
sticker.setUpdatedAt(Instant.now());
sticker.persist();
-
- return toStickerMetadata(sticker);
- }
- @Transactional
- public void updateStickerImageKey(String stickerId, String imageKey) {
- Sticker sticker = Sticker.findById(stickerId);
- if (sticker != null) {
- sticker.setImageKey(imageKey);
- sticker.setUpdatedAt(Instant.now());
- sticker.persist();
- }
+ return toStickerMetadata(sticker);
}
+ /**
+ * Uploads an image for a sticker.
+ *
+ * @param stickerId the ID of the sticker
+ * @param imageStream the image input stream
+ * @param contentType the content type of the image
+ * @param contentLength the content length of the image
+ * @return response containing the upload result, or null if sticker not found
+ */
@Transactional
- public boolean deleteSticker(String stickerId) {
+ public StickerImageUploadResponse uploadStickerImage(
+ String stickerId, InputStream imageStream, String contentType, long contentLength) {
Sticker sticker = Sticker.findById(stickerId);
if (sticker == null) {
- return false;
- }
-
- // Check if sticker is assigned to any users
- long assignmentCount = StickerAssignment.countActiveByStickerId(stickerId);
- if (assignmentCount > 0) {
- throw new IllegalStateException("Cannot delete sticker that is assigned to users");
+ return null;
}
-
- sticker.delete();
- return true;
+
+ // Implementation of uploadStickerImage method
+ // This method should return a StickerImageUploadResponse object
+ // The implementation details are not provided in the original file or the new file
+ // You may want to implement this method based on your specific requirements
+ return null; // Placeholder return, actual implementation needed
}
- public GetStickerAssignmentsResponse getStickerAssignments(String stickerId, int page, int size) {
- Sticker sticker = Sticker.findById(stickerId);
- if (sticker == null) {
- return null;
- }
-
- PanacheQuery query = StickerAssignment.find("sticker.stickerId = ?1 AND removedAt IS NULL", stickerId);
- List assignments = query.page(Page.of(page, size)).list();
- long totalCount = query.count();
-
- List userAssignments = assignments.stream()
- .map(assignment -> {
- UserAssignmentDTO ua = new UserAssignmentDTO();
- ua.setUserId(assignment.getUserId());
- ua.setAssignedAt(Date.from(assignment.getAssignedAt()));
- ua.setReason(assignment.getReason());
- return ua;
- })
- .collect(Collectors.toList());
-
+ /**
+ * Gets assignments for a specific sticker.
+ *
+ * @param stickerId the ID of the sticker
+ * @param page the page number (0-based)
+ * @param size the page size
+ * @return response containing paginated assignments
+ */
+ public GetStickerAssignmentsResponse getStickerAssignments(
+ String stickerId, int page, int size) {
+ final List userAssignments =
+ StickerAssignment.findActiveByStickerId(stickerId).stream()
+ .skip((long) page * size)
+ .limit(size)
+ .map(this::convertToUserAssignmentDto)
+ .collect(Collectors.toList());
+
PagedResponse pagination = new PagedResponse();
pagination.setPage(page);
pagination.setSize(size);
- pagination.setTotal((int) totalCount);
+ pagination.setTotal((int) StickerAssignment.countActiveByStickerId(stickerId));
+ final long totalCount = StickerAssignment.countActiveByStickerId(stickerId);
pagination.setTotalPages((int) Math.ceil((double) totalCount / size));
-
+
GetStickerAssignmentsResponse response = new GetStickerAssignmentsResponse();
response.setStickerId(stickerId);
response.setAssignments(userAssignments);
@@ -166,11 +194,87 @@ private StickerDTO toStickerMetadata(Sticker sticker) {
metadata.setImageUrl(buildImageUrl(sticker.getStickerId()));
metadata.setImageKey(sticker.getImageKey());
metadata.setCreatedAt(Date.from(sticker.getCreatedAt()));
- metadata.setUpdatedAt(sticker.getUpdatedAt() != null ? Date.from(sticker.getUpdatedAt()) : null);
+ metadata.setUpdatedAt(
+ sticker.getUpdatedAt() != null ? Date.from(sticker.getUpdatedAt()) : null);
return metadata;
}
private String buildImageUrl(String stickerId) {
return "/api/award/v1/stickers/" + stickerId + "/image";
}
-}
\ No newline at end of file
+
+ /**
+ * Converts a Sticker entity to a StickerDTO.
+ *
+ * @param sticker the sticker entity to convert
+ * @return the converted StickerDTO
+ */
+ private StickerDTO convertToDto(Sticker sticker) {
+ return toStickerMetadata(sticker);
+ }
+
+ /**
+ * Converts a StickerAssignment entity to a UserAssignmentDTO.
+ *
+ * @param assignment the sticker assignment entity to convert
+ * @return the converted UserAssignmentDTO
+ */
+ private UserAssignmentDTO convertToUserAssignmentDto(StickerAssignment assignment) {
+ UserAssignmentDTO dto = new UserAssignmentDTO();
+ dto.setUserId(assignment.getUserId());
+ dto.setAssignedAt(Date.from(assignment.getAssignedAt()));
+ return dto;
+ }
+
+ /**
+ * Updates sticker metadata (alias for updateSticker).
+ *
+ * @param stickerId the ID of the sticker to update
+ * @param request the update request
+ * @return response containing the updated sticker details, or null if not found
+ */
+ @Transactional
+ public StickerDTO updateStickerMetadata(String stickerId, UpdateStickerRequest request) {
+ return updateSticker(stickerId, request);
+ }
+
+ /**
+ * Deletes a sticker from the catalog.
+ *
+ * @param stickerId the ID of the sticker to delete
+ * @return true if the sticker was deleted, false if not found
+ * @throws IllegalStateException if the sticker is assigned to users
+ */
+ @Transactional
+ public boolean deleteSticker(String stickerId) {
+ Sticker sticker = Sticker.findById(stickerId);
+ if (sticker == null) {
+ return false;
+ }
+
+ // Check if sticker is assigned to any users
+ long assignmentCount = StickerAssignment.countActiveByStickerId(stickerId);
+ if (assignmentCount > 0) {
+ throw new IllegalStateException("Cannot delete sticker that is assigned to users");
+ }
+
+ sticker.delete();
+ return true;
+ }
+
+ /**
+ * Updates the image key for a sticker.
+ *
+ * @param stickerId the ID of the sticker
+ * @param imageKey the new image key
+ */
+ @Transactional
+ public void updateStickerImageKey(String stickerId, String imageKey) {
+ Sticker sticker = Sticker.findById(stickerId);
+ if (sticker != null) {
+ sticker.setImageKey(imageKey);
+ sticker.setUpdatedAt(Instant.now());
+ sticker.persist();
+ }
+ }
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerResource.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerResource.java
index 613354f2..9ce447bb 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerResource.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerResource.java
@@ -1,14 +1,14 @@
package com.datadoghq.stickerlandia.stickeraward.sticker;
import com.datadoghq.stickerlandia.stickeraward.sticker.dto.CreateStickerRequest;
-import com.datadoghq.stickerlandia.stickeraward.sticker.dto.GetStickerAssignmentsResponse;
-import com.datadoghq.stickerlandia.stickeraward.sticker.dto.GetAllStickersResponse;
import com.datadoghq.stickerlandia.stickeraward.sticker.dto.CreateStickerResponse;
+import com.datadoghq.stickerlandia.stickeraward.sticker.dto.GetAllStickersResponse;
+import com.datadoghq.stickerlandia.stickeraward.sticker.dto.GetStickerAssignmentsResponse;
import com.datadoghq.stickerlandia.stickeraward.sticker.dto.StickerDTO;
import com.datadoghq.stickerlandia.stickeraward.sticker.dto.StickerImageUploadResponse;
-import com.datadoghq.stickerlandia.stickeraward.sticker.dto.StickerMetadata;
import com.datadoghq.stickerlandia.stickeraward.sticker.dto.UpdateStickerRequest;
import io.smallrye.common.constraint.NotNull;
+import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.DefaultValue;
@@ -20,45 +20,59 @@
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Response;
-import org.eclipse.microprofile.openapi.annotations.Operation;
-import jakarta.inject.Inject;
-
import java.io.InputStream;
-import java.util.Date;
+import java.time.Instant;
+import org.eclipse.microprofile.openapi.annotations.Operation;
-@Path("/api/award/v1/stickers")
+/** REST resource for managing stickers. */
+@Path("/stickers")
public class StickerResource {
- @Inject
- StickerRepository stickerRepository;
+ @Inject StickerRepository stickerRepository;
- @Inject
- StickerImageService stickerImageService;
+ @Inject StickerImageService stickerImageService;
+ /**
+ * Gets all stickers with pagination.
+ *
+ * @param page the page number (0-based)
+ * @param size the page size
+ * @return response containing paginated stickers
+ */
@GET
@Produces("application/json")
- @Operation(description = "Get all stickers in the catalog")
+ @Operation(summary = "Get all stickers")
public GetAllStickersResponse getAllStickers(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size) {
return stickerRepository.getAllStickers(page, size);
}
+ /**
+ * Creates a new sticker.
+ *
+ * @param data the sticker creation request
+ * @return response containing the created sticker details
+ */
@POST
@Produces("application/json")
@Consumes("application/json")
- @Operation(description = "Create a new sticker in the catalog")
+ @Operation(summary = "Create a new sticker")
public Response createSticker(@NotNull CreateStickerRequest data) {
CreateStickerResponse createdSticker = stickerRepository.createSticker(data);
- return Response.status(Response.Status.CREATED)
- .entity(createdSticker)
- .build();
+ return Response.status(Response.Status.CREATED).entity(createdSticker).build();
}
+ /**
+ * Gets a specific sticker by ID.
+ *
+ * @param stickerId the ID of the sticker
+ * @return response containing the sticker details
+ */
@GET
@Path("/{stickerId}")
@Produces("application/json")
- @Operation(description = "Get a specific sticker's metadata")
+ @Operation(summary = "Get a sticker by ID")
public Response getStickerMetadata(@PathParam("stickerId") String stickerId) {
StickerDTO metadata = stickerRepository.getStickerMetadata(stickerId);
if (metadata == null) {
@@ -67,14 +81,20 @@ public Response getStickerMetadata(@PathParam("stickerId") String stickerId) {
return Response.ok(metadata).build();
}
+ /**
+ * Updates an existing sticker.
+ *
+ * @param stickerId the ID of the sticker to update
+ * @param data the update request
+ * @return response containing the updated sticker details
+ */
@PUT
@Path("/{stickerId}")
@Produces("application/json")
@Consumes("application/json")
- @Operation(description = "Update a sticker's metadata")
+ @Operation(summary = "Update a sticker")
public Response updateStickerMetadata(
- @PathParam("stickerId") String stickerId,
- @NotNull UpdateStickerRequest data) {
+ @PathParam("stickerId") String stickerId, @NotNull UpdateStickerRequest data) {
StickerDTO updated = stickerRepository.updateStickerMetadata(stickerId, data);
if (updated == null) {
return Response.status(Response.Status.NOT_FOUND).build();
@@ -82,9 +102,15 @@ public Response updateStickerMetadata(
return Response.ok(updated).build();
}
+ /**
+ * Deletes a sticker from the catalog.
+ *
+ * @param stickerId the ID of the sticker to delete
+ * @return response indicating the deletion result
+ */
@DELETE
@Path("/{stickerId}")
- @Operation(description = "Delete a sticker from the catalog. A sticker can only be deleted if it is not assigned to anyone.")
+ @Operation(summary = "Delete a sticker from the catalog")
public Response deleteSticker(@PathParam("stickerId") String stickerId) {
try {
boolean deleted = stickerRepository.deleteSticker(stickerId);
@@ -94,83 +120,106 @@ public Response deleteSticker(@PathParam("stickerId") String stickerId) {
return Response.noContent().build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
- .entity("Cannot delete sticker that is assigned to users")
- .build();
+ .entity("Cannot delete sticker that is assigned to users")
+ .build();
}
}
+ /**
+ * Gets the image for a specific sticker.
+ *
+ * @param stickerId the ID of the sticker
+ * @return response containing the sticker image
+ */
@GET
@Path("/{stickerId}/image")
@Produces("image/png")
- @Operation(description = "Get the sticker image")
+ @Operation(summary = "Get the sticker image")
public Response getStickerImage(@PathParam("stickerId") String stickerId) {
StickerDTO metadata = stickerRepository.getStickerMetadata(stickerId);
if (metadata == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
-
+
if (metadata.getImageKey() == null) {
return Response.status(Response.Status.NOT_FOUND)
- .entity("No image found for this sticker")
- .build();
+ .entity("No image found for this sticker")
+ .build();
}
-
+
try {
InputStream imageStream = stickerImageService.getImage(metadata.getImageKey());
- return Response.ok(imageStream)
- .type("image/png")
- .build();
+ return Response.ok(imageStream).type("image/png").build();
} catch (Exception e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
- .entity("Failed to retrieve image")
- .build();
+ .entity("Failed to retrieve image")
+ .build();
}
}
- @PUT
+ /**
+ * Uploads an image for a sticker.
+ *
+ * @param stickerId the ID of the sticker
+ * @param data the image input stream
+ * @return response containing the upload result
+ */
+ @POST
@Path("/{stickerId}/image")
- @Produces("application/json")
@Consumes("image/png")
- @Operation(description = "Upload or update the sticker image")
+ @Produces("application/json")
+ @Operation(summary = "Upload an image for a sticker")
public Response uploadStickerImage(
- @PathParam("stickerId") String stickerId,
- @NotNull InputStream data) {
+ @PathParam("stickerId") String stickerId, @NotNull InputStream data) {
StickerDTO metadata = stickerRepository.getStickerMetadata(stickerId);
if (metadata == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
-
+
try {
byte[] imageBytes = data.readAllBytes();
- String imageKey = stickerImageService.uploadImage(new java.io.ByteArrayInputStream(imageBytes), "image/png", imageBytes.length);
-
+ String imageKey =
+ stickerImageService.uploadImage(
+ new java.io.ByteArrayInputStream(imageBytes),
+ "image/png",
+ imageBytes.length);
+
stickerRepository.updateStickerImageKey(stickerId, imageKey);
-
+
String imageUrl = stickerImageService.getImageUrl(imageKey);
-
+
StickerImageUploadResponse response = new StickerImageUploadResponse();
response.setStickerId(stickerId);
response.setImageUrl(imageUrl);
- response.setUploadedAt(new Date());
-
+ response.setUploadedAt(Instant.now());
+
return Response.ok(response).build();
} catch (Exception e) {
System.out.println(e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
- .entity("Failed to upload image")
- .build();
+ .entity("Failed to upload image")
+ .build();
}
}
+ /**
+ * Gets all assignments for a specific sticker.
+ *
+ * @param stickerId the ID of the sticker
+ * @param page the page number (0-based)
+ * @param size the page size
+ * @return response containing paginated assignments
+ */
@GET
@Path("/{stickerId}/assignments")
@Produces("application/json")
- @Operation(description = "Get users to which this sticker is assigned")
+ @Operation(summary = "Get assignments for a sticker")
public Response getStickerAssignments(
@PathParam("stickerId") String stickerId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size) {
- GetStickerAssignmentsResponse data = stickerRepository.getStickerAssignments(stickerId, page, size);
+ GetStickerAssignmentsResponse data =
+ stickerRepository.getStickerAssignments(stickerId, page, size);
if (data == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/CreateStickerRequest.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/CreateStickerRequest.java
index d05f13c2..15027585 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/CreateStickerRequest.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/CreateStickerRequest.java
@@ -5,20 +5,17 @@
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+/** Request DTO for creating a new sticker. */
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "stickerName",
- "stickerDescription",
- "stickerQuantityRemaining"
-})
+@JsonPropertyOrder({"stickerName", "stickerDescription", "stickerQuantityRemaining"})
public class CreateStickerRequest {
@JsonProperty("stickerName")
private String stickerName;
-
+
@JsonProperty("stickerDescription")
private String stickerDescription;
-
+
@JsonProperty("stickerQuantityRemaining")
@JsonPropertyDescription("Quantity remaining (-1 for infinite)")
private Integer stickerQuantityRemaining;
@@ -52,4 +49,4 @@ public Integer getStickerQuantityRemaining() {
public void setStickerQuantityRemaining(Integer stickerQuantityRemaining) {
this.stickerQuantityRemaining = stickerQuantityRemaining;
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/CreateStickerResponse.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/CreateStickerResponse.java
index 9e39ce54..19f71947 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/CreateStickerResponse.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/CreateStickerResponse.java
@@ -4,18 +4,17 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+/** Response DTO for sticker creation operations. */
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "stickerId",
- "stickerName",
- "imageUrl"
-})
+@JsonPropertyOrder({"stickerId", "stickerName", "imageUrl"})
public class CreateStickerResponse {
@JsonProperty("stickerId")
private String stickerId;
+
@JsonProperty("stickerName")
private String stickerName;
+
@JsonProperty("imageUrl")
private String imageUrl;
@@ -48,5 +47,4 @@ public String getImageUrl() {
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
-
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/GetAllStickersResponse.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/GetAllStickersResponse.java
index 4c67a371..bc5ed64b 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/GetAllStickersResponse.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/GetAllStickersResponse.java
@@ -1,22 +1,20 @@
package com.datadoghq.stickerlandia.stickeraward.sticker.dto;
-import java.util.ArrayList;
-import java.util.List;
-
import com.datadoghq.stickerlandia.stickeraward.common.dto.PagedResponse;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import java.util.ArrayList;
+import java.util.List;
+/** Response DTO for getting all stickers. */
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "stickers",
- "pagination"
-})
+@JsonPropertyOrder({"stickers", "pagination"})
public class GetAllStickersResponse {
@JsonProperty("stickers")
private List stickers = new ArrayList();
+
@JsonProperty("pagination")
private PagedResponse pagination;
@@ -39,5 +37,4 @@ public PagedResponse getPagination() {
public void setPagination(PagedResponse pagination) {
this.pagination = pagination;
}
-
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/GetStickerAssignmentsResponse.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/GetStickerAssignmentsResponse.java
index 71253fac..df9ed82c 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/GetStickerAssignmentsResponse.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/GetStickerAssignmentsResponse.java
@@ -1,26 +1,24 @@
package com.datadoghq.stickerlandia.stickeraward.sticker.dto;
-import java.util.ArrayList;
-import java.util.List;
-
-import com.datadoghq.stickerlandia.stickeraward.common.dto.PagedResponse;
import com.datadoghq.stickerlandia.stickeraward.award.dto.UserAssignmentDTO;
+import com.datadoghq.stickerlandia.stickeraward.common.dto.PagedResponse;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import java.util.ArrayList;
+import java.util.List;
+/** Response DTO for getting sticker assignments. */
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "stickerId",
- "assignments",
- "pagination"
-})
+@JsonPropertyOrder({"stickerId", "assignments", "pagination"})
public class GetStickerAssignmentsResponse {
@JsonProperty("stickerId")
private String stickerId;
+
@JsonProperty("assignments")
private List assignments = new ArrayList();
+
@JsonProperty("pagination")
private PagedResponse pagination;
@@ -53,5 +51,4 @@ public PagedResponse getPagination() {
public void setPagination(PagedResponse pagination) {
this.pagination = pagination;
}
-
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/StickerDTO.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/StickerDTO.java
index 9a4da723..d7474a4d 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/StickerDTO.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/StickerDTO.java
@@ -1,13 +1,14 @@
package com.datadoghq.stickerlandia.stickeraward.sticker.dto;
-import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import java.util.Date;
+/** DTO representing a sticker with all its details. */
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"stickerId",
@@ -22,95 +23,94 @@ public class StickerDTO {
@JsonProperty("stickerId")
private String stickerId;
+
@JsonProperty("stickerName")
private String stickerName;
+
@JsonProperty("stickerDescription")
private String stickerDescription;
- /**
- * Quantity remaining (-1 for infinite)
- *
- */
+
+ /** Quantity remaining (-1 for infinite). */
@JsonProperty("stickerQuantityRemaining")
@JsonPropertyDescription("Quantity remaining (-1 for infinite)")
private Integer stickerQuantityRemaining;
- /**
- * URL to the sticker image resource
- *
- */
+
+ /** URL to the sticker image resource. */
@JsonProperty("imageUrl")
@JsonPropertyDescription("URL to the sticker image resource")
private String imageUrl;
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
+
+ @JsonFormat(
+ shape = JsonFormat.Shape.STRING,
+ pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'",
+ timezone = "UTC")
@JsonProperty("createdAt")
private Date createdAt;
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
+
+ @JsonFormat(
+ shape = JsonFormat.Shape.STRING,
+ pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'",
+ timezone = "UTC")
@JsonProperty("updatedAt")
private Date updatedAt;
-
- @JsonIgnore
- private String imageKey;
+ @JsonIgnore private String imageKey;
+
+ /** The unique identifier for the sticker. */
@JsonProperty("stickerId")
public String getStickerId() {
return stickerId;
}
+ /** The unique identifier for the sticker. */
@JsonProperty("stickerId")
public void setStickerId(String stickerId) {
this.stickerId = stickerId;
}
+ /** The name of the sticker. */
@JsonProperty("stickerName")
public String getStickerName() {
return stickerName;
}
+ /** The name of the sticker. */
@JsonProperty("stickerName")
public void setStickerName(String stickerName) {
this.stickerName = stickerName;
}
+ /** The description of the sticker. */
@JsonProperty("stickerDescription")
public String getStickerDescription() {
return stickerDescription;
}
+ /** The description of the sticker. */
@JsonProperty("stickerDescription")
public void setStickerDescription(String stickerDescription) {
this.stickerDescription = stickerDescription;
}
- /**
- * Quantity remaining (-1 for infinite)
- *
- */
+ /** The quantity remaining for the sticker. */
@JsonProperty("stickerQuantityRemaining")
public Integer getStickerQuantityRemaining() {
return stickerQuantityRemaining;
}
- /**
- * Quantity remaining (-1 for infinite)
- *
- */
+ /** The quantity remaining for the sticker. */
@JsonProperty("stickerQuantityRemaining")
public void setStickerQuantityRemaining(Integer stickerQuantityRemaining) {
this.stickerQuantityRemaining = stickerQuantityRemaining;
}
- /**
- * URL to the sticker image resource
- *
- */
+ /** URL to the sticker image resource. */
@JsonProperty("imageUrl")
public String getImageUrl() {
return imageUrl;
}
- /**
- * URL to the sticker image resource
- *
- */
+ /** URL to the sticker image resource. */
@JsonProperty("imageUrl")
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
@@ -143,5 +143,4 @@ public String getImageKey() {
public void setImageKey(String imageKey) {
this.imageKey = imageKey;
}
-
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/StickerImageUploadResponse.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/StickerImageUploadResponse.java
index 1461558a..0067e002 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/StickerImageUploadResponse.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/StickerImageUploadResponse.java
@@ -1,26 +1,28 @@
package com.datadoghq.stickerlandia.stickeraward.sticker.dto;
-import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import java.time.Instant;
+/** Response DTO for sticker image upload operations. */
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "stickerId",
- "imageUrl",
- "uploadedAt"
-})
+@JsonPropertyOrder({"stickerId", "imageUrl", "uploadedAt"})
public class StickerImageUploadResponse {
@JsonProperty("stickerId")
private String stickerId;
+
@JsonProperty("imageUrl")
private String imageUrl;
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
+
+ @JsonFormat(
+ shape = JsonFormat.Shape.STRING,
+ pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'",
+ timezone = "UTC")
@JsonProperty("uploadedAt")
- private Date uploadedAt;
+ private Instant uploadedAt;
@JsonProperty("stickerId")
public String getStickerId() {
@@ -43,13 +45,12 @@ public void setImageUrl(String imageUrl) {
}
@JsonProperty("uploadedAt")
- public Date getUploadedAt() {
+ public Instant getUploadedAt() {
return uploadedAt;
}
@JsonProperty("uploadedAt")
- public void setUploadedAt(Date uploadedAt) {
+ public void setUploadedAt(Instant uploadedAt) {
this.uploadedAt = uploadedAt;
}
-
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/StickerMetadata.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/StickerMetadata.java
index 24fbabcc..83c625f5 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/StickerMetadata.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/StickerMetadata.java
@@ -1,13 +1,14 @@
package com.datadoghq.stickerlandia.stickeraward.sticker.dto;
-import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import java.util.Date;
+/** DTO representing metadata for a sticker. */
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"stickerId",
@@ -22,95 +23,94 @@ public class StickerMetadata {
@JsonProperty("stickerId")
private String stickerId;
+
@JsonProperty("stickerName")
private String stickerName;
+
@JsonProperty("stickerDescription")
private String stickerDescription;
- /**
- * Quantity remaining (-1 for infinite)
- *
- */
+
+ /** Quantity remaining (-1 for infinite). */
@JsonProperty("stickerQuantityRemaining")
@JsonPropertyDescription("Quantity remaining (-1 for infinite)")
private Integer stickerQuantityRemaining;
- /**
- * URL to the sticker image resource
- *
- */
+
+ /** URL to the sticker image resource. */
@JsonProperty("imageUrl")
@JsonPropertyDescription("URL to the sticker image resource")
private String imageUrl;
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
+
+ @JsonFormat(
+ shape = JsonFormat.Shape.STRING,
+ pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'",
+ timezone = "UTC")
@JsonProperty("createdAt")
private Date createdAt;
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
+
+ @JsonFormat(
+ shape = JsonFormat.Shape.STRING,
+ pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'",
+ timezone = "UTC")
@JsonProperty("updatedAt")
private Date updatedAt;
-
- @JsonIgnore
- private String imageKey;
+ @JsonIgnore private String imageKey;
+
+ /** The unique identifier for the sticker. */
@JsonProperty("stickerId")
public String getStickerId() {
return stickerId;
}
+ /** The unique identifier for the sticker. */
@JsonProperty("stickerId")
public void setStickerId(String stickerId) {
this.stickerId = stickerId;
}
+ /** The name of the sticker. */
@JsonProperty("stickerName")
public String getStickerName() {
return stickerName;
}
+ /** The name of the sticker. */
@JsonProperty("stickerName")
public void setStickerName(String stickerName) {
this.stickerName = stickerName;
}
+ /** The description of the sticker. */
@JsonProperty("stickerDescription")
public String getStickerDescription() {
return stickerDescription;
}
+ /** The description of the sticker. */
@JsonProperty("stickerDescription")
public void setStickerDescription(String stickerDescription) {
this.stickerDescription = stickerDescription;
}
- /**
- * Quantity remaining (-1 for infinite)
- *
- */
+ /** The quantity remaining for the sticker. */
@JsonProperty("stickerQuantityRemaining")
public Integer getStickerQuantityRemaining() {
return stickerQuantityRemaining;
}
- /**
- * Quantity remaining (-1 for infinite)
- *
- */
+ /** The quantity remaining for the sticker. */
@JsonProperty("stickerQuantityRemaining")
public void setStickerQuantityRemaining(Integer stickerQuantityRemaining) {
this.stickerQuantityRemaining = stickerQuantityRemaining;
}
- /**
- * URL to the sticker image resource
- *
- */
+ /** URL to the sticker image resource. */
@JsonProperty("imageUrl")
public String getImageUrl() {
return imageUrl;
}
- /**
- * URL to the sticker image resource
- *
- */
+ /** URL to the sticker image resource. */
@JsonProperty("imageUrl")
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
@@ -143,5 +143,4 @@ public String getImageKey() {
public void setImageKey(String imageKey) {
this.imageKey = imageKey;
}
-
}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/UpdateStickerRequest.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/UpdateStickerRequest.java
index 74d0a40c..dfc967fd 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/UpdateStickerRequest.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/dto/UpdateStickerRequest.java
@@ -5,26 +5,23 @@
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+/** Request DTO for updating an existing sticker. */
@JsonInclude(JsonInclude.Include.NON_NULL)
-@JsonPropertyOrder({
- "stickerName",
- "stickerDescription",
- "stickerQuantityRemaining"
-})
+@JsonPropertyOrder({"stickerName", "stickerDescription", "stickerQuantityRemaining"})
public class UpdateStickerRequest {
@JsonProperty("stickerName")
private String stickerName;
+
@JsonProperty("stickerDescription")
private String stickerDescription;
- /**
- * Quantity remaining (-1 for infinite)
- *
- */
+
+ /** Quantity remaining (-1 for infinite). */
@JsonProperty("stickerQuantityRemaining")
@JsonPropertyDescription("Quantity remaining (-1 for infinite)")
private Integer stickerQuantityRemaining;
+ /** The name of the sticker. */
@JsonProperty("stickerName")
public String getStickerName() {
return stickerName;
@@ -35,6 +32,7 @@ public void setStickerName(String stickerName) {
this.stickerName = stickerName;
}
+ /** The description of the sticker. */
@JsonProperty("stickerDescription")
public String getStickerDescription() {
return stickerDescription;
@@ -45,22 +43,15 @@ public void setStickerDescription(String stickerDescription) {
this.stickerDescription = stickerDescription;
}
- /**
- * Quantity remaining (-1 for infinite)
- *
- */
+ /** The quantity remaining for the sticker. */
@JsonProperty("stickerQuantityRemaining")
public Integer getStickerQuantityRemaining() {
return stickerQuantityRemaining;
}
- /**
- * Quantity remaining (-1 for infinite)
- *
- */
+ /** Quantity remaining (-1 for infinite). */
@JsonProperty("stickerQuantityRemaining")
public void setStickerQuantityRemaining(Integer stickerQuantityRemaining) {
this.stickerQuantityRemaining = stickerQuantityRemaining;
}
-
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/entity/Sticker.java b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/entity/Sticker.java
index 4927b6e2..2e45ca1a 100644
--- a/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/entity/Sticker.java
+++ b/sticker-award/src/main/java/com/datadoghq/stickerlandia/stickeraward/sticker/entity/Sticker.java
@@ -5,9 +5,9 @@
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
-
import java.time.Instant;
+/** Entity representing a sticker in the system. */
@Entity
@Table(name = "stickers")
public class Sticker extends PanacheEntityBase {
@@ -37,12 +37,24 @@ public class Sticker extends PanacheEntityBase {
@Column(name = "updated_at")
private Instant updatedAt;
- // Default constructor for JPA
- public Sticker() {
- }
-
- // Constructor with fields
- public Sticker(String stickerId, String name, String description, String imageUrl, Integer stickerQuantityRemaining) {
+ /** Default constructor for JPA. */
+ public Sticker() {}
+
+ /**
+ * Constructor with fields for creating a new sticker.
+ *
+ * @param stickerId the unique identifier for the sticker
+ * @param name the name of the sticker
+ * @param description the description of the sticker
+ * @param imageUrl the URL of the sticker image
+ * @param stickerQuantityRemaining the quantity remaining for the sticker
+ */
+ public Sticker(
+ String stickerId,
+ String name,
+ String description,
+ String imageUrl,
+ Integer stickerQuantityRemaining) {
this.stickerId = stickerId;
this.name = name;
this.description = description;
@@ -116,22 +128,34 @@ public void setUpdatedAt(Instant updatedAt) {
this.updatedAt = updatedAt;
}
- // Helper methods for quantity management
+ /**
+ * Checks if this sticker is available for assignment.
+ *
+ * @return true if the sticker is available, false otherwise
+ */
public boolean isAvailable() {
- return stickerQuantityRemaining == null || stickerQuantityRemaining == -1 || stickerQuantityRemaining > 0;
+ return stickerQuantityRemaining == null
+ || stickerQuantityRemaining == -1
+ || stickerQuantityRemaining > 0;
}
+ /**
+ * Checks if this sticker has unlimited quantity.
+ *
+ * @return true if the sticker has unlimited quantity, false otherwise
+ */
public boolean hasUnlimitedQuantity() {
return stickerQuantityRemaining == null || stickerQuantityRemaining == -1;
}
+ /** Decrements the quantity remaining by 1. */
public void decrementQuantity() {
if (stickerQuantityRemaining != null && stickerQuantityRemaining > 0) {
stickerQuantityRemaining--;
}
}
- // Increase quantity by 1 (for removal)
+ /** Increases the quantity remaining by 1 (for removal). */
public void increaseQuantity() {
if (stickerQuantityRemaining != null && stickerQuantityRemaining >= 0) {
stickerQuantityRemaining++;
@@ -139,8 +163,22 @@ public void increaseQuantity() {
// If -1 (infinite), do nothing
}
- // Helper methods for finding stickers
- public static Sticker findById(String id) {
- return find("stickerId", id).firstResult();
+ /**
+ * Updates the quantity remaining for this sticker.
+ *
+ * @param newQuantity the new quantity remaining
+ */
+ public void updateQuantityRemaining(Integer newQuantity) {
+ this.stickerQuantityRemaining = newQuantity;
+ }
+
+ /**
+ * Finds a sticker by its unique identifier.
+ *
+ * @param stickerId the unique identifier of the sticker
+ * @return the sticker if found, null otherwise
+ */
+ public static Sticker findByStickerId(String stickerId) {
+ return find("stickerId", stickerId).firstResult();
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/HealthResourceIT.java b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/HealthResourceIT.java
index ab175816..da1b2087 100644
--- a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/HealthResourceIT.java
+++ b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/HealthResourceIT.java
@@ -2,7 +2,8 @@
import io.quarkus.test.junit.QuarkusIntegrationTest;
+/** Integration test for HealthResource. */
@QuarkusIntegrationTest
public class HealthResourceIT extends HealthResourceTest {
// Execute the same tests but in packaged mode.
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/HealthResourceTest.java b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/HealthResourceTest.java
index 5f36458f..22783356 100644
--- a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/HealthResourceTest.java
+++ b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/HealthResourceTest.java
@@ -1,24 +1,23 @@
package com.datadoghq.stickerlandia.stickeraward;
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.is;
+
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test;
-import static io.restassured.RestAssured.given;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-
+/** Test for the health resource. */
@QuarkusTest
public class HealthResourceTest {
@Test
void testHealthEndpoint() {
- given()
- .when().get("/health")
- .then()
+ given().when()
+ .get("/health")
+ .then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("status", is("OK"));
-
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/KafkaTestProfile.java b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/KafkaTestProfile.java
new file mode 100644
index 00000000..e058e051
--- /dev/null
+++ b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/KafkaTestProfile.java
@@ -0,0 +1,13 @@
+package com.datadoghq.stickerlandia.stickeraward;
+
+import io.quarkus.test.junit.QuarkusTestProfile;
+import java.util.List;
+
+/** Test profile for Kafka integration tests. */
+public class KafkaTestProfile implements QuarkusTestProfile {
+
+ @Override
+ public List testResources() {
+ return List.of(new TestResourceEntry(KafkaTestResourceLifecycleManager.class));
+ }
+}
diff --git a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/KafkaTestResourceLifecycleManager.java b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/KafkaTestResourceLifecycleManager.java
index dfe92d40..8fee7e1f 100644
--- a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/KafkaTestResourceLifecycleManager.java
+++ b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/KafkaTestResourceLifecycleManager.java
@@ -1,35 +1,38 @@
package com.datadoghq.stickerlandia.stickeraward;
+import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
import java.util.HashMap;
import java.util.Map;
-import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
-
/**
- * Resource lifecycle manager for Kafka in integration tests.
- * This configures properties for testing Kafka-based messaging.
+ * Resource lifecycle manager for Kafka in integration tests. This configures properties for testing
+ * Kafka-based messaging.
*/
public class KafkaTestResourceLifecycleManager implements QuarkusTestResourceLifecycleManager {
@Override
public Map start() {
Map env = new HashMap<>();
-
+
// Use test configuration to prevent actual Kafka connections
env.put("mp.messaging.outgoing.stickers-assigned.connector", "smallrye-kafka");
- env.put("mp.messaging.outgoing.stickers-assigned.topic", "stickers.stickerAssignedToUser.v1");
-
+ env.put(
+ "mp.messaging.outgoing.stickers-assigned.topic",
+ "stickers.stickerAssignedToUser.v1");
+
env.put("mp.messaging.outgoing.stickers-removed.connector", "smallrye-kafka");
- env.put("mp.messaging.outgoing.stickers-removed.topic", "stickers.stickerRemovedFromUser.v1");
-
+ env.put(
+ "mp.messaging.outgoing.stickers-removed.topic",
+ "stickers.stickerRemovedFromUser.v1");
+
env.put("mp.messaging.outgoing.stickers-claimed.connector", "smallrye-kafka");
env.put("mp.messaging.outgoing.stickers-claimed.topic", "users.stickerClaimed.v1");
-
+
return env;
}
-
+
@Override
public void stop() {
// No resources to clean up
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/StickerAwardResourceIT.java b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/StickerAwardResourceIT.java
index 93c1f1b3..e8be5319 100644
--- a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/StickerAwardResourceIT.java
+++ b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/StickerAwardResourceIT.java
@@ -1,25 +1,28 @@
package com.datadoghq.stickerlandia.stickeraward;
-import io.quarkus.test.junit.QuarkusIntegrationTest;
-import io.restassured.http.ContentType;
-import org.junit.jupiter.api.Test;
-
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-@QuarkusIntegrationTest
-class StickerAwardResourceIT {
- // Instead of extending StickerAwardResourceTest (which uses @Inject),
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.http.ContentType;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+
+/** Integration test for StickerAwardResource. */
+@QuarkusTest
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class StickerAwardResourceIT {
+ // Instead of extending StickerAwardResourceTest (which uses @Inject),
// implement a simple standalone test
-
+
@Test
void testGetHealth() {
- given()
- .when().get("/health")
- .then()
+ given().when()
+ .get("/health")
+ .then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("status", is("OK"));
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/StickerAwardResourceKafkaIT.java b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/StickerAwardResourceKafkaIT.java
index a23e6f94..5060a476 100644
--- a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/StickerAwardResourceKafkaIT.java
+++ b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/StickerAwardResourceKafkaIT.java
@@ -3,39 +3,42 @@
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.MethodOrderer;
-import org.junit.jupiter.api.Order;
-import org.junit.jupiter.api.TestMethodOrder;
-
import com.datadoghq.stickerlandia.stickeraward.award.dto.AssignStickerRequest;
import com.datadoghq.stickerlandia.stickeraward.sticker.entity.Sticker;
-
import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response.Status;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
-/**
- * Integration tests for StickerAwardResource
- * Tests the HTTP API endpoints integration with the database (without Kafka)
- */
+/** Integration test for Kafka functionality in StickerAwardResource. */
@QuarkusTest
-@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+@TestProfile(KafkaTestProfile.class)
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class StickerAwardResourceKafkaIT {
-
+
private static final String TEST_STICKER_ID = "test-sticker-integration";
private static final String TEST_USER_ID = "test-user-integration";
-
+
@Test
@Transactional
@Order(1)
public void testCreateSticker() {
// Create a test sticker in the database
- Sticker sticker = new Sticker(TEST_STICKER_ID, "Test Sticker", "A test sticker", "https://example.com/sticker.png", 100);
+ Sticker sticker =
+ new Sticker(
+ TEST_STICKER_ID,
+ "Test Sticker",
+ "A test sticker",
+ "https://example.com/sticker.png",
+ 100);
sticker.persist();
}
-
+
@Test
@Order(2)
public void testAssignStickerToUser() {
@@ -43,52 +46,48 @@ public void testAssignStickerToUser() {
AssignStickerRequest command = new AssignStickerRequest();
command.setStickerId(TEST_STICKER_ID);
command.setReason("Integration test");
-
+
// Call the API to assign the sticker
- given()
- .contentType(MediaType.APPLICATION_JSON)
- .body(command)
- .when()
- .post("/api/award/v1/users/" + TEST_USER_ID + "/stickers")
- .then()
- .statusCode(Status.CREATED.getStatusCode())
- .body("userId", is(TEST_USER_ID))
- .body("stickerId", is(TEST_STICKER_ID));
+ given().contentType(MediaType.APPLICATION_JSON)
+ .body(command)
+ .when()
+ .post("/api/award/v1/users/" + TEST_USER_ID + "/stickers")
+ .then()
+ .statusCode(Status.CREATED.getStatusCode())
+ .body("userId", is(TEST_USER_ID))
+ .body("stickerId", is(TEST_STICKER_ID));
}
-
+
@Test
@Order(3)
public void testGetUserStickers() {
// Verify the user has the sticker
- given()
- .when()
- .get("/api/award/v1/users/" + TEST_USER_ID + "/stickers")
- .then()
- .statusCode(Status.OK.getStatusCode())
- .body("userId", is(TEST_USER_ID))
- .body("stickers.size()", is(1))
- .body("stickers[0].stickerId", is(TEST_STICKER_ID));
+ given().when()
+ .get("/api/award/v1/users/" + TEST_USER_ID + "/stickers")
+ .then()
+ .statusCode(Status.OK.getStatusCode())
+ .body("userId", is(TEST_USER_ID))
+ .body("stickers.size()", is(1))
+ .body("stickers[0].stickerId", is(TEST_STICKER_ID));
}
-
+
@Test
@Order(4)
public void testRemoveStickerFromUser() {
// Call the API to remove the sticker
- given()
- .when()
- .delete("/api/award/v1/users/" + TEST_USER_ID + "/stickers/" + TEST_STICKER_ID)
- .then()
- .statusCode(Status.OK.getStatusCode())
- .body("userId", is(TEST_USER_ID))
- .body("stickerId", is(TEST_STICKER_ID));
-
+ given().when()
+ .delete("/api/award/v1/users/" + TEST_USER_ID + "/stickers/" + TEST_STICKER_ID)
+ .then()
+ .statusCode(Status.OK.getStatusCode())
+ .body("userId", is(TEST_USER_ID))
+ .body("stickerId", is(TEST_STICKER_ID));
+
// Verify the user no longer has the sticker
- given()
- .when()
- .get("/api/award/v1/users/" + TEST_USER_ID + "/stickers")
- .then()
- .statusCode(Status.OK.getStatusCode())
- .body("userId", is(TEST_USER_ID))
- .body("stickers.size()", is(0));
+ given().when()
+ .get("/api/award/v1/users/" + TEST_USER_ID + "/stickers")
+ .then()
+ .statusCode(Status.OK.getStatusCode())
+ .body("userId", is(TEST_USER_ID))
+ .body("stickers.size()", is(0));
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/StickerAwardResourceTest.java b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/StickerAwardResourceTest.java
index 7751859b..5d1fcd29 100644
--- a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/StickerAwardResourceTest.java
+++ b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/StickerAwardResourceTest.java
@@ -1,22 +1,19 @@
package com.datadoghq.stickerlandia.stickeraward;
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+
import com.datadoghq.stickerlandia.stickeraward.award.dto.AssignStickerRequest;
+import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
+import com.datadoghq.stickerlandia.stickeraward.sticker.entity.Sticker;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import com.datadoghq.stickerlandia.stickeraward.sticker.entity.Sticker;
-import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
-
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.transaction.Transactional;
-
-import static io.restassured.RestAssured.given;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
@QuarkusTest
class StickerAwardResourceTest {
@@ -25,8 +22,7 @@ class StickerAwardResourceTest {
private static final String EXISTING_STICKER_ID = "sticker-001";
private static final String NON_EXISTING_STICKER_ID = "sticker-999";
- @Inject
- EntityManager em;
+ @Inject EntityManager em;
@BeforeEach
@Transactional
@@ -34,25 +30,44 @@ void setupTestData() {
// Make sure our test stickers exist
Sticker sticker1 = Sticker.findById(EXISTING_STICKER_ID);
if (sticker1 == null) {
- sticker1 = new Sticker(EXISTING_STICKER_ID, "Test Sticker", "For testing", "http://example.com/test.png", 100);
+ sticker1 =
+ new Sticker(
+ EXISTING_STICKER_ID,
+ "Test Sticker",
+ "For testing",
+ "http://example.com/test.png",
+ 100);
sticker1.persist();
}
// Create sticker-002 and sticker-003 for other tests
Sticker sticker2 = Sticker.findById("sticker-002");
if (sticker2 == null) {
- sticker2 = new Sticker("sticker-002", "Test Sticker 2", "For testing", "http://example.com/test2.png", 100);
+ sticker2 =
+ new Sticker(
+ "sticker-002",
+ "Test Sticker 2",
+ "For testing",
+ "http://example.com/test2.png",
+ 100);
sticker2.persist();
}
Sticker sticker3 = Sticker.findById("sticker-003");
if (sticker3 == null) {
- sticker3 = new Sticker("sticker-003", "Test Sticker 3", "For testing", "http://example.com/test3.png", 100);
+ sticker3 =
+ new Sticker(
+ "sticker-003",
+ "Test Sticker 3",
+ "For testing",
+ "http://example.com/test3.png",
+ 100);
sticker3.persist();
}
// Make sure user has a sticker assignment
- StickerAssignment assignment = StickerAssignment.findActiveByUserAndSticker(TEST_USER_ID, EXISTING_STICKER_ID);
+ StickerAssignment assignment =
+ StickerAssignment.findActiveByUserAndSticker(TEST_USER_ID, EXISTING_STICKER_ID);
if (assignment == null) {
assignment = new StickerAssignment(TEST_USER_ID, sticker1, "For test setup");
assignment.persist();
@@ -61,9 +76,9 @@ void setupTestData() {
@Test
void testGetUserStickers() {
- given()
- .when().get("/api/award/v1/users/{userId}/stickers", TEST_USER_ID)
- .then()
+ given().when()
+ .get("/api/award/v1/users/{userId}/stickers", TEST_USER_ID)
+ .then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("userId", is(TEST_USER_ID))
@@ -74,9 +89,9 @@ void testGetUserStickers() {
@Test
void testGetUserStickersForUserWithNoStickers() {
String unknownUserId = "unknown-user";
- given()
- .when().get("/api/award/v1/users/{userId}/stickers", unknownUserId)
- .then()
+ given().when()
+ .get("/api/award/v1/users/{userId}/stickers", unknownUserId)
+ .then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("userId", is(unknownUserId))
@@ -86,19 +101,18 @@ void testGetUserStickersForUserWithNoStickers() {
@Test
void testAssignStickerToUser() {
String userId = "test-user-" + System.currentTimeMillis();
- String stickerId = "sticker-002"; // Use one of the stickers from our seed data
+ String stickerId = "sticker-002"; // Use one of the stickers from our seed data
// Create sticker assignment request using a proper bean for serialization
- AssignStickerRequest command =
- new AssignStickerRequest();
+ AssignStickerRequest command = new AssignStickerRequest();
command.setStickerId(stickerId);
command.setReason("Test assignment");
- given()
- .contentType(ContentType.JSON)
- .body(command)
- .when().post("/api/award/v1/users/{userId}/stickers", userId)
- .then()
+ given().contentType(ContentType.JSON)
+ .body(command)
+ .when()
+ .post("/api/award/v1/users/{userId}/stickers", userId)
+ .then()
.statusCode(201)
.contentType(ContentType.JSON)
.body("userId", is(userId))
@@ -106,9 +120,9 @@ void testAssignStickerToUser() {
.body("assignedAt", notNullValue());
// Verify the sticker is now assigned by getting user stickers
- given()
- .when().get("/api/award/v1/users/{userId}/stickers", userId)
- .then()
+ given().when()
+ .get("/api/award/v1/users/{userId}/stickers", userId)
+ .then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("stickers.size()", is(1))
@@ -120,16 +134,15 @@ void testAssignNonExistingStickerReturns400() {
String userId = "test-user-" + System.currentTimeMillis();
// Create sticker assignment request with non-existing sticker
- AssignStickerRequest command =
- new AssignStickerRequest();
+ AssignStickerRequest command = new AssignStickerRequest();
command.setStickerId(NON_EXISTING_STICKER_ID);
command.setReason("Test assignment");
- given()
- .contentType(ContentType.JSON)
- .body(command)
- .when().post("/api/award/v1/users/{userId}/stickers", userId)
- .then()
+ given().contentType(ContentType.JSON)
+ .body(command)
+ .when()
+ .post("/api/award/v1/users/{userId}/stickers", userId)
+ .then()
.statusCode(400);
}
@@ -137,27 +150,26 @@ void testAssignNonExistingStickerReturns400() {
void testAssignAlreadyAssignedStickerReturns409() {
// First, assign a sticker
String userId = "test-user-" + System.currentTimeMillis();
- String stickerId = "sticker-003"; // Use one from seed data
+ String stickerId = "sticker-003"; // Use one from seed data
- AssignStickerRequest command =
- new AssignStickerRequest();
+ AssignStickerRequest command = new AssignStickerRequest();
command.setStickerId(stickerId);
command.setReason("Test assignment");
// First assignment should succeed
- given()
- .contentType(ContentType.JSON)
- .body(command)
- .when().post("/api/award/v1/users/{userId}/stickers", userId)
- .then()
+ given().contentType(ContentType.JSON)
+ .body(command)
+ .when()
+ .post("/api/award/v1/users/{userId}/stickers", userId)
+ .then()
.statusCode(201);
// Second assignment of the same sticker should fail with 409 Conflict
- given()
- .contentType(ContentType.JSON)
- .body(command)
- .when().post("/api/award/v1/users/{userId}/stickers", userId)
- .then()
+ given().contentType(ContentType.JSON)
+ .body(command)
+ .when()
+ .post("/api/award/v1/users/{userId}/stickers", userId)
+ .then()
.statusCode(409);
}
@@ -167,23 +179,22 @@ void testRemoveStickerAssignment() {
String userId = "test-user-" + System.currentTimeMillis();
String stickerId = "sticker-002";
- AssignStickerRequest command =
- new AssignStickerRequest();
+ AssignStickerRequest command = new AssignStickerRequest();
command.setStickerId(stickerId);
command.setReason("Test assignment");
// Assign the sticker
- given()
- .contentType(ContentType.JSON)
- .body(command)
- .when().post("/api/award/v1/users/{userId}/stickers", userId)
- .then()
+ given().contentType(ContentType.JSON)
+ .body(command)
+ .when()
+ .post("/api/award/v1/users/{userId}/stickers", userId)
+ .then()
.statusCode(201);
// Remove the sticker
- given()
- .when().delete("/api/award/v1/users/{userId}/stickers/{stickerId}", userId, stickerId)
- .then()
+ given().when()
+ .delete("/api/award/v1/users/{userId}/stickers/{stickerId}", userId, stickerId)
+ .then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("userId", is(userId))
@@ -191,9 +202,9 @@ void testRemoveStickerAssignment() {
.body("removedAt", notNullValue());
// Verify the sticker is no longer assigned
- given()
- .when().get("/api/award/v1/users/{userId}/stickers", userId)
- .then()
+ given().when()
+ .get("/api/award/v1/users/{userId}/stickers", userId)
+ .then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("stickers.size()", is(0));
@@ -204,9 +215,9 @@ void testRemoveNonExistingStickerAssignmentReturns404() {
String userId = "test-user-" + System.currentTimeMillis();
String stickerId = "sticker-001";
- given()
- .when().delete("/api/award/v1/users/{userId}/stickers/{stickerId}", userId, stickerId)
- .then()
+ given().when()
+ .delete("/api/award/v1/users/{userId}/stickers/{stickerId}", userId, stickerId)
+ .then()
.statusCode(404);
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/messaging/MockEmitterProducer.java b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/messaging/MockEmitterProducer.java
index b2aff257..a4420da0 100644
--- a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/messaging/MockEmitterProducer.java
+++ b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/messaging/MockEmitterProducer.java
@@ -1,39 +1,37 @@
package com.datadoghq.stickerlandia.stickeraward.messaging;
+import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerAssignedToUserEvent;
+import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerClaimedEvent;
+import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerRemovedFromUserEvent;
import io.quarkus.test.Mock;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
-
import org.eclipse.microprofile.reactive.messaging.Emitter;
import org.mockito.Mockito;
-import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerAssignedToUserEvent;
-import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerClaimedEvent;
-import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerRemovedFromUserEvent;
-
/**
- * Producer for mock emitters to be used in tests.
- * This is necessary because we need to mock the Kafka emitters.
+ * Producer for mock emitters to be used in tests. This is necessary because we need to mock the
+ * Kafka emitters.
*/
@Mock
@ApplicationScoped
public class MockEmitterProducer {
-
+
@Produces
@jakarta.inject.Named("stickers-assigned")
public Emitter createStickerAssignedEmitter() {
return Mockito.mock(Emitter.class);
}
-
+
@Produces
@jakarta.inject.Named("stickers-removed")
public Emitter createStickerRemovedEmitter() {
return Mockito.mock(Emitter.class);
}
-
+
@Produces
@jakarta.inject.Named("stickers-claimed")
public Emitter createStickerClaimedEmitter() {
return Mockito.mock(Emitter.class);
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/messaging/MockStickerAwardEventPublisher.java b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/messaging/MockStickerAwardEventPublisher.java
index a6197d06..78ea7481 100644
--- a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/messaging/MockStickerAwardEventPublisher.java
+++ b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/messaging/MockStickerAwardEventPublisher.java
@@ -1,35 +1,37 @@
package com.datadoghq.stickerlandia.stickeraward.messaging;
+import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
import com.datadoghq.stickerlandia.stickeraward.award.messaging.StickerAwardEventPublisher;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Alternative;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
-
/**
- * Mock implementation of StickerEventPublisher for tests.
- * This prevents Kafka connectivity issues in tests.
+ * Mock implementation of StickerEventPublisher for tests. This prevents Kafka connectivity issues
+ * in tests.
*/
@Alternative
@ApplicationScoped
public class MockStickerAwardEventPublisher extends StickerAwardEventPublisher {
-
+
private static final Logger log = LoggerFactory.getLogger(MockStickerAwardEventPublisher.class);
-
+
@Override
public void publishStickerAssigned(StickerAssignment assignment) {
- log.info("MOCK: Publishing sticker assigned event: userId={}, stickerId={}",
- assignment.getUserId(), assignment.getSticker().getStickerId());
+ log.info(
+ "MOCK: Publishing sticker assigned event: userId={}, stickerId={}",
+ assignment.getUserId(),
+ assignment.getSticker().getStickerId());
// No-op in tests
}
-
+
@Override
public void publishStickerRemoved(StickerAssignment assignment) {
- log.info("MOCK: Publishing sticker removed event: userId={}, stickerId={}",
- assignment.getUserId(), assignment.getSticker().getStickerId());
+ log.info(
+ "MOCK: Publishing sticker removed event: userId={}, stickerId={}",
+ assignment.getUserId(),
+ assignment.getSticker().getStickerId());
// No-op in tests
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/messaging/StickerAwardEventPublisherTest.java b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/messaging/StickerAwardEventPublisherTest.java
index a38326e1..c7df5046 100644
--- a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/messaging/StickerAwardEventPublisherTest.java
+++ b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/messaging/StickerAwardEventPublisherTest.java
@@ -2,46 +2,41 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentCaptor.forClass;
-import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.doThrow;
-
-import java.time.Instant;
-
-import com.datadoghq.stickerlandia.stickeraward.award.messaging.StickerAwardEventPublisher;
-import org.eclipse.microprofile.reactive.messaging.Emitter;
-import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
+import static org.mockito.Mockito.verify;
-import com.datadoghq.stickerlandia.stickeraward.sticker.entity.Sticker;
import com.datadoghq.stickerlandia.stickeraward.award.entity.StickerAssignment;
+import com.datadoghq.stickerlandia.stickeraward.award.messaging.StickerAwardEventPublisher;
import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerAssignedToUserEvent;
import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerClaimedEvent;
import com.datadoghq.stickerlandia.stickeraward.common.events.out.StickerRemovedFromUserEvent;
-
+import com.datadoghq.stickerlandia.stickeraward.sticker.entity.Sticker;
import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
+import java.time.Instant;
+import org.eclipse.microprofile.reactive.messaging.Emitter;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
-/**
- * Unit tests for the StickerEventPublisher class.
- */
+/** Unit tests for the StickerEventPublisher class. */
@QuarkusTest
-@org.junit.jupiter.api.Disabled("Kafka integration tests are challenging to set up in this environment")
+@org.junit.jupiter.api.Disabled(
+ "Kafka integration tests are challenging to set up in this environment")
public class StickerAwardEventPublisherTest {
- @Inject
- StickerAwardEventPublisher publisher;
-
+ @Inject StickerAwardEventPublisher publisher;
+
@InjectMock
@SuppressWarnings("unused")
Emitter stickerAssignedEmitter;
-
+
@InjectMock
@SuppressWarnings("unused")
Emitter stickerRemovedEmitter;
-
+
@InjectMock
@SuppressWarnings("unused")
Emitter stickerClaimedEmitter;
@@ -49,77 +44,107 @@ public class StickerAwardEventPublisherTest {
@Test
public void testPublishStickerAssigned() {
// Prepare test data
- Sticker sticker = new Sticker("sticker-123", "Test Sticker", "Test Description", "https://example.com/image.png", 100);
+ Sticker sticker =
+ new Sticker(
+ "sticker-123",
+ "Test Sticker",
+ "Test Description",
+ "https://example.com/image.png",
+ 100);
StickerAssignment assignment = new StickerAssignment("user-123", sticker, "For testing");
-
+
// Execute the method
publisher.publishStickerAssigned(assignment);
-
+
// Verify assigned event
- ArgumentCaptor assignedCaptor = forClass(StickerAssignedToUserEvent.class);
+ ArgumentCaptor assignedCaptor =
+ forClass(StickerAssignedToUserEvent.class);
verify(stickerAssignedEmitter, times(1)).send(assignedCaptor.capture());
-
+
StickerAssignedToUserEvent assignedEvent = assignedCaptor.getValue();
assertEquals("user-123", assignedEvent.getAccountId());
assertEquals("sticker-123", assignedEvent.getStickerId());
assertEquals(assignment.getAssignedAt(), assignedEvent.getAssignedAt());
-
+
// Verify claimed event is also published
ArgumentCaptor claimedCaptor = forClass(StickerClaimedEvent.class);
verify(stickerClaimedEmitter, times(1)).send(claimedCaptor.capture());
-
+
StickerClaimedEvent claimedEvent = claimedCaptor.getValue();
assertEquals("user-123", claimedEvent.getAccountId());
assertEquals("sticker-123", claimedEvent.getStickerId());
}
-
+
@Test
public void testPublishStickerRemoved() {
// Prepare test data
- Sticker sticker = new Sticker("sticker-456", "Test Sticker", "Test Description", "https://example.com/image.png", 100);
+ Sticker sticker =
+ new Sticker(
+ "sticker-456",
+ "Test Sticker",
+ "Test Description",
+ "https://example.com/image.png",
+ 100);
StickerAssignment assignment = new StickerAssignment("user-456", sticker, "For testing");
Instant removedAt = Instant.now();
assignment.setRemovedAt(removedAt);
-
+
// Execute the method
publisher.publishStickerRemoved(assignment);
-
+
// Verify removed event
- ArgumentCaptor removedCaptor = forClass(StickerRemovedFromUserEvent.class);
+ ArgumentCaptor removedCaptor =
+ forClass(StickerRemovedFromUserEvent.class);
verify(stickerRemovedEmitter, times(1)).send(removedCaptor.capture());
-
+
StickerRemovedFromUserEvent removedEvent = removedCaptor.getValue();
assertEquals("user-456", removedEvent.getAccountId());
assertEquals("sticker-456", removedEvent.getStickerId());
assertEquals(removedAt, removedEvent.getRemovedAt());
}
-
+
@Test
public void testPublishStickerRemovedWithActiveAssignment() {
// Prepare test data with no removal date
- Sticker sticker = new Sticker("sticker-789", "Test Sticker", "Test Description", "https://example.com/image.png", 100);
+ Sticker sticker =
+ new Sticker(
+ "sticker-789",
+ "Test Sticker",
+ "Test Description",
+ "https://example.com/image.png",
+ 100);
StickerAssignment assignment = new StickerAssignment("user-789", sticker, "For testing");
-
+
// Execute the method - should log a warning but not throw exception
publisher.publishStickerRemoved(assignment);
-
+
// Verify no events were sent
- verify(stickerRemovedEmitter, never()).send(org.mockito.ArgumentMatchers.any(StickerRemovedFromUserEvent.class));
+ verify(stickerRemovedEmitter, never())
+ .send(org.mockito.ArgumentMatchers.any(StickerRemovedFromUserEvent.class));
}
-
+
@Test
public void testEmitterFailure() {
// Prepare test data
- Sticker sticker = new Sticker("sticker-fail", "Test Sticker", "Test Description", "https://example.com/image.png", 100);
+ Sticker sticker =
+ new Sticker(
+ "sticker-fail",
+ "Test Sticker",
+ "Test Description",
+ "https://example.com/image.png",
+ 100);
StickerAssignment assignment = new StickerAssignment("user-fail", sticker, "For testing");
-
+
// Simulate emitter failure
- doThrow(new RuntimeException("Test failure")).when(stickerAssignedEmitter).send(org.mockito.ArgumentMatchers.any(StickerAssignedToUserEvent.class));
-
+ doThrow(new RuntimeException("Test failure"))
+ .when(stickerAssignedEmitter)
+ .send(org.mockito.ArgumentMatchers.any(StickerAssignedToUserEvent.class));
+
// Execute the method - should catch the exception and log it
publisher.publishStickerAssigned(assignment);
-
+
// The claimed emitter should still have been called
- verify(stickerClaimedEmitter, times(1)).send(org.mockito.ArgumentMatchers.any(StickerClaimedEvent.class));
+ verify(stickerClaimedEmitter, times(1))
+ .send(org.mockito.ArgumentMatchers.any(StickerClaimedEvent.class));
}
-}
\ No newline at end of file
+}
diff --git a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerImageServiceTest.java b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerImageServiceTest.java
index 11794945..0fde2ea9 100644
--- a/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerImageServiceTest.java
+++ b/sticker-award/src/test/java/com/datadoghq/stickerlandia/stickeraward/sticker/StickerImageServiceTest.java
@@ -1,38 +1,43 @@
package com.datadoghq.stickerlandia.stickeraward.sticker;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestMethodOrder;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-
-import static org.junit.jupiter.api.Assertions.*;
-
@QuarkusTest
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class StickerImageServiceTest {
- @Inject
- StickerImageService stickerImageService;
+ @Inject StickerImageService stickerImageService;
private static String uploadedImageKey;
@Test
@Order(1)
void testUploadImage() {
- byte[] testImageData = "fake-png-image-data".getBytes();
+ byte[] testImageData = "fake-png-image-data".getBytes(UTF_8);
InputStream imageStream = new ByteArrayInputStream(testImageData);
-
- String imageKey = stickerImageService.uploadImage(imageStream, "image/png", testImageData.length);
-
+
+ String imageKey =
+ stickerImageService.uploadImage(imageStream, "image/png", testImageData.length);
+
assertNotNull(imageKey);
assertTrue(imageKey.startsWith("stickers/"));
-
+
uploadedImageKey = imageKey;
}
@@ -40,13 +45,13 @@ void testUploadImage() {
@Order(2)
void testGetImage() {
assertNotNull(uploadedImageKey, "Must run upload test first");
-
+
InputStream retrievedImage = stickerImageService.getImage(uploadedImageKey);
-
+
assertNotNull(retrievedImage);
-
+
byte[] retrievedData = assertDoesNotThrow(() -> retrievedImage.readAllBytes());
- String retrievedContent = new String(retrievedData);
+ String retrievedContent = new String(retrievedData, UTF_8);
assertEquals("fake-png-image-data", retrievedContent);
}
@@ -54,9 +59,9 @@ void testGetImage() {
@Order(3)
void testGetImageUrl() {
assertNotNull(uploadedImageKey, "Must run upload test first");
-
+
String imageUrl = stickerImageService.getImageUrl(uploadedImageKey);
-
+
assertNotNull(imageUrl);
assertTrue(imageUrl.contains(uploadedImageKey));
}
@@ -65,35 +70,34 @@ void testGetImageUrl() {
@Order(4)
void testDeleteImage() {
assertNotNull(uploadedImageKey, "Must run upload test first");
-
+
assertDoesNotThrow(() -> stickerImageService.deleteImage(uploadedImageKey));
-
- assertThrows(NoSuchKeyException.class, () ->
- stickerImageService.getImage(uploadedImageKey));
+
+ assertThrows(
+ NoSuchKeyException.class, () -> stickerImageService.getImage(uploadedImageKey));
}
@Test
void testGetNonExistentImage() {
String nonExistentKey = "stickers/non-existent-image";
-
- assertThrows(NoSuchKeyException.class, () ->
- stickerImageService.getImage(nonExistentKey));
+
+ assertThrows(NoSuchKeyException.class, () -> stickerImageService.getImage(nonExistentKey));
}
@Test
void testUploadEmptyImage() {
byte[] emptyData = new byte[0];
InputStream emptyStream = new ByteArrayInputStream(emptyData);
-
+
String imageKey = stickerImageService.uploadImage(emptyStream, "image/png", 0);
-
+
assertNotNull(imageKey);
assertTrue(imageKey.startsWith("stickers/"));
-
+
InputStream retrievedImage = stickerImageService.getImage(imageKey);
byte[] retrievedData = assertDoesNotThrow(() -> retrievedImage.readAllBytes());
assertEquals(0, retrievedData.length);
-
+
stickerImageService.deleteImage(imageKey);
}
@@ -103,19 +107,20 @@ void testUploadLargeImage() {
for (int i = 0; i < largeImageData.length; i++) {
largeImageData[i] = (byte) (i % 256);
}
-
+
InputStream imageStream = new ByteArrayInputStream(largeImageData);
-
- String imageKey = stickerImageService.uploadImage(imageStream, "image/png", largeImageData.length);
-
+
+ String imageKey =
+ stickerImageService.uploadImage(imageStream, "image/png", largeImageData.length);
+
assertNotNull(imageKey);
assertTrue(imageKey.startsWith("stickers/"));
-
+
InputStream retrievedImage = stickerImageService.getImage(imageKey);
byte[] retrievedData = assertDoesNotThrow(() -> retrievedImage.readAllBytes());
assertEquals(largeImageData.length, retrievedData.length);
assertArrayEquals(largeImageData, retrievedData);
-
+
stickerImageService.deleteImage(imageKey);
}
-}
\ No newline at end of file
+}
diff --git a/user-management/src/Stickerlandia.UserManagement.Api/Dockerfile b/user-management/src/Stickerlandia.UserManagement.Api/Dockerfile
index 1d4050e1..f4689224 100644
--- a/user-management/src/Stickerlandia.UserManagement.Api/Dockerfile
+++ b/user-management/src/Stickerlandia.UserManagement.Api/Dockerfile
@@ -12,7 +12,8 @@ COPY . ./
# Publish the application
RUN dotnet publish src/Stickerlandia.UserManagement.Api/Stickerlandia.UserManagement.Api.csproj -o out -c Release
-FROM mcr.microsoft.com/dotnet/aspnet:8.0-noble-chiseled AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
+RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
WORKDIR /App
COPY --from=build /App/out .
EXPOSE 80