Freitag, 26. Juni 2015

Easy startup of Hibernate Search GenericJPA

I've been talking about it in the last posts and it finally is done. I streamlined the whole startup process to not require extending a specific class. Before I go into detail on how this is done, let's take a look into what dependencies are needed to use Hibernate Search GenericJPA:

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-jpa</artifactId>
</dependency>
<!-- This is only needed in a Java EE environment -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-ejb</artifactId>
</dependency>
view raw gistfile1.txt hosted with ❤ by GitHub

The "hibernate-serach-jpa" module contains all the code needed to enable Hibernate Search in your JPA based application. The "hibernate-search-ejb" module contains the additional startup logic for Java EE containers (currently only default named EMF and properties @/META-INF/hsearch.properties are supported in this module. If you need different behaviour, you can just startup your Search module like in the Java SE case).

Starting up the Hibernate Search GenericJPA

Now, let's take a look into how we start this whole thing up in a Java SE environment:

Properties properties = new Properties();
properties.setProperty( "org.hibernate.search.genericjpa.searchfactory.triggerSource", "org.hibernate.search.genericjpa.db.events.MySQLTriggerSQLStringSource" );
properties.setProperty( "org.hibernate.search.genericjpa.searchfactory.type", "sql");
JPASearchFactoryController searchFactoryController = Setup.createUnmanagedSearchFactory( emf, properties );
//...
//use the searchFactoryController
//...
//in Java SE the user has to close this!
searchFactoryController.close();
view raw gistfile1.java hosted with ❤ by GitHub

If you are using the EJB module in a Java EE context, the startup is already done for you and you can just inject it like this:

@Inject
private JPASearchFactoryController searchFactoryController;
view raw gistfile1.java hosted with ❤ by GitHub

Configuration

No matter where your properties come from (manually specified or loaded from the EJB module), you will have to define some settings:

#must be set
org.hibernate.search.genericjpa.searchfactory.triggerSource=org.hibernate.search.genericjpa.db.events.MySQLTriggerSQLStringSource
#must be set ('sql' or 'manual-updates')
org.hibernate.search.genericjpa.searchfactory.type=sql
#this is a really low value, you might want to set it to a higher value
org.hibernate.search.genericjpa.searchfactory.batchSizeForUpdates=2
#the time between checks for updates in ms
org.hibernate.search.genericjpa.searchfactory.updateDelay=100
#default is 'false'
org.hibernate.search.genericjpa.searchfactory.useJTATransactions=false
#the name of your searchfactory, as of now this doesn't have any impact, default is 'default'
org.hibernate.search.genericjpa.searchfactory.name=default
view raw gistfile1.txt hosted with ❤ by GitHub
For *.useJTATransactions=true the JTA transaction manager (by default) is looked up via JNDI and you have to specify some extra parameters:
#Wildfly
org.hibernate.serach.genericjpa.searchfactory.transactionManagerProvider.jndi=java:jboss/TransactionManager
#TomEE
org.hibernate.serach.genericjpa.searchfactory.transactionManagerProvider.jndi=java:comp/TransactionManager
#GlassFish
org.hibernate.serach.genericjpa.searchfactory.transactionManagerProvider.jndi=java:appserver/TransactionManager
view raw gistfile1.txt hosted with ❤ by GitHub


This list might change in the future and I might have forgotten some properties in this posting. For a complete overview, you can always take a look at the Constants class

Donnerstag, 4. Juni 2015

Integration Tests with Arquillian & Case Sensitive MySQL

Google Summer of Code has officially started and I've been pretty busy working on some important things.

Integration Tests

The goal of my project is to support as many JPA providers as possible and that can only be done by constantly testing the current version against every JPA provider that we want to support. That's the reason why I spent the last few weeks implementing integration tests for Hibernate, EclipseLink and OpenJPA using Arquillian.

By doing so, I found several small bugs in the code that I would have missed otherwhise as I've only been testing against EclipseLink in the older unit-tests. Since unwrapping a javax.sql.Connection works different for each JPA provider there is a new method in the SQLJPASearchFactory (JPASearchFactory was split into two interfaces, one that requires a SQL database, one that doesn't) that you have to override for now:

@Override
protected Connection getConnectionForSetup(EntityManager em) {
if ( em instanceof OpenJPAEntityManager ) {
return em.unwrap(Connection.class);
}
throw new AssertionFailure( "unrecognized EntityManager implementation: " + em );
}
view raw gistfile1.java hosted with ❤ by GitHub
This connection is used to setup the triggers for Update processing. I updated the gists from earlier in this blog to reflect these changes.

Case Sensitive MySQL

I must confess, I have only tested the API on two similar setups until early this week. Both are Windows machines; one with MariaDB, one with MySQL Community Edition.

Then, a build on a linux box was tested and it couldn't find the tables needed in the unit-tests. Why? Because I haven't added @Table to every entity and the @Updates annotation requires you to write the table name.So the JPA providers ended up generating a different table name (concerning upper and lower case) than the one in the @Updates annotation.

I haven't noticed that on my Windows machine, since by default WIN-MySQL is case insensitive.

These kind of problems in the build can't happen anymore from now on since the project is now being periodically built by CI @ ci.hibernate.org.