You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by no...@apache.org on 2020/07/11 07:51:53 UTC
[lucene-solr] 01/01: SOLR-14155: Load all other SolrCore plugins
from packages
This is an automated email from the ASF dual-hosted git repository.
noble pushed a commit to branch jira/solr14155-1
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
commit 59053416fcf2115305c768e12f7db45fce042565
Author: noblepaul <no...@gmail.com>
AuthorDate: Sat Jul 11 17:51:03 2020 +1000
SOLR-14155: Load all other SolrCore plugins from packages
---
.../apache/solr/api/CustomContainerPlugins.java | 12 +--
.../java/org/apache/solr/core/CoreContainer.java | 24 +++---
.../src/java/org/apache/solr/core/PluginBag.java | 4 +
.../src/java/org/apache/solr/core/PluginInfo.java | 44 +++++++----
.../src/java/org/apache/solr/core/SolrConfig.java | 18 +++++
.../src/java/org/apache/solr/core/SolrCore.java | 58 +++++++-------
.../org/apache/solr/core/SolrResourceLoader.java | 11 +++
.../org/apache/solr/handler/StreamHandler.java | 4 +-
.../solr/handler/component/SearchHandler.java | 2 +-
.../apache/solr/packagemanager/PackageManager.java | 10 +--
.../solr/packagemanager/RepositoryManager.java | 6 +-
.../apache/solr/pkg/CoreRefreshingClassLoader.java | 88 ++++++++++++++++++++++
.../java/org/apache/solr/pkg/PackageListeners.java | 34 +++++++--
.../org/apache/solr/pkg/PackagePluginHolder.java | 21 +++---
.../java/org/apache/solr/search/CacheConfig.java | 17 ++++-
.../java/org/apache/solr/update/UpdateHandler.java | 57 +++++++-------
.../apache/solr/core/TestQuerySenderListener.java | 3 +-
.../apache/solr/core/TestQuerySenderNoQuery.java | 2 +-
18 files changed, 283 insertions(+), 132 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/api/CustomContainerPlugins.java b/solr/core/src/java/org/apache/solr/api/CustomContainerPlugins.java
index 6536276..80b570d 100644
--- a/solr/core/src/java/org/apache/solr/api/CustomContainerPlugins.java
+++ b/solr/core/src/java/org/apache/solr/api/CustomContainerPlugins.java
@@ -36,12 +36,12 @@ import org.apache.solr.common.MapWriter;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.annotation.JsonProperty;
import org.apache.solr.common.cloud.ClusterPropertiesListener;
-import org.apache.solr.common.util.Pair;
import org.apache.solr.common.util.PathTrie;
import org.apache.solr.common.util.ReflectMapWriter;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.Utils;
import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.PluginInfo;
import org.apache.solr.handler.admin.ContainerPluginsApi;
import org.apache.solr.pkg.PackageLoader;
import org.apache.solr.request.SolrQueryRequest;
@@ -225,12 +225,12 @@ public class CustomContainerPlugins implements ClusterPropertiesListener, MapWri
@SuppressWarnings({"unchecked","rawtypes"})
public ApiInfo(PluginMeta info, List<String> errs) {
this.info = info;
- Pair<String, String> klassInfo = org.apache.solr.core.PluginInfo.parseClassName(info.klass);
- pkg = klassInfo.first();
+ PluginInfo.CName klassInfo = new PluginInfo.CName(info.klass);
+ pkg = klassInfo.pkg;
if (pkg != null) {
PackageLoader.Package p = coreContainer.getPackageLoader().getPackage(pkg);
if (p == null) {
- errs.add("Invalid package " + klassInfo.first());
+ errs.add("Invalid package " + klassInfo.pkg);
return;
}
this.pkgVersion = p.getVersion(info.version);
@@ -239,7 +239,7 @@ public class CustomContainerPlugins implements ClusterPropertiesListener, MapWri
return;
}
try {
- klas = pkgVersion.getLoader().findClass(klassInfo.second(), Object.class);
+ klas = pkgVersion.getLoader().findClass(klassInfo.className, Object.class);
} catch (Exception e) {
log.error("Error loading class", e);
errs.add("Error loading class " + e.toString());
@@ -247,7 +247,7 @@ public class CustomContainerPlugins implements ClusterPropertiesListener, MapWri
}
} else {
try {
- klas = Class.forName(klassInfo.second());
+ klas = Class.forName(klassInfo.className);
} catch (ClassNotFoundException e) {
errs.add("Error loading class " + e.toString());
return;
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index 53373b6..ca74829 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -24,19 +24,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.spec.InvalidKeySpecException;
import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Properties;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -1588,20 +1576,28 @@ public class CoreContainer {
return ret;
}
+ public void reload(String name) {
+ reload(name, null);
+ }
/**
* Recreates a SolrCore.
* While the new core is loading, requests will continue to be dispatched to
* and processed by the old core
*
* @param name the name of the SolrCore to reload
+ * @param coreId The unique identifier of the core
*/
- public void reload(String name) {
+ public void reload(String name, UUID coreId) {
if (isShutDown) {
throw new AlreadyClosedException();
}
SolrCore newCore = null;
SolrCore core = solrCores.getCoreFromAnyList(name, false);
if (core != null) {
+ if(coreId != null && core.uniqueId != coreId) {
+ //trying to reload an already unloaded core
+ return;
+ }
// The underlying core properties files may have changed, we don't really know. So we have a (perhaps) stale
// CoreDescriptor and we need to reload it from the disk files
diff --git a/solr/core/src/java/org/apache/solr/core/PluginBag.java b/solr/core/src/java/org/apache/solr/core/PluginBag.java
index 2f82ccc..37a3450 100644
--- a/solr/core/src/java/org/apache/solr/core/PluginBag.java
+++ b/solr/core/src/java/org/apache/solr/core/PluginBag.java
@@ -368,6 +368,10 @@ public class PluginBag<T> implements AutoCloseable {
protected final PluginInfo pluginInfo;
boolean registerAPI = false;
+ public PluginHolder(T inst, SolrConfig.SolrPluginInfo info) {
+ this.inst = inst;
+ pluginInfo = new PluginInfo(info.tag, Collections.singletonMap("class", inst.getClass().getName()));
+ }
public PluginHolder(PluginInfo info) {
this.pluginInfo = info;
}
diff --git a/solr/core/src/java/org/apache/solr/core/PluginInfo.java b/solr/core/src/java/org/apache/solr/core/PluginInfo.java
index cc6615f..58fa73d 100644
--- a/solr/core/src/java/org/apache/solr/core/PluginInfo.java
+++ b/solr/core/src/java/org/apache/solr/core/PluginInfo.java
@@ -25,7 +25,6 @@ import java.util.Map;
import org.apache.solr.common.MapSerializable;
import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.Pair;
import org.apache.solr.util.DOMUtil;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -42,6 +41,7 @@ import static org.apache.solr.schema.FieldType.CLASS_NAME;
*/
public class PluginInfo implements MapSerializable {
public final String name, className, type, pkgName;
+ public final CName cName;
@SuppressWarnings({"rawtypes"})
public final NamedList initArgs;
public final Map<String, String> attributes;
@@ -53,9 +53,9 @@ public class PluginInfo implements MapSerializable {
public PluginInfo(String type, Map<String, String> attrs, @SuppressWarnings({"rawtypes"})NamedList initArgs, List<PluginInfo> children) {
this.type = type;
this.name = attrs.get(NAME);
- Pair<String, String> parsed = parseClassName(attrs.get(CLASS_NAME));
- this.className = parsed.second();
- this.pkgName = parsed.first();
+ cName = parseClassName(attrs.get(CLASS_NAME));
+ this.className = cName.className;
+ this.pkgName = cName.pkg;
this.initArgs = initArgs;
attributes = unmodifiableMap(attrs);
this.children = children == null ? Collections.<PluginInfo>emptyList(): unmodifiableList(children);
@@ -66,17 +66,29 @@ public class PluginInfo implements MapSerializable {
* This checks if it is a package name prefixed classname.
* the return value has first = package name and second = class name
*/
- public static Pair<String,String > parseClassName(String name) {
- String pkgName = null;
- String className = name;
- if (name != null) {
+ public static CName parseClassName(String name) {
+ return new CName(name);
+ }
+
+ public static class CName {
+ public final String pkg;
+ public final String className;
+
+ public CName(String name) {
+ if (name == null) {
+ pkg = null;
+ className = null;
+ return;
+ }
int colonIdx = name.indexOf(':');
if (colonIdx > -1) {
- pkgName = name.substring(0, colonIdx);
+ pkg = name.substring(0, colonIdx);
className = name.substring(colonIdx + 1);
+ } else {
+ pkg = null;
+ className = name;
}
}
- return new Pair<>(pkgName, className);
}
@@ -84,9 +96,9 @@ public class PluginInfo implements MapSerializable {
public PluginInfo(Node node, String err, boolean requireName, boolean requireClass) {
type = node.getNodeName();
name = DOMUtil.getAttr(node, NAME, requireName ? err : null);
- Pair<String, String> parsed = parseClassName(DOMUtil.getAttr(node, CLASS_NAME, requireClass ? err : null));
- className = parsed.second();
- pkgName = parsed.first();
+ cName = parseClassName(DOMUtil.getAttr(node, CLASS_NAME, requireClass ? err : null));
+ className = cName.className;
+ pkgName = cName.pkg;
initArgs = DOMUtil.childNodesToNamedList(node);
attributes = unmodifiableMap(DOMUtil.toMap(node.getAttributes()));
children = loadSubPlugins(node);
@@ -117,9 +129,9 @@ public class PluginInfo implements MapSerializable {
}
this.type = type;
this.name = (String) m.get(NAME);
- Pair<String, String> parsed = parseClassName((String) m.get(CLASS_NAME));
- this.className = parsed.second();
- this.pkgName = parsed.first();
+ cName = parseClassName((String) m.get(CLASS_NAME));
+ this.className = cName.className;
+ this.pkgName = cName.pkg;
attributes = unmodifiableMap(m);
this.children = Collections.<PluginInfo>emptyList();
isFromSolrConfig = true;
diff --git a/solr/core/src/java/org/apache/solr/core/SolrConfig.java b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
index 2daaa95..c189eb4 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
@@ -57,6 +57,7 @@ import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.util.IOUtils;
import org.apache.solr.handler.component.SearchComponent;
+import org.apache.solr.pkg.PackageListeners;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.response.transform.TransformerFactory;
@@ -105,6 +106,8 @@ public class SolrConfig extends XmlConfigFile implements MapSerializable {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
public static final String DEFAULT_CONF_FILE = "solrconfig.xml";
+ public static final String LATEST = "$LATEST";
+
private RequestParams requestParams;
@@ -971,6 +974,21 @@ public class SolrConfig extends XmlConfigFile implements MapSerializable {
return requestParams;
}
+ /**
+ * The version of package that should be loaded for a given package name
+ * This information is stored in the params.json in the same configset
+ * If params.json is absent or there is no corresponding version specified for a given package,
+ * the latest is used
+ */
+ public String maxPackageVersion(String pkg) {
+ RequestParams.ParamSet p = getRequestParams().getParams(PackageListeners.PACKAGE_VERSIONS);
+ if (p == null) {
+ return null;
+ }
+ Object o = p.get().get(pkg);
+ if (o == null || LATEST.equals(o)) return null;
+ return o.toString();
+ }
public RequestParams refreshRequestParams() {
requestParams = RequestParams.getFreshRequestParams(getResourceLoader(), requestParams);
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java
index 0b1c551..83526da 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -31,22 +31,7 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Properties;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -97,6 +82,7 @@ import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.common.util.SolrNamedThreadFactory;
import org.apache.solr.common.util.Utils;
import org.apache.solr.core.DirectoryFactory.DirContext;
+import org.apache.solr.core.PluginBag.PluginHolder;
import org.apache.solr.core.snapshots.SolrSnapshotManager;
import org.apache.solr.core.snapshots.SolrSnapshotMetaDataManager;
import org.apache.solr.core.snapshots.SolrSnapshotMetaDataManager.SnapshotMetaData;
@@ -112,6 +98,7 @@ import org.apache.solr.metrics.SolrMetricProducer;
import org.apache.solr.metrics.SolrMetricsContext;
import org.apache.solr.pkg.PackageListeners;
import org.apache.solr.pkg.PackageLoader;
+import org.apache.solr.pkg.PackagePluginHolder;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.BinaryResponseWriter;
@@ -137,10 +124,7 @@ import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.ManagedIndexSchema;
import org.apache.solr.schema.SimilarityFactory;
-import org.apache.solr.search.QParserPlugin;
-import org.apache.solr.search.SolrFieldCacheBean;
-import org.apache.solr.search.SolrIndexSearcher;
-import org.apache.solr.search.ValueSourceParser;
+import org.apache.solr.search.*;
import org.apache.solr.search.stats.LocalStatsCache;
import org.apache.solr.search.stats.StatsCache;
import org.apache.solr.update.DefaultSolrCoreState;
@@ -191,6 +175,11 @@ public final class SolrCore implements SolrInfoBean, Closeable {
private String name;
private String logid; // used to show what name is set
+ /**
+ * A unique id to differentiate multiple instances of the same core
+ * If we reload a core, the name remains same , but the id will be new
+ */
+ public final UUID uniqueId = UUID.randomUUID();
private boolean isReloaded = false;
@@ -626,25 +615,26 @@ public final class SolrCore implements SolrInfoBean, Closeable {
}
+ @SuppressWarnings("unchecked")
private void initListeners() {
final Class<SolrEventListener> clazz = SolrEventListener.class;
final String label = "Event Listener";
for (PluginInfo info : solrConfig.getPluginInfos(SolrEventListener.class.getName())) {
final String event = info.attributes.get("event");
if ("firstSearcher".equals(event)) {
- SolrEventListener obj = createInitInstance(info, clazz, label, null);
+ PluginHolder<SolrEventListener> obj = (PluginHolder<SolrEventListener>)PackagePluginHolder.createHolder(info, this, SolrEventListener.class, label);
firstSearcherListeners.add(obj);
- log.debug("[{}] Added SolrEventListener for firstSearcher: [{}]", logid, obj);
+ log.debug("[{}] Added SolrEventListener for firstSearcher: [{}]", logid, obj.get());
} else if ("newSearcher".equals(event)) {
- SolrEventListener obj = createInitInstance(info, clazz, label, null);
+ PluginHolder<SolrEventListener> obj = (PluginHolder<SolrEventListener>)PackagePluginHolder.createHolder(info, this, SolrEventListener.class, label);
newSearcherListeners.add(obj);
- log.debug("[{}] Added SolrEventListener for newSearcher: [{}]", logid, obj);
+ log.debug("[{}] Added SolrEventListener for newSearcher: [{}]", logid, obj.get());
}
}
}
- final List<SolrEventListener> firstSearcherListeners = new ArrayList<>();
- final List<SolrEventListener> newSearcherListeners = new ArrayList<>();
+ final List<PluginHolder<SolrEventListener>> firstSearcherListeners = new ArrayList<>();
+ final List<PluginHolder<SolrEventListener>> newSearcherListeners = new ArrayList<>();
/**
* NOTE: this function is not thread safe. However, it is safe to call within the
@@ -654,7 +644,8 @@ public final class SolrCore implements SolrInfoBean, Closeable {
* @see SolrCoreAware
*/
public void registerFirstSearcherListener(SolrEventListener listener) {
- firstSearcherListeners.add(listener);
+ firstSearcherListeners.add(new PluginHolder<>(listener,
+ SolrConfig.classVsSolrPluginInfo.get(SolrEventListener.class.getName())));
}
/**
@@ -665,7 +656,8 @@ public final class SolrCore implements SolrInfoBean, Closeable {
* @see SolrCoreAware
*/
public void registerNewSearcherListener(SolrEventListener listener) {
- newSearcherListeners.add(listener);
+ newSearcherListeners.add(
+ new PluginHolder<>(listener, SolrConfig.classVsSolrPluginInfo.get(SolrEventListener.class.getName())));
}
/**
@@ -938,6 +930,7 @@ public final class SolrCore implements SolrInfoBean, Closeable {
this.solrConfig = configSet.getSolrConfig();
this.resourceLoader = configSet.getSolrConfig().getResourceLoader();
+ this.resourceLoader.core = this;
this.configSetProperties = configSet.getProperties();
// Initialize the metrics manager
this.coreMetricManager = initCoreMetricManager(solrConfig);
@@ -2364,8 +2357,8 @@ public final class SolrCore implements SolrInfoBean, Closeable {
if (currSearcher == null) {
future = searcherExecutor.submit(() -> {
try {
- for (SolrEventListener listener : firstSearcherListeners) {
- listener.newSearcher(newSearcher, null);
+ for (PluginHolder<SolrEventListener> listener : firstSearcherListeners) {
+ listener.get().newSearcher(newSearcher, null);
}
} catch (Throwable e) {
SolrException.log(log, null, e);
@@ -2380,8 +2373,8 @@ public final class SolrCore implements SolrInfoBean, Closeable {
if (currSearcher != null) {
future = searcherExecutor.submit(() -> {
try {
- for (SolrEventListener listener : newSearcherListeners) {
- listener.newSearcher(newSearcher, currSearcher);
+ for (PluginHolder<SolrEventListener> listener : newSearcherListeners) {
+ listener.get().newSearcher(newSearcher, currSearcher);
}
} catch (Throwable e) {
SolrException.log(log, null, e);
@@ -3252,4 +3245,5 @@ public final class SolrCore implements SolrInfoBean, Closeable {
public void runAsync(Runnable r) {
coreAsyncTaskExecutor.submit(r);
}
+
}
diff --git a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
index 77c80bf..3ab1ba1 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
@@ -76,6 +76,12 @@ public class SolrResourceLoader implements ResourceLoader, Closeable {
protected URLClassLoader classLoader;
private final Path instanceDir;
+ /**
+ * this is set by the {@link SolrCore}
+ * This could be null if the core is not yet initialized
+ */
+ SolrCore core;
+
private final List<SolrCoreAware> waitingForCore = Collections.synchronizedList(new ArrayList<SolrCoreAware>());
private final List<SolrInfoBean> infoMBeans = Collections.synchronizedList(new ArrayList<SolrInfoBean>());
private final List<ResourceLoaderAware> waitingForResources = Collections.synchronizedList(new ArrayList<ResourceLoaderAware>());
@@ -198,6 +204,11 @@ public class SolrResourceLoader implements ResourceLoader, Closeable {
TokenizerFactory.reloadTokenizers(this.classLoader);
}
+ public SolrCore getCore(){
+ return core;
+ }
+
+
private static URLClassLoader addURLsToClassLoader(final URLClassLoader oldLoader, List<URL> urls) {
if (urls.size() == 0) {
return oldLoader;
diff --git a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
index f1b1544..d604616 100644
--- a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
@@ -158,8 +158,8 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
}
@Override
- protected void initNewInstance(PackageLoader.Package.Version newest) {
- clazz = newest.getLoader().findClass(pluginInfo.className, Expressible.class);
+ protected Object initNewInstance(PackageLoader.Package.Version newest) {
+ return clazz = newest.getLoader().findClass(pluginInfo.className, Expressible.class);
}
}
diff --git a/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java b/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
index b93d855..6ee180e 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
@@ -166,7 +166,7 @@ public class SearchHandler extends RequestHandlerBase implements SolrCoreAware,
}
@Override
- public void changed(PackageLoader.Package pkg) {
+ public void changed(PackageLoader.Package pkg, Ctx ctx) {
//we could optimize this by listening to only relevant packages,
// but it is not worth optimizing as these are lightweight objects
components = null;
diff --git a/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java b/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java
index ef042da..f9b746a 100644
--- a/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java
+++ b/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java
@@ -43,10 +43,10 @@ import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.util.Pair;
import org.apache.solr.common.util.Utils;
+import org.apache.solr.core.SolrConfig;
import org.apache.solr.packagemanager.SolrPackage.Command;
import org.apache.solr.packagemanager.SolrPackage.Manifest;
import org.apache.solr.packagemanager.SolrPackage.Plugin;
-import org.apache.solr.pkg.PackagePluginHolder;
import org.apache.solr.util.SolrCLI;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
@@ -250,7 +250,7 @@ public class PackageManager implements Closeable {
// Set the package version in the collection's parameters
try {
SolrCLI.postJsonToSolr(solrClient, PackageUtils.getCollectionParamsPath(collection),
- "{set:{PKG_VERSIONS:{" + packageInstance.name+": '" + (pegToLatest? PackagePluginHolder.LATEST: packageInstance.version)+"'}}}");
+ "{set:{PKG_VERSIONS:{" + packageInstance.name+": '" + (pegToLatest? SolrConfig.LATEST: packageInstance.version)+"'}}}");
} catch (Exception ex) {
throw new SolrException(ErrorCode.SERVER_ERROR, ex);
}
@@ -296,7 +296,7 @@ public class PackageManager implements Closeable {
// Set the package version in the collection's parameters
try {
SolrCLI.postJsonToSolr(solrClient, PackageUtils.getCollectionParamsPath(collection),
- "{update:{PKG_VERSIONS:{'" + packageInstance.name + "' : '" + (pegToLatest? PackagePluginHolder.LATEST: packageInstance.version) + "'}}}");
+ "{update:{PKG_VERSIONS:{'" + packageInstance.name + "' : '" + (pegToLatest? SolrConfig.LATEST: packageInstance.version) + "'}}}");
} catch (Exception ex) {
throw new SolrException(ErrorCode.SERVER_ERROR, ex);
}
@@ -550,7 +550,7 @@ public class PackageManager implements Closeable {
}
}
}
- if (version == null || version.equalsIgnoreCase(PackageUtils.LATEST) || version.equalsIgnoreCase(PackagePluginHolder.LATEST)) {
+ if (version == null || version.equalsIgnoreCase(PackageUtils.LATEST) || version.equalsIgnoreCase(SolrConfig.LATEST)) {
return latest;
} else return null;
}
@@ -671,7 +671,7 @@ public class PackageManager implements Closeable {
/**
* Given a package, return a map of collections where this package is
- * installed to the installed version (which can be {@link PackagePluginHolder#LATEST})
+ * installed to the installed version (which can be {@link org.apache.solr.core.SolrConfig#LATEST})
*/
public Map<String, String> getDeployedCollections(String packageName) {
List<String> allCollections;
diff --git a/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java b/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java
index 0d1fc17..e961a37 100644
--- a/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java
+++ b/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java
@@ -48,11 +48,11 @@ import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.core.BlobRepository;
+import org.apache.solr.core.SolrConfig;
import org.apache.solr.filestore.PackageStoreAPI;
import org.apache.solr.packagemanager.SolrPackage.Artifact;
import org.apache.solr.packagemanager.SolrPackage.SolrPackageRelease;
import org.apache.solr.pkg.PackageAPI;
-import org.apache.solr.pkg.PackagePluginHolder;
import org.apache.solr.util.SolrCLI;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
@@ -300,7 +300,7 @@ public class RepositoryManager {
/**
* Install a version of the package. Also, run verify commands in case some
- * collection was using {@link PackagePluginHolder#LATEST} version of this package and got auto-updated.
+ * collection was using {@link org.apache.solr.core.SolrConfig#LATEST} version of this package and got auto-updated.
*/
public boolean install(String packageName, String version) throws SolrException {
SolrPackageRelease pkg = getLastPackageRelease(packageName);
@@ -312,7 +312,7 @@ public class RepositoryManager {
Map<String, String> collectionsDeployedIn = packageManager.getDeployedCollections(packageName);
List<String> collectionsPeggedToLatest = collectionsDeployedIn.keySet().stream().
- filter(collection -> collectionsDeployedIn.get(collection).equals(PackagePluginHolder.LATEST)).collect(Collectors.toList());
+ filter(collection -> collectionsDeployedIn.get(collection).equals(SolrConfig.LATEST)).collect(Collectors.toList());
if (!collectionsPeggedToLatest.isEmpty()) {
PackageUtils.printGreen("Collections that will be affected (since they are configured to use $LATEST): "+collectionsPeggedToLatest);
}
diff --git a/solr/core/src/java/org/apache/solr/pkg/CoreRefreshingClassLoader.java b/solr/core/src/java/org/apache/solr/pkg/CoreRefreshingClassLoader.java
new file mode 100644
index 0000000..efad846
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/pkg/CoreRefreshingClassLoader.java
@@ -0,0 +1,88 @@
+/*
+ * 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.pkg;
+
+import org.apache.solr.core.PluginInfo;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.core.SolrResourceLoader;
+
+import java.util.function.Function;
+
+/**A utility class that loads classes from packages and reloads core if any of those packages are updated
+ *
+ */
+public class CoreRefreshingClassLoader implements PackageListeners.Listener {
+ private final SolrCore solrCore;
+ private final PluginInfo info;
+ private final PackageLoader.Package.Version version;
+
+ public CoreRefreshingClassLoader(SolrCore solrCore, PluginInfo info, PackageLoader.Package.Version version) {
+ this.solrCore = solrCore;
+ this.info = info;
+ this.version = version;
+ }
+
+ @Override
+ public String packageName() {
+ return info.cName.pkg;
+ }
+
+ public SolrResourceLoader getLoader() {
+ return version.getLoader();
+ }
+ @Override
+ public PluginInfo pluginInfo() {
+ return info;
+ }
+
+ @Override
+ public void changed(PackageLoader.Package pkg, Ctx ctx) {
+ PackageLoader.Package.Version version = pkg.getLatest(solrCore.getSolrConfig().maxPackageVersion(info.cName.pkg));
+ if(version != this.version) {
+ ctx.runLater(SolrCore.class.getName(), () -> solrCore.getCoreContainer().reload(CoreRefreshingClassLoader.class.getName() , solrCore.uniqueId));
+ }
+ }
+
+ @Override
+ public PackageLoader.Package.Version getPackageVersion() {
+ return version;
+ }
+
+ @SuppressWarnings({"rawtypes","unchecked"})
+ public static Class loadClass(SolrCore core, PluginInfo info, Class type) {
+ return _get(core, info, version -> version.getLoader().findClass(info.cName.className, type));
+
+ }
+
+ private static <T> T _get(SolrCore core, PluginInfo info, Function<PackageLoader.Package.Version, T> fun){
+ PluginInfo.CName cName = info.cName;
+ PackageLoader.Package.Version latest = core.getCoreContainer().getPackageLoader().getPackage(cName.pkg)
+ .getLatest(core.getSolrConfig().maxPackageVersion(cName.pkg));
+ T result = fun.apply(latest);
+ core.getPackageListeners().addListener(new CoreRefreshingClassLoader(core, info, latest));
+ return result;
+ }
+
+ public static <T> T createInst(SolrCore core, PluginInfo info, Class<T> type) {
+ if(info.cName.pkg == null) {
+ return core.getResourceLoader().newInstance(info.cName.className== null? type.getName(): info.cName.className , type);
+ }
+ return _get(core, info, version -> version.getLoader().newInstance(info.cName.className, type));
+ }
+
+}
diff --git a/solr/core/src/java/org/apache/solr/pkg/PackageListeners.java b/solr/core/src/java/org/apache/solr/pkg/PackageListeners.java
index b5b295f..a2b859e 100644
--- a/solr/core/src/java/org/apache/solr/pkg/PackageListeners.java
+++ b/solr/core/src/java/org/apache/solr/pkg/PackageListeners.java
@@ -20,10 +20,9 @@ package org.apache.solr.pkg;
import java.lang.invoke.MethodHandles;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
+
import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrCore;
import org.apache.solr.logging.MDCLoggingContext;
@@ -64,21 +63,23 @@ public class PackageListeners {
synchronized void packagesUpdated(List<PackageLoader.Package> pkgs) {
MDCLoggingContext.setCore(core);
+ Listener.Ctx ctx = new Listener.Ctx();
try {
for (PackageLoader.Package pkgInfo : pkgs) {
- invokeListeners(pkgInfo);
+ invokeListeners(pkgInfo, ctx);
}
} finally {
+ ctx.runLaterTasks();
MDCLoggingContext.clear();
}
}
- private synchronized void invokeListeners(PackageLoader.Package pkg) {
+ private synchronized void invokeListeners(PackageLoader.Package pkg, Listener.Ctx ctx) {
for (Reference<Listener> ref : listeners) {
Listener listener = ref.get();
if(listener == null) continue;
if (listener.packageName() == null || listener.packageName().equals(pkg.name())) {
- listener.changed(pkg);
+ listener.changed(pkg, ctx);
}
}
}
@@ -96,15 +97,32 @@ public class PackageListeners {
public interface Listener {
- /**Name of the package or null to loisten to all package changes
+ /**Name of the package or null to listen to all package changes
*/
String packageName();
PluginInfo pluginInfo();
- void changed(PackageLoader.Package pkg);
+ void changed(PackageLoader.Package pkg, Ctx ctx);
PackageLoader.Package.Version getPackageVersion();
+ class Ctx {
+ private Map<String, Runnable > runLater;
+ public void runLater(String name, Runnable runnable ){
+ if(runLater == null) runLater = new LinkedHashMap<>();
+ runLater.put(name, runnable);
+ }
+ private void runLaterTasks(){
+ if(runLater == null) return;
+ new Thread(() -> runLater.forEach((s, runnable) -> {
+ try {
+ runnable.run();
+ } catch (Exception e) {
+ log.error("Unknown error", e);
+ }
+ }));
+ }
+ }
}
}
diff --git a/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java b/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
index 322a1d3..9df1ec3 100644
--- a/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
+++ b/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
@@ -55,7 +55,7 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
}
@Override
- public void changed(PackageLoader.Package pkg) {
+ public void changed(PackageLoader.Package pkg, Ctx ctx) {
reload(pkg);
}
@@ -68,19 +68,17 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
});
}
- private String maxVersion() {
- RequestParams.ParamSet p = core.getSolrConfig().getRequestParams().getParams(PackageListeners.PACKAGE_VERSIONS);
- if (p == null) {
- return null;
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public static PluginBag.PluginHolder createHolder(PluginInfo info, SolrCore core, Class type, String msg) {
+ if(info.cName.pkg == null) {
+ return new PluginBag.PluginHolder(info, core.createInitInstance(info, type,msg, null));
+ } else {
+ return new PackagePluginHolder(info, core, SolrConfig.classVsSolrPluginInfo.get(type.getName()));
}
- Object o = p.get().get(info.pkgName);
- if (o == null || LATEST.equals(o)) return null;
- return o.toString();
}
-
private synchronized void reload(PackageLoader.Package pkg) {
- String lessThan = maxVersion();
+ String lessThan = core.getSolrConfig().maxPackageVersion(info.pkgName);
PackageLoader.Package.Version newest = pkg.getLatest(lessThan);
if (newest == null) {
log.error("No latest version available for package : {}", pkg.name());
@@ -113,7 +111,7 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
}
@SuppressWarnings({"unchecked"})
- protected void initNewInstance(PackageLoader.Package.Version newest) {
+ protected Object initNewInstance(PackageLoader.Package.Version newest) {
Object instance = SolrCore.createInstance(pluginInfo.className,
pluginMeta.clazz, pluginMeta.getCleanTag(), core, newest.getLoader());
PluginBag.initInstance(instance, pluginInfo);
@@ -128,6 +126,7 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
log.error("error closing plugin", e);
}
}
+ return inst;
}
private void handleAwareCallbacks(SolrResourceLoader loader, Object instance) {
diff --git a/solr/core/src/java/org/apache/solr/search/CacheConfig.java b/solr/core/src/java/org/apache/solr/search/CacheConfig.java
index 6470915..8b9a458 100644
--- a/solr/core/src/java/org/apache/solr/search/CacheConfig.java
+++ b/solr/core/src/java/org/apache/solr/search/CacheConfig.java
@@ -23,12 +23,15 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Supplier;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.MapSerializable;
+import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.SolrResourceLoader;
+import org.apache.solr.pkg.CoreRefreshingClassLoader;
import org.apache.solr.util.DOMUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,7 +53,7 @@ public class CacheConfig implements MapSerializable{
private String nodeName;
@SuppressWarnings({"rawtypes"})
- private Class<? extends SolrCache> clazz;
+ private Supplier<Class<? extends SolrCache>> clazz;
private Map<String,String> args;
private CacheRegenerator regenerator;
@@ -64,7 +67,7 @@ public class CacheConfig implements MapSerializable{
@SuppressWarnings({"rawtypes"})
public CacheConfig(Class<? extends SolrCache> clazz, Map<String,String> args, CacheRegenerator regenerator) {
- this.clazz = clazz;
+ this.clazz = () -> clazz;
this.args = args;
this.regenerator = regenerator;
}
@@ -134,8 +137,14 @@ public class CacheConfig implements MapSerializable{
SolrResourceLoader loader = solrConfig.getResourceLoader();
config.cacheImpl = config.args.get("class");
if(config.cacheImpl == null) config.cacheImpl = "solr.CaffeineCache";
+ config.clazz = () -> {
+ PluginInfo.CName cName = new PluginInfo.CName(config.cacheImpl);
+ if(cName.pkg == null) return loader.findClass(cName.className, SolrCache.class);
+ return CoreRefreshingClassLoader.loadClass(loader.getCore(),
+ new PluginInfo("cache", Collections.singletonMap("class", config.cacheImpl)),
+ SolrCache.class);
+ };
config.regenImpl = config.args.get("regenerator");
- config.clazz = loader.findClass(config.cacheImpl, SolrCache.class);
if (config.regenImpl != null) {
config.regenerator = loader.newInstance(config.regenImpl, CacheRegenerator.class);
}
@@ -146,7 +155,7 @@ public class CacheConfig implements MapSerializable{
@SuppressWarnings({"rawtypes"})
public SolrCache newInstance() {
try {
- SolrCache cache = clazz.getConstructor().newInstance();
+ SolrCache cache = clazz.get().getConstructor().newInstance();
persistence[0] = cache.init(args, persistence[0], regenerator);
return cache;
} catch (Exception e) {
diff --git a/solr/core/src/java/org/apache/solr/update/UpdateHandler.java b/solr/core/src/java/org/apache/solr/update/UpdateHandler.java
index 37397f7..6a5eb18 100644
--- a/solr/core/src/java/org/apache/solr/update/UpdateHandler.java
+++ b/solr/core/src/java/org/apache/solr/update/UpdateHandler.java
@@ -20,13 +20,11 @@ import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.Vector;
-import org.apache.solr.core.DirectoryFactory;
-import org.apache.solr.core.HdfsDirectoryFactory;
-import org.apache.solr.core.PluginInfo;
-import org.apache.solr.core.SolrCore;
-import org.apache.solr.core.SolrEventListener;
-import org.apache.solr.core.SolrInfoBean;
+import org.apache.solr.core.*;
+import org.apache.solr.core.PluginBag.PluginHolder;
import org.apache.solr.metrics.SolrMetricsContext;
+import org.apache.solr.pkg.CoreRefreshingClassLoader;
+import org.apache.solr.pkg.PackagePluginHolder;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.util.plugin.SolrCoreAware;
@@ -48,25 +46,26 @@ public abstract class UpdateHandler implements SolrInfoBean {
protected final SchemaField idField;
protected final FieldType idFieldType;
- protected Vector<SolrEventListener> commitCallbacks = new Vector<>();
- protected Vector<SolrEventListener> softCommitCallbacks = new Vector<>();
- protected Vector<SolrEventListener> optimizeCallbacks = new Vector<>();
+ protected Vector<PluginHolder<SolrEventListener>> commitCallbacks = new Vector<>();
+ protected Vector<PluginHolder<SolrEventListener>> softCommitCallbacks = new Vector<>();
+ protected Vector<PluginHolder<SolrEventListener>> optimizeCallbacks = new Vector<>();
protected final UpdateLog ulog;
protected SolrMetricsContext solrMetricsContext;
+ @SuppressWarnings("unchecked")
private void parseEventListeners() {
final Class<SolrEventListener> clazz = SolrEventListener.class;
final String label = "Event Listener";
for (PluginInfo info : core.getSolrConfig().getPluginInfos(SolrEventListener.class.getName())) {
String event = info.attributes.get("event");
if ("postCommit".equals(event)) {
- SolrEventListener obj = core.createInitInstance(info,clazz,label,null);
+ PluginHolder<SolrEventListener> obj = PackagePluginHolder.createHolder(info, core, SolrEventListener.class, label);
commitCallbacks.add(obj);
log.info("added SolrEventListener for postCommit: {}", obj);
} else if ("postOptimize".equals(event)) {
- SolrEventListener obj = core.createInitInstance(info,clazz,label,null);
+ PluginHolder<SolrEventListener> obj = PackagePluginHolder.createHolder(info, core, SolrEventListener.class, label);
optimizeCallbacks.add(obj);
log.info("added SolrEventListener for postOptimize: {}", obj);
}
@@ -77,33 +76,35 @@ public abstract class UpdateHandler implements SolrInfoBean {
* Call the {@link SolrCoreAware#inform(SolrCore)} on all the applicable registered listeners.
*/
public void informEventListeners(SolrCore core) {
- for (SolrEventListener listener: commitCallbacks) {
- if (listener instanceof SolrCoreAware) {
- ((SolrCoreAware) listener).inform(core);
+ for (PluginHolder<SolrEventListener> listener: commitCallbacks) {
+ if(listener instanceof PackagePluginHolder)continue;
+ if (listener.get() instanceof SolrCoreAware) {
+ ((SolrCoreAware) listener.get()).inform(core);
}
}
- for (SolrEventListener listener: optimizeCallbacks) {
- if (listener instanceof SolrCoreAware) {
- ((SolrCoreAware) listener).inform(core);
+ for (PluginHolder<SolrEventListener> listener: optimizeCallbacks) {
+ if(listener instanceof PackagePluginHolder)continue;
+ if (listener.get() instanceof SolrCoreAware) {
+ ((SolrCoreAware) listener.get()).inform(core);
}
}
}
protected void callPostCommitCallbacks() {
- for (SolrEventListener listener : commitCallbacks) {
- listener.postCommit();
+ for (PluginHolder<SolrEventListener> listener : commitCallbacks) {
+ listener.get(). postCommit();
}
}
protected void callPostSoftCommitCallbacks() {
- for (SolrEventListener listener : softCommitCallbacks) {
- listener.postSoftCommit();
+ for (PluginHolder<SolrEventListener> listener : softCommitCallbacks) {
+ listener.get().postSoftCommit();
}
}
protected void callPostOptimizeCallbacks() {
- for (SolrEventListener listener : optimizeCallbacks) {
- listener.postCommit();
+ for (PluginHolder<SolrEventListener> listener : optimizeCallbacks) {
+ listener.get().postCommit();
}
}
@@ -125,8 +126,8 @@ public abstract class UpdateHandler implements SolrInfoBean {
if (dirFactory instanceof HdfsDirectoryFactory) {
ulog = new HdfsUpdateLog(((HdfsDirectoryFactory)dirFactory).getConfDir());
} else {
- String className = ulogPluginInfo.className == null ? UpdateLog.class.getName() : ulogPluginInfo.className;
- ulog = core.getResourceLoader().newInstance(className, UpdateLog.class);
+ ulog = ulogPluginInfo.className == null ? new UpdateLog():
+ CoreRefreshingClassLoader.createInst(core, ulogPluginInfo, UpdateLog.class);
}
if (!core.isReloaded() && !dirFactory.isPersistent()) {
@@ -172,7 +173,7 @@ public abstract class UpdateHandler implements SolrInfoBean {
*/
public void registerCommitCallback( SolrEventListener listener )
{
- commitCallbacks.add( listener );
+ commitCallbacks.add( new PluginHolder<>(listener, SolrConfig.classVsSolrPluginInfo.get(SolrEventListener.class.getName())) );
}
/**
@@ -184,7 +185,7 @@ public abstract class UpdateHandler implements SolrInfoBean {
*/
public void registerSoftCommitCallback( SolrEventListener listener )
{
- softCommitCallbacks.add( listener );
+ softCommitCallbacks.add( new PluginHolder<>(listener, SolrConfig.classVsSolrPluginInfo.get(SolrEventListener.class.getName())) );
}
/**
@@ -196,7 +197,7 @@ public abstract class UpdateHandler implements SolrInfoBean {
*/
public void registerOptimizeCallback( SolrEventListener listener )
{
- optimizeCallbacks.add( listener );
+ optimizeCallbacks.add( new PluginHolder<>(listener, SolrConfig.classVsSolrPluginInfo.get(SolrEventListener.class.getName())) );
}
public abstract void split(SplitIndexCommand cmd) throws IOException;
diff --git a/solr/core/src/test/org/apache/solr/core/TestQuerySenderListener.java b/solr/core/src/test/org/apache/solr/core/TestQuerySenderListener.java
index ad564c2..0d66abe 100644
--- a/solr/core/src/test/org/apache/solr/core/TestQuerySenderListener.java
+++ b/solr/core/src/test/org/apache/solr/core/TestQuerySenderListener.java
@@ -60,7 +60,8 @@ public class TestQuerySenderListener extends SolrTestCaseJ4 {
@Test
public void testSearcherEvents() throws Exception {
SolrCore core = h.getCore();
- SolrEventListener newSearcherListener = core.newSearcherListeners.get(0);
+ SolrEventListener newSearcherListener = core.newSearcherListeners.get(0).get();
+
assertTrue("Not an instance of QuerySenderListener", newSearcherListener instanceof QuerySenderListener);
QuerySenderListener qsl = (QuerySenderListener) newSearcherListener;
diff --git a/solr/core/src/test/org/apache/solr/core/TestQuerySenderNoQuery.java b/solr/core/src/test/org/apache/solr/core/TestQuerySenderNoQuery.java
index a44fe3c..e113137 100644
--- a/solr/core/src/test/org/apache/solr/core/TestQuerySenderNoQuery.java
+++ b/solr/core/src/test/org/apache/solr/core/TestQuerySenderNoQuery.java
@@ -61,7 +61,7 @@ public class TestQuerySenderNoQuery extends SolrTestCaseJ4 {
@Test
public void testSearcherEvents() throws Exception {
SolrCore core = h.getCore();
- SolrEventListener newSearcherListener = core.newSearcherListeners.get(0);
+ SolrEventListener newSearcherListener = core.newSearcherListeners.get(0).get();
assertTrue("Not an instance of QuerySenderListener", newSearcherListener instanceof QuerySenderListener);
QuerySenderListener qsl = (QuerySenderListener) newSearcherListener;