Reputation: 13534
I have got installed two versions of solr on Tomcat 6, 1.3 and 4.7 each of them are accessible but in the tomcat configuration's tab Java -Dsolr.solr.home=C:\Solr\solr
where this path is the path of 1.3 However, I have the 4.7 on E:\new-solr.
When I try to create new core it created well but it disappeared after restarting Tomcat. I belive that the missing of correct Solr home is the reason. So, is there a way to set multiple solr home in Java properties of Tomcat?
Edit: When I run Tomcat with
-Dsolr.solr.home=C:\Solr\solr
I have got errors about missing cores in Solr 4.7 version where those cores works fine in Solr 1.3.SolrCore Initialization Failures archive: org.apache.solr.common.SolrException:org.apache.solr.common.SolrException: Could not load config file c:\solr\solr\archive\solrconfig.xml
Upvotes: 1
Views: 804
Reputation: 23529
Solr's SolrResourceLoader#locateSolrHome
first tries JNDI and then system properties to find its settings. As -D
system properties are shared between all applications in a single Tomcat instance, those cannot be used to configure multiple Solr instances.
If for some reason one cannot use JNDI (like <Environment name="solr/home" ...>
in XML files), or a single instance with multiple cores, then one could wrap the Solr WAR into one's own application and use a servlet context listener to (temporarily) change the system properties while starting.
This surely is a hack, and relies on Tomcat not starting applications in parallel, and on Solr only reading the system properties on startup. I've tested this to work nicely, but still it's probably only suitable for testing purposes.
Again, this first of all needs one to wrap Solr into one's own application. Next, create a folder /some/config
with a sub folder for each instance, matching its context name. In each sub folder create a custom.properties
file:
# This file /some/config/[servlet-context-name]/custom.properties is used
# if Tomcat is started with:
# -Dcustom.config.dir=/some/config
# ...and then (temporarily) overwrites any system properties specified below:
solr.solr.home=/some/other/folder/conf
solr.data.dir=/some/other/folder/data
To merge system properties based on some key-values in a properties file:
/**
* Tries to find the given file and merges its properties into the existing
* system properties.
*
* @param configFile
* full path of a property file
* @return {@code true} if the file was found and merged; {@code false}
* otherwise
*/
private boolean mergeSystemProperties(final String configFile) {
try (final FileInputStream is = new FileInputStream(configFile)) {
final Properties custom = new Properties();
custom.load(is);
for (final Map.Entry<Object, Object> prop : custom.entrySet()) {
LOG.info("Setting {}={}", prop.getKey(), prop.getValue());
System.setProperty((String)prop.getKey(), (String)prop.getValue());
}
return true;
} catch (final FileNotFoundException e) {
LOG.info("Could not find custom properties: {}", configFile);
} catch (final IOException e) {
LOG.error("Failed to read custom properties: " + configFile, e);
}
return false;
}
This can be used in a listener:
public class TestConfigContextListener implements ServletContextListener {
private static final Logger LOG = ...
private static final String PROP_DIR = "custom.config.dir";
private static final String FILE_NAME = "custom.properties";
@Override
public void contextInitialized(final ServletContextEvent event) {
final String configDir = System.getProperty(PROP_DIR);
if (configDir == null) {
LOG.info("No value for -D{}; not reading custom config", PROP_DIR);
} else {
LOG.info("Custom config dir: -D{}={}", PROP_DIR, configDir);
final ServletContext context = event.getServletContext();
// Either "" for the root, or "/some-path" otherwise
final String contextPath = context.getContextPath();
if (!contextPath.isEmpty()) {
if (mergeSystemProperties(configDir + File.separator
+ contextPath.substring(1, contextPath.length())
+ File.separator + FILE_NAME)) {
// We found the configuration in a subfolder matching the
// specific contextPath; done.
return;
}
}
// Root context, or no configuration in a subfolder matching the
// specific contextPath; try to load from configDir itself:
mergeSystemProperties(configDir + File.separator + FILE_NAME);
}
}
...
}
...with in web.xml
:
<!--
Tries to read a property file to set/override system properties just before
Solr is initialized, sort of allowing to run multiple instances with
different settings, IF THEY ARE NOT STARTED SIMULTANEOUSLY.
-->
<listener>
<listener-class>net.example.TestConfigContextListener</listener-class>
</listener>
Final notes: though one could use <env-entry>
in web.xml
for "fake" JNDI entries, using ServletContext#setInitParameter
to change those in the context listener has no effect. Also, the JNDI context java:comp/env
is read-only hence cannot be changed from code. So one really needs to fall back to (temporarily) setting the system properties.
Upvotes: 1
Reputation: 3450
Looks like you are passing in the value of solr home using JAVA_OPTS
. You need to edit server.xml
and add the appropriate Solr home to Context
. The following example is from SolrTomcat page on the Solr wiki.
<Context docBase="/opt/solr/example/solr/solr.war" debug="0" crossContext="true">
<Environment name="solr/home" type="java.lang.String" value="/opt/solr/example/solr" override="true"/>
</Context>
Upvotes: 1