You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by kr...@apache.org on 2022/09/21 16:07:09 UTC

[solr] branch branch_9x updated: SOLR-16418: Introduce SolrResponseUtil to handle NPE during query timeout or exception when parsing SolrResponse (#1026)

This is an automated email from the ASF dual-hosted git repository.

krisden pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/branch_9x by this push:
     new 6f5f8369e2d SOLR-16418: Introduce SolrResponseUtil to handle NPE during query timeout or exception when parsing SolrResponse (#1026)
6f5f8369e2d is described below

commit 6f5f8369e2d2a4ce7e4df023ced85534d8e9ccc3
Author: Kevin Risden <ri...@users.noreply.github.com>
AuthorDate: Wed Sep 21 12:04:35 2022 -0400

    SOLR-16418: Introduce SolrResponseUtil to handle NPE during query timeout or exception when parsing SolrResponse (#1026)
---
 solr/CHANGES.txt                                   |  2 +
 .../solr/handler/component/DebugComponent.java     |  6 +-
 .../solr/handler/component/ExpandComponent.java    |  9 ++-
 .../solr/handler/component/FacetComponent.java     | 55 ++++------------
 .../solr/handler/component/HighlightComponent.java |  8 ++-
 .../solr/handler/component/QueryComponent.java     | 39 +++++++++--
 .../handler/component/SpellCheckComponent.java     | 21 ++----
 .../solr/handler/component/StatsComponent.java     | 22 +++----
 .../solr/handler/component/SuggestComponent.java   | 22 ++++---
 .../handler/component/TermVectorComponent.java     | 21 +++---
 .../solr/handler/component/TermsComponent.java     |  7 +-
 .../SearchGroupShardResponseProcessor.java         | 44 +++++++------
 .../StoredFieldsShardResponseProcessor.java        | 15 +++--
 .../TopGroupsShardResponseProcessor.java           |  8 ++-
 .../org/apache/solr/util/SolrResponseUtil.java     | 77 ++++++++++++++++++++++
 .../apache/solr/search/RankQueryTestPlugin.java    | 41 +++++++++---
 16 files changed, 255 insertions(+), 142 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index b3ebc3bb9c1..71ab6fbffe1 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -133,6 +133,8 @@ Bug Fixes
 
 * SOLR-16414 : Race condition in PRS state updates (noble, Justin Sweeney, Patson Luk, Hitesh Khamesra, Ishan Chattopadhyaya)
 
+* SOLR-16418: Introduce SolrResponseUtil to handle NPE during query timeout or exception when parsing SolrResponse (Kevin Risden)
+
 Other Changes
 ---------------------
 * SOLR-16351: Upgrade Carrot2 to 4.4.3, upgrade randomizedtesting to 2.8.0. (Dawid Weiss)
diff --git a/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java b/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java
index b46b0f4260e..7212fc309d3 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java
@@ -41,6 +41,7 @@ import org.apache.solr.search.SolrIndexSearcher;
 import org.apache.solr.search.facet.FacetDebugInfo;
 import org.apache.solr.search.stats.StatsCache;
 import org.apache.solr.util.SolrPluginUtils;
+import org.apache.solr.util.SolrResponseUtil;
 
 /**
  * Adds debugging information to a request.
@@ -219,12 +220,13 @@ public class DebugComponent extends SearchComponent {
             continue;
           }
           NamedList<Object> sdebug =
-              (NamedList<Object>) srsp.getSolrResponse().getResponse().get("debug");
+              (NamedList<Object>)
+                  SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "debug", true);
 
           info = (NamedList<Object>) merge(sdebug, info, EXCLUDE_SET);
           if ((sreq.purpose & ShardRequest.PURPOSE_GET_DEBUG) != 0) {
             hasGetDebugResponses = true;
-            if (rb.isDebugResults()) {
+            if (rb.isDebugResults() && sdebug != null) {
               NamedList<Object> sexplain = (NamedList<Object>) sdebug.get("explain");
               SolrPluginUtils.copyNamedListIntoArrayByDocPosInResponse(sexplain, rb.resultIds, arr);
             }
diff --git a/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java b/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java
index 4430f0c781e..de5dcb7b9f8 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java
@@ -84,6 +84,7 @@ import org.apache.solr.search.ReturnFields;
 import org.apache.solr.search.SolrIndexSearcher;
 import org.apache.solr.search.SortSpecParsing;
 import org.apache.solr.search.SyntaxError;
+import org.apache.solr.util.SolrResponseUtil;
 import org.apache.solr.util.plugin.PluginInfoInitialized;
 
 /**
@@ -479,8 +480,12 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
       }
 
       for (ShardResponse srsp : sreq.responses) {
-        NamedList<Object> response = srsp.getSolrResponse().getResponse();
-        NamedList<?> ex = (NamedList<?>) response.get("expanded");
+        NamedList<?> ex =
+            (NamedList<?>)
+                SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "expanded", false);
+        if (ex == null) {
+          continue;
+        }
         for (int i = 0; i < ex.size(); i++) {
           String name = ex.getName(i);
           SolrDocumentList val = (SolrDocumentList) ex.getVal(i);
diff --git a/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java b/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
index 868441f67d5..77c0d426c32 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
@@ -34,21 +34,18 @@ import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.FixedBitSet;
-import org.apache.solr.client.solrj.SolrResponse;
 import org.apache.solr.client.solrj.util.ClientUtils;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.FacetParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
-import org.apache.solr.common.params.ShardParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.request.SimpleFacets;
 import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.PointField;
 import org.apache.solr.search.DocSet;
@@ -56,6 +53,7 @@ import org.apache.solr.search.QueryParsing;
 import org.apache.solr.search.SyntaxError;
 import org.apache.solr.search.facet.FacetDebugInfo;
 import org.apache.solr.util.RTimer;
+import org.apache.solr.util.SolrResponseUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -715,7 +713,9 @@ public class FacetComponent extends SearchComponent {
 
     for (ShardResponse srsp : sreq.responses) {
       int shardNum = rb.getShardNum(srsp.getShard());
-      NamedList<?> facet_counts = getFacetCountsFromShardResponse(rb, srsp);
+      NamedList<?> facet_counts =
+          (NamedList<?>)
+              SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, FACET_COUNTS_KEY, false);
       if (facet_counts == null) {
         continue; // looks like a shard did not return anything
       }
@@ -839,42 +839,6 @@ public class FacetComponent extends SearchComponent {
     removeQueryFacetsUnderLimits(rb);
   }
 
-  private static NamedList<?> getFacetCountsFromShardResponse(
-      ResponseBuilder rb, ShardResponse srsp) {
-    NamedList<?> facet_counts;
-    try {
-      SolrResponse solrResponse = srsp.getSolrResponse();
-      NamedList<Object> response = solrResponse.getResponse();
-      facet_counts = (NamedList<?>) response.get(FACET_COUNTS_KEY);
-      if (facet_counts != null) {
-        return facet_counts;
-      } else {
-        NamedList<?> responseHeader =
-            (NamedList<?>) response.get(SolrQueryResponse.RESPONSE_HEADER_KEY);
-        if (responseHeader.getBooleanArg(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY)) {
-          return null;
-        } else {
-          log.warn("corrupted response on {} : {}", srsp.getShardRequest(), solrResponse);
-          throw new SolrException(
-              ErrorCode.SERVER_ERROR,
-              FACET_COUNTS_KEY
-                  + " is absent in response from "
-                  + srsp.getNodeName()
-                  + ", but "
-                  + SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY
-                  + " isn't set in the response.");
-        }
-      }
-    } catch (Exception ex) {
-      if (ShardParams.getShardsTolerantAsBool(rb.req.getParams())) {
-        return null;
-      } else {
-        throw new SolrException(
-            ErrorCode.SERVER_ERROR, "Unable to read facet info for shard: " + srsp.getShard(), ex);
-      }
-    }
-  }
-
   private void removeQueryFacetsUnderLimits(ResponseBuilder rb) {
     if (rb.stage != ResponseBuilder.STAGE_EXECUTE_QUERY) {
       return;
@@ -1011,7 +975,9 @@ public class FacetComponent extends SearchComponent {
     FacetInfo fi = rb._facetInfo;
 
     for (ShardResponse srsp : sreq.responses) {
-      NamedList<?> facet_counts = getFacetCountsFromShardResponse(rb, srsp);
+      NamedList<?> facet_counts =
+          (NamedList<?>)
+              SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, FACET_COUNTS_KEY, false);
       if (facet_counts == null) {
         continue; // looks like a shard did not return anything
       }
@@ -1051,11 +1017,14 @@ public class FacetComponent extends SearchComponent {
     // This is after the shard has returned the refinement request
     FacetInfo fi = rb._facetInfo;
     for (ShardResponse srsp : sreq.responses) {
-
       int shardNumber = rb.getShardNum(srsp.getShard());
 
       NamedList<?> facetCounts =
-          (NamedList<?>) srsp.getSolrResponse().getResponse().get(FACET_COUNTS_KEY);
+          (NamedList<?>)
+              SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, FACET_COUNTS_KEY, false);
+      if (facetCounts == null) {
+        continue;
+      }
 
       @SuppressWarnings("unchecked")
       NamedList<List<NamedList<Object>>> pivotFacetResponsesFromShard =
diff --git a/solr/core/src/java/org/apache/solr/handler/component/HighlightComponent.java b/solr/core/src/java/org/apache/solr/handler/component/HighlightComponent.java
index 9c109fd34f2..918a036e787 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/HighlightComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/HighlightComponent.java
@@ -43,6 +43,7 @@ import org.apache.solr.search.QParserPlugin;
 import org.apache.solr.search.QueryParsing;
 import org.apache.solr.search.SyntaxError;
 import org.apache.solr.util.SolrPluginUtils;
+import org.apache.solr.util.SolrResponseUtil;
 import org.apache.solr.util.plugin.PluginInfoInitialized;
 import org.apache.solr.util.plugin.SolrCoreAware;
 
@@ -224,7 +225,12 @@ public class HighlightComponent extends SearchComponent
             // this should only happen when using shards.tolerant=true
             continue;
           }
-          Object hl = srsp.getSolrResponse().getResponse().get(highlightingResponseField);
+          Object hl =
+              SolrResponseUtil.getSubsectionFromShardResponse(
+                  rb, srsp, highlightingResponseField, false);
+          if (hl == null) {
+            continue;
+          }
           addHighlights(objArr, hl, rb.resultIds);
         }
       }
diff --git a/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java b/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
index 3624423c003..12c3d3f2812 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
@@ -32,6 +32,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import org.apache.lucene.index.ExitableDirectoryReader;
 import org.apache.lucene.index.IndexReaderContext;
 import org.apache.lucene.index.LeafReaderContext;
@@ -114,6 +115,7 @@ import org.apache.solr.search.grouping.endresulttransformer.MainEndResultTransfo
 import org.apache.solr.search.grouping.endresulttransformer.SimpleEndResultTransformer;
 import org.apache.solr.search.stats.StatsCache;
 import org.apache.solr.util.SolrPluginUtils;
+import org.apache.solr.util.SolrResponseUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -914,13 +916,23 @@ public class QueryComponent extends SearchComponent {
           }
         } else {
           responseHeader =
-              (NamedList<?>) srsp.getSolrResponse().getResponse().get("responseHeader");
+              (NamedList<?>)
+                  SolrResponseUtil.getSubsectionFromShardResponse(
+                      rb, srsp, "responseHeader", false);
+          if (responseHeader == null) {
+            continue;
+          }
           final Object rhste =
               responseHeader.get(SolrQueryResponse.RESPONSE_HEADER_SEGMENT_TERMINATED_EARLY_KEY);
           if (rhste != null) {
             nl.add(SolrQueryResponse.RESPONSE_HEADER_SEGMENT_TERMINATED_EARLY_KEY, rhste);
           }
-          docs = (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response");
+          docs =
+              (SolrDocumentList)
+                  SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "response", false);
+          if (docs == null) {
+            continue;
+          }
           nl.add("numFound", docs.getNumFound());
           nl.add("numFoundExact", docs.getNumFoundExact());
           nl.add("maxScore", docs.getMaxScore());
@@ -939,11 +951,18 @@ public class QueryComponent extends SearchComponent {
       }
 
       if (docs == null) { // could have been initialized in the shards info block above
-        docs = (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response");
+        docs =
+            Objects.requireNonNull(
+                (SolrDocumentList)
+                    SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "response", false));
       }
 
       if (responseHeader == null) { // could have been initialized in the shards info block above
-        responseHeader = (NamedList<?>) srsp.getSolrResponse().getResponse().get("responseHeader");
+        responseHeader =
+            Objects.requireNonNull(
+                (NamedList<?>)
+                    SolrResponseUtil.getSubsectionFromShardResponse(
+                        rb, srsp, "responseHeader", false));
       }
 
       final boolean thisResponseIsPartial;
@@ -974,7 +993,8 @@ public class QueryComponent extends SearchComponent {
 
       @SuppressWarnings("unchecked")
       NamedList<List<Object>> sortFieldValues =
-          (NamedList<List<Object>>) (srsp.getSolrResponse().getResponse().get("sort_values"));
+          (NamedList<List<Object>>)
+              SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "sort_values", true);
       if (null == sortFieldValues) {
         sortFieldValues = new NamedList<>();
       }
@@ -1287,7 +1307,10 @@ public class QueryComponent extends SearchComponent {
         }
         {
           NamedList<?> responseHeader =
-              (NamedList<?>) srsp.getSolrResponse().getResponse().get("responseHeader");
+              Objects.requireNonNull(
+                  (NamedList<?>)
+                      SolrResponseUtil.getSubsectionFromShardResponse(
+                          rb, srsp, "responseHeader", false));
           if (Boolean.TRUE.equals(
               responseHeader.getBooleanArg(
                   SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY))) {
@@ -1298,7 +1321,9 @@ public class QueryComponent extends SearchComponent {
           }
         }
         SolrDocumentList docs =
-            (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response");
+            Objects.requireNonNull(
+                (SolrDocumentList)
+                    SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "response", false));
         for (SolrDocument doc : docs) {
           Object id = doc.getFieldValue(keyFieldName);
           ShardDoc sdoc = rb.resultIds.get(id.toString());
diff --git a/solr/core/src/java/org/apache/solr/handler/component/SpellCheckComponent.java b/solr/core/src/java/org/apache/solr/handler/component/SpellCheckComponent.java
index d7eb2676803..03311aebaa2 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/SpellCheckComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/SpellCheckComponent.java
@@ -71,6 +71,7 @@ import org.apache.solr.spelling.SpellingOptions;
 import org.apache.solr.spelling.SpellingQueryConverter;
 import org.apache.solr.spelling.SpellingResult;
 import org.apache.solr.spelling.Token;
+import org.apache.solr.util.SolrResponseUtil;
 import org.apache.solr.util.plugin.SolrCoreAware;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -263,10 +264,7 @@ public class SpellCheckComponent extends SearchComponent implements SolrCoreAwar
               }
             }
           }
-        } catch (IOException e) {
-          log.error("Error", e);
-          return null;
-        } catch (SyntaxError e) {
+        } catch (IOException | SyntaxError e) {
           log.error("Error", e);
           return null;
         }
@@ -407,18 +405,9 @@ public class SpellCheckComponent extends SearchComponent implements SolrCoreAwar
     if (maxResultsForSuggest == null || !isCorrectlySpelled) {
       for (ShardRequest sreq : rb.finished) {
         for (ShardResponse srsp : sreq.responses) {
-          NamedList<?> nl = null;
-          try {
-            nl = (NamedList<?>) srsp.getSolrResponse().getResponse().get("spellcheck");
-          } catch (Exception e) {
-            if (ShardParams.getShardsTolerantAsBool(rb.req.getParams())) {
-              continue; // looks like a shard did not return anything
-            }
-            throw new SolrException(
-                SolrException.ErrorCode.SERVER_ERROR,
-                "Unable to read spelling info for shard: " + srsp.getShard(),
-                e);
-          }
+          NamedList<?> nl =
+              (NamedList<?>)
+                  SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "spellcheck", true);
           if (log.isDebugEnabled()) {
             log.debug("{} {}", srsp.getShard(), nl);
           }
diff --git a/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java b/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java
index 920c19d6533..1ef317d30c5 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java
@@ -20,11 +20,11 @@ import java.io.IOException;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import org.apache.solr.common.SolrException;
-import org.apache.solr.common.params.ShardParams;
 import org.apache.solr.common.params.StatsParams;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.search.DocSet;
+import org.apache.solr.util.SolrResponseUtil;
 
 /**
  * Stats component calculates simple statistics on numeric field values
@@ -86,25 +86,19 @@ public class StatsComponent extends SearchComponent {
   }
 
   @Override
-  @SuppressWarnings("unchecked")
   public void handleResponses(ResponseBuilder rb, ShardRequest sreq) {
     if (!rb.doStats || (sreq.purpose & ShardRequest.PURPOSE_GET_STATS) == 0) return;
 
     Map<String, StatsValues> allStatsValues = rb._statsInfo.getAggregateStatsValues();
 
     for (ShardResponse srsp : sreq.responses) {
-      NamedList<NamedList<NamedList<?>>> stats = null;
-      try {
-        stats =
-            (NamedList<NamedList<NamedList<?>>>) srsp.getSolrResponse().getResponse().get("stats");
-      } catch (Exception e) {
-        if (ShardParams.getShardsTolerantAsBool(rb.req.getParams())) {
-          continue; // looks like a shard did not return anything
-        }
-        throw new SolrException(
-            SolrException.ErrorCode.SERVER_ERROR,
-            "Unable to read stats info for shard: " + srsp.getShard(),
-            e);
+      @SuppressWarnings("unchecked")
+      NamedList<NamedList<NamedList<?>>> stats =
+          (NamedList<NamedList<NamedList<?>>>)
+              SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "stats", false);
+      ;
+      if (stats == null) {
+        continue;
       }
 
       NamedList<NamedList<?>> stats_fields = unwrapStats(stats);
diff --git a/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java b/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java
index 58c4530e204..608d15bdc17 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java
@@ -56,6 +56,7 @@ import org.apache.solr.spelling.suggest.SolrSuggester;
 import org.apache.solr.spelling.suggest.SuggesterOptions;
 import org.apache.solr.spelling.suggest.SuggesterParams;
 import org.apache.solr.spelling.suggest.SuggesterResult;
+import org.apache.solr.util.SolrResponseUtil;
 import org.apache.solr.util.plugin.SolrCoreAware;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -294,17 +295,18 @@ public class SuggestComponent extends SearchComponent
     // Collect Shard responses
     for (ShardRequest sreq : rb.finished) {
       for (ShardResponse srsp : sreq.responses) {
-        NamedList<Object> resp;
-        if ((resp = srsp.getSolrResponse().getResponse()) != null) {
-          @SuppressWarnings("unchecked")
-          SimpleOrderedMap<SimpleOrderedMap<NamedList<Object>>> namedList =
-              (SimpleOrderedMap<SimpleOrderedMap<NamedList<Object>>>)
-                  resp.get(SuggesterResultLabels.SUGGEST);
-          if (log.isInfoEnabled()) {
-            log.info("{} : {}", srsp.getShard(), namedList);
-          }
-          suggesterResults.add(toSuggesterResult(namedList));
+        @SuppressWarnings("unchecked")
+        SimpleOrderedMap<SimpleOrderedMap<NamedList<Object>>> namedList =
+            (SimpleOrderedMap<SimpleOrderedMap<NamedList<Object>>>)
+                SolrResponseUtil.getSubsectionFromShardResponse(
+                    rb, srsp, SuggesterResultLabels.SUGGEST, false);
+        if (namedList == null) {
+          continue;
+        }
+        if (log.isInfoEnabled()) {
+          log.info("{} : {}", srsp.getShard(), namedList);
         }
+        suggesterResults.add(toSuggesterResult(namedList));
       }
     }
 
diff --git a/solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java b/solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java
index 7f8b987bbcc..5ef1571d403 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java
@@ -52,6 +52,7 @@ import org.apache.solr.search.SolrDocumentFetcher;
 import org.apache.solr.search.SolrIndexSearcher;
 import org.apache.solr.search.SolrReturnFields;
 import org.apache.solr.util.SolrPluginUtils;
+import org.apache.solr.util.SolrResponseUtil;
 
 /**
  * Return term vectors for the documents in a query result set.
@@ -430,17 +431,19 @@ public class TermVectorComponent extends SearchComponent {
         for (ShardResponse srsp : sreq.responses) {
           @SuppressWarnings({"unchecked"})
           NamedList<Object> nl =
-              (NamedList<Object>) srsp.getSolrResponse().getResponse().get(TERM_VECTORS);
+              (NamedList<Object>)
+                  SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, TERM_VECTORS, false);
+          if (nl != null) {
+            // Add metadata (that which isn't a uniqueKey value):
+            Object warningsNL = nl.get(TV_KEY_WARNINGS);
+            // assume if that if warnings is already present; we don't need to merge.
+            if (warningsNL != null && termVectorsNL.indexOf(TV_KEY_WARNINGS, 0) < 0) {
+              termVectorsNL.add(TV_KEY_WARNINGS, warningsNL);
+            }
 
-          // Add metadata (that which isn't a uniqueKey value):
-          Object warningsNL = nl.get(TV_KEY_WARNINGS);
-          // assume if that if warnings is already present; we don't need to merge.
-          if (warningsNL != null && termVectorsNL.indexOf(TV_KEY_WARNINGS, 0) < 0) {
-            termVectorsNL.add(TV_KEY_WARNINGS, warningsNL);
+            // UniqueKey data
+            SolrPluginUtils.copyNamedListIntoArrayByDocPosInResponse(nl, rb.resultIds, arr);
           }
-
-          // UniqueKey data
-          SolrPluginUtils.copyNamedListIntoArrayByDocPosInResponse(nl, rb.resultIds, arr);
         }
       }
       // remove nulls in case not all docs were able to be retrieved
diff --git a/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java b/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java
index 68718bf4714..7d45a885855 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java
@@ -53,6 +53,7 @@ import org.apache.solr.schema.StrField;
 import org.apache.solr.search.PointMerger;
 import org.apache.solr.search.SolrIndexSearcher;
 import org.apache.solr.util.BoundedTreeSet;
+import org.apache.solr.util.SolrResponseUtil;
 
 /**
  * Return TermEnum information, useful for things like auto suggest.
@@ -383,12 +384,14 @@ public class TermsComponent extends SearchComponent {
       for (ShardResponse srsp : sreq.responses) {
         @SuppressWarnings("unchecked")
         NamedList<NamedList<Object>> terms =
-            (NamedList<NamedList<Object>>) srsp.getSolrResponse().getResponse().get("terms");
+            (NamedList<NamedList<Object>>)
+                SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "terms", false);
         th.parse(terms);
 
         @SuppressWarnings({"unchecked"})
         NamedList<Number> stats =
-            (NamedList<Number>) srsp.getSolrResponse().getResponse().get("indexstats");
+            (NamedList<Number>)
+                SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "indexstats", true);
         if (stats != null) {
           th.numDocs += stats.get("numDocs").longValue();
           th.stats = true;
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/SearchGroupShardResponseProcessor.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/SearchGroupShardResponseProcessor.java
index be351dd5770..a748f917977 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/SearchGroupShardResponseProcessor.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/SearchGroupShardResponseProcessor.java
@@ -28,6 +28,7 @@ import java.util.Set;
 import org.apache.lucene.search.Sort;
 import org.apache.lucene.search.grouping.SearchGroup;
 import org.apache.lucene.util.BytesRef;
+import org.apache.solr.client.solrj.SolrResponse;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.common.params.ShardParams;
 import org.apache.solr.common.util.NamedList;
@@ -40,12 +41,12 @@ import org.apache.solr.search.SortSpec;
 import org.apache.solr.search.grouping.distributed.ShardResponseProcessor;
 import org.apache.solr.search.grouping.distributed.command.SearchGroupsFieldCommandResult;
 import org.apache.solr.search.grouping.distributed.shardresultserializer.SearchGroupsResultTransformer;
+import org.apache.solr.util.SolrResponseUtil;
 
 /** Concrete implementation for merging {@link SearchGroup} instances from shard responses. */
 public class SearchGroupShardResponseProcessor implements ShardResponseProcessor {
 
   @Override
-  @SuppressWarnings("unchecked")
   public void process(ResponseBuilder rb, ShardRequest shardRequest) {
     SortSpec groupSortSpec = rb.getGroupingSpec().getGroupSortSpec();
     Sort groupSort = rb.getGroupingSpec().getGroupSortSpec().getSort();
@@ -58,17 +59,16 @@ public class SearchGroupShardResponseProcessor implements ShardResponseProcessor
     final Map<String, Map<SearchGroup<BytesRef>, Set<String>>> tempSearchGroupToShards =
         new HashMap<>(fields.length, 1.0f);
     for (String field : fields) {
-      commandSearchGroups.put(
-          field, new ArrayList<Collection<SearchGroup<BytesRef>>>(shardRequest.responses.size()));
-      tempSearchGroupToShards.put(field, new HashMap<SearchGroup<BytesRef>, Set<String>>());
+      commandSearchGroups.put(field, new ArrayList<>(shardRequest.responses.size()));
+      tempSearchGroupToShards.put(field, new HashMap<>());
       if (!rb.searchGroupToShards.containsKey(field)) {
-        rb.searchGroupToShards.put(field, new HashMap<SearchGroup<BytesRef>, Set<String>>());
+        rb.searchGroupToShards.put(field, new HashMap<>());
       }
     }
 
     SearchGroupsResultTransformer serializer =
         new SearchGroupsResultTransformer(rb.req.getSearcher());
-    int maxElapsedTime = 0;
+    long maxElapsedTime = 0;
     int hitCountDuringFirstPhase = 0;
 
     NamedList<Object> shardInfo = null;
@@ -78,24 +78,26 @@ public class SearchGroupShardResponseProcessor implements ShardResponseProcessor
     }
 
     for (ShardResponse srsp : shardRequest.responses) {
+      SolrResponse solrResponse = srsp.getSolrResponse();
+      NamedList<?> response = solrResponse.getResponse();
       if (shardInfo != null) {
         SimpleOrderedMap<Object> nl = new SimpleOrderedMap<>(4);
 
         if (srsp.getException() != null) {
           Throwable t = srsp.getException();
           if (t instanceof SolrServerException) {
-            t = ((SolrServerException) t).getCause();
+            t = t.getCause();
           }
           nl.add("error", t.toString());
           StringWriter trace = new StringWriter();
           t.printStackTrace(new PrintWriter(trace));
           nl.add("trace", trace.toString());
         } else {
-          nl.add("numFound", (Integer) srsp.getSolrResponse().getResponse().get("totalHitCount"));
-        }
-        if (srsp.getSolrResponse() != null) {
-          nl.add("time", srsp.getSolrResponse().getElapsedTime());
+          nl.add("numFound", response.get("totalHitCount"));
         }
+
+        nl.add("time", solrResponse.getElapsedTime());
+
         if (srsp.getShardAddress() != null) {
           nl.add("shardAddress", srsp.getShardAddress());
         }
@@ -108,9 +110,14 @@ public class SearchGroupShardResponseProcessor implements ShardResponseProcessor
             .put(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY, Boolean.TRUE);
         continue; // continue if there was an error and we're tolerant.
       }
-      maxElapsedTime = (int) Math.max(maxElapsedTime, srsp.getSolrResponse().getElapsedTime());
+      maxElapsedTime = Math.max(maxElapsedTime, solrResponse.getElapsedTime());
+      @SuppressWarnings("unchecked")
       NamedList<NamedList<?>> firstPhaseResult =
-          (NamedList<NamedList<?>>) srsp.getSolrResponse().getResponse().get("firstPhase");
+          (NamedList<NamedList<?>>)
+              SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "firstPhase", false);
+      if (firstPhaseResult == null) {
+        continue; // looks like a shard did not return anything
+      }
       final Map<String, SearchGroupsFieldCommandResult> result =
           serializer.transformToNative(
               firstPhaseResult, groupSort, withinGroupSort, srsp.getShard());
@@ -139,19 +146,14 @@ public class SearchGroupShardResponseProcessor implements ShardResponseProcessor
         entry.getValue().add(searchGroups);
         for (SearchGroup<BytesRef> searchGroup : searchGroups) {
           Map<SearchGroup<BytesRef>, Set<String>> map = tempSearchGroupToShards.get(field);
-          Set<String> shards = map.get(searchGroup);
-          if (shards == null) {
-            shards = new HashSet<>();
-            map.put(searchGroup, shards);
-          }
+          Set<String> shards = map.computeIfAbsent(searchGroup, k -> new HashSet<>());
           shards.add(srsp.getShard());
         }
       }
-      hitCountDuringFirstPhase +=
-          (Integer) srsp.getSolrResponse().getResponse().get("totalHitCount");
+      hitCountDuringFirstPhase += (Integer) response.get("totalHitCount");
     }
     rb.totalHitCount = hitCountDuringFirstPhase;
-    rb.firstPhaseElapsedTime = maxElapsedTime;
+    rb.firstPhaseElapsedTime = (int) maxElapsedTime;
     for (Map.Entry<String, List<Collection<SearchGroup<BytesRef>>>> entry :
         commandSearchGroups.entrySet()) {
       String groupField = entry.getKey();
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/StoredFieldsShardResponseProcessor.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/StoredFieldsShardResponseProcessor.java
index 243d9201c96..31cfb11ec39 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/StoredFieldsShardResponseProcessor.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/StoredFieldsShardResponseProcessor.java
@@ -16,7 +16,6 @@
  */
 package org.apache.solr.search.grouping.distributed.responseprocessor;
 
-import org.apache.lucene.search.FieldDoc;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.handler.component.ResponseBuilder;
@@ -25,6 +24,7 @@ import org.apache.solr.handler.component.ShardRequest;
 import org.apache.solr.handler.component.ShardResponse;
 import org.apache.solr.search.SolrIndexSearcher;
 import org.apache.solr.search.grouping.distributed.ShardResponseProcessor;
+import org.apache.solr.util.SolrResponseUtil;
 
 /** Concrete implementation for processing the stored field values from shard responses. */
 public class StoredFieldsShardResponseProcessor implements ShardResponseProcessor {
@@ -33,20 +33,25 @@ public class StoredFieldsShardResponseProcessor implements ShardResponseProcesso
   public void process(ResponseBuilder rb, ShardRequest shardRequest) {
     boolean returnScores = (rb.getFieldFlags() & SolrIndexSearcher.GET_SCORES) != 0;
     ShardResponse srsp = shardRequest.responses.get(0);
-    SolrDocumentList docs = (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response");
     String uniqueIdFieldName = rb.req.getSchema().getUniqueKeyField().getName();
 
     if (rb.rsp.getReturnFields().getFieldRenames().get(uniqueIdFieldName) != null) {
       // if id was renamed we need to use the new name
       uniqueIdFieldName = rb.rsp.getReturnFields().getFieldRenames().get(uniqueIdFieldName);
     }
+
+    SolrDocumentList docs =
+        (SolrDocumentList)
+            SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "response", false);
+    if (docs == null) {
+      return;
+    }
     for (SolrDocument doc : docs) {
       Object id = doc.getFieldValue(uniqueIdFieldName).toString();
       ShardDoc shardDoc = rb.resultIds.get(id);
-      FieldDoc fieldDoc = (FieldDoc) shardDoc;
       if (shardDoc != null) {
-        if (returnScores && !Float.isNaN(fieldDoc.score)) {
-          doc.setField("score", fieldDoc.score);
+        if (returnScores && !Float.isNaN(shardDoc.score)) {
+          doc.setField("score", shardDoc.score);
         }
         rb.retrievedDocuments.put(id, doc);
       }
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/TopGroupsShardResponseProcessor.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/TopGroupsShardResponseProcessor.java
index 665ca95236f..39060f60782 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/TopGroupsShardResponseProcessor.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/TopGroupsShardResponseProcessor.java
@@ -44,6 +44,7 @@ import org.apache.solr.search.SortSpec;
 import org.apache.solr.search.grouping.distributed.ShardResponseProcessor;
 import org.apache.solr.search.grouping.distributed.command.QueryCommandResult;
 import org.apache.solr.search.grouping.distributed.shardresultserializer.TopGroupsResultTransformer;
+import org.apache.solr.util.SolrResponseUtil;
 
 /** Concrete implementation for merging {@link TopGroups} instances from shard responses. */
 public class TopGroupsShardResponseProcessor implements ShardResponseProcessor {
@@ -122,8 +123,11 @@ public class TopGroupsShardResponseProcessor implements ShardResponseProcessor {
         continue; // continue if there was an error and we're tolerant.
       }
       NamedList<NamedList<?>> secondPhaseResult =
-          (NamedList<NamedList<?>>) srsp.getSolrResponse().getResponse().get("secondPhase");
-      if (secondPhaseResult == null) continue;
+          (NamedList<NamedList<?>>)
+              SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "secondPhase", false);
+      if (secondPhaseResult == null) {
+        continue;
+      }
       Map<String, ?> result =
           serializer.transformToNative(
               secondPhaseResult, groupSort, withinGroupSort, srsp.getShard());
diff --git a/solr/core/src/java/org/apache/solr/util/SolrResponseUtil.java b/solr/core/src/java/org/apache/solr/util/SolrResponseUtil.java
new file mode 100644
index 00000000000..eb12dc9d779
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/util/SolrResponseUtil.java
@@ -0,0 +1,77 @@
+/*
+ * 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.util;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Objects;
+import org.apache.solr.client.solrj.SolrResponse;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.ShardParams;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.handler.component.ResponseBuilder;
+import org.apache.solr.handler.component.ShardResponse;
+import org.apache.solr.response.SolrQueryResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SolrResponseUtil {
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  private SolrResponseUtil() {}
+
+  public static Object getSubsectionFromShardResponse(
+      ResponseBuilder rb, ShardResponse srsp, String shardResponseKey, boolean subSectionOptional) {
+    Object shardResponseSubsection;
+    try {
+      SolrResponse solrResponse = srsp.getSolrResponse();
+      NamedList<Object> response = solrResponse.getResponse();
+      shardResponseSubsection = response.get(shardResponseKey);
+      if (shardResponseSubsection != null) {
+        return shardResponseSubsection;
+      } else {
+        NamedList<?> responseHeader =
+            Objects.requireNonNull(
+                (NamedList<?>) response.get(SolrQueryResponse.RESPONSE_HEADER_KEY));
+        if (subSectionOptional
+            || Boolean.TRUE.equals(
+                responseHeader.getBooleanArg(
+                    SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY))) {
+          return null;
+        } else {
+          log.warn("corrupted response on {} : {}", srsp.getShardRequest(), solrResponse);
+          throw new SolrException(
+              SolrException.ErrorCode.SERVER_ERROR,
+              shardResponseKey
+                  + " is absent in response from "
+                  + srsp.getNodeName()
+                  + ", but "
+                  + SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY
+                  + " isn't set in the response.");
+        }
+      }
+    } catch (Exception ex) {
+      if (rb != null && ShardParams.getShardsTolerantAsBool(rb.req.getParams())) {
+        return null;
+      } else {
+        throw new SolrException(
+            SolrException.ErrorCode.SERVER_ERROR,
+            "Unable to read " + shardResponseKey + " info for shard: " + srsp.getShard(),
+            ex);
+      }
+    }
+  }
+}
diff --git a/solr/core/src/test/org/apache/solr/search/RankQueryTestPlugin.java b/solr/core/src/test/org/apache/solr/search/RankQueryTestPlugin.java
index fb37c243b95..6ea1e0d899c 100644
--- a/solr/core/src/test/org/apache/solr/search/RankQueryTestPlugin.java
+++ b/solr/core/src/test/org/apache/solr/search/RankQueryTestPlugin.java
@@ -25,6 +25,7 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.IndexReaderContext;
 import org.apache.lucene.index.LeafReaderContext;
@@ -64,6 +65,7 @@ import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.schema.SchemaField;
+import org.apache.solr.util.SolrResponseUtil;
 
 public class RankQueryTestPlugin extends QParserPlugin {
 
@@ -158,7 +160,6 @@ public class RankQueryTestPlugin extends QParserPlugin {
 
     public void handleMergeFields(ResponseBuilder rb, SolrIndexSearcher searcher) {}
 
-    @SuppressWarnings({"unchecked"})
     public void merge(ResponseBuilder rb, ShardRequest sreq) {
 
       // id to shard mapping, to eliminate any accidental dups
@@ -197,7 +198,11 @@ public class RankQueryTestPlugin extends QParserPlugin {
               nl.add("shardAddress", srsp.getShardAddress());
             }
           } else {
-            docs = (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response");
+            docs =
+                Objects.requireNonNull(
+                    (SolrDocumentList)
+                        SolrResponseUtil.getSubsectionFromShardResponse(
+                            null, srsp, "response", false));
             nl.add("numFound", docs.getNumFound());
             nl.add("maxScore", docs.getMaxScore());
             nl.add("shardAddress", srsp.getShardAddress());
@@ -215,11 +220,17 @@ public class RankQueryTestPlugin extends QParserPlugin {
         }
 
         if (docs == null) { // could have been initialized in the 'shardInfo' block above
-          docs = (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response");
+          docs =
+              Objects.requireNonNull(
+                  (SolrDocumentList)
+                      SolrResponseUtil.getSubsectionFromShardResponse(
+                          null, srsp, "response", false));
         }
 
         NamedList<?> responseHeader =
-            (NamedList<?>) srsp.getSolrResponse().getResponse().get("responseHeader");
+            (NamedList<?>)
+                SolrResponseUtil.getSubsectionFromShardResponse(
+                    null, srsp, "responseHeader", false);
         if (responseHeader != null
             && Boolean.TRUE.equals(
                 responseHeader.get(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY))) {
@@ -499,7 +510,11 @@ public class RankQueryTestPlugin extends QParserPlugin {
               nl.add("shardAddress", srsp.getShardAddress());
             }
           } else {
-            docs = (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response");
+            docs =
+                Objects.requireNonNull(
+                    (SolrDocumentList)
+                        SolrResponseUtil.getSubsectionFromShardResponse(
+                            null, srsp, "response", false));
             nl.add("numFound", docs.getNumFound());
             nl.add("maxScore", docs.getMaxScore());
             nl.add("shardAddress", srsp.getShardAddress());
@@ -517,11 +532,17 @@ public class RankQueryTestPlugin extends QParserPlugin {
         }
 
         if (docs == null) { // could have been initialized in the 'shardInfo' block above
-          docs = (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response");
+          docs =
+              Objects.requireNonNull(
+                  (SolrDocumentList)
+                      SolrResponseUtil.getSubsectionFromShardResponse(
+                          null, srsp, "response", false));
         }
 
         NamedList<?> responseHeader =
-            (NamedList<?>) srsp.getSolrResponse().getResponse().get("responseHeader");
+            (NamedList<?>)
+                SolrResponseUtil.getSubsectionFromShardResponse(
+                    null, srsp, "responseHeader", false);
         if (responseHeader != null
             && Boolean.TRUE.equals(
                 responseHeader.get(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY))) {
@@ -538,7 +559,11 @@ public class RankQueryTestPlugin extends QParserPlugin {
 
         @SuppressWarnings({"rawtypes"})
         NamedList sortFieldValues =
-            (NamedList) (srsp.getSolrResponse().getResponse().get("merge_values"));
+            (NamedList)
+                SolrResponseUtil.getSubsectionFromShardResponse(rb, srsp, "merge_values", false);
+        if (sortFieldValues == null) {
+          continue;
+        }
         @SuppressWarnings({"rawtypes"})
         NamedList unmarshalledSortFieldValues = unmarshalSortValues(ss, sortFieldValues);
         @SuppressWarnings({"rawtypes"})