/ SOLR, SPRING DATA

Solr, as a Spring Data module

At the end of October, I attended a 3-days Solr training. It was very interesting, in light of the former Elastic Search talk I attended mid-year. As an old Spring Data fan, when I found out Spring Data offered a Solr module, I jumped at the chance to try it.

In this case, I’m well aware that an abstraction layer over Solr doesn’t mean we can easily change the underlying datastore: Solr is designed as an inverted index, while other Spring Data modules are much more specialized (JPA, MongoDB, etc.). However, there are still some advantages of using Spring Data over Solr:

  • Quick prototyping, when you don’t need the whole nine yards
  • Use Solr when most of the team already knows about Spring Data and not Solr
  • Spring integration from the bottom
  • Last but not least important of all, you can easily switch between the embedded Solr and the standalone one. Spring Data nicely wraps both the Solrj API and HTTP behind its own API. If you think this is not a relevant use-case as it never will happen, think about integration testing

After having initialized Solr with relevant data, here are steps you have to go through to start developing:

  1. The initial step is to configure the Spring context with the underlying Solr. Spring Data Solr requires a bean named solrTemplate of type SolrOperations. Let use the JavaConfig for this:
    @Configuration
    @EnableSolrRepositories("ch.frankel.blog.springdata.solr.repository")
    public class JavaConfig {
    
        @Bean
        protected HttpSolrServerFactoryBean solrServerFactory() {
            HttpSolrServerFactoryBean factory = new HttpSolrServerFactoryBean();
            factory.setUrl("http://localhost:8983/solr");
            return factory;
        }
    
        @Bean
        public SolrOperations solrTemplate() throws Exception {
            return new SolrTemplate(solrServerFactory().getObject());
        }
    }
  2. Create the managed entity. All fields stored in Solr have to be annotated with @Field. If the entity attribute name is different from Solr field name, @Field accepts a value to override the name:
    public class Loan {
    
        @Field
        private String id;
    
        @Field("gov_type")
        private String governmentType;
    
        // Getters and setters
    }
  3. Create the repository interface: either inherit from SolrRepository<Bean,ID> or SolrCrudRepository<Bean,ID>. Note the former only provides the count() method.
    public interface LoanRepository extends SolrRepository<Loan, String> {}
  4. Add query methods to the former interface:
    • Simple query methods benefit from Spring Data parsing: List<Loan> findByLoanType(String) will translate into ?q=loan_type:…​
    • More advanced queries (or method whose name do not follow the pattern) should be annotated with @Query: @Query("state_name:[* TO *]") will find all loans which have a value for state_name. The annotation can bind as many parameters as necessary, through the use of ?x where x is the parameter index in the method parameters list.
    • Facets are also handled through the @Facet annotation, which takes the field names the facet should use. This changes the method signature, though, to a FacetPage and it is up to the calling method (probably located the service layer) to handle that.

The final class should look something like that, which is awesome considering all capabilities it provides:

public interface LoanRepository extends SolrRepository<Loan, String> {

    List<Loan> findByLoanType(String loan);
    List<Loan> findByTitleContaining(String title);

    @Query("state_name:[* TO *]")
    List<Loan> findLocalized();

    @Query("*:*")
    @Facet(fields = "loan_type")
    FacetPage<Loan> findAllLoanTypes(Pageable page);
}

The entire project source code is available there in IntelliJ/Maven format, complete with tests. Note that you’ll need a running Solr instance with a specific Solr schema and documents in it. Both the schema and the document files (federal.xml) are provided, but those are not automated: you’ll need to overwrite your schema and the document file to the running instance (with the classic java -jar post.jar command line).

Nicolas Fränkel

Nicolas Fränkel

Developer Advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with focused interests like Rich Internet Applications, Testing, CI/CD and DevOps. Also double as a trainer and triples as a book author.

Read More
Solr, as a Spring Data module
Share this