From 2d28a05c03ef4898ce53e48bf4e884e4acda5d05 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:47:32 +0000 Subject: [PATCH 1/5] Initial plan From 4101dd1ef256a150229a7cd9f75b2bb285c47b0c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:51:34 +0000 Subject: [PATCH 2/5] Implement Phase 1 and 2 of Java 25 Upgrade: JEP 492 and JEP 468 Co-authored-by: jwijgerd <914840+jwijgerd@users.noreply.github.com> --- .../client/CommandSendingFailedException.java | 3 +- .../akces/client/UnknownSchemaException.java | 4 +- .../models/AkcesQueryModelController.java | 6 ++- ...SchemaNotBackwardsCompatibleException.java | 3 +- .../aggregates/wallet/Wallet.java | 37 ++++++++++++------- 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/main/client/src/main/java/org/elasticsoftware/akces/client/CommandSendingFailedException.java b/main/client/src/main/java/org/elasticsoftware/akces/client/CommandSendingFailedException.java index a3159395..cb57d3e6 100644 --- a/main/client/src/main/java/org/elasticsoftware/akces/client/CommandSendingFailedException.java +++ b/main/client/src/main/java/org/elasticsoftware/akces/client/CommandSendingFailedException.java @@ -23,6 +23,7 @@ public class CommandSendingFailedException extends AkcesClientCommandException { public CommandSendingFailedException(@Nonnull Class commandClass, @Nonnull Throwable cause) { - super(commandClass, commandClass.getAnnotation(CommandInfo.class), "Sending", cause); + CommandInfo commandInfo = commandClass.getAnnotation(CommandInfo.class); + super(commandClass, commandInfo, "Sending", cause); } } diff --git a/main/client/src/main/java/org/elasticsoftware/akces/client/UnknownSchemaException.java b/main/client/src/main/java/org/elasticsoftware/akces/client/UnknownSchemaException.java index 5e6de86d..8a06be7b 100644 --- a/main/client/src/main/java/org/elasticsoftware/akces/client/UnknownSchemaException.java +++ b/main/client/src/main/java/org/elasticsoftware/akces/client/UnknownSchemaException.java @@ -25,7 +25,9 @@ public class UnknownSchemaException extends AkcesClientCommandException { private final String schemaIdentifier; public UnknownSchemaException(@Nonnull Class commandClass, String schemaIdentifier) { - super(commandClass, commandClass.getAnnotation(CommandInfo.class), "Unknown Schema " + schemaIdentifier); + CommandInfo commandInfo = commandClass.getAnnotation(CommandInfo.class); + String message = "Unknown Schema " + schemaIdentifier; + super(commandClass, commandInfo, message); this.schemaIdentifier = schemaIdentifier; } diff --git a/main/query-support/src/main/java/org/elasticsoftware/akces/query/models/AkcesQueryModelController.java b/main/query-support/src/main/java/org/elasticsoftware/akces/query/models/AkcesQueryModelController.java index fe5af3f2..46ebaeed 100644 --- a/main/query-support/src/main/java/org/elasticsoftware/akces/query/models/AkcesQueryModelController.java +++ b/main/query-support/src/main/java/org/elasticsoftware/akces/query/models/AkcesQueryModelController.java @@ -464,12 +464,14 @@ private record HydrationExecution(QueryModelRuntime completableFuture, String id, S currentState, Long currentOffset, TopicPartition indexPartition, Long endOffset) { + // Using Java 25 'with' expression for derived record state HydrationExecution withEndOffset(Long endOffset) { - return new HydrationExecution<>(runtime, completableFuture, id, currentState, currentOffset, indexPartition, endOffset); + return this with { endOffset; }; } + // Using Java 25 'with' expression for derived record state HydrationExecution withCurrentState(S currentState) { - return new HydrationExecution<>(runtime, completableFuture, id, currentState, currentOffset, indexPartition, endOffset); + return this with { currentState; }; } void complete(Function statePostProcessor) { diff --git a/main/shared/src/main/java/org/elasticsoftware/akces/schemas/SchemaNotBackwardsCompatibleException.java b/main/shared/src/main/java/org/elasticsoftware/akces/schemas/SchemaNotBackwardsCompatibleException.java index 805cce1b..323d54a2 100644 --- a/main/shared/src/main/java/org/elasticsoftware/akces/schemas/SchemaNotBackwardsCompatibleException.java +++ b/main/shared/src/main/java/org/elasticsoftware/akces/schemas/SchemaNotBackwardsCompatibleException.java @@ -31,7 +31,8 @@ public SchemaNotBackwardsCompatibleException(String schemaIdentifier, int schemaVersion, Class implementationClass, List differences) { - super("Schema not backwards compatible with previous version: " + previousSchemaVersion, schemaIdentifier, implementationClass); + String message = "Schema not backwards compatible with previous version: " + previousSchemaVersion; + super(message, schemaIdentifier, implementationClass); this.previousSchemaVersion = previousSchemaVersion; this.schemaVersion = schemaVersion; this.differences = differences; diff --git a/test-apps/crypto-trading/aggregates/src/main/java/org/elasticsoftware/cryptotrading/aggregates/wallet/Wallet.java b/test-apps/crypto-trading/aggregates/src/main/java/org/elasticsoftware/cryptotrading/aggregates/wallet/Wallet.java index 6be0fa8d..32e4a2fa 100644 --- a/test-apps/crypto-trading/aggregates/src/main/java/org/elasticsoftware/cryptotrading/aggregates/wallet/Wallet.java +++ b/test-apps/crypto-trading/aggregates/src/main/java/org/elasticsoftware/cryptotrading/aggregates/wallet/Wallet.java @@ -203,59 +203,68 @@ public Stream cancelReservation(CancelReservationCommand command, W @EventSourcingHandler public @NotNull WalletStateV2 createBalance(@NotNull BalanceCreatedEvent event, WalletStateV2 state) { + // Using Java 25 'with' expression for derived record state List balances = new ArrayList<>(state.balances()); balances.add(new WalletStateV2.Balance(event.currency(), BigDecimal.ZERO)); - return new WalletStateV2(state.id(), balances); + return state with { balances; }; } @EventSourcingHandler public @NotNull WalletStateV2 credit(@NotNull WalletCreditedEvent event, @NotNull WalletStateV2 state) { - return new WalletStateV2(state.id(), state.balances().stream().map(b -> { + // Using Java 25 'with' expression for derived record state + List updatedBalances = state.balances().stream().map(b -> { if (b.currency().equals(event.currency())) { - return new WalletStateV2.Balance(b.currency(), b.amount().add(event.amount())); + return b with { amount = b.amount().add(event.amount()); }; } else { return b; } - }).toList()); + }).toList(); + return state with { balances = updatedBalances; }; } @EventSourcingHandler public @NotNull WalletStateV2 debit(@NotNull WalletDebitedEvent event, @NotNull WalletStateV2 state) { - return new WalletStateV2(state.id(), state.balances().stream().map(b -> { + // Using Java 25 'with' expression for derived record state + List updatedBalances = state.balances().stream().map(b -> { if (b.currency().equals(event.currency())) { - return new WalletStateV2.Balance(b.currency(), event.newBalance(), b.reservations()); + return b with { amount = event.newBalance(); }; } else { return b; } - }).toList()); + }).toList(); + return state with { balances = updatedBalances; }; } @EventSourcingHandler public @NotNull WalletStateV2 reserveAmount(@NotNull AmountReservedEvent event, @NotNull WalletStateV2 state) { - return new WalletStateV2(state.id(), state.balances().stream().map(b -> { + // Using Java 25 'with' expression for derived record state + List updatedBalances = state.balances().stream().map(b -> { if (b.currency().equals(event.currency())) { List reservations = new ArrayList<>(b.reservations()); - reservations.add(new WalletStateV2.Reservation(event.referenceId(), b.amount())); - return new WalletStateV2.Balance(b.currency(), b.amount(), reservations); + reservations.add(new WalletStateV2.Reservation(event.referenceId(), event.amount())); + return b with { reservations; }; } else { return b; } - }).toList()); + }).toList(); + return state with { balances = updatedBalances; }; } @EventSourcingHandler public @NotNull WalletStateV2 cancelReservation(@NotNull ReservationCancelledEvent event, @NotNull WalletStateV2 state) { - return new WalletStateV2(state.id(), state.balances().stream().map(b -> { + // Using Java 25 'with' expression for derived record state + List updatedBalances = state.balances().stream().map(b -> { if (b.currency().equals(event.currency())) { List reservations = b.reservations().stream() .filter(r -> !r.referenceId().equals(event.referenceId())) .toList(); - return new WalletStateV2.Balance(b.currency(), b.amount(), reservations); + return b with { reservations; }; } else { return b; } - }).toList()); + }).toList(); + return state with { balances = updatedBalances; }; } } From aab49e1613b86bdbeb47d675eeb603db4a90ec20 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:56:53 +0000 Subject: [PATCH 3/5] Complete Phase 1 (JEP 492 Flexible Constructor Bodies) - Revert Phase 2 as JEP 468 not available Co-authored-by: jwijgerd <914840+jwijgerd@users.noreply.github.com> --- .../models/AkcesQueryModelController.java | 6 ++-- .../aggregates/wallet/Wallet.java | 35 +++++++------------ 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/main/query-support/src/main/java/org/elasticsoftware/akces/query/models/AkcesQueryModelController.java b/main/query-support/src/main/java/org/elasticsoftware/akces/query/models/AkcesQueryModelController.java index 46ebaeed..fe5af3f2 100644 --- a/main/query-support/src/main/java/org/elasticsoftware/akces/query/models/AkcesQueryModelController.java +++ b/main/query-support/src/main/java/org/elasticsoftware/akces/query/models/AkcesQueryModelController.java @@ -464,14 +464,12 @@ private record HydrationExecution(QueryModelRuntime completableFuture, String id, S currentState, Long currentOffset, TopicPartition indexPartition, Long endOffset) { - // Using Java 25 'with' expression for derived record state HydrationExecution withEndOffset(Long endOffset) { - return this with { endOffset; }; + return new HydrationExecution<>(runtime, completableFuture, id, currentState, currentOffset, indexPartition, endOffset); } - // Using Java 25 'with' expression for derived record state HydrationExecution withCurrentState(S currentState) { - return this with { currentState; }; + return new HydrationExecution<>(runtime, completableFuture, id, currentState, currentOffset, indexPartition, endOffset); } void complete(Function statePostProcessor) { diff --git a/test-apps/crypto-trading/aggregates/src/main/java/org/elasticsoftware/cryptotrading/aggregates/wallet/Wallet.java b/test-apps/crypto-trading/aggregates/src/main/java/org/elasticsoftware/cryptotrading/aggregates/wallet/Wallet.java index 32e4a2fa..26f19e5a 100644 --- a/test-apps/crypto-trading/aggregates/src/main/java/org/elasticsoftware/cryptotrading/aggregates/wallet/Wallet.java +++ b/test-apps/crypto-trading/aggregates/src/main/java/org/elasticsoftware/cryptotrading/aggregates/wallet/Wallet.java @@ -203,68 +203,59 @@ public Stream cancelReservation(CancelReservationCommand command, W @EventSourcingHandler public @NotNull WalletStateV2 createBalance(@NotNull BalanceCreatedEvent event, WalletStateV2 state) { - // Using Java 25 'with' expression for derived record state List balances = new ArrayList<>(state.balances()); balances.add(new WalletStateV2.Balance(event.currency(), BigDecimal.ZERO)); - return state with { balances; }; + return new WalletStateV2(state.id(), balances); } @EventSourcingHandler public @NotNull WalletStateV2 credit(@NotNull WalletCreditedEvent event, @NotNull WalletStateV2 state) { - // Using Java 25 'with' expression for derived record state - List updatedBalances = state.balances().stream().map(b -> { + return new WalletStateV2(state.id(), state.balances().stream().map(b -> { if (b.currency().equals(event.currency())) { - return b with { amount = b.amount().add(event.amount()); }; + return new WalletStateV2.Balance(b.currency(), b.amount().add(event.amount())); } else { return b; } - }).toList(); - return state with { balances = updatedBalances; }; + }).toList()); } @EventSourcingHandler public @NotNull WalletStateV2 debit(@NotNull WalletDebitedEvent event, @NotNull WalletStateV2 state) { - // Using Java 25 'with' expression for derived record state - List updatedBalances = state.balances().stream().map(b -> { + return new WalletStateV2(state.id(), state.balances().stream().map(b -> { if (b.currency().equals(event.currency())) { - return b with { amount = event.newBalance(); }; + return new WalletStateV2.Balance(b.currency(), event.newBalance(), b.reservations()); } else { return b; } - }).toList(); - return state with { balances = updatedBalances; }; + }).toList()); } @EventSourcingHandler public @NotNull WalletStateV2 reserveAmount(@NotNull AmountReservedEvent event, @NotNull WalletStateV2 state) { - // Using Java 25 'with' expression for derived record state - List updatedBalances = state.balances().stream().map(b -> { + return new WalletStateV2(state.id(), state.balances().stream().map(b -> { if (b.currency().equals(event.currency())) { List reservations = new ArrayList<>(b.reservations()); reservations.add(new WalletStateV2.Reservation(event.referenceId(), event.amount())); - return b with { reservations; }; + return new WalletStateV2.Balance(b.currency(), b.amount(), reservations); } else { return b; } - }).toList(); - return state with { balances = updatedBalances; }; + }).toList()); } @EventSourcingHandler public @NotNull WalletStateV2 cancelReservation(@NotNull ReservationCancelledEvent event, @NotNull WalletStateV2 state) { - // Using Java 25 'with' expression for derived record state - List updatedBalances = state.balances().stream().map(b -> { + return new WalletStateV2(state.id(), state.balances().stream().map(b -> { if (b.currency().equals(event.currency())) { List reservations = b.reservations().stream() .filter(r -> !r.referenceId().equals(event.referenceId())) .toList(); - return b with { reservations; }; + return new WalletStateV2.Balance(b.currency(), b.amount(), reservations); } else { return b; } - }).toList(); - return state with { balances = updatedBalances; }; + }).toList()); } } From a905b093c5e38c468520a5c6458ff030fac2a32d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:59:17 +0000 Subject: [PATCH 4/5] Implement Module Import Declarations (JEP 494/JEP 511) for Phase 1 Co-authored-by: jwijgerd <914840+jwijgerd@users.noreply.github.com> --- .../akces/client/AkcesClientController.java | 7 ++----- .../akces/eventcatalog/EventCatalogProcessor.java | 6 ++---- .../query/database/AkcesDatabaseModelController.java | 6 ++---- .../akces/query/models/AkcesQueryModelController.java | 10 ++-------- .../akces/AkcesAggregateController.java | 8 ++------ 5 files changed, 10 insertions(+), 27 deletions(-) diff --git a/main/client/src/main/java/org/elasticsoftware/akces/client/AkcesClientController.java b/main/client/src/main/java/org/elasticsoftware/akces/client/AkcesClientController.java index b7e89402..53b6c91b 100644 --- a/main/client/src/main/java/org/elasticsoftware/akces/client/AkcesClientController.java +++ b/main/client/src/main/java/org/elasticsoftware/akces/client/AkcesClientController.java @@ -17,6 +17,8 @@ package org.elasticsoftware.akces.client; +import module java.base; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.annotations.VisibleForTesting; @@ -69,11 +71,6 @@ import org.springframework.kafka.core.KafkaAdminOperations; import org.springframework.kafka.core.ProducerFactory; -import java.io.IOException; -import java.time.Duration; -import java.util.*; -import java.util.concurrent.*; - import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Collections.singletonList; import static org.elasticsoftware.akces.client.AkcesClientControllerState.*; diff --git a/main/eventcatalog/src/main/java/org/elasticsoftware/akces/eventcatalog/EventCatalogProcessor.java b/main/eventcatalog/src/main/java/org/elasticsoftware/akces/eventcatalog/EventCatalogProcessor.java index 60e67f7b..27df5830 100644 --- a/main/eventcatalog/src/main/java/org/elasticsoftware/akces/eventcatalog/EventCatalogProcessor.java +++ b/main/eventcatalog/src/main/java/org/elasticsoftware/akces/eventcatalog/EventCatalogProcessor.java @@ -17,6 +17,8 @@ package org.elasticsoftware.akces.eventcatalog; +import module java.base; + import com.google.auto.service.AutoService; import org.elasticsoftware.akces.annotations.*; @@ -28,10 +30,6 @@ import javax.tools.Diagnostic; import javax.tools.FileObject; import javax.tools.StandardLocation; -import java.io.IOException; -import java.io.Writer; -import java.util.*; -import java.util.stream.Stream; import static java.util.Objects.requireNonNull; diff --git a/main/query-support/src/main/java/org/elasticsoftware/akces/query/database/AkcesDatabaseModelController.java b/main/query-support/src/main/java/org/elasticsoftware/akces/query/database/AkcesDatabaseModelController.java index 74a99e74..f7e0c1d5 100644 --- a/main/query-support/src/main/java/org/elasticsoftware/akces/query/database/AkcesDatabaseModelController.java +++ b/main/query-support/src/main/java/org/elasticsoftware/akces/query/database/AkcesDatabaseModelController.java @@ -17,6 +17,8 @@ package org.elasticsoftware.akces.query.database; +import module java.base; + import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.annotation.Nonnull; import org.apache.kafka.clients.consumer.Consumer; @@ -51,10 +53,6 @@ import org.springframework.kafka.core.ConsumerFactory; import org.springframework.scheduling.concurrent.CustomizableThreadFactory; -import java.time.Duration; -import java.util.*; -import java.util.concurrent.*; - import static org.elasticsoftware.akces.query.database.AkcesDatabaseModelControllerState.*; public class AkcesDatabaseModelController extends Thread implements AutoCloseable, ConsumerRebalanceListener, ApplicationContextAware, AkcesRegistry { diff --git a/main/query-support/src/main/java/org/elasticsoftware/akces/query/models/AkcesQueryModelController.java b/main/query-support/src/main/java/org/elasticsoftware/akces/query/models/AkcesQueryModelController.java index fe5af3f2..d75cf645 100644 --- a/main/query-support/src/main/java/org/elasticsoftware/akces/query/models/AkcesQueryModelController.java +++ b/main/query-support/src/main/java/org/elasticsoftware/akces/query/models/AkcesQueryModelController.java @@ -17,6 +17,8 @@ package org.elasticsoftware.akces.query.models; +import module java.base; + import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.benmanes.caffeine.cache.Cache; @@ -56,14 +58,6 @@ import org.springframework.kafka.core.ConsumerFactory; import org.springframework.kafka.core.KafkaAdminOperations; -import java.io.IOException; -import java.time.Duration; -import java.util.*; -import java.util.concurrent.*; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - import static java.nio.charset.StandardCharsets.UTF_8; import static org.elasticsoftware.akces.query.models.AkcesQueryModelControllerState.*; import static org.elasticsoftware.akces.util.KafkaUtils.getIndexTopicName; diff --git a/main/runtime/src/main/java/org/elasticsoftware/akces/AkcesAggregateController.java b/main/runtime/src/main/java/org/elasticsoftware/akces/AkcesAggregateController.java index 0f3fbdaf..98684844 100644 --- a/main/runtime/src/main/java/org/elasticsoftware/akces/AkcesAggregateController.java +++ b/main/runtime/src/main/java/org/elasticsoftware/akces/AkcesAggregateController.java @@ -17,6 +17,8 @@ package org.elasticsoftware.akces; +import module java.base; + import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing; @@ -66,12 +68,6 @@ import org.springframework.kafka.core.ProducerFactory; import org.springframework.scheduling.concurrent.CustomizableThreadFactory; -import java.time.Duration; -import java.util.*; -import java.util.concurrent.*; -import java.util.function.BiFunction; -import java.util.stream.IntStream; - import static java.nio.charset.StandardCharsets.UTF_8; import static org.elasticsoftware.akces.AkcesControllerState.*; import static org.elasticsoftware.akces.gdpr.GDPRAnnotationUtils.hasPIIDataAnnotation; From 64752b6b1774b0a262e1f5ea2acf15192c8231ef Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 11:40:21 +0000 Subject: [PATCH 5/5] Revert flexible constructor body changes in UnknownSchemaException and SchemaNotBackwardsCompatibleException Co-authored-by: jwijgerd <914840+jwijgerd@users.noreply.github.com> --- .../elasticsoftware/akces/client/UnknownSchemaException.java | 4 +--- .../akces/schemas/SchemaNotBackwardsCompatibleException.java | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/main/client/src/main/java/org/elasticsoftware/akces/client/UnknownSchemaException.java b/main/client/src/main/java/org/elasticsoftware/akces/client/UnknownSchemaException.java index 8a06be7b..5e6de86d 100644 --- a/main/client/src/main/java/org/elasticsoftware/akces/client/UnknownSchemaException.java +++ b/main/client/src/main/java/org/elasticsoftware/akces/client/UnknownSchemaException.java @@ -25,9 +25,7 @@ public class UnknownSchemaException extends AkcesClientCommandException { private final String schemaIdentifier; public UnknownSchemaException(@Nonnull Class commandClass, String schemaIdentifier) { - CommandInfo commandInfo = commandClass.getAnnotation(CommandInfo.class); - String message = "Unknown Schema " + schemaIdentifier; - super(commandClass, commandInfo, message); + super(commandClass, commandClass.getAnnotation(CommandInfo.class), "Unknown Schema " + schemaIdentifier); this.schemaIdentifier = schemaIdentifier; } diff --git a/main/shared/src/main/java/org/elasticsoftware/akces/schemas/SchemaNotBackwardsCompatibleException.java b/main/shared/src/main/java/org/elasticsoftware/akces/schemas/SchemaNotBackwardsCompatibleException.java index 323d54a2..805cce1b 100644 --- a/main/shared/src/main/java/org/elasticsoftware/akces/schemas/SchemaNotBackwardsCompatibleException.java +++ b/main/shared/src/main/java/org/elasticsoftware/akces/schemas/SchemaNotBackwardsCompatibleException.java @@ -31,8 +31,7 @@ public SchemaNotBackwardsCompatibleException(String schemaIdentifier, int schemaVersion, Class implementationClass, List differences) { - String message = "Schema not backwards compatible with previous version: " + previousSchemaVersion; - super(message, schemaIdentifier, implementationClass); + super("Schema not backwards compatible with previous version: " + previousSchemaVersion, schemaIdentifier, implementationClass); this.previousSchemaVersion = previousSchemaVersion; this.schemaVersion = schemaVersion; this.differences = differences;