Skip to content

Commit 3c0e49b

Browse files
adityamparikhclaude
andcommitted
feat(deps): upgrade solr-solrj from 9.9.0 to 10.0.0
- Bump solr version to 10.0.0 in libs.versions.toml - Remove Jetty BOM alignment (Solr 10 uses Jetty 12; no longer needed) - Remove Apache HttpComponents exclusion (SolrJ 10 no longer uses it) - Replace Http2SolrClient with HttpJdkSolrClient (new JDK HTTP client) - Move SolrQuery import: solrj → solrj.request package - Move ResponseParser import: solrj → solrj.response package - Adapt ResponseParser: getContentType() → getContentTypes() returning Collection<String>; remove processResponse(Reader) (no longer abstract) - Fix CoreAdminResponse.getCoreStatus(): now returns Map<String, SingleCoreData> instead of NamedList — update listCollections() and CollectionServiceTest accordingly All unit and Testcontainers integration tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: adityamparikh <aditya.m.parikh@gmail.com>
1 parent 5d5db1b commit 3c0e49b

10 files changed

Lines changed: 31 additions & 51 deletions

File tree

build.gradle.kts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,7 @@ dependencies {
9696
implementation(libs.spring.boot.starter.web)
9797
implementation(libs.spring.boot.starter.actuator)
9898
implementation(libs.spring.ai.starter.mcp.server.webmvc)
99-
implementation(libs.solr.solrj) {
100-
exclude(group = "org.apache.httpcomponents")
101-
}
99+
implementation(libs.solr.solrj)
102100
implementation(libs.commons.csv)
103101
// JSpecify for nullability annotations
104102
implementation(libs.jspecify)
@@ -119,8 +117,6 @@ dependencies {
119117
dependencyManagement {
120118
imports {
121119
mavenBom("org.springframework.ai:spring-ai-bom:${libs.versions.spring.ai.get()}")
122-
// Align Jetty family to 10.x compatible with SolrJ 9.x
123-
mavenBom("org.eclipse.jetty:jetty-bom:${libs.versions.jetty.get()}")
124120
}
125121
}
126122

gradle/libs.versions.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ spotless = "7.0.2"
88

99
# Main dependencies
1010
spring-ai = "1.1.2"
11-
solr = "9.9.0"
11+
solr = "10.0.0"
1212
commons-csv = "1.10.0"
1313
jspecify = "1.0.0"
1414
mcp-server-security = "0.0.4"
@@ -17,8 +17,6 @@ mcp-server-security = "0.0.4"
1717
errorprone-core = "2.38.0"
1818
nullaway = "0.12.7"
1919

20-
# Jetty BOM version
21-
jetty = "10.0.22"
2220

2321
# Test dependencies
2422
testcontainers = "1.21.3"

src/main/java/org/apache/solr/mcp/server/collection/CollectionService.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@
2727
import java.util.Date;
2828
import java.util.List;
2929
import org.apache.solr.client.solrj.SolrClient;
30-
import org.apache.solr.client.solrj.SolrQuery;
3130
import org.apache.solr.client.solrj.SolrRequest;
3231
import org.apache.solr.client.solrj.SolrServerException;
3332
import org.apache.solr.client.solrj.impl.CloudSolrClient;
3433
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
3534
import org.apache.solr.client.solrj.request.CoreAdminRequest;
3635
import org.apache.solr.client.solrj.request.GenericSolrRequest;
3736
import org.apache.solr.client.solrj.request.LukeRequest;
37+
import org.apache.solr.client.solrj.request.SolrQuery;
3838
import org.apache.solr.client.solrj.response.CollectionAdminResponse;
3939
import org.apache.solr.client.solrj.response.CoreAdminResponse;
4040
import org.apache.solr.client.solrj.response.LukeResponse;
@@ -371,12 +371,7 @@ public List<String> listCollections() {
371371
coreAdminRequest.setAction(CoreAdminParams.CoreAdminAction.STATUS);
372372
CoreAdminResponse coreResponse = coreAdminRequest.process(solrClient);
373373

374-
List<String> cores = new ArrayList<>();
375-
NamedList<NamedList<Object>> coreStatus = coreResponse.getCoreStatus();
376-
for (int i = 0; i < coreStatus.size(); i++) {
377-
cores.add(coreStatus.getName(i));
378-
}
379-
return cores;
374+
return new ArrayList<>(coreResponse.getCoreStatus().keySet());
380375
}
381376
} catch (SolrServerException | IOException e) {
382377
return new ArrayList<>();

src/main/java/org/apache/solr/mcp/server/config/JsonResponseParser.java

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
import com.fasterxml.jackson.databind.ObjectMapper;
2121
import java.io.IOException;
2222
import java.io.InputStream;
23-
import java.io.Reader;
2423
import java.util.ArrayList;
24+
import java.util.Collection;
2525
import java.util.List;
26-
import org.apache.solr.client.solrj.ResponseParser;
26+
import org.apache.solr.client.solrj.response.ResponseParser;
2727
import org.apache.solr.common.SolrDocument;
2828
import org.apache.solr.common.SolrDocumentList;
2929
import org.apache.solr.common.SolrException;
@@ -75,8 +75,8 @@ public String getWriterType() {
7575
}
7676

7777
@Override
78-
public String getContentType() {
79-
return "application/json; charset=UTF-8";
78+
public Collection<String> getContentTypes() {
79+
return List.of("application/json; charset=UTF-8");
8080
}
8181

8282
@Override
@@ -88,15 +88,6 @@ public NamedList<Object> processResponse(InputStream body, String encoding) {
8888
}
8989
}
9090

91-
@Override
92-
public NamedList<Object> processResponse(Reader reader) {
93-
try {
94-
return toNamedList(MAPPER.readTree(reader));
95-
} catch (IOException e) {
96-
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Failed to parse Solr JSON response", e);
97-
}
98-
}
99-
10091
private SimpleOrderedMap<Object> toNamedList(JsonNode objectNode) {
10192
SimpleOrderedMap<Object> result = new SimpleOrderedMap<>();
10293
objectNode.fields().forEachRemaining(entry -> result.add(entry.getKey(), convertValue(entry.getValue())));

src/main/java/org/apache/solr/mcp/server/config/SolrConfig.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import java.util.concurrent.TimeUnit;
2020
import org.apache.solr.client.solrj.SolrClient;
21-
import org.apache.solr.client.solrj.impl.Http2SolrClient;
21+
import org.apache.solr.client.solrj.impl.HttpJdkSolrClient;
2222
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2323
import org.springframework.context.annotation.Bean;
2424
import org.springframework.context.annotation.Configuration;
@@ -95,7 +95,7 @@
9595
* @version 1.0.0
9696
* @since 1.0.0
9797
* @see SolrConfigurationProperties
98-
* @see Http2SolrClient
98+
* @see HttpJdkSolrClient
9999
* @see org.springframework.boot.context.properties.EnableConfigurationProperties
100100
*/
101101
@Configuration
@@ -164,7 +164,7 @@ public class SolrConfig {
164164
* the injected Solr configuration properties containing connection
165165
* URL
166166
* @return configured SolrClient instance ready for use in application services
167-
* @see Http2SolrClient.Builder
167+
* @see HttpJdkSolrClient.Builder
168168
* @see SolrConfigurationProperties#url()
169169
*/
170170
@Bean
@@ -192,7 +192,7 @@ SolrClient solrClient(SolrConfigurationProperties properties, JsonResponseParser
192192
}
193193

194194
// Use with explicit base URL; JSON wire format replaces the JavaBin default
195-
return new Http2SolrClient.Builder(url).withConnectionTimeout(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)
195+
return new HttpJdkSolrClient.Builder(url).withConnectionTimeout(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)
196196
.withIdleTimeout(SOCKET_TIMEOUT_MS, TimeUnit.MILLISECONDS).withResponseParser(jsonResponseParser)
197197
.build();
198198
}

src/main/java/org/apache/solr/mcp/server/search/SearchService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
import java.util.List;
2323
import java.util.Map;
2424
import org.apache.solr.client.solrj.SolrClient;
25-
import org.apache.solr.client.solrj.SolrQuery;
2625
import org.apache.solr.client.solrj.SolrServerException;
26+
import org.apache.solr.client.solrj.request.SolrQuery;
2727
import org.apache.solr.client.solrj.response.FacetField;
2828
import org.apache.solr.client.solrj.response.QueryResponse;
2929
import org.apache.solr.common.SolrDocument;

src/test/java/org/apache/solr/mcp/server/collection/CollectionServiceTest.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
import java.lang.reflect.Method;
2727
import java.util.Arrays;
2828
import java.util.Collections;
29+
import java.util.HashMap;
2930
import java.util.List;
31+
import java.util.Map;
3032
import org.apache.solr.client.solrj.SolrClient;
3133
import org.apache.solr.client.solrj.SolrRequest;
3234
import org.apache.solr.client.solrj.SolrServerException;
@@ -744,15 +746,13 @@ void listCollections_CloudClient_Error() throws Exception {
744746

745747
@Test
746748
void listCollections_NonCloudClient_Success() throws Exception {
747-
// Create a NamedList to represent the core status response
749+
// Create a NamedList to represent the core status response.
750+
// The "status" value must be a Map so SolrJ 10 can use Jackson convertValue
751+
// to produce Map<String, SingleCoreData>.
748752
NamedList<Object> response = new NamedList<>();
749-
NamedList<Object> status = new NamedList<>();
750-
751-
NamedList<Object> core1Status = new NamedList<>();
752-
NamedList<Object> core2Status = new NamedList<>();
753-
754-
status.add("core1", core1Status);
755-
status.add("core2", core2Status);
753+
Map<String, Object> status = new HashMap<>();
754+
status.put("core1", new HashMap<>());
755+
status.put("core2", new HashMap<>());
756756
response.add("status", status);
757757

758758
// Mock the solrClient request to return the response

src/test/java/org/apache/solr/mcp/server/config/SolrConfigTest.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import static org.junit.jupiter.api.Assertions.*;
2020

2121
import org.apache.solr.client.solrj.SolrClient;
22-
import org.apache.solr.client.solrj.impl.Http2SolrClient;
22+
import org.apache.solr.client.solrj.impl.HttpJdkSolrClient;
2323
import org.apache.solr.mcp.server.TestcontainersConfiguration;
2424
import org.junit.jupiter.api.Test;
2525
import org.junit.jupiter.params.ParameterizedTest;
@@ -51,9 +51,9 @@ void testSolrClientConfiguration() {
5151

5252
// Verify that the SolrClient is using the correct URL
5353
// Note: SolrConfig normalizes the URL to have trailing slash, but
54-
// Http2SolrClient removes
54+
// HttpJdkSolrClient removes
5555
// it
56-
var httpSolrClient = assertInstanceOf(Http2SolrClient.class, solrClient);
56+
var httpSolrClient = assertInstanceOf(HttpJdkSolrClient.class, solrClient);
5757
String expectedUrl = "http://" + solrContainer.getHost() + ":" + solrContainer.getMappedPort(8983) + "/solr";
5858
assertEquals(expectedUrl, httpSolrClient.getBaseURL());
5959
}
@@ -84,7 +84,7 @@ void testUrlNormalization(String inputUrl, String expectedUrl) {
8484
SolrClient client = solrConfig.solrClient(testProperties, new JsonResponseParser());
8585
assertNotNull(client);
8686

87-
var httpClient = assertInstanceOf(Http2SolrClient.class, client);
87+
var httpClient = assertInstanceOf(HttpJdkSolrClient.class, client);
8888
assertEquals(expectedUrl, httpClient.getBaseURL());
8989

9090
// Clean up
@@ -102,7 +102,7 @@ void testUrlWithoutTrailingSlash() {
102102
SolrConfig solrConfig = new SolrConfig();
103103

104104
SolrClient client = solrConfig.solrClient(testProperties, new JsonResponseParser());
105-
Http2SolrClient httpClient = (Http2SolrClient) client;
105+
HttpJdkSolrClient httpClient = (HttpJdkSolrClient) client;
106106

107107
// Should add trailing slash and solr path
108108
assertEquals("http://localhost:8983/solr", httpClient.getBaseURL());
@@ -121,7 +121,7 @@ void testUrlWithTrailingSlashButNoSolrPath() {
121121
SolrConfig solrConfig = new SolrConfig();
122122

123123
SolrClient client = solrConfig.solrClient(testProperties, new JsonResponseParser());
124-
Http2SolrClient httpClient = (Http2SolrClient) client;
124+
HttpJdkSolrClient httpClient = (HttpJdkSolrClient) client;
125125

126126
// Should add solr path to existing trailing slash
127127
assertEquals("http://localhost:8983/solr", httpClient.getBaseURL());
@@ -140,7 +140,7 @@ void testUrlWithSolrPathButNoTrailingSlash() {
140140
SolrConfig solrConfig = new SolrConfig();
141141

142142
SolrClient client = solrConfig.solrClient(testProperties, new JsonResponseParser());
143-
Http2SolrClient httpClient = (Http2SolrClient) client;
143+
HttpJdkSolrClient httpClient = (HttpJdkSolrClient) client;
144144

145145
// Should add trailing slash
146146
assertEquals("http://localhost:8983/solr", httpClient.getBaseURL());
@@ -159,7 +159,7 @@ void testUrlAlreadyProperlyFormatted() {
159159
SolrConfig solrConfig = new SolrConfig();
160160

161161
SolrClient client = solrConfig.solrClient(testProperties, new JsonResponseParser());
162-
Http2SolrClient httpClient = (Http2SolrClient) client;
162+
HttpJdkSolrClient httpClient = (HttpJdkSolrClient) client;
163163

164164
// Should remain unchanged
165165
assertEquals("http://localhost:8983/solr", httpClient.getBaseURL());

src/test/java/org/apache/solr/mcp/server/search/SearchServiceDirectTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
import java.util.List;
2727
import java.util.Map;
2828
import org.apache.solr.client.solrj.SolrClient;
29-
import org.apache.solr.client.solrj.SolrQuery;
3029
import org.apache.solr.client.solrj.SolrServerException;
30+
import org.apache.solr.client.solrj.request.SolrQuery;
3131
import org.apache.solr.client.solrj.response.FacetField;
3232
import org.apache.solr.client.solrj.response.QueryResponse;
3333
import org.apache.solr.common.SolrDocument;

src/test/java/org/apache/solr/mcp/server/search/SearchServiceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@
2828
import java.util.Map;
2929
import java.util.OptionalDouble;
3030
import org.apache.solr.client.solrj.SolrClient;
31-
import org.apache.solr.client.solrj.SolrQuery;
3231
import org.apache.solr.client.solrj.SolrServerException;
3332
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
33+
import org.apache.solr.client.solrj.request.SolrQuery;
3434
import org.apache.solr.client.solrj.response.FacetField;
3535
import org.apache.solr.client.solrj.response.QueryResponse;
3636
import org.apache.solr.common.SolrDocument;

0 commit comments

Comments
 (0)