Skip to content

Commit 080077f

Browse files
khareyash05claude
andauthored
feat(spring-mysql-redis): add endpoint to trigger COM_STMT_RESET (#136)
Adds GET /api/todos/stmt-reset/{id}/{n} which re-executes a server-side prepared statement n times on the same connection. Combined with the new JDBC URL flags (useServerPrepStmts, cachePrepStmts, useCursorFetch), MySQL Connector/J 8.x emits COM_STMT_RESET between re-executions, which exercises the synthetic-OK fallback path added in keploy/keploy#4217 so record/replay can be validated. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent aa16aa2 commit 080077f

2 files changed

Lines changed: 56 additions & 1 deletion

File tree

spring-mysql-redis/src/main/java/org/example/todo/controller/TodoController.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,15 @@
66
import org.springframework.http.ResponseEntity;
77
import org.springframework.web.bind.annotation.*;
88

9+
import javax.sql.DataSource;
10+
import java.sql.Connection;
11+
import java.sql.PreparedStatement;
12+
import java.sql.ResultSet;
13+
import java.sql.SQLException;
14+
import java.util.ArrayList;
15+
import java.util.HashMap;
916
import java.util.List;
17+
import java.util.Map;
1018
import java.util.Optional;
1119

1220
@RestController
@@ -16,6 +24,9 @@ public class TodoController {
1624
@Autowired
1725
private TodoService todoService;
1826

27+
@Autowired
28+
private DataSource dataSource;
29+
1930
@GetMapping
2031
public List<Todo> getAllTodos() {
2132
return todoService.findAll();
@@ -52,4 +63,48 @@ public ResponseEntity<Void> deleteTodo(@PathVariable Long id) {
5263
todoService.deleteById(id);
5364
return ResponseEntity.ok().build();
5465
}
66+
67+
/**
68+
* Re-executes a server-side prepared statement {@code n} times on the same
69+
* connection. With {@code useServerPrepStmts=true} and
70+
* {@code useCursorFetch=true} (set in application.properties) plus a
71+
* non-zero fetchSize, MySQL Connector/J 8.x sends a COM_STMT_RESET packet
72+
* between re-executions to clear the cursor state. This endpoint exists to
73+
* exercise that code path so Keploy record/replay can capture and match
74+
* COM_STMT_RESET frames.
75+
*/
76+
@GetMapping("/stmt-reset/{id}/{n}")
77+
public ResponseEntity<Map<String, Object>> stmtReset(@PathVariable Long id,
78+
@PathVariable int n) throws SQLException {
79+
List<Map<String, Object>> rows = new ArrayList<>();
80+
String sql = "SELECT id, title, description, completed FROM todo WHERE id = ?";
81+
82+
try (Connection conn = dataSource.getConnection();
83+
PreparedStatement ps = conn.prepareStatement(sql)) {
84+
85+
// Forces server-side cursor (with useCursorFetch=true), which is
86+
// what causes Connector/J to emit COM_STMT_RESET on re-execution.
87+
ps.setFetchSize(1);
88+
89+
for (int i = 0; i < n; i++) {
90+
ps.setLong(1, id);
91+
try (ResultSet rs = ps.executeQuery()) {
92+
if (rs.next()) {
93+
Map<String, Object> row = new HashMap<>();
94+
row.put("id", rs.getLong("id"));
95+
row.put("title", rs.getString("title"));
96+
row.put("description", rs.getString("description"));
97+
row.put("completed", rs.getBoolean("completed"));
98+
rows.add(row);
99+
}
100+
}
101+
}
102+
}
103+
104+
Map<String, Object> response = new HashMap<>();
105+
response.put("iterations", n);
106+
response.put("rowsFetched", rows.size());
107+
response.put("results", rows);
108+
return ResponseEntity.ok(response);
109+
}
55110
}

spring-mysql-redis/src/main/resources/application.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# MySQL Configuration
2-
spring.datasource.url=jdbc:mysql://localhost:3306/todoapp?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
2+
spring.datasource.url=jdbc:mysql://localhost:3306/todoapp?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true&useServerPrepStmts=true&cachePrepStmts=true&useCursorFetch=true
33
spring.datasource.username=yourusername
44
spring.datasource.password=yourpassword
55
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

0 commit comments

Comments
 (0)