diff --git a/changelog/unreleased/SOLR-18085.yml b/changelog/unreleased/SOLR-18085.yml new file mode 100644 index 000000000000..d6ca801ddc8e --- /dev/null +++ b/changelog/unreleased/SOLR-18085.yml @@ -0,0 +1,8 @@ +# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc +title: Removed the wt=standard concept that was used internally by Solr. +type: removed # added, changed, fixed, deprecated, removed, dependency_update, security, other +authors: + - name: Eric Pugh +links: + - name: SOLR-18085 + url: https://issues.apache.org/jira/browse/SOLR-18085 diff --git a/solr/core/src/java/org/apache/solr/core/PluginBag.java b/solr/core/src/java/org/apache/solr/core/PluginBag.java index 7624a4c13ddd..1af3445e7aaa 100644 --- a/solr/core/src/java/org/apache/solr/core/PluginBag.java +++ b/solr/core/src/java/org/apache/solr/core/PluginBag.java @@ -202,7 +202,7 @@ public T get(String name) { * Fetches a plugin by name , or the default * * @param name name using which it is registered - * @param useDefault Return the default , if a plugin by that name does not exist + * @param useDefault Return the default, if a plugin by that name does not exist */ public T get(String name, boolean useDefault) { T result = get(name); diff --git a/solr/core/src/java/org/apache/solr/core/RequestHandlers.java b/solr/core/src/java/org/apache/solr/core/RequestHandlers.java index dca7c832e3fa..39f043d95f90 100644 --- a/solr/core/src/java/org/apache/solr/core/RequestHandlers.java +++ b/solr/core/src/java/org/apache/solr/core/RequestHandlers.java @@ -117,7 +117,7 @@ void initHandlersFromConfig(SolrConfig config) { modifiedInfos.add(applyInitParams(config, info)); } handlers.init(Collections.emptyMap(), core, modifiedInfos); - handlers.alias(handlers.getDefault(), ""); + if (log.isDebugEnabled()) { log.debug("Registered paths: {}", StrUtils.join(new ArrayList<>(handlers.keySet()), ',')); } diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java index c3aac28380e7..c936dda686f1 100644 --- a/solr/core/src/java/org/apache/solr/core/SolrCore.java +++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java @@ -3131,14 +3131,11 @@ private void initWriters() { // Initialize with the built defaults responseWriters.init(defaultWriters, this); - - // configure the default response writer; this one should never be null - if (responseWriters.getDefault() == null) responseWriters.setDefault("standard"); } - /** Finds a writer by name, or returns the default writer if not found. */ + /** Finds a writer by name, or null if not found. */ public final QueryResponseWriter getQueryResponseWriter(String writerName) { - return responseWriters.get(writerName, true); + return responseWriters.get(writerName, false); } /** diff --git a/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java b/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java index 0ce4d82e5516..c4aecf0c47ed 100644 --- a/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java +++ b/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java @@ -204,14 +204,7 @@ default CloudDescriptor getCloudDescriptor() { */ default QueryResponseWriter getResponseWriter() { // it's weird this method is here instead of SolrQueryResponse, but it's practical/convenient - SolrCore core = getCore(); - String wt = getParams().get(CommonParams.WT); - // Use core writers if available, otherwise fall back to built-in writers - if (core != null) { - return core.getQueryResponseWriter(wt); - } else { - return ResponseWritersRegistry.getWriter(wt); - } + return ResponseWritersRegistry.getWriter(getParams().get(CommonParams.WT), getCore()); } /** diff --git a/solr/core/src/java/org/apache/solr/response/RawResponseWriter.java b/solr/core/src/java/org/apache/solr/response/RawResponseWriter.java index 922b49329525..fe5269497ff1 100644 --- a/solr/core/src/java/org/apache/solr/response/RawResponseWriter.java +++ b/solr/core/src/java/org/apache/solr/response/RawResponseWriter.java @@ -47,7 +47,7 @@ public class RawResponseWriter implements QueryResponseWriter { */ public static final String CONTENT = "content"; - private String _baseWriter = null; + private String baseWriter = null; /** * A fallback writer used for requests that don't return raw content and that aren't associated @@ -62,14 +62,17 @@ public void init(NamedList n) { if (n != null) { Object base = n.get("base"); if (base != null) { - _baseWriter = base.toString(); + baseWriter = base.toString(); } } } protected QueryResponseWriter getBaseWriter(SolrQueryRequest request) { if (request.getCore() != null) { - return request.getCore().getQueryResponseWriter(_baseWriter); + // When baseWriter is null, use the core's default writer (useDefault=true) + // Otherwise, look up the specific writer by name (useDefault=false for explicit lookups) + boolean useDefault = (baseWriter == null); + return request.getCore().getResponseWriters().get(baseWriter, useDefault); } // Requests to a specific core already have writers, but we still need a 'default writer' for diff --git a/solr/core/src/java/org/apache/solr/response/ResponseWritersRegistry.java b/solr/core/src/java/org/apache/solr/response/ResponseWritersRegistry.java index f7d342bc2868..12d860cad394 100644 --- a/solr/core/src/java/org/apache/solr/response/ResponseWritersRegistry.java +++ b/solr/core/src/java/org/apache/solr/response/ResponseWritersRegistry.java @@ -20,7 +20,9 @@ import static org.apache.solr.util.stats.MetricUtils.PROMETHEUS_METRICS_WT; import java.util.Map; +import org.apache.solr.common.SolrException; import org.apache.solr.common.params.CommonParams; +import org.apache.solr.core.SolrCore; import org.apache.solr.handler.admin.api.ReplicationAPIBase; /** @@ -46,21 +48,14 @@ private ResponseWritersRegistry() { PrometheusResponseWriter prometheusWriter = new PrometheusResponseWriter(); BUILTIN_WRITERS = - Map.of( - CommonParams.JAVABIN, - new JavaBinResponseWriter(), - CommonParams.JSON, - jsonWriter, - "standard", - jsonWriter, // Alias for JSON - "xml", - new XMLResponseWriter(), - PROMETHEUS_METRICS_WT, - prometheusWriter, - OPEN_METRICS_WT, - prometheusWriter, - ReplicationAPIBase.FILE_STREAM, - new FileStreamResponseWriter()); + Map.ofEntries( + Map.entry(CommonParams.JAVABIN, new JavaBinResponseWriter()), + Map.entry(CommonParams.JSON, jsonWriter), + Map.entry("xml", new XMLResponseWriter()), + Map.entry("raw", new RawResponseWriter()), + Map.entry(PROMETHEUS_METRICS_WT, prometheusWriter), + Map.entry(OPEN_METRICS_WT, prometheusWriter), + Map.entry(ReplicationAPIBase.FILE_STREAM, new FileStreamResponseWriter())); } /** @@ -69,17 +64,68 @@ private ResponseWritersRegistry() { *

Built-in writers are always available and provide essential formats needed by admin APIs and * core functionality. They do not depend on core configuration or ImplicitPlugins.json settings. * - *

If the requested writer is not available, returns the "standard" (JSON) writer as a - * fallback. This ensures requests always get a valid response format. + *

If the requested writer is not available, returns the JSON writer as a fallback. This + * ensures requests always get a valid response format. * * @param writerName the writer name (e.g., "json", "xml", "javabin"), or null for default - * @return the response writer, never null (returns "standard"/JSON if not found) + * @return the response writer, never null (returns JSON if not found) */ public static QueryResponseWriter getWriter(String writerName) { if (writerName == null || writerName.isEmpty()) { - return BUILTIN_WRITERS.get("standard"); + writerName = CommonParams.JSON; } - return BUILTIN_WRITERS.getOrDefault(writerName, BUILTIN_WRITERS.get("standard")); + return BUILTIN_WRITERS.get(writerName); + } + + /** + * Gets a response writer, trying the core's registry first, then falling back to built-in + * writers. This is the unified entry point for all writer resolution. + * + *

Resolution order: + * + *

    + *
  1. If core is provided, check core's writer registry + *
  2. If not found in core (or no core), check built-in writers + *
  3. If writer name is explicitly specified but not found anywhere, throw exception + *
  4. If writer name is null/empty, return default (JSON) + *
+ * + * @param writerName the writer name (e.g., "json", "xml", "javabin"), or null for default + * @param core the SolrCore to check first, or null for node-level requests + * @return the response writer, never null + * @throws SolrException if an explicitly requested writer type is not found + */ + public static QueryResponseWriter getWriter(String writerName, SolrCore core) { + QueryResponseWriter writer = null; + + // Try core registry first if available + if (core != null) { + writer = core.getQueryResponseWriter(writerName); + } + + // If not found and writer is explicitly requested, validate it exists in built-in + if (writer == null) { + if (!hasWriter(writerName)) { + throw new SolrException( + SolrException.ErrorCode.SERVER_ERROR, "Unknown response writer type: " + writerName); + } else { + writer = getWriter(writerName); + } + } + return writer; + } + + /** + * Checks if a writer with the given name exists in the built-in writers. + * + * @param writerName the writer name to check + * @return true if the writer exists, false otherwise + */ + public static boolean hasWriter(String writerName) { + if (writerName == null || writerName.isEmpty()) { + return true; // null/empty is valid, will use default + } + return BUILTIN_WRITERS.containsKey(writerName); } /** diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java index 1229aed8d0a0..b73da05e0bfd 100644 --- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java +++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java @@ -727,7 +727,7 @@ private void handleAdminRequest() throws IOException { protected void logAndFlushAdminRequest(SolrQueryResponse solrResp) throws IOException { if (solrResp.getToLog().size() > 0) { - // has to come second and in it's own if to keep ./gradlew check happy. + // has to come second and in its own "if" to keep ./gradlew check happy. if (log.isInfoEnabled()) { log.info( handler != null diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java b/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java index 3cf12aa7982b..e835d844db86 100644 --- a/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java +++ b/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java @@ -67,13 +67,6 @@ public class SolrRequestParsers { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - // Should these constants be in a more public place? - public static final String MULTIPART = "multipart"; - public static final String FORMDATA = "formdata"; - public static final String RAW = "raw"; - public static final String SIMPLE = "simple"; - public static final String STANDARD = "standard"; - private static final Charset CHARSET_US_ASCII = StandardCharsets.US_ASCII; public static final String INPUT_ENCODING_KEY = "ie"; @@ -81,8 +74,7 @@ public class SolrRequestParsers { public static final String REQUEST_TIMER_SERVLET_ATTRIBUTE = "org.apache.solr.RequestTimer"; - private final HashMap parsers = new HashMap<>(); - private StandardRequestParser standard; + private StandardRequestParser parser; /** * Default instance for e.g. admin requests. Limits to 2 MB uploads and does not allow remote @@ -91,7 +83,7 @@ public class SolrRequestParsers { public static final SolrRequestParsers DEFAULT = new SolrRequestParsers(); /** - * Pass in an xml configuration. A null configuration will enable everything with maximum values. + * Pass in a xml configuration. A null configuration will enable everything with maximum values. */ public SolrRequestParsers(SolrConfig globalConfig) { final int multipartUploadLimitKB, formUploadLimitKB; @@ -116,21 +108,12 @@ private void init(int multipartUploadLimitKB, int formUploadLimitKB) { MultipartRequestParser multi = new MultipartRequestParser(multipartUploadLimitKB); RawRequestParser raw = new RawRequestParser(); FormDataRequestParser formdata = new FormDataRequestParser(formUploadLimitKB); - standard = new StandardRequestParser(multi, raw, formdata); - - // I don't see a need to have this publicly configured just yet - // adding it is trivial - parsers.put(MULTIPART, multi); - parsers.put(FORMDATA, formdata); - parsers.put(RAW, raw); - parsers.put(SIMPLE, new SimpleRequestParser()); - parsers.put(STANDARD, standard); - parsers.put("", standard); + parser = new StandardRequestParser(multi, raw, formdata); } private static RTimerTree getRequestTimer(HttpServletRequest req) { final Object reqTimer = req.getAttribute(REQUEST_TIMER_SERVLET_ATTRIBUTE); - if (reqTimer != null && reqTimer instanceof RTimerTree) { + if (reqTimer instanceof RTimerTree) { return ((RTimerTree) reqTimer); } @@ -139,7 +122,6 @@ private static RTimerTree getRequestTimer(HttpServletRequest req) { public SolrQueryRequest parse(SolrCore core, String path, HttpServletRequest req) throws Exception { - SolrRequestParser parser = standard; // TODO -- in the future, we could pick a different parser based on the request @@ -164,13 +146,12 @@ public SolrQueryRequest parse(SolrCore core, String path, HttpServletRequest req /** For embedded Solr use; not related to HTTP. */ public SolrQueryRequest buildRequestFrom( - SolrCore core, SolrParams params, Collection streams) throws Exception { + SolrCore core, SolrParams params, Collection streams) { return buildRequestFrom(core, params, streams, new RTimerTree(), null, null); } public SolrQueryRequest buildRequestFrom( - SolrCore core, SolrParams params, Collection streams, Principal principal) - throws Exception { + SolrCore core, SolrParams params, Collection streams, Principal principal) { return buildRequestFrom(core, params, streams, new RTimerTree(), null, principal); } @@ -181,7 +162,7 @@ private SolrQueryRequest buildRequestFrom( RTimerTree requestTimer, final HttpServletRequest req, final Principal principal) // from req, if req was provided, otherwise from elsewhere - throws Exception { + { // ensure streams is non-null and mutable so we can easily add to it if (streams == null) { streams = new ArrayList<>(); @@ -213,7 +194,7 @@ public List getCommands(boolean validateInput) { @Override public Map getPathTemplateValues() { - if (httpSolrCall != null && httpSolrCall instanceof V2HttpCall) { + if (httpSolrCall instanceof V2HttpCall) { return ((V2HttpCall) httpSolrCall).getUrlParts(); } return super.getPathTemplateValues(); @@ -337,9 +318,9 @@ static long parseFormDataContent( // we have no charset decoder until now, buffer the keys / values for later // processing: buffer.add(keyBytes); - buffer.add(Long.valueOf(keyPos)); + buffer.add(keyPos); buffer.add(valueBytes); - buffer.add(Long.valueOf(valuePos)); + buffer.add(valuePos); } else { // we already have a charsetDecoder, so we can directly decode without buffering: final String key = decodeChars(keyBytes, keyPos, charsetDecoder), @@ -457,7 +438,7 @@ private static int digit16(int b) { // ----------------------------------------------------------------- // ----------------------------------------------------------------- - // I guess we don't really even need the interface, but i'll keep it here just for kicks + // I guess we don't really even need the interface, but I'll keep it here just for kicks interface SolrRequestParser { public SolrParams parseParamsAndFillStreams( final HttpServletRequest req, ArrayList streams) throws Exception; @@ -466,15 +447,6 @@ public SolrParams parseParamsAndFillStreams( // ----------------------------------------------------------------- // ----------------------------------------------------------------- - /** The simple parser just uses the params directly, does not support POST URL-encoded forms */ - static class SimpleRequestParser implements SolrRequestParser { - @Override - public SolrParams parseParamsAndFillStreams( - final HttpServletRequest req, ArrayList streams) throws Exception { - return parseQueryString(req.getQueryString()); - } - } - /** Wrap an HttpServletRequest as a ContentStream */ static class HttpRequestContentStream extends ContentStreamBase { private final InputStream inputStream; @@ -515,7 +487,7 @@ public SolrParams parseParamsAndFillStreams( || req.getHeader("Transfer-Encoding") != null || !NO_BODY_METHODS.contains(req.getMethod())) { // If Content-Length > 0 OR Transfer-Encoding exists OR - // it's a method that can have a body (POST/PUT/PATCH etc) + // it's a method that can have a body (POST/PUT/PATCH etc.) streams.add(new HttpRequestContentStream(req, req.getInputStream())); } @@ -543,7 +515,7 @@ public SolrParams parseParamsAndFillStreams( throw new SolrException( ErrorCode.BAD_REQUEST, "Not multipart content! " + req.getContentType()); } - // Magic way to tell Jetty dynamically we want multi-part processing. + // Magic way to tell Jetty dynamically we want multipart processing. // This is taken from: // https://github.com/eclipse/jetty.project/blob/jetty-10.0.12/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java#L144 req.setAttribute("org.eclipse.jetty.multipartConfig", multipartConfigElement); @@ -735,7 +707,7 @@ static class StandardRequestParser implements SolrRequestParser { public SolrParams parseParamsAndFillStreams( final HttpServletRequest req, ArrayList streams) throws Exception { String contentType = req.getContentType(); - String method = req.getMethod(); // No need to uppercase... HTTP verbs are case sensitive + String method = req.getMethod(); // No need to uppercase... HTTP verbs are case-sensitive String uri = req.getRequestURI(); boolean isV2 = getHttpSolrCall(req) instanceof V2HttpCall; boolean isPost = "POST".equals(method); diff --git a/solr/core/src/test/org/apache/solr/OutputWriterTest.java b/solr/core/src/test/org/apache/solr/OutputWriterTest.java index 30df9ed98fab..7f711631ce17 100644 --- a/solr/core/src/test/org/apache/solr/OutputWriterTest.java +++ b/solr/core/src/test/org/apache/solr/OutputWriterTest.java @@ -29,32 +29,16 @@ /** Tests the ability to configure multiple query output writers, and select those at query time. */ public class OutputWriterTest extends SolrTestCaseJ4 { - /** The XML string that's output for testing purposes. */ - public static final String USELESS_OUTPUT = "useless output"; - @BeforeClass public static void beforeClass() throws Exception { initCore("solr/crazy-path-to-config.xml", "solr/crazy-path-to-schema.xml"); } - /** - * responseHeader has changed in SOLR-59, check old and new variants, In SOLR-2413, we removed - * support for the deprecated versions - */ - @Test - public void testSOLR59responseHeaderVersions() { - // default results in "new" responseHeader - lrf.args.put("wt", "standard"); - assertQ(req("foo"), "/response/lst[@name='responseHeader']/int[@name='status'][.='0']"); - lrf.args.remove("wt"); - assertQ(req("foo"), "/response/lst[@name='responseHeader']/int[@name='QTime']"); - } - @Test public void testUselessWriter() throws Exception { lrf.args.put("wt", "useless"); String out = h.query(req("foo")); - assertEquals(USELESS_OUTPUT, out); + assertEquals(UselessOutputWriter.USELESS_OUTPUT, out); } public void testLazy() { @@ -71,6 +55,9 @@ public void testLazy() { /** An output writer that doesn't do anything useful. */ public static class UselessOutputWriter implements TextQueryResponseWriter { + /** The XML string that's output for testing purposes. */ + public static final String USELESS_OUTPUT = "useless output"; + public UselessOutputWriter() {} @Override diff --git a/solr/core/src/test/org/apache/solr/handler/V2ApiIntegrationTest.java b/solr/core/src/test/org/apache/solr/handler/V2ApiIntegrationTest.java index 3b7a85eb0967..f58e8994107f 100644 --- a/solr/core/src/test/org/apache/solr/handler/V2ApiIntegrationTest.java +++ b/solr/core/src/test/org/apache/solr/handler/V2ApiIntegrationTest.java @@ -48,7 +48,7 @@ import org.junit.Test; public class V2ApiIntegrationTest extends SolrCloudTestCase { - private static String COLL_NAME = "collection1"; + private static final String COLL_NAME = "collection1"; @BeforeClass public static void createCluster() throws Exception { @@ -80,11 +80,7 @@ private void testException( .build(); v2Request.setResponseParser(responseParser); RemoteSolrException ex = - expectThrows( - RemoteSolrException.class, - () -> { - v2Request.process(cluster.getSolrClient()); - }); + expectThrows(RemoteSolrException.class, () -> v2Request.process(cluster.getSolrClient())); assertEquals(expectedCode, ex.code()); } @@ -114,26 +110,27 @@ public void testIntrospect() throws Exception { } @Test - public void testWTParam() throws Exception { + public void testInvalidWTParamReturnsError() throws Exception { V2Request request = new V2Request.Builder("/c/" + COLL_NAME + "/get/_introspect").build(); - // TODO: If possible do this in a better way + // Using an invalid wt parameter should return a 500 error request.setResponseParser(new InputStreamResponseParser("bleh")); NamedList res = cluster.getSolrClient().request(request); String respString = InputStreamResponseParser.consumeResponseToString(res); - assertFalse(respString.contains("

HTTP ERROR 500

")); - assertFalse(respString.contains("500")); - assertFalse(respString.contains("NullPointerException")); - assertFalse( - respString.contains( - "

Problem accessing /solr/____v2/c/collection1/get/_introspect. Reason:")); - // since no-op response writer is used, doing contains match - assertTrue(respString.contains("/c/collection1/get")); + // Should get a 500 Server Error for unknown writer type + assertTrue( + "Expected error message about unknown writer type", + respString.contains("Unknown response writer type")); + assertTrue("Expected 500 error code", respString.contains("500")); + } - // no response parser + @Test + public void testWTParam() throws Exception { + // When no response parser is set, the default JSON writer should be used + V2Request request = new V2Request.Builder("/c/" + COLL_NAME + "/get/_introspect").build(); request.setResponseParser(null); Map resp = resAsMap(cluster.getSolrClient(), request); - respString = resp.toString(); + String respString = resp.toString(); assertFalse(respString.contains("

HTTP ERROR 500

")); assertFalse( diff --git a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java index 530a2ba60093..9fd4edee073a 100644 --- a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java +++ b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java @@ -194,7 +194,8 @@ public void testUnsupportedMetricsFormat() throws Exception { try (SolrClient adminClient = getHttpSolrClient(solrTestRule.getBaseUrl())) { NamedList res = adminClient.request(req); - assertEquals(400, res.get("responseStatus")); + // Unknown wt parameter should return a 500 error + assertEquals(500, res.get("responseStatus")); } } } diff --git a/solr/core/src/test/org/apache/solr/response/TestRawResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestRawResponseWriter.java index 7b822b18848d..34e006b727ba 100644 --- a/solr/core/src/test/org/apache/solr/response/TestRawResponseWriter.java +++ b/solr/core/src/test/org/apache/solr/response/TestRawResponseWriter.java @@ -56,7 +56,9 @@ public static void setupCoreAndWriters() throws Exception { // we spin up. initCore("solrconfig.xml", "schema.xml"); - writerNoBase = newRawResponseWriter(null); /* defaults to standard writer as base */ + writerNoBase = + newRawResponseWriter( + null); /* null base uses core's default writer (XML for this core), or JSON if no core */ writerXmlBase = newRawResponseWriter("xml"); writerJsonBase = newRawResponseWriter("json"); writerBinBase = newRawResponseWriter("javabin"); @@ -120,7 +122,7 @@ public void testRawStringContentStream() throws IOException { // we should have UTF-8 Bytes if we use an OutputStream ByteArrayOutputStream bout = new ByteArrayOutputStream(); writer.write(bout, req(), rsp); - assertEquals(data, bout.toString(StandardCharsets.UTF_8.toString())); + assertEquals(data, bout.toString(StandardCharsets.UTF_8)); } } @@ -153,13 +155,12 @@ public void testStructuredDataViaBaseWriters() throws IOException { assertEquals(xml, writerXmlBase.writeToString(req(), rsp)); ByteArrayOutputStream xmlBout = new ByteArrayOutputStream(); writerXmlBase.write(xmlBout, req(), rsp); - assertEquals(xml, xmlBout.toString(StandardCharsets.UTF_8.toString())); + assertEquals(xml, xmlBout.toString(StandardCharsets.UTF_8)); - // assertEquals(xml, writerNoBase.writeToString(req(), rsp)); ByteArrayOutputStream noneBout = new ByteArrayOutputStream(); writerNoBase.write(noneBout, req(), rsp); - assertEquals(xml, noneBout.toString(StandardCharsets.UTF_8.toString())); + assertEquals(xml, noneBout.toString(StandardCharsets.UTF_8)); // json String json = "{\n" + " \"content\":\"test\",\n" + " \"foo\":\"bar\"}\n"; @@ -206,7 +207,7 @@ private byte[] convertJsonToCborFormat(byte[] inputJson) throws IOException { } /** - * Generates a new {@link RawResponseWriter} wrapping the specified baseWriter name (which much + * Generates a new {@link RawResponseWriter} wrapping the specified baseWriter name (which must * either be an implicitly defined response writer, or one explicitly configured in * solrconfig.xml) * diff --git a/solr/core/src/test/org/apache/solr/response/TestResponseWritersRegistry.java b/solr/core/src/test/org/apache/solr/response/TestResponseWritersRegistry.java index 695ad0e1278c..8fc7b178571b 100644 --- a/solr/core/src/test/org/apache/solr/response/TestResponseWritersRegistry.java +++ b/solr/core/src/test/org/apache/solr/response/TestResponseWritersRegistry.java @@ -31,34 +31,32 @@ public class TestResponseWritersRegistry extends SolrTestCaseJ4 { @Test public void testBuiltInWriterFallbackBehavior() { - QueryResponseWriter standardWriter = ResponseWritersRegistry.getWriter("standard"); + QueryResponseWriter defaultWriter = ResponseWritersRegistry.getWriter("json"); // Test null fallback QueryResponseWriter nullWriter = ResponseWritersRegistry.getWriter(null); - assertThat("null writer should not be null", nullWriter, is(not(nullValue()))); - assertThat("null writer should be same as standard", nullWriter, is(standardWriter)); + assertThat("null writer should be same as default", nullWriter, is(defaultWriter)); // Test empty string fallback QueryResponseWriter emptyWriter = ResponseWritersRegistry.getWriter(""); assertThat("empty writer should not be null", emptyWriter, is(not(nullValue()))); - assertThat("empty writer should be same as standard", emptyWriter, is(standardWriter)); + assertThat("empty writer should be same as default", emptyWriter, is(defaultWriter)); // Test unknown format fallback QueryResponseWriter unknownWriter = ResponseWritersRegistry.getWriter("nonexistent"); - assertThat("unknown writer should not be null", unknownWriter, is(not(nullValue()))); - assertThat("unknown writer should be same as standard", unknownWriter, is(standardWriter)); + assertThat("unknown writer should be null", unknownWriter, is(nullValue())); } @Test public void testBuiltInWriterLimitedSet() { - QueryResponseWriter standardWriter = ResponseWritersRegistry.getWriter("standard"); + QueryResponseWriter standardWriter = ResponseWritersRegistry.getWriter("json"); // Built-in writers should NOT include extended format writers (csv, geojson, etc.) - // These should all fall back to standard - // I think this standard thing is weird... I think it should throw an exception! + // These should all fall back to json + // I think this json thing is weird... I think it should throw an exception! assertThat( - "geojson should fall back to standard", + "geojson should fall back to json", ResponseWritersRegistry.getWriter("geojson"), - is(standardWriter)); + is(nullValue())); } } diff --git a/solr/packaging/test/test_rolling_upgrade.bats b/solr/packaging/test/test_rolling_upgrade.bats index 3902189eeb3f..ae956a868ba4 100644 --- a/solr/packaging/test/test_rolling_upgrade.bats +++ b/solr/packaging/test/test_rolling_upgrade.bats @@ -19,7 +19,7 @@ load bats_helper # You can test alternative images via # export SOLR_BEGIN_IMAGE="apache/solr-nightly:9.9.0-slim" and then running -# ./gradlw iTest --tests test_docker_solrcloud.bats +# ./gradlew iTest --tests test_rolling_upgrade.bats SOLR_BEGIN_IMAGE="${SOLR_BEGIN_IMAGE:-apache/solr-nightly:9.10.0-SNAPSHOT-slim}" SOLR_END_IMAGE="${SOLR_END_IMAGE:-apache/solr-nightly:10.0.0-SNAPSHOT-slim}" diff --git a/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java b/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java index 29caa318a048..a933605466fc 100644 --- a/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java +++ b/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java @@ -419,6 +419,7 @@ public LocalRequestFactory() {} @SuppressWarnings({"unchecked"}) public LocalSolrQueryRequest makeRequest(String... q) { if (q.length == 1) { + args.computeIfAbsent("wt", k -> "xml"); return new LocalSolrQueryRequest( TestHarness.this.getCore(), q[0], qtype, start, limit, args); }