Skip to content

Commit 92dad43

Browse files
feat(java-dedup): add simple Java smoke sample
Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>
1 parent dcef3ad commit 92dad43

24 files changed

Lines changed: 1049 additions & 0 deletions

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ This repo contains the sample for [Keploy's](https://keploy.io) Java Application
2525
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.
2626
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.
2727
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.
28+
9. [Simple Java Dynamic Deduplication](https://github.com/keploy/samples-java/tree/main/simple-java-dedup) - A minimal plain-Java HTTP server used to smoke-test Java dynamic dedup on Java 8 and Java 17 in native and Docker launch modes.
2829

2930
## Community Support ❤️
3031

simple-java-dedup/.dockerignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
**
2+
!target/simple-java-dedup.jar
3+
!target/classes/**
4+
!target/keploy-sdk.jar
5+
!target/jacocoagent.jar

simple-java-dedup/.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
target/
2+
dedupData.yaml
3+
duplicates.yaml
4+
test-results/
5+
coverage-reports/
6+
docker-compose-tmp.yaml
7+
jacoco.exec
8+
*.log
9+
keploy-logs.txt

simple-java-dedup/Dockerfile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
ARG JAVA_VERSION=8
2+
FROM eclipse-temurin:${JAVA_VERSION}-jre
3+
4+
WORKDIR /app
5+
6+
RUN groupadd --gid 10001 appuser \
7+
&& useradd --uid 10001 --gid 10001 --home-dir /home/appuser --create-home --shell /usr/sbin/nologin appuser
8+
9+
COPY --chown=10001:10001 target/simple-java-dedup.jar /app/app.jar
10+
COPY --chown=10001:10001 target/classes /app/classes
11+
COPY --chown=10001:10001 target/keploy-sdk.jar /app/keploy-sdk.jar
12+
COPY --chown=10001:10001 target/jacocoagent.jar /app/jacocoagent.jar
13+
14+
ENV KEPLOY_JAVA_CLASS_DIRS=/app/classes
15+
16+
EXPOSE 8080
17+
USER 10001:10001
18+
ENTRYPOINT ["java", "-javaagent:/app/keploy-sdk.jar", "-javaagent:/app/jacocoagent.jar=destfile=/tmp/jacoco.exec", "-jar", "/app/app.jar"]

simple-java-dedup/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Simple Java Dynamic Deduplication Sample
2+
3+
This is a small plain-Java HTTP service used to smoke-test Keploy Enterprise Java dynamic deduplication on Java 8 and Java 17. It uses only JDK APIs (`com.sun.net.httpserver.HttpServer`) and does not compile against the Keploy SDK.
4+
5+
The checked-in fixtures exercise `/healthz`, `/grade`, `/shipping`, `/inventory`, and `/invoice`. They intentionally contain duplicate coverage paths:
6+
7+
- `/grade?score=95` and `/grade?score=98` execute the same high-score branch.
8+
- `/shipping?country=US&total=150` and `/shipping?country=US&total=175` execute the same free-shipping branch.
9+
- `/inventory?sku=BOOK-1&quantity=3` and `/inventory?sku=BOOK-2&quantity=4` execute the same priority-reservation branch.
10+
- `/invoice?customer=vip&subtotal=200` and `/invoice?customer=vip&subtotal=250` execute the same VIP-large discount branch.
11+
12+
## Build
13+
14+
```bash
15+
mvn -B -DskipTests -Dkeploy.agent.version=2.0.6 clean package
16+
```
17+
18+
## Native Dedup
19+
20+
```bash
21+
keploy test \
22+
-c "java -javaagent:target/keploy-sdk.jar -javaagent:target/jacocoagent.jar -jar target/simple-java-dedup.jar" \
23+
--path . --dedup --language java --delay 1 \
24+
--health-url "http://127.0.0.1:8080/healthz" \
25+
--health-poll-timeout 30s \
26+
--disableMockUpload --disableReportUpload
27+
28+
keploy dedup --path .
29+
```
30+
31+
## Docker Dedup
32+
33+
```bash
34+
JAVA_VERSION=17 docker compose build
35+
keploy test \
36+
-c "docker compose up" \
37+
--container-name simple-java-dedup \
38+
--path . --dedup --language java --delay 10 \
39+
--health-url "http://127.0.0.1:8080/healthz" \
40+
--health-poll-timeout 30s \
41+
--disableMockUpload --disableReportUpload
42+
43+
keploy dedup --path .
44+
```
45+
46+
Keep the `-c` value as `docker compose up` so Keploy detects Docker Compose and mounts the shared `/tmp` socket volume used by Java dynamic deduplication. Pass `JAVA_VERSION`, `JAVA_DEDUP_IMAGE`, or port overrides in the shell environment instead of prefixing them inside the `-c` command.
47+
48+
## Expected Result
49+
50+
All 14 replayed fixtures should pass. Dedup should retain 10 test cases and mark 4 as duplicate, with exactly one duplicate from each intentional pair listed above.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
services:
2+
simple-java-dedup:
3+
build:
4+
context: .
5+
args:
6+
JAVA_VERSION: ${JAVA_VERSION:-8}
7+
image: ${JAVA_DEDUP_IMAGE:-simple-java-dedup:local}
8+
container_name: simple-java-dedup
9+
ports:
10+
- "${JAVA_DEDUP_HOST_PORT:-8080}:8080"

simple-java-dedup/keploy.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Generated by Keploy (3-dev)
2+
path: ""
3+
appId: 0
4+
appName: ""
5+
command: ""
6+
templatize:
7+
testSets: []
8+
port: 0
9+
proxyPort: 16789
10+
incomingProxyPort: 36789
11+
dnsPort: 26789
12+
debug: false
13+
disableANSI: false
14+
disableTele: false
15+
generateGithubActions: false
16+
containerName: ""
17+
networkName: ""
18+
buildDelay: 30
19+
test:
20+
selectedTests: {}
21+
ignoredTests: {}
22+
globalNoise:
23+
global: {}
24+
test-sets: {}
25+
replaceWith:
26+
global: {}
27+
test-sets: {}
28+
delay: 5
29+
host: "localhost"
30+
port: 0
31+
grpcPort: 0
32+
ssePort: 0
33+
protocol:
34+
http:
35+
port: 0
36+
sse:
37+
port: 0
38+
grpc:
39+
port: 0
40+
apiTimeout: 5
41+
skipCoverage: false
42+
coverageReportPath: ""
43+
ignoreOrdering: true
44+
mongoPassword: "default@123"
45+
language: ""
46+
removeUnusedMocks: false
47+
fallBackOnMiss: false
48+
jacocoAgentPath: ""
49+
basePath: ""
50+
mocking: true
51+
disableLineCoverage: false
52+
disableMockUpload: false
53+
useLocalMock: false
54+
updateTemplate: false
55+
mustPass: false
56+
maxFailAttempts: 5
57+
maxFlakyChecks: 1
58+
protoFile: ""
59+
protoDir: ""
60+
protoInclude: []
61+
compareAll: false
62+
updateTestMapping: false
63+
disableAutoHeaderNoise: false
64+
strictMockWindow: true
65+
dedup: false
66+
freezeTime: false
67+
fuzzyMatch: false
68+
record:
69+
recordTimer: 0s
70+
filters: []
71+
sync: false
72+
memoryLimit: 0
73+
configPath: ""
74+
bypassRules: []
75+
disableMapping: true
76+
contract:
77+
driven: "consumer"
78+
mappings:
79+
servicesMapping: {}
80+
self: "s1"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
/reports/
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Generated by Keploy (3-dev)
2+
version: api.keploy.io/v1beta1
3+
kind: Http
4+
name: test-1
5+
spec:
6+
metadata: {}
7+
req:
8+
method: GET
9+
proto_major: 1
10+
proto_minor: 1
11+
url: http://127.0.0.1:8080/healthz
12+
header:
13+
Host: '127.0.0.1:8080'
14+
User-Agent: curl/8.19.0
15+
Accept: '*/*'
16+
body: ''
17+
timestamp: 2026-04-30T23:19:11Z
18+
resp:
19+
status_code: 200
20+
header:
21+
Date: 'Thu, 30 Apr 2026 23:19:11 GMT'
22+
Content-Type: application/json
23+
Content-Length: 15
24+
body: '{"status":"ok"}'
25+
status_message: OK
26+
proto_major: 0
27+
proto_minor: 0
28+
timestamp: 2026-04-30T23:19:11Z
29+
objects: []
30+
assertions:
31+
noise:
32+
header.Date: []
33+
header.Content-Length: []
34+
created: 1777591151
35+
app_port: 8080
36+
curl: |
37+
curl --request GET \
38+
--url http://127.0.0.1:8080/healthz \
39+
--header 'Host: 127.0.0.1:8080' \
40+
--header 'User-Agent: curl/8.19.0' \
41+
--header 'Accept: */*'
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Generated by Keploy (3-dev)
2+
version: api.keploy.io/v1beta1
3+
kind: Http
4+
name: test-10
5+
spec:
6+
metadata: {}
7+
req:
8+
method: GET
9+
proto_major: 1
10+
proto_minor: 1
11+
url: http://127.0.0.1:8080/inventory?sku=BOOK-2&quantity=4
12+
header:
13+
Host: '127.0.0.1:8080'
14+
User-Agent: curl/8.19.0
15+
Accept: '*/*'
16+
body: ''
17+
timestamp: 2026-04-30T23:19:20Z
18+
resp:
19+
status_code: 200
20+
header:
21+
Date: 'Thu, 30 Apr 2026 23:19:20 GMT'
22+
Content-Type: application/json
23+
Content-Length: 63
24+
body: '{"sku":"BOOK-2","quantity":4,"lane":"priority","reserved":true}'
25+
status_message: OK
26+
proto_major: 0
27+
proto_minor: 0
28+
timestamp: 2026-04-30T23:19:20Z
29+
objects: []
30+
assertions:
31+
noise:
32+
header.Date: []
33+
header.Content-Length: []
34+
created: 1777591160
35+
app_port: 8080
36+
curl: |
37+
curl --request GET \
38+
--url 'http://127.0.0.1:8080/inventory?sku=BOOK-2&quantity=4' \
39+
--header 'Host: 127.0.0.1:8080' \
40+
--header 'User-Agent: curl/8.19.0' \
41+
--header 'Accept: */*'

0 commit comments

Comments
 (0)