Skip to content

Commit d59b1ad

Browse files
feat: add Java dynamic dedup sample
Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>
1 parent 7be4e04 commit d59b1ad

12 files changed

Lines changed: 393 additions & 0 deletions

File tree

java-dedup/.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/target/
2+
/keploy/
3+
/keploy.yml
4+
/dedupData.yaml
5+
/duplicates.yaml
6+
/*.log

java-dedup/Dockerfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
ARG JAVA_VERSION=8
2+
FROM eclipse-temurin:${JAVA_VERSION}-jre
3+
4+
WORKDIR /app
5+
COPY target/java-dedup-0.0.1-SNAPSHOT.jar /app/app.jar
6+
COPY target/jacocoagent.jar /app/jacocoagent.jar
7+
COPY target/classes /app/target/classes
8+
9+
ENV KEPLOY_JAVA_CLASS_DIRS=/app/target/classes
10+
EXPOSE 8080
11+
ENTRYPOINT ["java", "-javaagent:/app/jacocoagent.jar=address=127.0.0.1,port=36320,destfile=/tmp/jacoco-keploy.exec,output=tcpserver", "-jar", "/app/app.jar"]

java-dedup/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Java Dynamic Deduplication Sample
2+
3+
This sample is a small Spring Boot application used by Keploy CI to validate Java dynamic deduplication in native and Docker runs.
4+
5+
Build the application after installing the Java SDK locally:
6+
7+
```bash
8+
mvn -B -DskipTests package
9+
```
10+
11+
Run it natively with JaCoCo TCP server mode:
12+
13+
```bash
14+
java -javaagent:target/jacocoagent.jar=address=127.0.0.1,port=36320,destfile=target/jacoco-keploy.exec,output=tcpserver \
15+
-jar target/java-dedup-0.0.1-SNAPSHOT.jar
16+
```
17+
18+
Run it with Docker Compose after the Maven package step has created `target/java-dedup-0.0.1-SNAPSHOT.jar`:
19+
20+
```bash
21+
docker compose up --build
22+
```
23+
24+
For a more restricted container run:
25+
26+
```bash
27+
docker compose -f docker-compose.yml -f docker-compose.restricted.yml up --build
28+
```
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
services:
2+
java-dedup:
3+
read_only: true
4+
tmpfs:
5+
- /tmp
6+
cap_drop:
7+
- ALL
8+
security_opt:
9+
- no-new-privileges:true

java-dedup/docker-compose.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
services:
2+
java-dedup:
3+
build:
4+
context: .
5+
dockerfile: Dockerfile
6+
args:
7+
JAVA_VERSION: ${JAVA_VERSION:-8}
8+
container_name: dedup-java
9+
ports:
10+
- "8080:8080"
11+
environment:
12+
KEPLOY_JAVA_CLASS_DIRS: /app/target/classes

java-dedup/pom.xml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>org.springframework.boot</groupId>
9+
<artifactId>spring-boot-starter-parent</artifactId>
10+
<version>2.7.18</version>
11+
<relativePath/>
12+
</parent>
13+
14+
<groupId>io.keploy.samples</groupId>
15+
<artifactId>java-dedup</artifactId>
16+
<version>0.0.1-SNAPSHOT</version>
17+
<name>java-dedup</name>
18+
<description>Keploy Java dynamic deduplication sample</description>
19+
20+
<properties>
21+
<java.version>1.8</java.version>
22+
<keploy.sdk.version>0.0.1-SNAPSHOT</keploy.sdk.version>
23+
<jacoco.version>0.8.12</jacoco.version>
24+
</properties>
25+
26+
<dependencies>
27+
<dependency>
28+
<groupId>org.springframework.boot</groupId>
29+
<artifactId>spring-boot-starter-web</artifactId>
30+
</dependency>
31+
<dependency>
32+
<groupId>io.keploy</groupId>
33+
<artifactId>keploy-sdk</artifactId>
34+
<version>${keploy.sdk.version}</version>
35+
</dependency>
36+
<dependency>
37+
<groupId>org.jacoco</groupId>
38+
<artifactId>org.jacoco.agent</artifactId>
39+
<version>${jacoco.version}</version>
40+
<classifier>runtime</classifier>
41+
<scope>runtime</scope>
42+
</dependency>
43+
</dependencies>
44+
45+
<build>
46+
<plugins>
47+
<plugin>
48+
<groupId>org.springframework.boot</groupId>
49+
<artifactId>spring-boot-maven-plugin</artifactId>
50+
</plugin>
51+
<plugin>
52+
<groupId>org.apache.maven.plugins</groupId>
53+
<artifactId>maven-dependency-plugin</artifactId>
54+
<version>3.6.1</version>
55+
<executions>
56+
<execution>
57+
<id>copy-jacoco-agent</id>
58+
<phase>package</phase>
59+
<goals>
60+
<goal>copy</goal>
61+
</goals>
62+
<configuration>
63+
<artifactItems>
64+
<artifactItem>
65+
<groupId>org.jacoco</groupId>
66+
<artifactId>org.jacoco.agent</artifactId>
67+
<version>${jacoco.version}</version>
68+
<classifier>runtime</classifier>
69+
<type>jar</type>
70+
<outputDirectory>${project.build.directory}</outputDirectory>
71+
<destFileName>jacocoagent.jar</destFileName>
72+
</artifactItem>
73+
</artifactItems>
74+
</configuration>
75+
</execution>
76+
</executions>
77+
</plugin>
78+
</plugins>
79+
</build>
80+
</project>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package io.keploy.samples.javadedup;
2+
3+
import io.keploy.samples.javadedup.model.Item;
4+
import io.keploy.samples.javadedup.model.Product;
5+
import io.keploy.samples.javadedup.model.User;
6+
import org.springframework.http.HttpStatus;
7+
import org.springframework.http.ResponseEntity;
8+
import org.springframework.web.bind.annotation.DeleteMapping;
9+
import org.springframework.web.bind.annotation.GetMapping;
10+
import org.springframework.web.bind.annotation.PathVariable;
11+
import org.springframework.web.bind.annotation.PostMapping;
12+
import org.springframework.web.bind.annotation.PutMapping;
13+
import org.springframework.web.bind.annotation.RequestBody;
14+
import org.springframework.web.bind.annotation.RestController;
15+
16+
import java.time.Instant;
17+
import java.util.Arrays;
18+
import java.util.LinkedHashMap;
19+
import java.util.List;
20+
import java.util.Map;
21+
22+
@RestController
23+
public class DedupController {
24+
25+
@GetMapping("/")
26+
public Map<String, Object> health() {
27+
Map<String, Object> response = new LinkedHashMap<>();
28+
response.put("status", "ok");
29+
return response;
30+
}
31+
32+
@GetMapping("/hello/{name}")
33+
public String hello(@PathVariable String name) {
34+
return greeting(name);
35+
}
36+
37+
@PostMapping("/user")
38+
public Map<String, Object> createUser(@RequestBody User user) {
39+
Map<String, Object> response = new LinkedHashMap<>();
40+
response.put("message", "User created successfully");
41+
response.put("user", user);
42+
return response;
43+
}
44+
45+
@PutMapping("/item/{id}")
46+
public Map<String, Object> updateItem(@PathVariable String id, @RequestBody Item item) {
47+
Map<String, Object> response = new LinkedHashMap<>();
48+
response.put("message", "Item updated successfully");
49+
response.put("id", id);
50+
response.put("updatedData", item);
51+
return response;
52+
}
53+
54+
@GetMapping("/products")
55+
public List<Product> products() {
56+
return Arrays.asList(
57+
new Product("prod001", "Eco-friendly Water Bottle", "A reusable bottle.",
58+
Arrays.asList("eco", "kitchen")),
59+
new Product("prod002", "Wireless Charger", "Charges your devices.",
60+
Arrays.asList("tech", "mobile"))
61+
);
62+
}
63+
64+
@DeleteMapping("/products/{id}")
65+
public Map<String, Object> deleteProduct(@PathVariable String id) {
66+
Map<String, Object> response = new LinkedHashMap<>();
67+
response.put("status", "product " + id + " deleted");
68+
return response;
69+
}
70+
71+
@GetMapping("/api/v2/users")
72+
public Map<String, Object> apiUsers() {
73+
Map<String, Object> first = new LinkedHashMap<>();
74+
first.put("name", "gamma");
75+
Map<String, Object> second = new LinkedHashMap<>();
76+
second.put("name", "delta");
77+
78+
Map<String, Object> response = new LinkedHashMap<>();
79+
response.put("version", 2);
80+
response.put("users", Arrays.asList(first, second));
81+
return response;
82+
}
83+
84+
@GetMapping("/timestamp")
85+
public Map<String, Object> timestamp() {
86+
Map<String, Object> response = new LinkedHashMap<>();
87+
response.put("current_time", Instant.now().toString());
88+
return response;
89+
}
90+
91+
@GetMapping("/status/{name}")
92+
public ResponseEntity<Map<String, Object>> status(@PathVariable String name) {
93+
Map<String, Object> response = new LinkedHashMap<>();
94+
response.put("message", greeting(name));
95+
response.put("service", "java-dedup");
96+
return new ResponseEntity<>(response, HttpStatus.OK);
97+
}
98+
99+
private String greeting(String name) {
100+
return "Hello, " + name + "!";
101+
}
102+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.keploy.samples.javadedup;
2+
3+
import io.keploy.servlet.KeployMiddleware;
4+
import org.springframework.boot.SpringApplication;
5+
import org.springframework.boot.autoconfigure.SpringBootApplication;
6+
import org.springframework.context.annotation.Import;
7+
8+
@SpringBootApplication
9+
@Import(KeployMiddleware.class)
10+
public class JavaDedupApplication {
11+
12+
public static void main(String[] args) {
13+
SpringApplication.run(JavaDedupApplication.class, args);
14+
}
15+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package io.keploy.samples.javadedup.model;
2+
3+
import java.math.BigDecimal;
4+
5+
public class Item {
6+
7+
private String id;
8+
private String name;
9+
private BigDecimal price;
10+
11+
public Item() {
12+
}
13+
14+
public Item(String id, String name, BigDecimal price) {
15+
this.id = id;
16+
this.name = name;
17+
this.price = price;
18+
}
19+
20+
public String getId() {
21+
return id;
22+
}
23+
24+
public void setId(String id) {
25+
this.id = id;
26+
}
27+
28+
public String getName() {
29+
return name;
30+
}
31+
32+
public void setName(String name) {
33+
this.name = name;
34+
}
35+
36+
public BigDecimal getPrice() {
37+
return price;
38+
}
39+
40+
public void setPrice(BigDecimal price) {
41+
this.price = price;
42+
}
43+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package io.keploy.samples.javadedup.model;
2+
3+
import java.util.List;
4+
5+
public class Product {
6+
7+
private String productId;
8+
private String name;
9+
private String description;
10+
private List<String> tags;
11+
12+
public Product() {
13+
}
14+
15+
public Product(String productId, String name, String description, List<String> tags) {
16+
this.productId = productId;
17+
this.name = name;
18+
this.description = description;
19+
this.tags = tags;
20+
}
21+
22+
public String getProductId() {
23+
return productId;
24+
}
25+
26+
public void setProductId(String productId) {
27+
this.productId = productId;
28+
}
29+
30+
public String getName() {
31+
return name;
32+
}
33+
34+
public void setName(String name) {
35+
this.name = name;
36+
}
37+
38+
public String getDescription() {
39+
return description;
40+
}
41+
42+
public void setDescription(String description) {
43+
this.description = description;
44+
}
45+
46+
public List<String> getTags() {
47+
return tags;
48+
}
49+
50+
public void setTags(List<String> tags) {
51+
this.tags = tags;
52+
}
53+
}

0 commit comments

Comments
 (0)