Fix serialization of empty field capabilities response (#33263)
Fix serialization of empty field capabilities response When no response are required (no indices match the requested patterns) the empty response throws an NPE in the transport serialization (writeTo).
This commit is contained in:
parent
1404dd2a42
commit
d0630093cd
|
@ -166,14 +166,14 @@ public class FieldCapabilities implements Writeable, ToXContentObject {
|
|||
}
|
||||
|
||||
/**
|
||||
* Whether this field is indexed for search on all indices.
|
||||
* Whether this field can be aggregated on all indices.
|
||||
*/
|
||||
public boolean isAggregatable() {
|
||||
return isAggregatable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this field can be aggregated on all indices.
|
||||
* Whether this field is indexed for search on all indices.
|
||||
*/
|
||||
public boolean isSearchable() {
|
||||
return isSearchable;
|
||||
|
|
|
@ -111,7 +111,6 @@ public final class FieldCapabilitiesRequest extends ActionRequest implements Ind
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The list of indices to lookup
|
||||
*/
|
||||
public FieldCapabilitiesRequest indices(String... indices) {
|
||||
|
|
|
@ -35,6 +35,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -56,15 +57,15 @@ public class FieldCapabilitiesResponse extends ActionResponse implements ToXCont
|
|||
|
||||
private FieldCapabilitiesResponse(Map<String, Map<String, FieldCapabilities>> responseMap,
|
||||
List<FieldCapabilitiesIndexResponse> indexResponses) {
|
||||
this.responseMap = responseMap;
|
||||
this.indexResponses = indexResponses;
|
||||
this.responseMap = Objects.requireNonNull(responseMap);
|
||||
this.indexResponses = Objects.requireNonNull(indexResponses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for serialization
|
||||
*/
|
||||
FieldCapabilitiesResponse() {
|
||||
this.responseMap = Collections.emptyMap();
|
||||
this(Collections.emptyMap(), Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,6 +82,7 @@ public class FieldCapabilitiesResponse extends ActionResponse implements ToXCont
|
|||
List<FieldCapabilitiesIndexResponse> getIndexResponses() {
|
||||
return indexResponses;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Get the field capabilities per type for the provided {@code field}.
|
||||
|
|
|
@ -90,7 +90,7 @@ public class TransportFieldCapabilitiesAction extends HandledTransportAction<Fie
|
|||
}
|
||||
};
|
||||
if (totalNumRequest == 0) {
|
||||
listener.onResponse(new FieldCapabilitiesResponse());
|
||||
listener.onResponse(new FieldCapabilitiesResponse(Collections.emptyMap()));
|
||||
} else {
|
||||
ActionListener<FieldCapabilitiesIndexResponse> innerListener = new ActionListener<FieldCapabilitiesIndexResponse>() {
|
||||
@Override
|
||||
|
|
|
@ -455,7 +455,7 @@ public interface Client extends ElasticsearchClient, Releasable {
|
|||
/**
|
||||
* Builder for the field capabilities request.
|
||||
*/
|
||||
FieldCapabilitiesRequestBuilder prepareFieldCaps();
|
||||
FieldCapabilitiesRequestBuilder prepareFieldCaps(String... indices);
|
||||
|
||||
/**
|
||||
* An action that returns the field capabilities from the provided request
|
||||
|
|
|
@ -651,8 +651,8 @@ public abstract class AbstractClient extends AbstractComponent implements Client
|
|||
}
|
||||
|
||||
@Override
|
||||
public FieldCapabilitiesRequestBuilder prepareFieldCaps() {
|
||||
return new FieldCapabilitiesRequestBuilder(this, FieldCapabilitiesAction.INSTANCE);
|
||||
public FieldCapabilitiesRequestBuilder prepareFieldCaps(String... indices) {
|
||||
return new FieldCapabilitiesRequestBuilder(this, FieldCapabilitiesAction.INSTANCE, indices);
|
||||
}
|
||||
|
||||
static class Admin implements AdminClient {
|
||||
|
|
|
@ -28,11 +28,15 @@ import org.elasticsearch.common.xcontent.XContentType;
|
|||
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomAsciiLettersOfLength;
|
||||
|
||||
|
||||
public class FieldCapabilitiesResponseTests extends AbstractStreamableXContentTestCase<FieldCapabilitiesResponse> {
|
||||
|
||||
|
@ -48,22 +52,46 @@ public class FieldCapabilitiesResponseTests extends AbstractStreamableXContentTe
|
|||
|
||||
@Override
|
||||
protected FieldCapabilitiesResponse createTestInstance() {
|
||||
Map<String, Map<String, FieldCapabilities>> responses = new HashMap<>();
|
||||
if (randomBoolean()) {
|
||||
// merged responses
|
||||
Map<String, Map<String, FieldCapabilities>> responses = new HashMap<>();
|
||||
|
||||
String[] fields = generateRandomStringArray(5, 10, false, true);
|
||||
assertNotNull(fields);
|
||||
|
||||
for (String field : fields) {
|
||||
Map<String, FieldCapabilities> typesToCapabilities = new HashMap<>();
|
||||
String[] types = generateRandomStringArray(5, 10, false, false);
|
||||
assertNotNull(types);
|
||||
|
||||
for (String type : types) {
|
||||
typesToCapabilities.put(type, FieldCapabilitiesTests.randomFieldCaps(field));
|
||||
}
|
||||
responses.put(field, typesToCapabilities);
|
||||
}
|
||||
return new FieldCapabilitiesResponse(responses);
|
||||
} else {
|
||||
// non-merged responses
|
||||
List<FieldCapabilitiesIndexResponse> responses = new ArrayList<>();
|
||||
int numResponse = randomIntBetween(0, 10);
|
||||
for (int i = 0; i < numResponse; i++) {
|
||||
responses.add(createRandomIndexResponse());
|
||||
}
|
||||
return new FieldCapabilitiesResponse(responses);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private FieldCapabilitiesIndexResponse createRandomIndexResponse() {
|
||||
Map<String, FieldCapabilities> responses = new HashMap<>();
|
||||
|
||||
String[] fields = generateRandomStringArray(5, 10, false, true);
|
||||
assertNotNull(fields);
|
||||
|
||||
for (String field : fields) {
|
||||
Map<String, FieldCapabilities> typesToCapabilities = new HashMap<>();
|
||||
String[] types = generateRandomStringArray(5, 10, false, false);
|
||||
assertNotNull(types);
|
||||
|
||||
for (String type : types) {
|
||||
typesToCapabilities.put(type, FieldCapabilitiesTests.randomFieldCaps(field));
|
||||
}
|
||||
responses.put(field, typesToCapabilities);
|
||||
responses.put(field, FieldCapabilitiesTests.randomFieldCaps(field));
|
||||
}
|
||||
return new FieldCapabilitiesResponse(responses);
|
||||
return new FieldCapabilitiesIndexResponse(randomAsciiLettersOfLength(10), responses);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -138,6 +166,11 @@ public class FieldCapabilitiesResponseTests extends AbstractStreamableXContentTe
|
|||
"}").replaceAll("\\s+", ""), generatedResponse);
|
||||
}
|
||||
|
||||
public void testEmptyResponse() throws IOException {
|
||||
FieldCapabilitiesResponse testInstance = new FieldCapabilitiesResponse();
|
||||
assertSerialization(testInstance);
|
||||
}
|
||||
|
||||
private static FieldCapabilitiesResponse createSimpleResponse() {
|
||||
Map<String, FieldCapabilities> titleCapabilities = new HashMap<>();
|
||||
titleCapabilities.put("text", new FieldCapabilities("title", "text", true, false));
|
||||
|
|
Loading…
Reference in New Issue