2

I have prepared an application in Spring Boot, demonstrating the use and the

functioning of Hibernate Search.

Problem/Error : When I try to run the application, it gives me an error :

Exception in thread "main" java.lang.IllegalArgumentException: java.lang.Object is not an indexed entity or a subclass of an indexed entity


I have referred the link : http://blog.netgloo.com/2014/10/27/using-mysql-in-spring-boot-via-spring-data-jpa-and-hibernate/

My Code :

------------------------------Application.java-------------------

package netgloo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

}

-------------------------------BuildSearchIndex.java---------------------

package netgloo;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.Search;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

/**
 * The only meaning for this class is to build the Lucene index at application
 * startup. This is needed in this example because the database is filled 
 * before and each time the web application is started. In a normal web 
 * application probably you don't need to do this.

 */
@Component
public class BuildSearchIndex implements ApplicationListener<ContextRefreshedEvent> {

    @PersistenceContext
    private EntityManager entityManager;

    /**
     * Create an initial Lucene index for the data already present in the
     * database.
     * This method is called during Spring's startup.
     * 
     * @param event Event raised when an ApplicationContext gets initialized or
     * refreshed.
     */
    @Override
    public void onApplicationEvent(final ContextRefreshedEvent event) {
        try {
            FullTextEntityManager fullTextEntityManager =
                    Search.getFullTextEntityManager(entityManager);
            fullTextEntityManager.createIndexer().startAndWait();
        }
        catch (InterruptedException e) {
            System.out.println(
                    "An error occurred trying to build the serach index: " +
                            e.toString());
        }
        return;
    }


} 

---------------------------------Controller-------------------------

package netgloo.controllers;

import java.util.List;

import netgloo.models.Employee;
import netgloo.search.EmployeeSearch;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MainController {
    @Autowired
    private EmployeeSearch emprSearch;

    @RequestMapping("/")
    @ResponseBody
    public String index() {
        return "Welcome !!!:)";
    }

    @RequestMapping("/search")
    public String search(String query, Model model) {
        List<Employee> searchResults = null;
        try {
            searchResults = emprSearch.search(query);
        } catch (Exception ex) {
            return "";
        }
        model.addAttribute("searchResults", searchResults);
        return "search";
    }
}

------------------------------Model-------------------------------

package netgloo.models;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

@Entity
@Table(name = "employees")
public class Employee {

  // An autogenerated id (unique for each user in the db)
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;

  @NotNull
  private String email;

  @NotNull
  private String name;

  // Public methods

  public Employee() { }

  public Employee(long id) { 
    this.id = id;
  }

  public Employee(String email, String name) {
    this.email = email;
    this.name = name;
  }

  // Getter and setter methods
  // ...

}

///////////////////////////EmployeeSearch.java///////////////////////

package netgloo.search;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

import netgloo.models.Employee;

import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.springframework.stereotype.Repository;

@Repository
@Transactional
public class EmployeeSearch {

    // Spring will inject here the entity manager object
    @PersistenceContext
    private EntityManager entityManager;

    public List<Employee> search(String text) {

        // get the full text entity manager
        FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search
                .getFullTextEntityManager(entityManager);

        // create the query using Hibernate Search query
        QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Employee.class)
                .get();

        // a very basic query by keywords
        org.apache.lucene.search.Query query = queryBuilder.keyword().onFields("name", "city", "email").matching(text)
                .createQuery();

        // wrap Lucene query in an Hibernate Query object
        org.hibernate.search.jpa.FullTextQuery jpaQuery = fullTextEntityManager.createFullTextQuery(query, Employee.class);

        // execute search and return results (sorted by relevance as default)
        @SuppressWarnings("unchecked")
        List<Employee> results = jpaQuery.getResultList();

        return results;
    }

}

/////////////////////////search.html//////////////////////////////////

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">

<head>
  <title>Search</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>

<body>

  <ol>
    <li th:each="employee : ${searchResults}">
      <b><span th:text="${employee.username}"></span></b> - 
      <span th:text="${employee.city}"></span> -
      <span th:text="${employee.email}"></span>
    </li>
  </ol>

  <p th:if="${searchResults.isEmpty()}">
    <strong>Hint</strong>: the query "<a href='/search?query=amy'>amy</a>" 
    should return some results.
  </p>

</body>

</html>

///////////////////////////application.properties///////////////////////

# Datasource settings 
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/myschema
spring.datasource.username=root
spring.datasource.password=admin123

# Hibernate settings
spring.jpa.hibernate.ddl-auto=create
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming_strategy =org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.show-sql = true

# Specify the DirectoryProvider to use (the Lucene Directory)
spring.jpa.properties.hibernate.search.default.directory_provider = filesystem

# Using the filesystem DirectoryProvider you also have to specify the default
# base directory for all indexes (make sure that the application have write
# permissions on such directory)
spring.jpa.properties.hibernate.search.default.indexBase = c:\\indexeFiles


# ===============================
# = THYMELEAF
# ===============================

spring.thymeleaf.cache = false
server.port=9001

///////////////////////////////pom.xml///////////////////////////

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>netgloo</groupId>
  <artifactId>spring-boot-hibernate-search</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>spring-boot-hibernate-search</name>
  <description>How to integrate Hibernate Search in Spring Boot</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.3.RELEASE</version>
    <relativePath />
  </parent>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!-- Maven artifact identifier for Hibernate Search -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-search-orm</artifactId>
      <version>4.5.1.Final</version>
    </dependency>

    <!-- Optional: to use JPA 2.1 -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
    </dependency>

  </dependencies>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <start-class>netgloo.Application</start-class>
    <java.version>1.7</java.version>
  </properties>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

my Stacktrace:

Exception in thread "main" java.lang.IllegalArgumentException: java.lang.Object is not an indexed entity or a subclass of an indexed entity
    at org.hibernate.search.impl.MassIndexerImpl.toRootEntities(MassIndexerImpl.java:102)
    at org.hibernate.search.impl.MassIndexerImpl.<init>(MassIndexerImpl.java:74)
    at org.hibernate.search.impl.DefaultMassIndexerFactory.createMassIndexer(DefaultMassIndexerFactory.java:47)
    at org.hibernate.search.impl.FullTextSessionImpl.createIndexer(FullTextSessionImpl.java:181)
    at org.hibernate.search.jpa.impl.FullTextEntityManagerImpl.createIndexer(FullTextEntityManagerImpl.java:349)
    at netgloo.BuildSearchIndex.onApplicationEvent(BuildSearchIndex.java:38)
    at netgloo.BuildSearchIndex.onApplicationEvent(BuildSearchIndex.java:1)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:331)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:773)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:140)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:483)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
    at netgloo.Application.main(Application.java:10)

Thank you!!!

2
  • any suggestions??? Commented Aug 29, 2016 at 13:15
  • I have updated my question with my stacktrace Commented Aug 29, 2016 at 13:27

1 Answer 1

4

Your entity should be annotated with @Indexed, to say the least. You should also annotate your entity class's fields with @Field according to your requirements.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.