diff --git a/changelog/unreleased/SOLR-16458-migrate-node-properties-api.yml b/changelog/unreleased/SOLR-16458-migrate-node-properties-api.yml new file mode 100644 index 000000000000..2f4a23beaa48 --- /dev/null +++ b/changelog/unreleased/SOLR-16458-migrate-node-properties-api.yml @@ -0,0 +1,8 @@ +title: "v2 GET /api/node/properties is now a JAX-RS API; a single property is fetched at /api/node/properties/{propertyName} (SolrJ: NodeApi.GetNodeProperties / GetNodeProperty)" +type: added +authors: + - name: Prithvi S + nick: iprithv +links: + - name: SOLR-16458 + url: https://issues.apache.org/jira/browse/SOLR-16458 diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/NodePropertiesApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/NodePropertiesApi.java new file mode 100644 index 000000000000..7c986e5ad828 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/NodePropertiesApi.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.client.api.endpoint; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import org.apache.solr.client.api.model.NodePropertiesResponse; + +/** V2 API definition for listing JRE system properties on a Solr node. */ +@Path("/node/properties") +public interface NodePropertiesApi { + + @GET + @Operation( + summary = "List system properties for the target Solr node.", + tags = {"node"}) + NodePropertiesResponse getNodeProperties(); + + @GET + @Path("/{propertyName}") + @Operation( + summary = "Get a single system property for the target Solr node.", + tags = {"node"}) + NodePropertiesResponse getNodeProperty( + @Parameter(description = "Name of the system property to return.") @PathParam("propertyName") + String propertyName); +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/NodePropertiesResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/NodePropertiesResponse.java new file mode 100644 index 000000000000..81ca0331fdde --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/NodePropertiesResponse.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.Map; + +/** + * Response body for {@code GET /api/node/properties} and {@code GET + * /api/node/properties/{propertyName}}. + */ +public class NodePropertiesResponse extends SolrJerseyResponse { + + public static final String SYSTEM_PROPERTIES = "system.properties"; + + @Schema(description = "JRE system properties for the Solr node. Secret values are redacted.") + @JsonProperty(SYSTEM_PROPERTIES) + public Map systemProperties; +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/PropertiesRequestHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/PropertiesRequestHandler.java index 8658adf3c528..37f9a786c36e 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/PropertiesRequestHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/PropertiesRequestHandler.java @@ -16,24 +16,27 @@ */ package org.apache.solr.handler.admin; +import static org.apache.solr.client.api.model.NodePropertiesResponse.SYSTEM_PROPERTIES; import static org.apache.solr.common.params.CommonParams.NAME; -import java.io.IOException; import java.util.Collection; -import java.util.Enumeration; -import org.apache.solr.api.AnnotatedApi; +import java.util.List; +import java.util.Map; import org.apache.solr.api.Api; +import org.apache.solr.api.JerseyResource; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SimpleOrderedMap; import org.apache.solr.core.CoreContainer; -import org.apache.solr.core.NodeConfig; import org.apache.solr.handler.RequestHandlerBase; -import org.apache.solr.handler.admin.api.NodePropertiesAPI; +import org.apache.solr.handler.admin.api.GetNodeProperties; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.security.AuthorizationContext; /** + * v1 implementation of {@code GET /admin/info/properties}. Business logic lives in {@link + * GetNodeProperties}. + * * @since solr 1.2 */ public class PropertiesRequestHandler extends RequestHandlerBase { @@ -50,22 +53,14 @@ public PropertiesRequestHandler(CoreContainer cc) { } @Override - public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException { - NamedList props = new SimpleOrderedMap<>(); - String name = req.getParams().get(NAME); - NodeConfig nodeConfig = getCoreContainer(req).getNodeConfig(); - if (name != null) { - String property = nodeConfig.getRedactedSysPropValue(name); - props.add(name, property); - } else { - Enumeration enumeration = System.getProperties().propertyNames(); - while (enumeration.hasMoreElements()) { - name = (String) enumeration.nextElement(); - props.add(name, nodeConfig.getRedactedSysPropValue(name)); - } - } - rsp.add("system.properties", props); + public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { rsp.setHttpCaching(false); + String name = req.getParams().get(NAME); + Map props = + new GetNodeProperties(getCoreContainer(req)).collectProperties(name); + NamedList values = new SimpleOrderedMap<>(); + props.forEach(values::add); + rsp.add(SYSTEM_PROPERTIES, values); } //////////////////////// SolrInfoMBeans methods ////////////////////// @@ -82,7 +77,12 @@ public Category getCategory() { @Override public Collection getApis() { - return AnnotatedApi.getApis(new NodePropertiesAPI(this)); + return List.of(); + } + + @Override + public Collection> getJerseyResources() { + return List.of(GetNodeProperties.class); } @Override diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetNodeProperties.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetNodeProperties.java new file mode 100644 index 000000000000..5296b1cd7760 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetNodeProperties.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.handler.admin.api; + +import jakarta.inject.Inject; +import java.util.Enumeration; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.solr.api.JerseyResource; +import org.apache.solr.client.api.endpoint.NodePropertiesApi; +import org.apache.solr.client.api.model.NodePropertiesResponse; +import org.apache.solr.core.CoreContainer; +import org.apache.solr.core.NodeConfig; +import org.apache.solr.jersey.PermissionName; +import org.apache.solr.security.PermissionNameProvider; + +/** + * V2 API for listing system properties on the receiving node. + * + *

GET /api/node/properties lists all properties. GET /api/node/properties/{propertyName} returns + * a single property. Both are analogous to v1 /admin/info/properties, which still uses a {@code + * name} query parameter for the single-property form. + * + *

The v1 {@link org.apache.solr.handler.admin.PropertiesRequestHandler} delegates to this class. + */ +public class GetNodeProperties extends JerseyResource implements NodePropertiesApi { + + private final CoreContainer coreContainer; + + @Inject + public GetNodeProperties(CoreContainer coreContainer) { + this.coreContainer = coreContainer; + } + + @Override + @PermissionName(PermissionNameProvider.Name.CONFIG_READ_PERM) + public NodePropertiesResponse getNodeProperties() { + return buildResponse(null); + } + + @Override + @PermissionName(PermissionNameProvider.Name.CONFIG_READ_PERM) + public NodePropertiesResponse getNodeProperty(String propertyName) { + return buildResponse(propertyName); + } + + private NodePropertiesResponse buildResponse(String name) { + final NodePropertiesResponse response = instantiateJerseyResponse(NodePropertiesResponse.class); + response.systemProperties = collectProperties(name); + return response; + } + + /** Collect redacted system properties, optionally limited to a single named property. */ + public Map collectProperties(String name) { + final NodeConfig nodeConfig = coreContainer.getNodeConfig(); + final Map props = new LinkedHashMap<>(); + if (name != null) { + props.put(name, nodeConfig.getRedactedSysPropValue(name)); + } else { + Enumeration enumeration = System.getProperties().propertyNames(); + while (enumeration.hasMoreElements()) { + String propertyName = (String) enumeration.nextElement(); + props.put(propertyName, nodeConfig.getRedactedSysPropValue(propertyName)); + } + } + return props; + } +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/NodePropertiesAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/NodePropertiesAPI.java deleted file mode 100644 index d9cf81f8a8b1..000000000000 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/NodePropertiesAPI.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.solr.handler.admin.api; - -import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET; -import static org.apache.solr.security.PermissionNameProvider.Name.CONFIG_READ_PERM; - -import org.apache.solr.api.EndPoint; -import org.apache.solr.handler.admin.PropertiesRequestHandler; -import org.apache.solr.request.SolrQueryRequest; -import org.apache.solr.response.SolrQueryResponse; - -/** - * V2 API for listing system properties for each node. - * - *

This API (GET /v2/node/properties) is analogous to the v1 /admin/info/properties. - */ -public class NodePropertiesAPI { - private final PropertiesRequestHandler handler; - - public NodePropertiesAPI(PropertiesRequestHandler handler) { - this.handler = handler; - } - - @EndPoint( - path = {"/node/properties"}, - method = GET, - permission = CONFIG_READ_PERM) - public void getRequestedProperties(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { - handler.handleRequestBody(req, rsp); - } -} diff --git a/solr/core/src/test/org/apache/solr/handler/admin/InfoHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/InfoHandlerTest.java index 3e0100b14fbf..90f95cb86ddb 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/InfoHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/InfoHandlerTest.java @@ -111,7 +111,7 @@ public static class CountPropertiesRequestHandler extends PropertiesRequestHandl private int requestCount = 0; @Override - public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException { + public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { ++requestCount; super.handleRequestBody(req, rsp); } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/PropertiesRequestHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/PropertiesRequestHandlerTest.java index f64b96ae3114..2c7854e75986 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/PropertiesRequestHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/PropertiesRequestHandlerTest.java @@ -21,6 +21,7 @@ import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer; import org.apache.solr.client.solrj.request.GenericSolrRequest; +import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.core.NodeConfig; import org.junit.BeforeClass; @@ -54,12 +55,32 @@ public void testRedaction() throws Exception { } } - @SuppressWarnings({"unchecked"}) + @Test + public void testSingleProperty() throws Exception { + System.setProperty("GetNodeProperties.v1.visible", "hello"); + try { + NamedList properties = readProperties("GetNodeProperties.v1.visible"); + assertEquals(1, properties.size()); + assertEquals("hello", properties.get("GetNodeProperties.v1.visible")); + } finally { + System.clearProperty("GetNodeProperties.v1.visible"); + } + } + private NamedList readProperties() throws Exception { - SolrClient client = new EmbeddedSolrServer(h.getCore()); + return readProperties(null); + } + @SuppressWarnings({"unchecked"}) + private NamedList readProperties(String name) throws Exception { + SolrClient client = new EmbeddedSolrServer(h.getCore()); + ModifiableSolrParams params = new ModifiableSolrParams(); + if (name != null) { + params.set("name", name); + } NamedList properties = - client.request(new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/info/properties")); + client.request( + new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/info/properties", params)); return (NamedList) properties.get("system.properties"); } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetNodePropertiesTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetNodePropertiesTest.java new file mode 100644 index 000000000000..79745cf66353 --- /dev/null +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetNodePropertiesTest.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.handler.admin.api; + +import org.apache.solr.SolrTestCase; +import org.apache.solr.client.api.model.NodePropertiesResponse; +import org.apache.solr.client.solrj.request.NodeApi; +import org.apache.solr.core.NodeConfig; +import org.apache.solr.util.SolrJettyTestRule; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; + +/** + * HTTP tests for {@code GET /api/node/properties} and {@code GET + * /api/node/properties/{propertyName}} via the generated SolrJ client classes. + */ +public class GetNodePropertiesTest extends SolrTestCase { + + private static final String VISIBLE_PROP = "GetNodePropertiesTest.visible"; + private static final String SECRET_PROP = "GetNodePropertiesTest.password"; + private static final String PASSWORD = "secret123"; + + @ClassRule public static final SolrJettyTestRule solrTestRule = new SolrJettyTestRule(); + + @BeforeClass + public static void setupSolr() throws Exception { + solrTestRule.startSolr(createTempDir()); + } + + @After + public void clearTestProperties() { + System.clearProperty(VISIBLE_PROP); + System.clearProperty(SECRET_PROP); + } + + @Test + public void testNamedProperty() throws Exception { + var req = new NodeApi.GetNodeProperty("java.version"); + var rsp = req.process(solrTestRule.getAdminClient()); + + assertNotNull(rsp); + assertNull(rsp.error); + assertEquals(1, rsp.systemProperties.size()); + assertEquals(System.getProperty("java.version"), rsp.systemProperties.get("java.version")); + } + + @Test + public void testAllProperties() throws Exception { + System.setProperty(VISIBLE_PROP, "hello"); + + NodePropertiesResponse rsp = fetchProperties(null); + + assertTrue("expected more than one system property", rsp.systemProperties.size() > 1); + assertEquals(System.getProperty("java.version"), rsp.systemProperties.get("java.version")); + assertEquals("hello", rsp.systemProperties.get(VISIBLE_PROP)); + } + + @Test + public void testRedactsHiddenProperties() throws Exception { + System.setProperty(SECRET_PROP, PASSWORD); + + NodePropertiesResponse named = fetchProperties(SECRET_PROP); + assertEquals(1, named.systemProperties.size()); + assertEquals(NodeConfig.REDACTED_SYS_PROP_VALUE, named.systemProperties.get(SECRET_PROP)); + assertFalse(named.systemProperties.containsValue(PASSWORD)); + + NodePropertiesResponse all = fetchProperties(null); + assertEquals(NodeConfig.REDACTED_SYS_PROP_VALUE, all.systemProperties.get(SECRET_PROP)); + assertFalse(all.systemProperties.containsValue(PASSWORD)); + } + + private NodePropertiesResponse fetchProperties(String name) throws Exception { + NodePropertiesResponse rsp = + name == null + ? new NodeApi.GetNodeProperties().process(solrTestRule.getAdminClient()) + : new NodeApi.GetNodeProperty(name).process(solrTestRule.getAdminClient()); + assertNotNull(rsp); + assertNull(rsp.error); + assertNotNull(rsp.systemProperties); + return rsp; + } +} diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/V2NodeAPIMappingTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/V2NodeAPIMappingTest.java index 6b3c63de45b4..ac2b660bc88e 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/V2NodeAPIMappingTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/V2NodeAPIMappingTest.java @@ -35,8 +35,6 @@ import org.apache.solr.handler.RequestHandlerBase; import org.apache.solr.handler.admin.CoreAdminHandler; import org.apache.solr.handler.admin.InfoHandler; -import org.apache.solr.handler.admin.LoggingHandler; -import org.apache.solr.handler.admin.PropertiesRequestHandler; import org.apache.solr.handler.admin.ThreadDumpHandler; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrQueryRequestBase; @@ -52,8 +50,6 @@ public class V2NodeAPIMappingTest extends SolrTestCaseJ4 { private ArgumentCaptor queryRequestCaptor; private CoreAdminHandler mockCoresHandler; private InfoHandler infoHandler; - private LoggingHandler mockLoggingHandler; - private PropertiesRequestHandler mockPropertiesHandler; private ThreadDumpHandler mockThreadDumpHandler; @BeforeClass @@ -65,13 +61,9 @@ public static void ensureWorkingMockito() { public void setupApiBag() { mockCoresHandler = mock(CoreAdminHandler.class); infoHandler = mock(InfoHandler.class); - mockLoggingHandler = mock(LoggingHandler.class); - mockPropertiesHandler = mock(PropertiesRequestHandler.class); mockThreadDumpHandler = mock(ThreadDumpHandler.class); queryRequestCaptor = ArgumentCaptor.forClass(SolrQueryRequest.class); - when(infoHandler.getLoggingHandler()).thenReturn(mockLoggingHandler); - when(infoHandler.getPropertiesHandler()).thenReturn(mockPropertiesHandler); when(infoHandler.getThreadDumpHandler()).thenReturn(mockThreadDumpHandler); apiBag = new ApiBag(false); @@ -116,16 +108,6 @@ public void testRejoinLeaderElectionApiAllProperties() throws Exception { assertEquals("true", v1Params.get("rejoinAtHead")); } - @Test - public void testSystemPropsApiAllProperties() throws Exception { - final ModifiableSolrParams solrParams = new ModifiableSolrParams(); - solrParams.add("name", "specificPropertyName"); - final SolrParams v1Params = - captureConvertedPropertiesV1Params("/node/properties", "GET", solrParams); - - assertEquals("specificPropertyName", v1Params.get("name")); - } - @Test public void testThreadDumpApiAllProperties() throws Exception { final ModifiableSolrParams solrParams = new ModifiableSolrParams(); @@ -143,11 +125,6 @@ private SolrParams captureConvertedCoreV1Params(String path, String method, Stri path, method, new ModifiableSolrParams(), v2RequestBody, mockCoresHandler); } - private SolrParams captureConvertedPropertiesV1Params( - String path, String method, SolrParams inputParams) throws Exception { - return doCaptureParams(path, method, inputParams, null, mockPropertiesHandler); - } - private SolrParams captureConvertedThreadDumpV1Params( String path, String method, SolrParams inputParams) throws Exception { return doCaptureParams(path, method, inputParams, null, mockThreadDumpHandler); @@ -188,7 +165,6 @@ private static void registerAllNodeApis( ApiBag apiBag, CoreAdminHandler coreHandler, InfoHandler infoHandler) { apiBag.registerObject(new OverseerOperationAPI(coreHandler)); apiBag.registerObject(new RejoinLeaderElectionAPI(coreHandler)); - apiBag.registerObject(new NodePropertiesAPI(infoHandler.getPropertiesHandler())); apiBag.registerObject(new NodeThreadsAPI(infoHandler.getThreadDumpHandler())); } } diff --git a/solr/solr-ref-guide/modules/configuration-guide/pages/implicit-requesthandlers.adoc b/solr/solr-ref-guide/modules/configuration-guide/pages/implicit-requesthandlers.adoc index 4380337752c9..005742a7cec8 100644 --- a/solr/solr-ref-guide/modules/configuration-guide/pages/implicit-requesthandlers.adoc +++ b/solr/solr-ref-guide/modules/configuration-guide/pages/implicit-requesthandlers.adoc @@ -92,14 +92,21 @@ This handler must have a collection name in the path to the endpoint. |=== System Properties:: Return JRE system properties. +Secret values are redacted. ++ +*Documentation*: xref:deployment-guide:jvm-settings.adoc#java-properties-screen[Java Properties Screen] + [cols="3*.",frame=none,grid=cols,options="header"] |=== |API Endpoints |Class & Javadocs |Paramset |v1: `solr/admin/info/properties` -v2: `api/node/properties` |{solr-javadocs}/core/org/apache/solr/handler/admin/PropertiesRequestHandler.html[PropertiesRequestHandler] |`_ADMIN_PROPERTIES` +v2: `api/node/properties` |v1: {solr-javadocs}/core/org/apache/solr/handler/admin/PropertiesRequestHandler.html[PropertiesRequestHandler] + +v2: {solr-javadocs}/core/org/apache/solr/handler/admin/api/GetNodeProperties.html[GetNodeProperties] |`_ADMIN_PROPERTIES` |=== ++ +To fetch a single property, v1 uses a `name` query parameter (`solr/admin/info/properties?name=java.version`) and v2 uses a path segment (`api/node/properties/java.version`). Segments:: Return info on last commit generation Lucene index segments. + diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/jvm-settings.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/jvm-settings.adoc index a40cdc4073ef..a426496caa71 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/jvm-settings.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/jvm-settings.adoc @@ -78,6 +78,10 @@ Many of the system environment variables include Java settings, and these can be The Java Properties screen, however, provides easy access to all the properties of the JVM running Solr, including the classpaths, file encodings, JVM memory settings, operating system, and more. +The same information is available from the Node Properties API: `GET /solr/admin/info/properties` (v1) or `GET /api/node/properties` (v2). +A single property can be requested with v1 `?name=java.version` or v2 `GET /api/node/properties/java.version`. +Secret values are redacted. + In the Admin UI, it is available in the left-hand menu *Java Properties*. .Java Properties Screen