Prompt file imported from aerospike/aerospike-client-java (
.cursor/commands/port-to-jdk8.md). Copyright stays with the author.
Port Branch Changes from stage (Java 21) to stage-jdk8 (Java 8)
Port changes from the source branch (based on stage) to a new branch based on stage-jdk8.
Instructions
The user will provide a source branch name as an argument. Use it to perform the port.
Target Branch Naming
The target branch name MUST be derived from the source branch name by appending _jdk8:
- Source:
CLIENT-1234_feature-> Target:CLIENT-1234_feature_jdk8 - Source:
bugfix-something-> Target:bugfix-something_jdk8
Steps
- Validate the source branch exists and is based on
stage. - Analyze the commits on the source branch that are not on
stage:git log --oneline stage..<source-branch> - Create the target branch off
stage-jdk8:git checkout stage-jdk8 git pull git checkout -b <target-branch-name> - Cherry-pick the commits from the source branch onto the target branch. If there are conflicts, resolve them with the Java 8 adaptations listed below.
- Adapt the code for Java 8 compatibility (see adaptation rules below).
- Purge Maven cache to avoid stale JDK 21 artifacts causing build failures:
mvn dependency:purge-local-repository \ -DreResolve=true \ -DactTransitively=false - Build to verify:
mvn clean install -U
Java 21 to Java 8 Adaptation Rules
When porting code, apply these transformations:
Language Features
- Records -> Replace with traditional classes (private final fields, constructor, getters, equals/hashCode/toString)
- Sealed classes/interfaces -> Remove
sealed,permits,non-sealedkeywords; use regular class hierarchy - Pattern matching for instanceof -> Use traditional instanceof + explicit cast
// Java 21 if (obj instanceof String s) { use(s); } // Java 8 if (obj instanceof String) { String s = (String) obj; use(s); } - Switch expressions -> Convert to switch statements or if-else chains
// Java 21 var result = switch (x) { case 1 -> "one"; case 2 -> "two"; default -> "other"; }; // Java 8 String result; switch (x) { case 1: result = "one"; break; case 2: result = "two"; break; default: result = "other"; break; } - Text blocks (triple quotes) -> Use string concatenation or
String.join varkeyword -> Replace with explicit types- Enhanced switch with arrow syntax -> Use traditional colon-case syntax
API Differences
List.of(),Set.of(),Map.of()-> UseCollections.unmodifiableList(Arrays.asList(...)),Collections.unmodifiableSet(new HashSet<>(Arrays.asList(...))), or manual map constructionString.isBlank()-> Usestring.trim().isEmpty()String.strip()-> Usestring.trim()String.repeat(n)-> Use a loop orString.join("", Collections.nCopies(n, str))Optional.isEmpty()-> Use!optional.isPresent()Stream.toList()-> Use.collect(Collectors.toList())Map.entry()-> Usenew AbstractMap.SimpleEntry<>()Files.readString()/Files.writeString()-> Use traditional I/O withBufferedReader/BufferedWriter
Project-Specific Differences
- The
stage-jdk8branch usesaerospike-client-jdk8artifact instead ofaerospike-client-jdk21 - pom.xml uses
java.version=1.8andjava.api=8instead ofjava.version=21 - Some features like
estimateKeySize()do not exist in the jdk8 branch - Do NOT modify pom.xml java version settings - those are already correct on
stage-jdk8
Important
- Preserve the original commit messages when cherry-picking
- If a file does not exist on
stage-jdk8, check if the functionality lives in a different file or should be skipped - After all changes, run
mvn clean install -Uand fix any compilation errors