Problem
In our product, user is able to create additional core: Solr will update solr.xml to add extra core information. But at some time, we need update solr.xml to add our extra cores.
This is a common requirement: we need upgrade solr config files in future release, but at same time keep customer's change.
For solrconfig.xml or solrschema.xml, we can use xi:include to put our change in one xml(for example solrconfig-upgrade.xml), user should only change solrconfig.xml either manually or via GUI.
Please refer to http://wiki.apache.org/solr/SolrConfigXml#XInclude
But this doesn't work for solr.xml, as if we define xi:include in solr.xml:
later if user creates another solr core, solr will update solr.xml: it will delete <xi:include> and overwrite cores section to include all cores.
Solution
We can define extra cores in a property file: cvanalytics_solr_extra.propertie like below:
In our product, user is able to create additional core: Solr will update solr.xml to add extra core information. But at some time, we need update solr.xml to add our extra cores.
This is a common requirement: we need upgrade solr config files in future release, but at same time keep customer's change.
For solrconfig.xml or solrschema.xml, we can use xi:include to put our change in one xml(for example solrconfig-upgrade.xml), user should only change solrconfig.xml either manually or via GUI.
Please refer to http://wiki.apache.org/solr/SolrConfigXml#XInclude
But this doesn't work for solr.xml, as if we define xi:include in solr.xml:
<solr persistent="true" sharedLib="lib" shareSchema="true"> <cores adminPath="/admin/cores" defaultCoreName="collection1"
host="${host:}" hostPort="${jetty.port:}" hostContext="${hostContext:}" zkClientTimeout="${zkClientTimeout:15000}">
<core name="collection1" instanceDir="collection1"/> <!-- this doesn't work --> <xi:include href="solr_extracores.xml"/> </cores> </solr>
later if user creates another solr core, solr will update solr.xml: it will delete <xi:include> and overwrite cores section to include all cores.
Solution
We can define extra cores in a property file: cvanalytics_solr_extra.propertie like below:
# support corename_name, corename_instanceDir, corename_schemaName, corename_configName extra_cores=extracore1, extracore2 extracore1_name=extracore1 extracore1_instanceDir=extracore1 extracore1_schemaName=extracore1_schema.xml extracore1_configName=extracore1_config.xml ....We will iterate all core names in extra_cores, if it's already loaded: CoreContainer.getCoreFromAnyList(core_name) returns not null, we ignore, Otherwise, we create a SolrCore and register it.
Implementation Code
org.apache.solr.core.CoreContainer.Initializer private void initExtraCores(CoreContainer cores) throws RuntimeException { try { Properties cvProps = cores.getCVProperties(); String solrxml_extra = cvProps.getProperty("solrxml_extra"); if (!StringUtils.isBlank(solrxml_extra)) { File solrxml_extraFile = new File(cores.getSolrHome(), solrxml_extra); Properties solrxml_extraProps = readProperties(solrxml_extraFile); String extra_cores = solrxml_extraProps.getProperty("extra_cores"); if (!StringUtils.isBlank(extra_cores)) { String[] extra_coresArr = extra_cores.split(","); for (String extra_core : extra_coresArr) { extra_core = extra_core.trim(); if (cores.getCoreFromAnyList(extra_core) == null) { String coreName = solrxml_extraProps.getProperty(extra_core + "_name"); if (StringUtils.isBlank(coreName)) { coreName = extra_core; } String instanceDir = solrxml_extraProps.getProperty(extra_core + "_instanceDir"); if (StringUtils.isBlank(instanceDir)) { throw new RuntimeException("No instanceDir defined for " + coreName + "in " + solrxml_extraFile); } CoreDescriptor cd = new CoreDescriptor(cores, coreName, instanceDir); String schemaName = solrxml_extraProps.getProperty(extra_core + "_schemaName"); if (!StringUtils.isBlank(schemaName)) { cd.setSchemaName(schemaName); } String configName = solrxml_extraProps.getProperty(extra_core + "_configName"); if (!StringUtils.isBlank(configName)) { cd.setConfigName(configName); } SolrCore core = cores.create(cd); cores.register(core, false); } } } } } catch (Exception e) { throw new RuntimeException(e); } } public CoreContainer initialize() { CoreContainer cores = null; String solrHome = SolrResourceLoader.locateSolrHome(); cores = new CoreContainer(solrHome); if (fconf.exists()) { cores.load(solrHome, fconf); } else { log.info("no solr.xml file found - using default"); try { cores.load(solrHome, new InputSource(new ByteArrayInputStream(DEF_SOLR_XML.getBytes("UTF-8")))); } catch (Exception e) { throw new SolrException(ErrorCode.SERVER_ERROR, "CoreContainer.Initialize failed when trying to load default solr.xml file", e); } cores.configFile = fconf; } // call initExtraCores initExtraCores(cores); return cores; }