diff --git a/README.md b/README.md
index 4be947f3..497f9d37 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,7 @@ This repo contains the sample for [Keploy's](https://keploy.io) Java Application
5. [Springboot PetClinic](https://github.com/keploy/samples-java/tree/main/spring-petclinic) - This is a Pet Clinic app where you can record testcases and mocks by interacting with the UI, and then test them using Keploy.
6. [SAP Demo (Customer 360)](https://github.com/keploy/samples-java/tree/main/sap-demo-java) - A Spring Boot "Customer 360" API that fronts SAP S/4HANA Cloud (Business Partner + Sales Order OData) and a local PostgreSQL store. Includes docker-compose, a kind-based k8s deploy, and Tosca-style flow scripts suitable for recording end-to-end Keploy testcases against PostgreSQL + outbound SAP HTTPS.
7. [Java Dynamic Deduplication](https://github.com/keploy/samples-java/tree/main/java-dedup) - A Spring Boot sample used by CI to validate Enterprise Java dynamic dedup in native, Docker, and restricted Docker replay runs. CI uses checked-in fixtures and does not record this sample in the pipeline.
+8. [Dropwizard Dynamic Deduplication](https://github.com/keploy/samples-java/tree/main/dropwizard-dedup) - A Dropwizard/Jersey sample used by Enterprise CI to validate that Java dynamic dedup works outside Spring Boot with the runtime Java agent, checked-in HTTP fixtures, native launch, classpath launch, Docker, distroless, and restricted Docker.
## Community Support ❤️
diff --git a/dropwizard-dedup/.dockerignore b/dropwizard-dedup/.dockerignore
new file mode 100644
index 00000000..5cc92828
--- /dev/null
+++ b/dropwizard-dedup/.dockerignore
@@ -0,0 +1,13 @@
+target/*
+!target/dropwizard-dedup-0.0.1-SNAPSHOT.jar
+!target/keploy-sdk.jar
+!target/jacocoagent.jar
+!target/classes/
+!target/classes/**
+!target/dependency/
+!target/dependency/**
+keploy/reports
+dedupData.yaml
+duplicates.yaml
+replay-*.log
+dedup-*.log
diff --git a/dropwizard-dedup/.gitignore b/dropwizard-dedup/.gitignore
new file mode 100644
index 00000000..eea631b8
--- /dev/null
+++ b/dropwizard-dedup/.gitignore
@@ -0,0 +1,3 @@
+/target/
+/*.log
+/META-INF/
diff --git a/dropwizard-dedup/Dockerfile b/dropwizard-dedup/Dockerfile
new file mode 100644
index 00000000..f6ee75da
--- /dev/null
+++ b/dropwizard-dedup/Dockerfile
@@ -0,0 +1,15 @@
+ARG JAVA_VERSION=8
+FROM eclipse-temurin:${JAVA_VERSION}-jre
+
+WORKDIR /app
+
+RUN groupadd --gid 10001 appuser \
+ && useradd --uid 10001 --gid 10001 --home-dir /home/appuser --create-home --shell /usr/sbin/nologin appuser
+
+COPY --chown=10001:10001 target/dropwizard-dedup.jar /app/app.jar
+COPY --chown=10001:10001 target/keploy-sdk.jar /app/keploy-sdk.jar
+COPY --chown=10001:10001 target/jacocoagent.jar /app/jacocoagent.jar
+COPY --chown=10001:10001 config.yml /app/config.yml
+EXPOSE 8080
+USER 10001:10001
+ENTRYPOINT ["java", "-javaagent:/app/keploy-sdk.jar", "-javaagent:/app/jacocoagent.jar=destfile=/tmp/jacoco.exec", "-jar", "/app/app.jar", "server", "/app/config.yml"]
diff --git a/dropwizard-dedup/Dockerfile.classpath b/dropwizard-dedup/Dockerfile.classpath
new file mode 100644
index 00000000..0e26748d
--- /dev/null
+++ b/dropwizard-dedup/Dockerfile.classpath
@@ -0,0 +1,19 @@
+ARG JAVA_VERSION=8
+FROM eclipse-temurin:${JAVA_VERSION}-jre
+
+WORKDIR /app
+
+RUN groupadd --gid 10001 appuser \
+ && useradd --uid 10001 --gid 10001 --home-dir /home/appuser --create-home --shell /usr/sbin/nologin appuser
+
+COPY --chown=10001:10001 target/classes /app/classes
+COPY --chown=10001:10001 target/dependency /app/libs
+COPY --chown=10001:10001 target/keploy-sdk.jar /app/keploy-sdk.jar
+COPY --chown=10001:10001 target/jacocoagent.jar /app/jacocoagent.jar
+COPY --chown=10001:10001 config.yml /app/config.yml
+
+ENV KEPLOY_JAVA_CLASS_DIRS=/app/classes
+
+EXPOSE 8080
+USER 10001:10001
+ENTRYPOINT ["java", "-javaagent:/app/keploy-sdk.jar", "-javaagent:/app/jacocoagent.jar=destfile=/tmp/jacoco.exec", "-cp", "/app/classes:/app/libs/*", "io.keploy.samples.dropwizarddedup.DropwizardDedupApplication", "server", "/app/config.yml"]
diff --git a/dropwizard-dedup/Dockerfile.distroless b/dropwizard-dedup/Dockerfile.distroless
new file mode 100644
index 00000000..d65aa067
--- /dev/null
+++ b/dropwizard-dedup/Dockerfile.distroless
@@ -0,0 +1,11 @@
+FROM gcr.io/distroless/java17-debian12:nonroot
+WORKDIR /app
+
+COPY --chown=10001:10001 target/dropwizard-dedup.jar /app/app.jar
+COPY --chown=10001:10001 target/keploy-sdk.jar /app/keploy-sdk.jar
+COPY --chown=10001:10001 target/jacocoagent.jar /app/jacocoagent.jar
+COPY --chown=10001:10001 config.yml /app/config.yml
+
+EXPOSE 8080
+USER 10001:10001
+ENTRYPOINT ["java", "-javaagent:/app/keploy-sdk.jar", "-javaagent:/app/jacocoagent.jar=destfile=/tmp/jacoco.exec", "-jar", "/app/app.jar", "server", "/app/config.yml"]
diff --git a/dropwizard-dedup/README.md b/dropwizard-dedup/README.md
new file mode 100644
index 00000000..24fec41e
--- /dev/null
+++ b/dropwizard-dedup/README.md
@@ -0,0 +1,26 @@
+# Dropwizard Dynamic Deduplication Sample
+
+This sample validates that Keploy Java dynamic deduplication works for a non-Spring Java service. The app is a Dropwizard/Jersey HTTP service and does not import or depend on the Keploy SDK at compile time.
+
+CI does not record this sample. The `keploy/` directory contains checked-in fixtures, so Enterprise CI only builds the app and runs replay with `--dedup`. When the sample behavior changes, record the fixtures locally and push the updated `keploy/` files.
+
+Build without Keploy on the compile classpath:
+
+```bash
+mvn -B -DskipTests clean package
+```
+
+Build with the runtime Java agent copied into `target/keploy-sdk.jar`:
+
+```bash
+mvn -B -DskipTests -Dkeploy.agent.version=2.0.2 clean package
+```
+
+Run with the agent:
+
+```bash
+java \
+ -javaagent:target/keploy-sdk.jar \
+ -javaagent:target/jacocoagent.jar=destfile=/tmp/jacoco.exec \
+ -jar target/dropwizard-dedup.jar server config.yml
+```
diff --git a/dropwizard-dedup/config.yml b/dropwizard-dedup/config.yml
new file mode 100644
index 00000000..540bcebc
--- /dev/null
+++ b/dropwizard-dedup/config.yml
@@ -0,0 +1,12 @@
+server:
+ applicationConnectors:
+ - type: http
+ port: ${DW_HTTP_PORT:-8080}
+ adminConnectors:
+ - type: http
+ port: ${DW_ADMIN_PORT:-8081}
+
+logging:
+ level: WARN
+ appenders:
+ - type: console
diff --git a/dropwizard-dedup/docker-compose.classpath.yml b/dropwizard-dedup/docker-compose.classpath.yml
new file mode 100644
index 00000000..6c2b31c9
--- /dev/null
+++ b/dropwizard-dedup/docker-compose.classpath.yml
@@ -0,0 +1,4 @@
+services:
+ dropwizard-dedup:
+ build:
+ dockerfile: Dockerfile.classpath
diff --git a/dropwizard-dedup/docker-compose.distroless.yml b/dropwizard-dedup/docker-compose.distroless.yml
new file mode 100644
index 00000000..42cf8edb
--- /dev/null
+++ b/dropwizard-dedup/docker-compose.distroless.yml
@@ -0,0 +1,4 @@
+services:
+ dropwizard-dedup:
+ build:
+ dockerfile: Dockerfile.distroless
diff --git a/dropwizard-dedup/docker-compose.restricted.yml b/dropwizard-dedup/docker-compose.restricted.yml
new file mode 100644
index 00000000..4db205be
--- /dev/null
+++ b/dropwizard-dedup/docker-compose.restricted.yml
@@ -0,0 +1,7 @@
+services:
+ dropwizard-dedup:
+ read_only: true
+ cap_drop:
+ - ALL
+ security_opt:
+ - no-new-privileges:true
diff --git a/dropwizard-dedup/docker-compose.yml b/dropwizard-dedup/docker-compose.yml
new file mode 100644
index 00000000..f39df96e
--- /dev/null
+++ b/dropwizard-dedup/docker-compose.yml
@@ -0,0 +1,13 @@
+services:
+ dropwizard-dedup:
+ image: ${JAVA_DEDUP_IMAGE:-dropwizard-dedup:local}
+ build:
+ context: .
+ dockerfile: Dockerfile
+ args:
+ JAVA_VERSION: ${JAVA_VERSION:-8}
+ environment:
+ KEPLOY_JAVA_DEDUP_DIAGNOSTICS: ${KEPLOY_JAVA_DEDUP_DIAGNOSTICS:-}
+ container_name: dedup-java
+ ports:
+ - "${JAVA_DEDUP_HOST_PORT:-8080}:8080"
diff --git a/dropwizard-dedup/keploy.yml b/dropwizard-dedup/keploy.yml
new file mode 100644
index 00000000..c756c59c
--- /dev/null
+++ b/dropwizard-dedup/keploy.yml
@@ -0,0 +1,91 @@
+# Generated by Keploy (3-dev)
+path: ""
+appId: 0
+appName: ""
+command: ""
+templatize:
+ testSets: []
+port: 0
+proxyPort: 16789
+incomingProxyPort: 36789
+dnsPort: 26789
+debug: false
+disableANSI: false
+disableTele: false
+generateGithubActions: false
+containerName: ""
+networkName: ""
+buildDelay: 30
+test:
+ selectedTests: {}
+ ignoredTests: {}
+ globalNoise:
+ global: {}
+ test-sets: {}
+ replaceWith:
+ global: {}
+ test-sets: {}
+ delay: 5
+ host: "localhost"
+ port: 0
+ grpcPort: 0
+ ssePort: 0
+ protocol:
+ http:
+ port: 0
+ sse:
+ port: 0
+ grpc:
+ port: 0
+ apiTimeout: 5
+ skipCoverage: false
+ coverageReportPath: ""
+ ignoreOrdering: true
+ mongoPassword: "default@123"
+ language: ""
+ removeUnusedMocks: false
+ fallBackOnMiss: false
+ jacocoAgentPath: ""
+ basePath: ""
+ mocking: true
+ disableLineCoverage: false
+ disableMockUpload: false
+ useLocalMock: false
+ updateTemplate: false
+ mustPass: false
+ maxFailAttempts: 5
+ maxFlakyChecks: 1
+ protoFile: ""
+ protoDir: ""
+ protoInclude: []
+ compareAll: false
+ updateTestMapping: false
+ disableAutoHeaderNoise: false
+ strictMockWindow: true
+ dedup: false
+ freezeTime: false
+ fuzzyMatch: false
+record:
+ recordTimer: 0s
+ filters: []
+ sync: false
+ memoryLimit: 0
+configPath: ""
+bypassRules: []
+disableMapping: true
+contract:
+ driven: "consumer"
+ mappings:
+ servicesMapping: {}
+ self: "s1"
+ services: []
+ tests: []
+ path: ""
+ download: false
+ generate: false
+inCi: false
+cmdType: "native"
+enableTesting: false
+inDocker: false
+keployContainer: "keploy-v3"
+keployNetwork: "keploy-network"
diff --git a/java-dedup/keploy/test-set-0/tests/test-161.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-1.yaml
similarity index 75%
rename from java-dedup/keploy/test-set-0/tests/test-161.yaml
rename to dropwizard-dedup/keploy/test-set-0/tests/test-1.yaml
index 641ff73e..c4b0e3b0 100644
--- a/java-dedup/keploy/test-set-0/tests/test-161.yaml
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-1.yaml
@@ -1,7 +1,7 @@
# Generated by Keploy (3-dev)
version: api.keploy.io/v1beta1
kind: Http
-name: test-161
+name: test-1
spec:
metadata: {}
req:
@@ -14,26 +14,27 @@ spec:
Host: 127.0.0.1:8080
User-Agent: curl/8.19.0
body: ""
- timestamp: 2026-04-24T12:48:16.9818066+05:30
+ timestamp: 2026-04-30T04:48:59Z
resp:
status_code: 200
header:
Content-Type: application/json
- Date: Fri, 24 Apr 2026 07:18:16 GMT
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
body: '{"healthy":true}'
status_message: OK
proto_major: 0
proto_minor: 0
- timestamp: 2026-04-24T12:48:16.984289985+05:30
+ timestamp: 2026-04-30T04:48:59Z
objects: []
assertions:
noise:
header.Date: []
- created: 1777015096
+ header.Vary: []
+ created: 1777524539
app_port: 8080
curl: |
curl --request GET \
--url http://127.0.0.1:8080/healthz \
- --header 'User-Agent: curl/8.19.0' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
+ --header 'User-Agent: curl/8.19.0'
diff --git a/dropwizard-dedup/keploy/test-set-0/tests/test-10.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-10.yaml
new file mode 100644
index 00000000..4bd626c5
--- /dev/null
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-10.yaml
@@ -0,0 +1,40 @@
+# Generated by Keploy (3-dev)
+version: api.keploy.io/v1beta1
+kind: Http
+name: test-10
+spec:
+ metadata: {}
+ req:
+ method: PUT
+ proto_major: 1
+ proto_minor: 1
+ url: http://127.0.0.1:8080/orders/ORD-42
+ header:
+ Accept: '*/*'
+ Content-Type: application/json
+ Host: 127.0.0.1:8080
+ User-Agent: curl/8.19.0
+ body: '{"status":"shipped"}'
+ timestamp: 2026-04-30T04:48:59Z
+ resp:
+ status_code: 200
+ header:
+ Content-Type: application/json
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"orderId":"ORD-42","status":"shipped","updated":true}'
+ status_message: OK
+ proto_major: 0
+ proto_minor: 0
+ timestamp: 2026-04-30T04:48:59Z
+ objects: []
+ assertions:
+ noise:
+ header.Date: []
+ header.Vary: []
+ created: 1777524539
+ app_port: 8080
+curl: |
+ curl --request PUT \
+ --url http://127.0.0.1:8080/orders/ORD-42 \
+ --header 'Content-Type: application/json' \
+ --data '{"status":"shipped"}'
diff --git a/java-dedup/keploy/test-set-0/tests/test-251.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-11.yaml
similarity index 62%
rename from java-dedup/keploy/test-set-0/tests/test-251.yaml
rename to dropwizard-dedup/keploy/test-set-0/tests/test-11.yaml
index 5ebff6fc..de51c8d4 100644
--- a/java-dedup/keploy/test-set-0/tests/test-251.yaml
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-11.yaml
@@ -1,39 +1,40 @@
# Generated by Keploy (3-dev)
version: api.keploy.io/v1beta1
kind: Http
-name: test-251
+name: test-11
spec:
metadata: {}
req:
- method: GET
+ method: DELETE
proto_major: 1
proto_minor: 1
- url: http://127.0.0.1:8080/everything
+ url: http://127.0.0.1:8080/orders/ORD-42
header:
Accept: '*/*'
Host: 127.0.0.1:8080
User-Agent: curl/8.19.0
body: ""
- timestamp: 2026-04-24T12:48:18.003518256+05:30
+ timestamp: 2026-04-30T04:48:59Z
resp:
status_code: 200
header:
Content-Type: application/json
- Date: Fri, 24 Apr 2026 07:18:17 GMT
- body: '{"message":"Everything"}'
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"orderId":"ORD-42","deleted":true}'
status_message: OK
proto_major: 0
proto_minor: 0
- timestamp: 2026-04-24T12:48:18.005594789+05:30
+ timestamp: 2026-04-30T04:48:59Z
objects: []
assertions:
noise:
header.Date: []
- created: 1777015098
+ header.Vary: []
+ created: 1777524539
app_port: 8080
curl: |
- curl --request GET \
- --url http://127.0.0.1:8080/everything \
- --header 'User-Agent: curl/8.19.0' \
+ curl --request DELETE \
+ --url http://127.0.0.1:8080/orders/ORD-42 \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
+ --header 'User-Agent: curl/8.19.0'
diff --git a/java-dedup/keploy/test-set-0/tests/test-105.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-12.yaml
similarity index 57%
rename from java-dedup/keploy/test-set-0/tests/test-105.yaml
rename to dropwizard-dedup/keploy/test-set-0/tests/test-12.yaml
index 07b5ecfc..ea23727b 100644
--- a/java-dedup/keploy/test-set-0/tests/test-105.yaml
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-12.yaml
@@ -1,39 +1,40 @@
# Generated by Keploy (3-dev)
version: api.keploy.io/v1beta1
kind: Http
-name: test-105
+name: test-12
spec:
metadata: {}
req:
method: GET
proto_major: 1
proto_minor: 1
- url: http://127.0.0.1:8080/info
+ url: http://127.0.0.1:8080/files/reports/2026/q1.csv?download=true
header:
Accept: '*/*'
Host: 127.0.0.1:8080
User-Agent: curl/8.19.0
body: ""
- timestamp: 2026-04-24T12:48:16.354841905+05:30
+ timestamp: 2026-04-30T04:48:59Z
resp:
status_code: 200
header:
Content-Type: application/json
- Date: Fri, 24 Apr 2026 07:18:16 GMT
- body: '{"version":"1.0.2","author":"Keploy"}'
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"requested_file":"/reports/2026/q1.csv","download":true}'
status_message: OK
proto_major: 0
proto_minor: 0
- timestamp: 2026-04-24T12:48:16.357237035+05:30
+ timestamp: 2026-04-30T04:48:59Z
objects: []
assertions:
noise:
header.Date: []
- created: 1777015096
+ header.Vary: []
+ created: 1777524539
app_port: 8080
curl: |
curl --request GET \
- --url http://127.0.0.1:8080/info \
+ --url 'http://127.0.0.1:8080/files/reports/2026/q1.csv?download=true' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
- --header 'User-Agent: curl/8.19.0' \
+ --header 'User-Agent: curl/8.19.0'
diff --git a/dropwizard-dedup/keploy/test-set-0/tests/test-13.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-13.yaml
new file mode 100644
index 00000000..73ff3a84
--- /dev/null
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-13.yaml
@@ -0,0 +1,41 @@
+# Generated by Keploy (3-dev)
+version: api.keploy.io/v1beta1
+kind: Http
+name: test-13
+spec:
+ metadata: {}
+ req:
+ method: GET
+ proto_major: 1
+ proto_minor: 1
+ url: http://127.0.0.1:8080/headers
+ header:
+ Accept: '*/*'
+ Host: 127.0.0.1:8080
+ User-Agent: curl/8.19.0
+ X-Request-Id: req-123
+ X-Tenant: flipkart
+ body: ""
+ timestamp: 2026-04-30T04:48:59Z
+ resp:
+ status_code: 200
+ header:
+ Content-Type: application/json
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"tenant":"flipkart","requestId":"req-123"}'
+ status_message: OK
+ proto_major: 0
+ proto_minor: 0
+ timestamp: 2026-04-30T04:48:59Z
+ objects: []
+ assertions:
+ noise:
+ header.Date: []
+ header.Vary: []
+ created: 1777524539
+ app_port: 8080
+curl: |
+ curl --request GET \
+ --url http://127.0.0.1:8080/headers \
+ --header 'X-Tenant: flipkart' \
+ --header 'X-Request-Id: req-123'
diff --git a/java-dedup/keploy/test-set-0/tests/test-102.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-14.yaml
similarity index 58%
rename from java-dedup/keploy/test-set-0/tests/test-102.yaml
rename to dropwizard-dedup/keploy/test-set-0/tests/test-14.yaml
index ec18140b..bd4816ce 100644
--- a/java-dedup/keploy/test-set-0/tests/test-102.yaml
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-14.yaml
@@ -1,39 +1,40 @@
# Generated by Keploy (3-dev)
version: api.keploy.io/v1beta1
kind: Http
-name: test-102
+name: test-14
spec:
metadata: {}
req:
method: GET
proto_major: 1
proto_minor: 1
- url: http://127.0.0.1:8080/anybody
+ url: http://127.0.0.1:8080/platform/routes/us-east/az1
header:
Accept: '*/*'
Host: 127.0.0.1:8080
User-Agent: curl/8.19.0
body: ""
- timestamp: 2026-04-24T12:48:16.322102113+05:30
+ timestamp: 2026-04-30T04:48:59Z
resp:
status_code: 200
header:
Content-Type: application/json
- Date: Fri, 24 Apr 2026 07:18:16 GMT
- body: '{"message":"Anybody"}'
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"region":"us-east","zone":"az1","target":"us-east-az1-api"}'
status_message: OK
proto_major: 0
proto_minor: 0
- timestamp: 2026-04-24T12:48:16.324511112+05:30
+ timestamp: 2026-04-30T04:48:59Z
objects: []
assertions:
noise:
header.Date: []
- created: 1777015096
+ header.Vary: []
+ created: 1777524539
app_port: 8080
curl: |
curl --request GET \
- --url http://127.0.0.1:8080/anybody \
+ --url http://127.0.0.1:8080/platform/routes/us-east/az1 \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
- --header 'User-Agent: curl/8.19.0' \
+ --header 'User-Agent: curl/8.19.0'
diff --git a/java-dedup/keploy/test-set-0/tests/test-103.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-15.yaml
similarity index 58%
rename from java-dedup/keploy/test-set-0/tests/test-103.yaml
rename to dropwizard-dedup/keploy/test-set-0/tests/test-15.yaml
index 4c8546b8..e1e92e97 100644
--- a/java-dedup/keploy/test-set-0/tests/test-103.yaml
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-15.yaml
@@ -1,39 +1,40 @@
# Generated by Keploy (3-dev)
version: api.keploy.io/v1beta1
kind: Http
-name: test-103
+name: test-15
spec:
metadata: {}
req:
method: GET
proto_major: 1
proto_minor: 1
- url: http://127.0.0.1:8080/noone
+ url: http://127.0.0.1:8080/platform/content/html
header:
Accept: '*/*'
Host: 127.0.0.1:8080
User-Agent: curl/8.19.0
body: ""
- timestamp: 2026-04-24T12:48:16.333013067+05:30
+ timestamp: 2026-04-30T04:48:59Z
resp:
status_code: 200
header:
- Content-Type: application/json
- Date: Fri, 24 Apr 2026 07:18:16 GMT
- body: '{"message":"No one"}'
+ Content-Type: text/html
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '
dropwizard
'
status_message: OK
proto_major: 0
proto_minor: 0
- timestamp: 2026-04-24T12:48:16.335524182+05:30
+ timestamp: 2026-04-30T04:48:59Z
objects: []
assertions:
noise:
header.Date: []
- created: 1777015096
+ header.Vary: []
+ created: 1777524539
app_port: 8080
curl: |
curl --request GET \
- --url http://127.0.0.1:8080/noone \
+ --url http://127.0.0.1:8080/platform/content/html \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
- --header 'User-Agent: curl/8.19.0' \
+ --header 'User-Agent: curl/8.19.0'
diff --git a/dropwizard-dedup/keploy/test-set-0/tests/test-16.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-16.yaml
new file mode 100644
index 00000000..64a1f78b
--- /dev/null
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-16.yaml
@@ -0,0 +1,40 @@
+# Generated by Keploy (3-dev)
+version: api.keploy.io/v1beta1
+kind: Http
+name: test-16
+spec:
+ metadata: {}
+ req:
+ method: GET
+ proto_major: 1
+ proto_minor: 1
+ url: http://127.0.0.1:8080/catalog/MISSING
+ header:
+ Accept: '*/*'
+ Host: 127.0.0.1:8080
+ User-Agent: curl/8.19.0
+ body: ""
+ timestamp: 2026-04-30T04:48:59Z
+ resp:
+ status_code: 404
+ header:
+ Content-Type: application/json
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"error":"not_found","status":404}'
+ status_message: Not Found
+ proto_major: 0
+ proto_minor: 0
+ timestamp: 2026-04-30T04:48:59Z
+ objects: []
+ assertions:
+ noise:
+ header.Date: []
+ header.Vary: []
+ created: 1777524539
+ app_port: 8080
+curl: |
+ curl --request GET \
+ --url http://127.0.0.1:8080/catalog/MISSING \
+ --header 'Accept: */*' \
+ --header 'Host: 127.0.0.1:8080' \
+ --header 'User-Agent: curl/8.19.0'
diff --git a/dropwizard-dedup/keploy/test-set-0/tests/test-2.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-2.yaml
new file mode 100644
index 00000000..efdcd8d0
--- /dev/null
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-2.yaml
@@ -0,0 +1,40 @@
+# Generated by Keploy (3-dev)
+version: api.keploy.io/v1beta1
+kind: Http
+name: test-2
+spec:
+ metadata: {}
+ req:
+ method: GET
+ proto_major: 1
+ proto_minor: 1
+ url: http://127.0.0.1:8080/catalog?category=books&limit=2
+ header:
+ Accept: '*/*'
+ Host: 127.0.0.1:8080
+ User-Agent: curl/8.19.0
+ body: ""
+ timestamp: 2026-04-30T04:48:59Z
+ resp:
+ status_code: 200
+ header:
+ Content-Type: application/json
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"category":"books","limit":2,"items":[{"sku":"BK-1","name":"Clean Architecture","category":"books","status":"available","price":"32.50"},{"sku":"BK-2","name":"Effective Java","category":"books","status":"available","price":"45.00"}],"source":"warehouse-a"}'
+ status_message: OK
+ proto_major: 0
+ proto_minor: 0
+ timestamp: 2026-04-30T04:48:59Z
+ objects: []
+ assertions:
+ noise:
+ header.Date: []
+ header.Vary: []
+ created: 1777524539
+ app_port: 8080
+curl: |
+ curl --request GET \
+ --url 'http://127.0.0.1:8080/catalog?category=books&limit=2' \
+ --header 'Accept: */*' \
+ --header 'Host: 127.0.0.1:8080' \
+ --header 'User-Agent: curl/8.19.0'
diff --git a/dropwizard-dedup/keploy/test-set-0/tests/test-3.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-3.yaml
new file mode 100644
index 00000000..3b8329f5
--- /dev/null
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-3.yaml
@@ -0,0 +1,40 @@
+# Generated by Keploy (3-dev)
+version: api.keploy.io/v1beta1
+kind: Http
+name: test-3
+spec:
+ metadata: {}
+ req:
+ method: GET
+ proto_major: 1
+ proto_minor: 1
+ url: http://127.0.0.1:8080/catalog?category=electronics&limit=1
+ header:
+ Accept: '*/*'
+ Host: 127.0.0.1:8080
+ User-Agent: curl/8.19.0
+ body: ""
+ timestamp: 2026-04-30T04:48:59Z
+ resp:
+ status_code: 200
+ header:
+ Content-Type: application/json
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"category":"electronics","limit":1,"items":[{"sku":"EL-1","name":"Noise Cancelling Headphones","category":"electronics","status":"backorder","price":"199.99"}],"source":"warehouse-b"}'
+ status_message: OK
+ proto_major: 0
+ proto_minor: 0
+ timestamp: 2026-04-30T04:48:59Z
+ objects: []
+ assertions:
+ noise:
+ header.Date: []
+ header.Vary: []
+ created: 1777524539
+ app_port: 8080
+curl: |
+ curl --request GET \
+ --url 'http://127.0.0.1:8080/catalog?category=electronics&limit=1' \
+ --header 'Accept: */*' \
+ --header 'Host: 127.0.0.1:8080' \
+ --header 'User-Agent: curl/8.19.0'
diff --git a/java-dedup/keploy/test-set-0/tests/test-106.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-4.yaml
similarity index 58%
rename from java-dedup/keploy/test-set-0/tests/test-106.yaml
rename to dropwizard-dedup/keploy/test-set-0/tests/test-4.yaml
index 78f7a984..09ab199a 100644
--- a/java-dedup/keploy/test-set-0/tests/test-106.yaml
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-4.yaml
@@ -1,39 +1,40 @@
# Generated by Keploy (3-dev)
version: api.keploy.io/v1beta1
kind: Http
-name: test-106
+name: test-4
spec:
metadata: {}
req:
method: GET
proto_major: 1
proto_minor: 1
- url: http://127.0.0.1:8080/proxy
+ url: http://127.0.0.1:8080/catalog/BK-1
header:
Accept: '*/*'
Host: 127.0.0.1:8080
User-Agent: curl/8.19.0
body: ""
- timestamp: 2026-04-24T12:48:16.365291128+05:30
+ timestamp: 2026-04-30T04:48:59Z
resp:
status_code: 200
header:
Content-Type: application/json
- Date: Fri, 24 Apr 2026 07:18:16 GMT
- body: '{"forwarding_to":"downstream-service"}'
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"sku":"BK-1","name":"Clean Architecture","category":"books","status":"available","price":"32.50"}'
status_message: OK
proto_major: 0
proto_minor: 0
- timestamp: 2026-04-24T12:48:16.367623521+05:30
+ timestamp: 2026-04-30T04:48:59Z
objects: []
assertions:
noise:
header.Date: []
- created: 1777015096
+ header.Vary: []
+ created: 1777524539
app_port: 8080
curl: |
curl --request GET \
- --url http://127.0.0.1:8080/proxy \
- --header 'User-Agent: curl/8.19.0' \
+ --url http://127.0.0.1:8080/catalog/BK-1 \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
+ --header 'User-Agent: curl/8.19.0'
diff --git a/dropwizard-dedup/keploy/test-set-0/tests/test-5.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-5.yaml
new file mode 100644
index 00000000..3c21108d
--- /dev/null
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-5.yaml
@@ -0,0 +1,40 @@
+# Generated by Keploy (3-dev)
+version: api.keploy.io/v1beta1
+kind: Http
+name: test-5
+spec:
+ metadata: {}
+ req:
+ method: GET
+ proto_major: 1
+ proto_minor: 1
+ url: http://127.0.0.1:8080/search?term=phone&sort=price
+ header:
+ Accept: '*/*'
+ Host: 127.0.0.1:8080
+ User-Agent: curl/8.19.0
+ body: ""
+ timestamp: 2026-04-30T04:48:59Z
+ resp:
+ status_code: 200
+ header:
+ Content-Type: application/json
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"term":"phone","sort":"price","ranking":"discount-first","hits":[{"sku":"EL-1","name":"Noise Cancelling Headphones","category":"electronics","status":"backorder","price":"199.99"},{"sku":"BK-1","name":"Clean Architecture","category":"books","status":"available","price":"32.50"}]}'
+ status_message: OK
+ proto_major: 0
+ proto_minor: 0
+ timestamp: 2026-04-30T04:48:59Z
+ objects: []
+ assertions:
+ noise:
+ header.Date: []
+ header.Vary: []
+ created: 1777524539
+ app_port: 8080
+curl: |
+ curl --request GET \
+ --url 'http://127.0.0.1:8080/search?term=phone&sort=price' \
+ --header 'Accept: */*' \
+ --header 'Host: 127.0.0.1:8080' \
+ --header 'User-Agent: curl/8.19.0'
diff --git a/dropwizard-dedup/keploy/test-set-0/tests/test-6.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-6.yaml
new file mode 100644
index 00000000..0dde8163
--- /dev/null
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-6.yaml
@@ -0,0 +1,40 @@
+# Generated by Keploy (3-dev)
+version: api.keploy.io/v1beta1
+kind: Http
+name: test-6
+spec:
+ metadata: {}
+ req:
+ method: GET
+ proto_major: 1
+ proto_minor: 1
+ url: http://127.0.0.1:8080/search?term=phone&sort=relevance
+ header:
+ Accept: '*/*'
+ Host: 127.0.0.1:8080
+ User-Agent: curl/8.19.0
+ body: ""
+ timestamp: 2026-04-30T04:48:59Z
+ resp:
+ status_code: 200
+ header:
+ Content-Type: application/json
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"term":"phone","sort":"relevance","ranking":"relevance-first","hits":[{"sku":"EL-1","name":"Noise Cancelling Headphones","category":"electronics","status":"backorder","price":"199.99"},{"sku":"BK-1","name":"Clean Architecture","category":"books","status":"available","price":"32.50"}]}'
+ status_message: OK
+ proto_major: 0
+ proto_minor: 0
+ timestamp: 2026-04-30T04:48:59Z
+ objects: []
+ assertions:
+ noise:
+ header.Date: []
+ header.Vary: []
+ created: 1777524539
+ app_port: 8080
+curl: |
+ curl --request GET \
+ --url 'http://127.0.0.1:8080/search?term=phone&sort=relevance' \
+ --header 'Accept: */*' \
+ --header 'Host: 127.0.0.1:8080' \
+ --header 'User-Agent: curl/8.19.0'
diff --git a/dropwizard-dedup/keploy/test-set-0/tests/test-7.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-7.yaml
new file mode 100644
index 00000000..dabcb77b
--- /dev/null
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-7.yaml
@@ -0,0 +1,40 @@
+# Generated by Keploy (3-dev)
+version: api.keploy.io/v1beta1
+kind: Http
+name: test-7
+spec:
+ metadata: {}
+ req:
+ method: POST
+ proto_major: 1
+ proto_minor: 1
+ url: http://127.0.0.1:8080/orders
+ header:
+ Accept: '*/*'
+ Content-Type: application/json
+ Host: 127.0.0.1:8080
+ User-Agent: curl/8.19.0
+ body: '{"customer":"ashish","sku":"BK-1","quantity":2,"priority":false}'
+ timestamp: 2026-04-30T04:48:59Z
+ resp:
+ status_code: 201
+ header:
+ Content-Type: application/json
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"orderId":"ORD-STANDARD","customer":"ashish","sku":"BK-1","quantity":2,"priority":false,"route":"ground","checks":["inventory","pricing","standard"]}'
+ status_message: Created
+ proto_major: 0
+ proto_minor: 0
+ timestamp: 2026-04-30T04:48:59Z
+ objects: []
+ assertions:
+ noise:
+ header.Date: []
+ header.Vary: []
+ created: 1777524539
+ app_port: 8080
+curl: |
+ curl --request POST \
+ --url http://127.0.0.1:8080/orders \
+ --header 'Content-Type: application/json' \
+ --data '{"customer":"ashish","sku":"BK-1","quantity":2,"priority":false}'
diff --git a/dropwizard-dedup/keploy/test-set-0/tests/test-8.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-8.yaml
new file mode 100644
index 00000000..5ce2ae60
--- /dev/null
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-8.yaml
@@ -0,0 +1,40 @@
+# Generated by Keploy (3-dev)
+version: api.keploy.io/v1beta1
+kind: Http
+name: test-8
+spec:
+ metadata: {}
+ req:
+ method: POST
+ proto_major: 1
+ proto_minor: 1
+ url: http://127.0.0.1:8080/orders
+ header:
+ Accept: '*/*'
+ Content-Type: application/json
+ Host: 127.0.0.1:8080
+ User-Agent: curl/8.19.0
+ body: '{"customer":"flipkart","sku":"EL-1","quantity":1,"priority":true}'
+ timestamp: 2026-04-30T04:48:59Z
+ resp:
+ status_code: 201
+ header:
+ Content-Type: application/json
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"orderId":"ORD-PRIORITY","customer":"flipkart","sku":"EL-1","quantity":1,"priority":true,"route":"air","checks":["inventory","pricing","expedite"]}'
+ status_message: Created
+ proto_major: 0
+ proto_minor: 0
+ timestamp: 2026-04-30T04:48:59Z
+ objects: []
+ assertions:
+ noise:
+ header.Date: []
+ header.Vary: []
+ created: 1777524539
+ app_port: 8080
+curl: |
+ curl --request POST \
+ --url http://127.0.0.1:8080/orders \
+ --header 'Content-Type: application/json' \
+ --data '{"customer":"flipkart","sku":"EL-1","quantity":1,"priority":true}'
diff --git a/dropwizard-dedup/keploy/test-set-0/tests/test-9.yaml b/dropwizard-dedup/keploy/test-set-0/tests/test-9.yaml
new file mode 100644
index 00000000..1a4619ae
--- /dev/null
+++ b/dropwizard-dedup/keploy/test-set-0/tests/test-9.yaml
@@ -0,0 +1,40 @@
+# Generated by Keploy (3-dev)
+version: api.keploy.io/v1beta1
+kind: Http
+name: test-9
+spec:
+ metadata: {}
+ req:
+ method: GET
+ proto_major: 1
+ proto_minor: 1
+ url: http://127.0.0.1:8080/orders/ORD-42?expand=true
+ header:
+ Accept: '*/*'
+ Host: 127.0.0.1:8080
+ User-Agent: curl/8.19.0
+ body: ""
+ timestamp: 2026-04-30T04:48:59Z
+ resp:
+ status_code: 200
+ header:
+ Content-Type: application/json
+ Date: Thu, 30 Apr 2026 04:48:59 GMT
+ body: '{"orderId":"ORD-42","status":"packed","expand":true,"audit":["created","paid","packed"]}'
+ status_message: OK
+ proto_major: 0
+ proto_minor: 0
+ timestamp: 2026-04-30T04:48:59Z
+ objects: []
+ assertions:
+ noise:
+ header.Date: []
+ header.Vary: []
+ created: 1777524539
+ app_port: 8080
+curl: |
+ curl --request GET \
+ --url 'http://127.0.0.1:8080/orders/ORD-42?expand=true' \
+ --header 'Accept: */*' \
+ --header 'Host: 127.0.0.1:8080' \
+ --header 'User-Agent: curl/8.19.0'
diff --git a/dropwizard-dedup/pom.xml b/dropwizard-dedup/pom.xml
new file mode 100644
index 00000000..c799b847
--- /dev/null
+++ b/dropwizard-dedup/pom.xml
@@ -0,0 +1,150 @@
+
+
+ 4.0.0
+
+ io.keploy.samples
+ dropwizard-dedup
+ 1.0.0
+ dropwizard-dedup
+ Keploy Java dynamic deduplication Dropwizard sample
+
+
+ 2.1.12
+ 0.8.12
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+
+
+ io.dropwizard
+ dropwizard-dependencies
+ ${dropwizard.version}
+ pom
+ import
+
+
+
+
+
+
+ io.dropwizard
+ dropwizard-core
+
+
+
+
+ dropwizard-dedup
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.11.0
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.5.3
+
+ false
+
+
+
+ io.keploy.samples.dropwizarddedup.DropwizardDedupApplication
+
+
+
+
+
+ package
+
+ shade
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 3.6.1
+
+
+ copy-jacoco-agent
+ package
+
+ copy
+
+
+
+
+ org.jacoco
+ org.jacoco.agent
+ ${jacoco.version}
+ runtime
+ jar
+ ${project.build.directory}
+ jacocoagent.jar
+
+
+
+
+
+ copy-runtime-dependencies
+ package
+
+ copy-dependencies
+
+
+ runtime
+ ${project.build.directory}/dependency
+
+
+
+
+
+
+
+
+
+ copy-keploy-agent
+
+
+ keploy.agent.version
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 3.6.1
+
+
+ copy-keploy-java-agent
+ package
+
+ copy
+
+
+
+
+ io.keploy
+ keploy-sdk
+ ${keploy.agent.version}
+ ${project.build.directory}
+ keploy-sdk.jar
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dropwizard-dedup/src/main/java/io/keploy/samples/dropwizarddedup/DropwizardDedupApplication.java b/dropwizard-dedup/src/main/java/io/keploy/samples/dropwizarddedup/DropwizardDedupApplication.java
new file mode 100644
index 00000000..21e46788
--- /dev/null
+++ b/dropwizard-dedup/src/main/java/io/keploy/samples/dropwizarddedup/DropwizardDedupApplication.java
@@ -0,0 +1,43 @@
+package io.keploy.samples.dropwizarddedup;
+
+import io.dropwizard.Application;
+import io.dropwizard.configuration.EnvironmentVariableSubstitutor;
+import io.dropwizard.configuration.SubstitutingSourceProvider;
+import io.dropwizard.setup.Bootstrap;
+import io.dropwizard.setup.Environment;
+import io.keploy.samples.dropwizarddedup.core.CatalogService;
+import io.keploy.samples.dropwizarddedup.errors.ApiExceptionMapper;
+import io.keploy.samples.dropwizarddedup.health.ApplicationHealthCheck;
+import io.keploy.samples.dropwizarddedup.resources.InventoryResource;
+import io.keploy.samples.dropwizarddedup.resources.OrderResource;
+import io.keploy.samples.dropwizarddedup.resources.PlatformResource;
+
+public class DropwizardDedupApplication extends Application {
+
+ public static void main(String[] args) throws Exception {
+ new DropwizardDedupApplication().run(args);
+ }
+
+ @Override
+ public String getName() {
+ return "dropwizard-dedup";
+ }
+
+ @Override
+ public void initialize(Bootstrap bootstrap) {
+ bootstrap.setConfigurationSourceProvider(new SubstitutingSourceProvider(
+ bootstrap.getConfigurationSourceProvider(),
+ new EnvironmentVariableSubstitutor(false)
+ ));
+ }
+
+ @Override
+ public void run(DropwizardDedupConfiguration configuration, Environment environment) {
+ CatalogService catalogService = new CatalogService();
+ environment.jersey().register(new InventoryResource(catalogService));
+ environment.jersey().register(new OrderResource(catalogService));
+ environment.jersey().register(new PlatformResource());
+ environment.jersey().register(new ApiExceptionMapper());
+ environment.healthChecks().register("application", new ApplicationHealthCheck());
+ }
+}
diff --git a/dropwizard-dedup/src/main/java/io/keploy/samples/dropwizarddedup/DropwizardDedupConfiguration.java b/dropwizard-dedup/src/main/java/io/keploy/samples/dropwizarddedup/DropwizardDedupConfiguration.java
new file mode 100644
index 00000000..77ec425e
--- /dev/null
+++ b/dropwizard-dedup/src/main/java/io/keploy/samples/dropwizarddedup/DropwizardDedupConfiguration.java
@@ -0,0 +1,6 @@
+package io.keploy.samples.dropwizarddedup;
+
+import io.dropwizard.Configuration;
+
+public class DropwizardDedupConfiguration extends Configuration {
+}
diff --git a/dropwizard-dedup/src/main/java/io/keploy/samples/dropwizarddedup/core/CatalogService.java b/dropwizard-dedup/src/main/java/io/keploy/samples/dropwizarddedup/core/CatalogService.java
new file mode 100644
index 00000000..c842d704
--- /dev/null
+++ b/dropwizard-dedup/src/main/java/io/keploy/samples/dropwizarddedup/core/CatalogService.java
@@ -0,0 +1,97 @@
+package io.keploy.samples.dropwizarddedup.core;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CatalogService {
+
+ public Map catalog(String category, int limit) {
+ Map response = map(
+ "category", category,
+ "limit", limit
+ );
+ response.put("items", selectItems(category, limit));
+ response.put("source", category.equals("electronics") ? "warehouse-b" : "warehouse-a");
+ return response;
+ }
+
+ public Map item(String sku) {
+ if ("BK-1".equals(sku)) {
+ return item("BK-1", "Clean Architecture", "books", "available", "32.50");
+ }
+ if ("EL-1".equals(sku)) {
+ return item("EL-1", "Noise Cancelling Headphones", "electronics", "backorder", "199.99");
+ }
+ return null;
+ }
+
+ public Map search(String term, String sort) {
+ Map response = map("term", term, "sort", sort);
+ response.put("ranking", "price".equals(sort) ? "discount-first" : "relevance-first");
+ response.put("hits", Arrays.asList(
+ item("EL-1", "Noise Cancelling Headphones", "electronics", "backorder", "199.99"),
+ item("BK-1", "Clean Architecture", "books", "available", "32.50")
+ ));
+ return response;
+ }
+
+ public Map order(String customer, String sku, int quantity, boolean priority) {
+ Map response = map(
+ "orderId", priority ? "ORD-PRIORITY" : "ORD-STANDARD",
+ "customer", customer,
+ "sku", sku,
+ "quantity", quantity,
+ "priority", priority,
+ "route", priority ? "air" : "ground"
+ );
+ response.put("checks", Arrays.asList("inventory", "pricing", priority ? "expedite" : "standard"));
+ return response;
+ }
+
+ public Map orderStatus(String orderId, boolean expand) {
+ Map response = map(
+ "orderId", orderId,
+ "status", "packed",
+ "expand", expand
+ );
+ if (expand) {
+ response.put("audit", Arrays.asList("created", "paid", "packed"));
+ }
+ return response;
+ }
+
+ public Map updateOrder(String orderId, String status) {
+ return map("orderId", orderId, "status", status, "updated", true);
+ }
+
+ public Map deleteOrder(String orderId) {
+ return map("orderId", orderId, "deleted", true);
+ }
+
+ private List