From 44b5f9da6f3d7f01fde58a0b360780ee3d962462 Mon Sep 17 00:00:00 2001 From: adityamparikh Date: Fri, 24 Apr 2026 14:15:38 -0400 Subject: [PATCH] refactor: replace mutable Date with Instant in DTO records Replace java.util.Date with java.time.Instant in SolrMetrics, SolrHealthStatus, and CollectionCreationResult records to achieve true immutability. Date is mutable and can be modified through record accessors, breaking the immutability contract of records. - Update Dtos.java: Date -> Instant, simplify @JsonFormat annotations - Update CollectionService.java: new Date() -> Instant.now() - Update CollectionServiceIntegrationTest.java: adapt timestamp assertion Closes #15 Signed-off-by: Aditya Parikh Co-Authored-By: Claude Opus 4.6 (1M context) Signed-off-by: adityamparikh --- .../solr/mcp/server/collection/CollectionService.java | 10 +++++----- .../org/apache/solr/mcp/server/collection/Dtos.java | 8 ++++---- .../collection/CollectionServiceIntegrationTest.java | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/apache/solr/mcp/server/collection/CollectionService.java b/src/main/java/org/apache/solr/mcp/server/collection/CollectionService.java index 48ec56d3..f42a15fc 100644 --- a/src/main/java/org/apache/solr/mcp/server/collection/CollectionService.java +++ b/src/main/java/org/apache/solr/mcp/server/collection/CollectionService.java @@ -24,8 +24,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.micrometer.observation.annotation.Observed; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; -import java.util.Date; import java.util.List; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; @@ -428,7 +428,7 @@ public SolrMetrics getCollectionStats( QueryResponse statsResponse = solrClient.query(actualCollection, new SolrQuery(ALL_DOCUMENTS_QUERY).setRows(0)); return new SolrMetrics(buildIndexStats(lukeResponse), buildQueryStats(statsResponse), - fetchCacheMetrics(actualCollection), fetchHandlerMetrics(actualCollection), new Date()); + fetchCacheMetrics(actualCollection), fetchHandlerMetrics(actualCollection), Instant.now()); } /** @@ -967,10 +967,10 @@ public SolrHealthStatus checkHealth(@McpToolParam(description = "Solr collection new SolrQuery(ALL_DOCUMENTS_QUERY).setRows(0)); return new SolrHealthStatus(true, null, pingResponse.getElapsedTime(), - statsResponse.getResults().getNumFound(), new Date(), actualCollection, null, null); + statsResponse.getResults().getNumFound(), Instant.now(), actualCollection, null, null); } catch (Exception e) { - return new SolrHealthStatus(false, e.getMessage(), null, null, new Date(), actualCollection, null, null); + return new SolrHealthStatus(false, e.getMessage(), null, null, Instant.now(), actualCollection, null, null); } } @@ -1027,6 +1027,6 @@ public CollectionCreationResult createCollection( CollectionAdminRequest.createCollection(name, effectiveConfigSet, effectiveShards, effectiveRf) .process(solrClient); - return new CollectionCreationResult(name, true, "Collection created successfully", new Date()); + return new CollectionCreationResult(name, true, "Collection created successfully", Instant.now()); } } diff --git a/src/main/java/org/apache/solr/mcp/server/collection/Dtos.java b/src/main/java/org/apache/solr/mcp/server/collection/Dtos.java index 13a898ef..7a377991 100644 --- a/src/main/java/org/apache/solr/mcp/server/collection/Dtos.java +++ b/src/main/java/org/apache/solr/mcp/server/collection/Dtos.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; -import java.util.Date; +import java.time.Instant; /** * Data Transfer Objects (DTOs) for the Apache Solr MCP Server. @@ -104,7 +104,7 @@ record SolrMetrics( HandlerStats handlerStats, /** Timestamp when these metrics were collected, formatted as ISO 8601 */ - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") Date timestamp) { + @JsonFormat(shape = JsonFormat.Shape.STRING) Instant timestamp) { } /** @@ -464,7 +464,7 @@ record SolrHealthStatus( Long totalDocuments, /** Timestamp when this health check was performed, formatted as ISO 8601 */ - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") Date lastChecked, + @JsonFormat(shape = JsonFormat.Shape.STRING) Instant lastChecked, /** Name of the collection that was checked */ String collection, @@ -497,5 +497,5 @@ record CollectionCreationResult( String message, /** Timestamp when the collection was created, formatted as ISO 8601 */ - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") Date createdAt) { + @JsonFormat(shape = JsonFormat.Shape.STRING) Instant createdAt) { } diff --git a/src/test/java/org/apache/solr/mcp/server/collection/CollectionServiceIntegrationTest.java b/src/test/java/org/apache/solr/mcp/server/collection/CollectionServiceIntegrationTest.java index 788b9527..3c3a2e1d 100644 --- a/src/test/java/org/apache/solr/mcp/server/collection/CollectionServiceIntegrationTest.java +++ b/src/test/java/org/apache/solr/mcp/server/collection/CollectionServiceIntegrationTest.java @@ -173,7 +173,7 @@ void testCheckHealth_healthy() { assertEquals((long) DOC_COUNT, status.totalDocuments(), "Health check should report indexed document count"); assertNotNull(status.lastChecked()); - assertTrue(System.currentTimeMillis() - status.lastChecked().getTime() < 5000); + assertTrue(java.time.Duration.between(status.lastChecked(), java.time.Instant.now()).toMillis() < 5000); } @Test