package org.infinispan.hibernate.search;
import java.io.IOException;
import java.util.List;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.TermQuery;
import org.hibernate.Transaction;
import org.hibernate.cfg.Environment;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.test.util.FullTextSessionBuilder;
import org.infinispan.hibernate.search.impl.DefaultCacheManagerService;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
/**
* Verifies we're able to start from an existing index in Infinispan, stored in a CacheLoader. Requires a persistent
* database so that we can shutdown the SessionFactory and start over again (simulated via a custom H2 service)
*
* @author Sanne Grinovero <sanne@hibernate.org> (C) 2012 Red Hat Inc.
*/
public class StoredIndexTest {
private FullTextSessionBuilder node;
@ClassRule
public static TemporaryFolder temporaryFolderFolder = new TemporaryFolder();
@Test
public void testRestartingNode() {
// Run 1 of application:
startNode(true);
try {
storeEmail("there are some problems on this planet!");
assertEmailsFound("some", 1);
} finally {
//shutdown
stopNode();
}
// Restart same application:
startNode(false);
try {
assertEmailsFound("some", 1);
storeEmail("stored stuff should not vanish on this planet");
assertEmailsFound("stuff", 1);
assertEmailsFound("some", 1);
assertEmailsFound("planet", 2);
} finally {
cleanupStoredIndex();
stopNode();
}
}
/**
* Verifies a query on a specific term returns an expected amount of results. We do actually load entities from
* database, so both database and index are tested.
*
* @param termMatch
* @param expectedMatches
*/
private void assertEmailsFound(String termMatch, int expectedMatches) {
FullTextSession fullTextSession = node.openFullTextSession();
try {
TermQuery termQuery = new TermQuery(new Term("message", termMatch));
FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(termQuery, SimpleEmail.class);
List<SimpleEmail> list = fullTextQuery.list();
Assert.assertEquals(expectedMatches, list.size());
if (expectedMatches != 0) {
Assert.assertEquals("complaints-office@world.com", list.get(0).to);
}
} finally {
fullTextSession.close();
}
}
/**
* Saves a new test email
*/
private void storeEmail(String content) {
SimpleEmail email = new SimpleEmail();
email.to = "complaints-office@world.com";
email.message = content;
FullTextSession fullTextSession = node.openFullTextSession();
Transaction transaction = fullTextSession.beginTransaction();
fullTextSession.save(email);
transaction.commit();
fullTextSession.close();
}
/**
* Creates a new SessionFactory using a shared H2 connection pool, and running an Infinispan Directory storing the
* index in memory and write-through filesystem.
*
* @param createSchema set to false to not drop an existing schema
*/
private void startNode(boolean createSchema) {
node = new FullTextSessionBuilder()
.setProperty("hibernate.search.default.directory_provider", "infinispan")
.setProperty(DefaultCacheManagerService.INFINISPAN_CONFIGURATION_RESOURCENAME, "filesystem-loading-infinispan.xml")
// avoid killing the schema when you still have to run the second node:
.setProperty(Environment.HBM2DDL_AUTO, createSchema ? "create" : "validate")
// share the same in-memory database connection pool
.setProperty(
Environment.CONNECTION_PROVIDER,
org.infinispan.hibernate.search.ClusterSharedConnectionProvider.class.getName()
)
.addAnnotatedClass(SimpleEmail.class)
.build();
}
/**
* Closes the SessionFactory, SearchFactory and Infinispan CacheManagers. Only service to survive is the H2 in memory
* database, and the data stored by the CacheLoader enabled in the Infinispan configuration.
*/
public void stopNode() {
if (node != null) {
node.close();
node = null;
}
}
/**
* This test uses and Infinispan CacheLoader writing in $tmp directory. Make sure we at least clear the index so that
* subsequent runs of the same test won't fail.
*/
private void cleanupStoredIndex() {
FullTextSession fullTextSession = node.openFullTextSession();
try {
Transaction transaction = fullTextSession.beginTransaction();
fullTextSession.purgeAll(SimpleEmail.class);
transaction.commit();
} finally {
fullTextSession.close();
}
}
/**
* We need to use the custom H2 connector pool to make sure that when shutting down the first node we don't kill the
* database with all data we need for the second phase of the test.
*/
@BeforeClass
public static void prepareConnectionPool() throws IOException {
System.setProperty("tempTestDataDir", temporaryFolderFolder.newFolder().getAbsolutePath());
ClusterSharedConnectionProvider.realStart();
}
/**
* Kills the static connection pool of H2 started by {@link #prepareConnectionPool()}
*/
@AfterClass
public static void shutdownConnectionPool() {
ClusterSharedConnectionProvider.realStop();
}
}