mirror of https://github.com/apache/lucene.git
SOLR-10406: SolrJ must throw exception if server throws an error
This commit is contained in:
parent
d0d30464dd
commit
ad2cb7784e
|
@ -79,9 +79,8 @@ public class AutoScalingHandlerTest extends SolrCloudTestCase {
|
||||||
SolrRequest req = createAutoScalingRequest(SolrRequest.METHOD.POST, setPolicyCommand);
|
SolrRequest req = createAutoScalingRequest(SolrRequest.METHOD.POST, setPolicyCommand);
|
||||||
NamedList<Object> response = null;
|
NamedList<Object> response = null;
|
||||||
try {
|
try {
|
||||||
response = solrClient.request(req);
|
solrClient.request(req);
|
||||||
String errorMsg = (String) ((NamedList)response.get("error")).get("msg");
|
fail("Adding a policy with 'cores' attribute should not have succeeded.");
|
||||||
assertTrue(errorMsg.contains("cores is only allowed in 'cluster-policy'"));
|
|
||||||
} catch (SolrServerException e) {
|
} catch (SolrServerException e) {
|
||||||
// todo one of these catch blocks should not be needed after SOLR-10768
|
// todo one of these catch blocks should not be needed after SOLR-10768
|
||||||
if (e.getRootCause() instanceof HttpSolrClient.RemoteSolrException) {
|
if (e.getRootCause() instanceof HttpSolrClient.RemoteSolrException) {
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.apache.solr.client.solrj.SolrRequest;
|
||||||
import org.apache.solr.client.solrj.SolrServerException;
|
import org.apache.solr.client.solrj.SolrServerException;
|
||||||
import org.apache.solr.client.solrj.impl.BinaryResponseParser;
|
import org.apache.solr.client.solrj.impl.BinaryResponseParser;
|
||||||
import org.apache.solr.client.solrj.impl.CloudSolrClient;
|
import org.apache.solr.client.solrj.impl.CloudSolrClient;
|
||||||
|
import org.apache.solr.client.solrj.impl.HttpSolrClient;
|
||||||
import org.apache.solr.client.solrj.impl.XMLResponseParser;
|
import org.apache.solr.client.solrj.impl.XMLResponseParser;
|
||||||
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
|
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
|
||||||
import org.apache.solr.client.solrj.request.V2Request;
|
import org.apache.solr.client.solrj.request.V2Request;
|
||||||
|
@ -67,8 +68,13 @@ public class V2ApiIntegrationTest extends SolrCloudTestCase {
|
||||||
.withPayload(payload)
|
.withPayload(payload)
|
||||||
.build();
|
.build();
|
||||||
v2Request.setResponseParser(responseParser);
|
v2Request.setResponseParser(responseParser);
|
||||||
V2Response response = v2Request.process(cluster.getSolrClient());
|
try {
|
||||||
assertEquals(getStatus(response), expectedCode);
|
v2Request.process(cluster.getSolrClient());
|
||||||
|
fail("expected an exception with error code: "+expectedCode);
|
||||||
|
} catch (HttpSolrClient.RemoteExecutionException e) {
|
||||||
|
assertEquals(expectedCode, e.code());
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -82,6 +82,8 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.slf4j.MDC;
|
import org.slf4j.MDC;
|
||||||
|
|
||||||
|
import static org.apache.solr.common.util.Utils.getObjectByPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A SolrClient implementation that talks directly to a Solr server via HTTP
|
* A SolrClient implementation that talks directly to a Solr server via HTTP
|
||||||
*/
|
*/
|
||||||
|
@ -575,6 +577,12 @@ public class HttpSolrClient extends SolrClient {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RemoteSolrException(baseUrl, httpStatus, e.getMessage(), e);
|
throw new RemoteSolrException(baseUrl, httpStatus, e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
if (isV2Api) {
|
||||||
|
Object err = rsp.get("error");
|
||||||
|
if (err != null) {
|
||||||
|
throw RemoteExecutionException.create(baseUrl, rsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (httpStatus != HttpStatus.SC_OK && !isV2Api) {
|
if (httpStatus != HttpStatus.SC_OK && !isV2Api) {
|
||||||
NamedList<String> metadata = null;
|
NamedList<String> metadata = null;
|
||||||
String reason = null;
|
String reason = null;
|
||||||
|
@ -758,6 +766,39 @@ public class HttpSolrClient extends SolrClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should be thrown when a server has an error in executing the request and
|
||||||
|
* it sends a proper payload back to the client
|
||||||
|
*/
|
||||||
|
public static class RemoteExecutionException extends RemoteSolrException {
|
||||||
|
private NamedList meta;
|
||||||
|
|
||||||
|
public RemoteExecutionException(String remoteHost, int code, String msg, NamedList meta) {
|
||||||
|
super(remoteHost, code, msg, null);
|
||||||
|
this.meta = meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static RemoteExecutionException create(String host, NamedList errResponse) {
|
||||||
|
Object errObj = errResponse.get("error");
|
||||||
|
if (errObj != null) {
|
||||||
|
Number code = (Number) getObjectByPath(errObj, true, Collections.singletonList("code"));
|
||||||
|
String msg = (String) getObjectByPath(errObj, true, Collections.singletonList("msg"));
|
||||||
|
return new RemoteExecutionException(host, code == null ? ErrorCode.UNKNOWN.code : code.intValue(),
|
||||||
|
msg == null ? "Unknown Error" : msg, errResponse);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("No error");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public NamedList getMetaData() {
|
||||||
|
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs {@link HttpSolrClient} instances from provided configuration.
|
* Constructs {@link HttpSolrClient} instances from provided configuration.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.apache.solr.client.solrj.SolrClient;
|
||||||
import org.apache.solr.client.solrj.SolrQuery;
|
import org.apache.solr.client.solrj.SolrQuery;
|
||||||
import org.apache.solr.client.solrj.SolrRequest;
|
import org.apache.solr.client.solrj.SolrRequest;
|
||||||
import org.apache.solr.client.solrj.SolrServerException;
|
import org.apache.solr.client.solrj.SolrServerException;
|
||||||
|
import org.apache.solr.client.solrj.impl.HttpSolrClient.RemoteExecutionException;
|
||||||
import org.apache.solr.client.solrj.request.IsUpdateRequest;
|
import org.apache.solr.client.solrj.request.IsUpdateRequest;
|
||||||
import org.apache.solr.client.solrj.request.RequestWriter;
|
import org.apache.solr.client.solrj.request.RequestWriter;
|
||||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||||
|
@ -460,7 +461,9 @@ public class LBHttpSolrClient extends SolrClient {
|
||||||
if (isZombie) {
|
if (isZombie) {
|
||||||
zombieServers.remove(zombieKey);
|
zombieServers.remove(zombieKey);
|
||||||
}
|
}
|
||||||
} catch (SolrException e) {
|
} catch (RemoteExecutionException e){
|
||||||
|
throw e;
|
||||||
|
} catch(SolrException e) {
|
||||||
// we retry on 404 or 403 or 503 or 500
|
// we retry on 404 or 403 or 503 or 500
|
||||||
// unless it's an update - then we only retry on connect exception
|
// unless it's an update - then we only retry on connect exception
|
||||||
if (!isNonRetryable && RETRY_CODES.contains(e.code())) {
|
if (!isNonRetryable && RETRY_CODES.contains(e.code())) {
|
||||||
|
|
|
@ -213,15 +213,20 @@ public class Utils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object getObjectByPath(Map root, boolean onlyPrimitive, String hierarchy) {
|
public static Object getObjectByPath(Object root, boolean onlyPrimitive, String hierarchy) {
|
||||||
|
if(root == null) return null;
|
||||||
|
if(!isMapLike(root)) throw new RuntimeException("must be a Map or NamedList");
|
||||||
List<String> parts = StrUtils.splitSmart(hierarchy, '/');
|
List<String> parts = StrUtils.splitSmart(hierarchy, '/');
|
||||||
if (parts.get(0).isEmpty()) parts.remove(0);
|
if (parts.get(0).isEmpty()) parts.remove(0);
|
||||||
return getObjectByPath(root, onlyPrimitive, parts);
|
return getObjectByPath(root, onlyPrimitive, parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object getObjectByPath(Map root, boolean onlyPrimitive, List<String> hierarchy) {
|
|
||||||
|
|
||||||
|
public static Object getObjectByPath(Object root, boolean onlyPrimitive, List<String> hierarchy) {
|
||||||
if(root == null) return null;
|
if(root == null) return null;
|
||||||
Map obj = root;
|
if(!isMapLike(root)) throw new RuntimeException("must be a Map or NamedList");
|
||||||
|
Object obj = root;
|
||||||
for (int i = 0; i < hierarchy.size(); i++) {
|
for (int i = 0; i < hierarchy.size(); i++) {
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
String s = hierarchy.get(i);
|
String s = hierarchy.get(i);
|
||||||
|
@ -233,22 +238,22 @@ public class Utils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i < hierarchy.size() - 1) {
|
if (i < hierarchy.size() - 1) {
|
||||||
Object o = obj.get(s);
|
Object o = getVal(obj, s);
|
||||||
if (o == null) return null;
|
if (o == null) return null;
|
||||||
if (idx > -1) {
|
if (idx > -1) {
|
||||||
List l = (List) o;
|
List l = (List) o;
|
||||||
o = idx < l.size() ? l.get(idx) : null;
|
o = idx < l.size() ? l.get(idx) : null;
|
||||||
}
|
}
|
||||||
if (!(o instanceof Map)) return null;
|
if (!isMapLike(o)) return null;
|
||||||
obj = (Map) o;
|
obj = o;
|
||||||
} else {
|
} else {
|
||||||
Object val = obj.get(s);
|
Object val = getVal(obj, s);
|
||||||
if (val == null) return null;
|
if (val == null) return null;
|
||||||
if (idx > -1) {
|
if (idx > -1) {
|
||||||
List l = (List) val;
|
List l = (List) val;
|
||||||
val = idx < l.size() ? l.get(idx) : null;
|
val = idx < l.size() ? l.get(idx) : null;
|
||||||
}
|
}
|
||||||
if (onlyPrimitive && val instanceof Map) {
|
if (onlyPrimitive && isMapLike(val)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
|
@ -257,7 +262,17 @@ public class Utils {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isMapLike(Object o) {
|
||||||
|
return o instanceof Map || o instanceof NamedList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object getVal(Object obj, String key) {
|
||||||
|
if(obj instanceof NamedList) return ((NamedList) obj).get(key);
|
||||||
|
else if (obj instanceof Map) return ((Map) obj).get(key);
|
||||||
|
else throw new RuntimeException("must be a NamedList or Map");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the passed entity has content, make sure it is fully
|
* If the passed entity has content, make sure it is fully
|
||||||
* read and closed.
|
* read and closed.
|
||||||
|
|
Loading…
Reference in New Issue