Skip to content
Merged
8 changes: 8 additions & 0 deletions dev-docs/v2-api-conventions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ For use within the v2 API, the four "popular" HTTP methods have the following se
* `PUT` - used for idempotent resource modifications.
* `DELETE` - Used to delete or cleanup resource

== Errors

v2 APIs should be consistent in how they report errors. Throwing a `SolrException` will convey
1.the error code as the HTTP response status code, as `responseHeader.status` and as `error.code`, and
1.the error message as `error.msg`.

API calls that reference a specific resource (e.g. `specificCollName`, `specificAliasName`, `specificPropertyName` and others per the above list) that do not exist should return `SolrException.ErrorCode.NOT_FOUND` (HTTP 404).

== Exceptional Cases - "Command" APIs

The pairing of semantic HTTP verbs and "resource"-based paths gives Solr an intuitive pattern for representing many operations, but not all.
Expand Down
6 changes: 6 additions & 0 deletions solr/CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,12 @@ Improvements

* SOLR-17390: EmbeddedSolrServer now considers the ResponseParser (David Smiley)

* SOLR-16390: v2 "cluster prop" APIs have been updated to be more REST-ful. Cluster prop creation/update are now available
at `PUT /api/cluster/properties/somePropName`. Deletion is now available at `DELETE /api/cluster/properties/somePropName`.
New APIs for listing-all and fetching-single cluster props are also now available at `GET /api/cluster/properties` and
`GET /api/cluster/properties/somePropName`, respectively. (Carlos Ugarte via Jason Gerlowski)


Optimizations
---------------------
* SOLR-14985: Solrj CloudSolrClient with Solr URLs had serious performance regressions (since the
Expand Down
Original file line number Diff line number Diff line change
@@ -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.client.api.endpoint;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import java.util.Map;
import org.apache.solr.client.api.model.ListClusterPropertiesResponse;
import org.apache.solr.client.api.model.SetClusterPropertyRequestBody;
import org.apache.solr.client.api.model.SolrJerseyResponse;

/** Definitions for v2 JAX-RS cluster properties APIs. */
@Path("/cluster/properties")
public interface ClusterPropertyApis {
@GET
@Operation(
summary = "List all cluster properties in this Solr cluster.",
tags = {"cluster-properties"})
ListClusterPropertiesResponse listClusterProperties();

@GET
@Path("/{propertyName}")
@Operation(
summary = "Get a cluster property in this Solr cluster.",
tags = {"cluster-properties"})
SolrJerseyResponse getClusterProperty(
@Parameter(description = "The name of the property being retrieved.", required = true)
@PathParam("propertyName")
String propertyName);

@PUT
@Path("/{propertyName}")
@Operation(
summary = "Set a single new or existing cluster property in this Solr cluster.",
tags = {"cluster-properties"})
SolrJerseyResponse createOrUpdateClusterProperty(
@Parameter(description = "The name of the property being set.", required = true)
@PathParam("propertyName")
String propertyName,
@RequestBody(description = "Value to set for the property", required = true)
SetClusterPropertyRequestBody requestBody)
throws Exception;

@PUT
@Operation(
summary = "Set nested cluster properties in this Solr cluster.",
tags = {"cluster-properties"})
SolrJerseyResponse createOrUpdateNestedClusterProperty(
@RequestBody(description = "Property/ies to be set", required = true)
Map<String, Object> propertyValuesByName)
throws Exception;

@DELETE
@Path("/{propertyName}")
@Operation(
summary = "Delete a cluster property in this Solr cluster.",
tags = {"cluster-properties"})
SolrJerseyResponse deleteClusterProperty(
@Parameter(description = "The name of the property being deleted.", required = true)
@PathParam("propertyName")
String propertyName);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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;

public class ClusterPropertyDetails {
@JsonProperty("name")
@Schema(description = "The name of the cluster property.")
public String name;

@JsonProperty("value")
@Schema(description = "The value of the cluster property.")
public Object value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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;

public class GetClusterPropertyResponse extends SolrJerseyResponse {
@JsonProperty("clusterProperty")
@Schema(description = "The requested cluster property.")
public ClusterPropertyDetails clusterProperty;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* 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.List;

public class ListClusterPropertiesResponse extends SolrJerseyResponse {
@JsonProperty("clusterProperties")
@Schema(description = "The list of cluster properties.")
public List<String> clusterProperties;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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;

public class SetClusterPropertyRequestBody {
@Schema(description = "The value to assign to the property.")
@JsonProperty("value")
public String value;
}
22 changes: 0 additions & 22 deletions solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import static org.apache.solr.cloud.api.collections.CollectionHandlingUtils.REQUESTID;
import static org.apache.solr.common.params.CollectionParams.ACTION;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.ADDROLE;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.CLUSTERPROP;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.DELETESTATUS;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.OVERSEERSTATUS;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.REMOVEROLE;
Expand All @@ -43,7 +42,6 @@
import org.apache.solr.api.EndPoint;
import org.apache.solr.api.PayloadObj;
import org.apache.solr.client.solrj.cloud.DistribStateManager;
import org.apache.solr.client.solrj.request.beans.ClusterPropPayload;
import org.apache.solr.client.solrj.request.beans.RateLimiterPayload;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.annotation.JsonProperty;
Expand Down Expand Up @@ -275,26 +273,6 @@ public void removeRole(PayloadObj<RoleInfo> obj) throws Exception {
collectionsHandler.handleRequestBody(wrapParams(obj.getRequest(), m), obj.getResponse());
}

@Command(name = "set-obj-property")
public void setObjProperty(PayloadObj<ClusterPropPayload> obj) {
// Not using the object directly here because the API differentiate between {name:null} and {}
Map<String, Object> m = obj.getDataMap();
ClusterProperties clusterProperties =
new ClusterProperties(getCoreContainer().getZkController().getZkClient());
try {
clusterProperties.setClusterProperties(m);
} catch (Exception e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error in API", e);
}
}

@Command(name = "set-property")
public void setProperty(PayloadObj<Map<String, String>> obj) throws Exception {
Map<String, Object> m = obj.getDataMap();
m.put("action", CLUSTERPROP.toString());
collectionsHandler.handleRequestBody(wrapParams(obj.getRequest(), m), obj.getResponse());
}

@Command(name = "set-ratelimiter")
public void setRateLimiters(PayloadObj<RateLimiterPayload> payLoad) {
RateLimiterPayload rateLimiterConfig = payLoad.get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
import org.apache.solr.client.api.model.InstallShardDataRequestBody;
import org.apache.solr.client.api.model.ListCollectionSnapshotsResponse;
import org.apache.solr.client.api.model.ReplaceNodeRequestBody;
import org.apache.solr.client.api.model.SetClusterPropertyRequestBody;
import org.apache.solr.client.api.model.SolrJerseyResponse;
import org.apache.solr.client.api.model.UpdateAliasPropertiesRequestBody;
import org.apache.solr.client.api.model.UpdateCollectionPropertyRequestBody;
Expand All @@ -142,7 +143,6 @@
import org.apache.solr.cloud.api.collections.ReindexCollectionCmd;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.cloud.ClusterProperties;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.Replica.State;
Expand Down Expand Up @@ -172,6 +172,7 @@
import org.apache.solr.handler.admin.api.AliasProperty;
import org.apache.solr.handler.admin.api.BalanceReplicas;
import org.apache.solr.handler.admin.api.BalanceShardUnique;
import org.apache.solr.handler.admin.api.ClusterProperty;
import org.apache.solr.handler.admin.api.CollectionProperty;
import org.apache.solr.handler.admin.api.CollectionStatusAPI;
import org.apache.solr.handler.admin.api.CreateAlias;
Expand Down Expand Up @@ -771,11 +772,12 @@ public enum CollectionOperation implements CollectionOp {
CLUSTERPROP_OP(
CLUSTERPROP,
(req, rsp, h) -> {
ClusterProperty clusterProperty = new ClusterProperty(req.getCoreContainer(), req, rsp);
SetClusterPropertyRequestBody setClusterPropertyRequestBody =
new SetClusterPropertyRequestBody();
String name = req.getParams().required().get(NAME);
String val = req.getParams().get(VALUE_LONG);
ClusterProperties cp =
new ClusterProperties(h.coreContainer.getZkController().getZkClient());
cp.setClusterProperty(name, val);
setClusterPropertyRequestBody.value = req.getParams().get(VALUE_LONG);
clusterProperty.createOrUpdateClusterProperty(name, setClusterPropertyRequestBody);
return null;
}),
COLLECTIONPROP_OP(
Expand Down Expand Up @@ -1385,7 +1387,8 @@ public Collection<Class<? extends JerseyResource>> getJerseyResources() {
AliasProperty.class,
ListCollectionSnapshots.class,
CreateCollectionSnapshot.class,
DeleteCollectionSnapshot.class);
DeleteCollectionSnapshot.class,
ClusterProperty.class);
}

@Override
Expand Down
Loading
Loading