Solr is an open source search server that is built by using the indexing and search capabilities of Lucene Core, and it can be used for implementing scalable search engines with almost any programming language.

Even though Solr has many advantages, setting up a development environment is not one of them. This blog post fixes that problem.

We will learn how we can run Solr by using Maven and ensure that each developer uses the same configuration, schema, and Solr version.

Let’s start by getting the Solr configuration files.

Getting the Solr Configuration Files

The first thing that we have to do is to get the Solr configuration files and copy them to our project. We can do this by following these steps:

  1. Download the binary distribution of Solr 4.3.0.
  2. Extract the downloaded package to the desired directory.
  3. Go the root directory of the extracted binary distribution.
  4. Copy the following files from the directory example/solr/collection1/conf to the directory src/main/config: admin-extra.html, admin-extra-menu.menu-bottom.html, admin-extra.menu-top.html, currency.xml, elevate.xml, mapping-FoldToASCII.txt, mapping-ISOLatin1Accent.txt, protwords.xml, schema.xml, scripts.conf, solrconfig.xml, spellings.txt, stopwords.txt, synonyms.txt and update-script.js.
  5. Copy the language specific configuration files found from the directory example/solr/collection1/conf/lang to the directry src/main/config/lang.
  6. Copy the Velocity macros and other files found from the directory example/solr/collection1/conf/velocity to the directry src/main/config/velocity.
  7. Copy the XSL style sheets found from the directory example/solr/collection1/conf/xslt to the directry src/main/config/xslt.
  8. Copy the solr.xml file from the directory exaple/solr/collection1 to the directory src/main/resources.
  9. Create the directory src/main/webapp/WEB-INF. If we don’t create this directory, we cannot start our Solr instance.

Let’s move on and find out how we can configure our Maven build.

Configuring Our Maven Build

After we have copied the Solr configuration files to our project, we have to configure our Maven build. The requirements of our Maven build are:

  • The properties of our Maven build must be read from an external property file. The only exception to this rule is that the version numbers of the dependencies can be declared in our POM file.
  • The build process must copy the Solr configuration files to the configured directory when our Solr instance is started.
  • The build process must delete the home directory of our Solr instance when we execute the mvn clean command at command prompt.
  • It must be possible to start our Solr instance by using the Jetty Maven plugin.

We can create a Maven build that fulfils these requirements by following these steps:

  1. Create a POM file.
  2. Get the required dependencies.
  3. Create the properties file that contains the properties of our Maven build.
  4. Edit the solr.xml file.
  5. Read the property values from an external properties file.
  6. Copy the Solr configuration files to the correct directories.
  7. Clean the build.
  8. Configure the Jetty Maven plugin.

Let’s get started.

Creating the POM File

We have to create a basic POM file for a web application project. This POM file looks as follows:

 1<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 2         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 3    <modelVersion>4.0.0</modelVersion>
 4    <groupId>net.petrikainulainen.maven</groupId>
 5    <artifactId>running-solr-with-maven</artifactId>
 6    <packaging>war</packaging>
 7    <version>0.1</version>
 8     
 9    <profiles>
10        <!-- Add profile configuration here -->
11    </profiles>
12    <dependencies>
13        <!-- Add dependencies here -->
14    </dependencies>
15    <build>
16        <finalName>solr</finalName>
17        <!-- Add filter configuration here -->
18        <!-- Add resources configuration here -->
19        <plugins>
20            <!-- Add plugin configuration here -->
21        </plugins>
22    </build>
23</project>

Getting the Required Dependencies

We can get the required dependencies by declaring the following dependencies in our pom.xml file:

  • SLF4J
  • SLF4J interceptors for the java.util.logging (JUL) and the java.commons.logging (JCL) logging frameworks.
  • SLF4J Log4J 1.2.X binding.
  • Log4J
  • Solr 4.3.0 (war)
We need to declare the logging dependencies in our POM file because the logging configuration of Solr was changed when Solr 4.3.0 was released.

The dependencies section of our POM file looks as follows:

 1<!-- SLF4J -->
 2<dependency>
 3    <groupId>org.slf4j</groupId>
 4    <artifactId>slf4j-api</artifactId>
 5    <version>1.7.7</version>
 6</dependency>
 7<dependency>
 8    <groupId>org.slf4j</groupId>
 9    <artifactId>jcl-over-slf4j</artifactId>
10    <version>1.7.7</version>
11</dependency>
12<dependency>
13    <groupId>org.slf4j</groupId>
14    <artifactId>jul-to-slf4j</artifactId>
15    <version>1.7.7</version>
16</dependency>
17<dependency>
18    <groupId>org.slf4j</groupId>
19    <artifactId>slf4j-log4j12</artifactId>
20    <version>1.7.7</version>
21</dependency>
22<!-- Log4j -->
23<dependency>
24    <groupId>log4j</groupId>
25    <artifactId>log4j</artifactId>
26    <version>1.2.17</version>
27</dependency>
28<!-- Solr 4.3.0 -->
29<dependency>
30    <groupId>org.apache.solr</groupId>
31    <artifactId>solr</artifactId>
32    <version>4.3.0</version>
33    <type>war</type>
34</dependency>

Creating the Properties File

Our next step is to create the properties file that is used in our Maven build, and add the required build profile configuration to our POM file.

First, we have to create the properties file which is used in our Maven build. We can do this by following these steps:

  1. Create the directory profiles/dev to the root directory of our Maven project.
  2. Create the properties file called config.properties to the profiles/dev directory.

Our properties file has three properties which are described in the following:

  • The solr.detault.core.directory property configures the value of the default core directory. This is a directory that is created under the home directory of our Solr instance. This directory has two subdirectories:
    • The conf directory contains the configuration of our Solr instance.
    • The data directory contains the Solr index.
  • The solr.default.core.name property configures the name of the default core.
  • The solr.solr.home property configures the home directory of our Solr installation. In other words, it configures the directory in which the Solr configuration file (solr.xml) and the core specific configuration files are copied when the compile phase of the Maven default lifecycle is invoked.

Our config.properties file looks as follows:

1#SOLR PROPERTIES
2#Configures the directory used to store the data and configuration of the Solr default core
3solr.default.core.directory=todo
4#Configures the name of the Solr default core.
5solr.default.core.name=todo
6 
7#SYSTEM PROPERTIES
8#Configures the home directory of Solr. Set the preferred directory path here.
9solr.solr.home=

Second, we must configure the build profiles of our Maven build and use filtering to replace replace the variables included in our resources. We can do this by following these steps:

  1. Create a single profile called dev and ensure that it is the default profile of our build.
  2. Declare a property called build.profile.id and set its value to ‘dev’.
  3. Create a filter that reads the profile specific configuration file and replaces the variables found from our resources with the actual property values.

We can finish the steps one and two by adding the following profile configuration to the profiles section of our POM file:

1<profile>
2    <id>dev</id>
3    <activation>
4        <activeByDefault>true</activeByDefault>
5    </activation>
6    <properties>
7        <build.profile.id>dev</build.profile.id>
8    </properties>
9</profile>

We can finish the step three by adding the following XML to the build section of our POM file:

1<filters>
2    <filter>${project.basedir}/profiles/${build.profile.id}/config.properties</filter>
3</filters>
4<resources>
5    <resource>
6        <filtering>true</filtering>
7        <directory>src/main/resources</directory>
8    </resource>
9</resources>

Editing the solr.xml File

Because we configure the name and the instance directory of the Solr default core in our profile specific configuration file, we have to make some changes to the solr.xml file. We can make these changes by following these steps:

  1. Set the value of the defaultCoreName attribute of the cores element. Use the value of the solr.default.core.name property that is found from our profile specific properties file.
  2. Set the value of the name attribute of the core element. Use the value of the solr.default.core.name property that is found from our profile specific configuration file.
  3. Set the value of the instanceDir attribute of the core element. Use the value of the solr.default.core.directory property that is found from our profile specific configuration file.

The solr.xml file looks as follows (the relevant parts are highlighted):

 1<?xml version="1.0" encoding="UTF-8" ?>
 2<solr persistent="true">
 3  <cores adminPath="/admin/cores"
 4         defaultCoreName="${solr.default.core.name}"
 5         host="${host:}"
 6         hostPort="${jetty.port:}"
 7         hostContext="${hostContext:}"
 8         zkClientTimeout="${zkClientTimeout:15000}">
 9    <core name="${solr.default.core.name}" instanceDir="${solr.default.core.directory}" />
10  </cores>
11</solr>

Reading the Property Values From an External Properties File

Because we want that all property values used in our POM file are read from an external properties file, we have to use a plugin called the Properties Maven plugin. We can configure this plugin by following these steps:

  1. Ensure that the properties are read from the profile specific configuration file.
  2. Create an execution that runs the read-project-properties goal of the Properties Maven plugin in the initialize phase of the Maven default lifecycle.
  3. Create an execution that runs the read-project-properties goal of the Properties Maven plugin in the pre-clean phase of the Maven clean lifecycle.

The configuration of the Properties Maven plugin looks as follows:

 1<plugin>
 2    <groupId>org.codehaus.mojo</groupId>
 3    <artifactId>properties-maven-plugin</artifactId>
 4    <version>1.0-alpha-2</version>
 5    <configuration>
 6        <files>
 7            <!-- Properties are read from profile specific property file -->
 8            <file>${project.basedir}/profiles/${build.profile.id}/config.properties</file>
 9        </files>
10    </configuration>
11    <executions>
12        <!-- Load properties for the default lifecycle -->
13        <execution>
14            <id>default-lifecycle-properties</id>
15            <phase>initialize</phase>
16            <goals>
17                <goal>read-project-properties</goal>
18            </goals>
19        </execution>
20        <!-- Load properties for the clean lifecycle -->
21        <execution>
22            <id>clean-lifecycle-properties</id>
23            <phase>pre-clean</phase>
24            <goals>
25                <goal>read-project-properties</goal>
26            </goals>
27        </execution>
28    </executions>
29</plugin>

Copying the Solr Configuration Files to the Correct Directories

Our next step is to copy the Solr configuration files to the home directory of our Solr instance. We will use the Maven Resources plugin for this purpose.

The first thing that we have to do is to add the Maven Resources plugin to the plugins section of our pom.xml file. We can do this by adding the following snippet to the plugins section of our POM file:

1<plugin>
2	<groupId>org.apache.maven.plugins</groupId>
3	<artifactId>maven-resources-plugin</artifactId>
4	<version>2.7</version>
5	<executions>
6		<!-- Add executions here -->
7	</executions>
8</plugin>

Now we need to configure the executions that copies the Solr configuration files to the correct directories. We can do this by following these steps:

  1. We need to copy the solr.xml file found from the src/main/resources directory to the ${solr.solr.home} directory. This directory is the home directory of our Solr instance. Also, we need apply properties filtering to it because we want replace the placeholders found from that file with the property values found from our profile specific properties file.
  2. We need to copy the contents of the src/main/config directory to the ${solr.solr.home}/${solr.default.core.directory}/conf directory. This directory contains the configuration of our Solr instance’s default core.

First, we need to copy the solr.xml file to the home directory of our Solr instance. We can do this by following these steps:

  1. Create an execution that invokes the copy-resources goal of the Resources Maven plugin in the compile phase of the default lifecycle.
  2. Configure the execution to copy the solr.xml file found from the src/main/resources directory to the ${solr.solr.home} directory. Remember to apply properties filtering to the solr.xml file.

The configuration of our execution looks as follows:

 1<execution>
 2    <id>copy-solr-xml</id>
 3    <phase>compile</phase>
 4    <goals>
 5        <goal>copy-resources</goal>
 6    </goals>
 7    <configuration>
 8        <!-- Configure the directory in which the file is copied. -->
 9        <outputDirectory>${solr.solr.home}</outputDirectory>
10        <resources>
11            <!--
12                Configure the copied file and apply properties filtering to it.
13            -->
14            <resource>
15                <directory>${project.basedir}/src/main/resources</directory>
16                <filtering>true</filtering>
17                <includes>
18                    <include>solr.xml</include>
19                </includes>
20            </resource>
21        </resources>
22    </configuration>
23</execution>

Second, we need to copy the contents of the src/main/config directory to the ${solr.solr.home}/${solr.default.core.directory}/conf directory. We can do this by following these steps:

  1. Create an execution that invokes the copy-resources goal of the Resources Maven plugin in the compile phase of the default lifecycle.
  2. Configure the execution to copy contents of the src/main/config directory to the to the ${solr.solr.home}/${solr.default.core.directory}/conf directory.

The configuration of our execution looks as follows:

 1<execution>
 2    <id>copy-solr-config</id>
 3    <phase>compile</phase>
 4    <goals>
 5        <goal>copy-resources</goal>
 6    </goals>
 7    <configuration>
 8        <!-- Configure the target directory in which the files are copied. -->
 9        <outputDirectory>${solr.solr.home}/${solr.default.core.directory}/conf</outputDirectory>
10        <!--
11            Configure the directory which contents are copied to the target directory.
12            Disable properties filtering.
13        -->
14        <resources>
15            <resource>
16                <directory>${project.basedir}/src/main/config</directory>
17                <filtering>false</filtering>
18            </resource>
19        </resources>
20    </configuration>
21</execution>

Cleaning the Build

When we clean our build, we have to delete two directories that are described in the following:

  • We need to delete the home directory of our Solr instance.
  • We need to delete the overlays directory that is created to the root directory of our project when we start our Solr instance by using the Jetty Maven plugin.

We can configure the Maven Clean plugin to delete these directories. If we want to delete additional directories when the command mvn clean is invoked, we have to follow these steps:

  1. Add the fileSets element to the configuration of the Maven Clean plugin.
  2. Configure the deleted directories by adding fileSet elements inside the fileSets element. We can configure the path of the deleted directory by adding the directory element inside the fileSet element. We can use both relative and absolute paths. If we use relative paths, the starting point of that path is the root directory of our project.

If we want to delete the foo directory that is found from the root directory of our project, we have to use the following configuration:

1<configuration>
2	<filesets>
3		<!-- Configure the deleted directory. -->
4		<fileset>
5			<directory>foo</directory>
6		</fileset>
7	</filesets>
8</configuration>

The configuration of the Maven Clean plugin that deletes the target directory, the overlays directory, and the home directory of our Solr instance looks as follows:

 1<plugin>
 2	<groupId>org.apache.maven.plugins</groupId>
 3	<artifactId>maven-clean-plugin</artifactId>
 4	<version>2.6</version>
 5	<configuration>
 6		<filesets>
 7			<!-- Delete the overlays directory from the project root directory -->
 8			<fileset>
 9				<directory>overlays</directory>
10			</fileset>
11			<!-- Delete the Solr home directory -->
12			<fileset>
13				<directory>${solr.solr.home}</directory>
14			</fileset>
15		</filesets>
16	</configuration>
17</plugin>

Configuring the Jetty Maven Plugin

We will run our Solr by using the Jetty Maven plugin. We can configure it by following these steps:

  1. Configure Jetty to listen the port 8983.
  2. Ensure that system properties are read from the profile specific configuration file. This property file contains a property called solr.solr.home which specifies the home directory of our Solr instance. If this property is missing, we cannot start our Solr instance because Solr cannot find its configuration files.
  3. Specify that the context path of our application is /solr.

The configuration of the Jetty Maven plugin looks as follows:

 1<plugin>
 2	<groupId>org.eclipse.jetty</groupId>
 3	<artifactId>jetty-maven-plugin</artifactId>
 4	<version>9.2.3.v20140905</version>
 5	<configuration>
 6		<stopPort>9966</stopPort>
 7		<stopKey>stop</stopKey>
 8		<!-- Listen to port 8983 -->
 9		<httpConnector>
10			<port>8983</port>
11			<idleTimeout>60000</idleTimeout>
12		</httpConnector>
13		<!-- Read system properties from profile specific configuration file -->
14		<systemPropertiesFile>${project.basedir}/profiles/${build.profile.id}/config.properties
15</systemPropertiesFile>
16		<!-- Set the context path -->
17		<webApp>
18			<contextPath>/solr</contextPath>
19		</webApp>
20	</configuration>
21</plugin>

Running Solr

We have now created a Maven build that can be used for running Solr in a development environment. We have got two options for starting our Solr instance:

  • We can execute the mvn jetty:run command at command prompt.
  • We can execute the mvn jetty:run-war command at command prompt.

After we have started our Solr instance, we can access its admin interface by using the following url address: http://localhost:8983/solr.

If you want play around with the example application, you can get it from Github. This example uses a custom schema because I plan to use it in my Spring Data Solr tutorial. The original example schema is found from the etc directory.

If you want to learn how to use Spring Data Solr, you should read my Spring Data Solr tutorial.