2

(Please note : while investigating on this issue I better spotted the source of problem that I introduce here)

I am very new to Hibernate and SpringBoot. My project deals with a search engine which indexing (javafx client) and searching (web client) parts are separated. The web client uses SpringBoot and during the process of the user's request, I need to retrieve information on the Solr Index to search against. These information are stored in a Hibernate / H2 local database where I use the following Entity class :

@Entity
@Table(name = "IndexSetups")
@Access(AccessType.PROPERTY)
public class IndexSetup {
 private final SimpleIntegerProperty id = new SimpleIntegerProperty();

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO) // For H2 AUTO is required to auto increment the id
 public int getId() {
  return id.get();
}

 //... other properties, getters and setters

}

A LocalDatabase class features a method to list all IndexSetups from the DB (there are also other methods but focusing on this one is enough to understand the issue). I need to call it in a controller but I get a "Not an entity : class IndexSetup".

However the only way to use my Entity is to prevent the launching of SpringBoot (ie commenting the line starting with SpingApplication.run(...)) :

@SpringBootApplication
public class ServerApplication {

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

ArrayList<IndexSetup> availableSearchIndex = 
LocalDatabase.getInstance(false) // no GUI
            .getAllIndexSetups();

// The list is displayed as long as SpringApplication.run() call is commented. Otherwise "Not an entity"
System.err.println("The Index setups are " + availableSearchIndex); 
  }
}

Of course this is not a solution since I do need to process the user's request via Spring Boot :-D!

Finally the hibernate.cfg.xml file reads :

<hibernate-configuration>
  <session-factory>      
    <!-- Database connection settings -->
    <property name="connection.driver_class">org.h2.Driver</property>
    <!--The db file resides wihtin the parent project (so one level above the calling project see ../)-->
    <!--We use the auto server mode to be able to open the database from server and from indexer simultaneously
    see http://www.h2database.com/html/features.html#auto_mixed_mode -->
    <property name="connection.url">jdbc:h2:file:../MyAppDB;DB_CLOSE_ON_EXIT=TRUE;AUTO_SERVER=TRUE</property>
    <property name="connection.username">test</property>
    <property name="connection.password"/>
    <!-- JDBC connection pool (use the built-in) -->
    <property name="connection.pool_size">1</property>
    <!-- SQL dialect -->
    <property name="dialect">org.hibernate.dialect.H2Dialect</property>
    <!-- Disable the second-level cache -->
    <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
    <!-- Echo all executed SQL to stdout -->
    <property name="show_sql">false</property>
    <!-- Updates the existing database schema on startup -->
    <property name="hbm2ddl.auto">update</property>
    <!-- The mapping information of entities -->
    <mapping class="my.package.Entities.IndexSetup"/>
 </session-factory>
</hibernate-configuration>

The stack trace is :

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)

Caused by: java.lang.IllegalArgumentException: Not an entity: class my.package.Entities.IndexSetup
at org.hibernate.metamodel.internal.MetamodelImpl.entity(MetamodelImpl.java:457)
at org.hibernate.query.criteria.internal.QueryStructure.from(QueryStructure.java:126)
at org.hibernate.query.criteria.internal.CriteriaQueryImpl.from(CriteriaQueryImpl.java:153)
at my.package.LocalDatabase.getAllIndexSetups(LocalDatabase.java:99)
at my.package.ServerApplication.main(ServerApplication.java:15)

And I've just noticed those two lines printed by Spring Boot at startup :

2018-10-15 11:47:46.208  INFO 27730 --- [  restartedMain] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found // Maybe this one is not just "INFO"
2018-10-15 11:47:46.591  WARN 27730 --- [  restartedMain] org.hibernate.orm.connections.pooling    : HHH10001002: Using Hibernate built-in connection pool (not for production use!)
2018-10-15 11:47:46.594  INFO 27730 --- [  restartedMain] org.hibernate.orm.connections.pooling    : HHH10001005: using driver [org.h2.Driver] at URL [jdbc:h2:file:../MyAppDB;DB_CLOSE_ON_EXIT=TRUE;FILE_LOCK=NO] // Just to show that my bibernate.cfg.xml is found

It looks unlikely to be a dependency problem as it only stops working when Spring application is run.

So my question is : what should I do to make my Entity work within SpringBoot ?

Any help much appreciated!

HelloWorld
  • 2,275
  • 18
  • 29
  • 1
    Could you provide us the error-stacktrace as code? – Christian Oct 15 '18 at 09:32
  • @Christian see my edit. – HelloWorld Oct 15 '18 at 09:57
  • 1
    Your code isn't using Spring boot. At least the main method isn't starting anything boot related. It also appears that you are trying to work around Spring Boot, judging from the fact you use plain hibernate and hibernate to configure that. All of that can be done by Spring Boot. Also you want your `ServerApplication` to be in a toplevel package so that every feature can be detected (as advised by the Spring Boot team). This also shows in your other question linked there. – M. Deinum Oct 15 '18 at 11:14
  • Thanks @M.Deinum but `hibernate.cfg.xml` is needed for the indexing client which stores IndexSetups in the database. And in the end the user must be able to start the indexer independently from the server and vice versa. Can you advise an architecture maybe the one I designed with a parent pom.xml is not suitable ? By the way it used to work when indexer and server were in the same project. – HelloWorld Oct 15 '18 at 13:29
  • @M.Deinum I eventually got it working based on your comment as well as many other sources! I will write my solution in the [linked question](https://stackoverflow.com/questions/52799706/springboot-not-an-entity/52801932?noredirect=1#comment92558078_52801932). Basically I removed the `hibernate.cfg.xml` created a jpa repository as explained [here](https://spring.io/guides/gs/accessing-data-jpa/) and solved each and evey problem that came one after the other! – HelloWorld Oct 16 '18 at 09:25
  • can you add your package name to your IndexSetup(.java) code sample? – granadaCoder Mar 21 '19 at 17:46

1 Answers1

1

Add @EntityScan to ServerApplication.class.

@EntityScan (org.springframework.boot.autoconfigure.domain.EntityScan) identifies which classes should be used by a specific persistence context.

  • Thanks @martinywwan I already tried [in the related question](https://stackoverflow.com/a/52800599/6351897) without luck. – HelloWorld Oct 15 '18 at 09:59
  • Actually this was part of the solution, so I mark yours as accepted. Yet for the records even though you only have a single entity placed in a `Entities` subfolder (like me) you have to provide `@EntityScan` with the path only up to this subfolder not up to the entity. So `@EntityScan("my.package.Entities")` works whereas `@EntityScan("my.package.Entities.IndexSetups")` does NOT. – HelloWorld Oct 16 '18 at 09:20