0
votes

I'm trying to implement Hibernate search on Google App Engine using Hibernate-Gae-Search library.

Hibernate Search 4.0.0 using multithreading so I'm getting exceptions.

Is there a way avoid this or we cant use Hibernate Search on gae ? Is there a alternative to Hbernate Search for gae ?

Exception trace :

org.hibernate.search.exception.impl.LogErrorHandler handleException [INFO] ERROR: HSEARCH000058: HSEARCH000116: Unexpected error during MassIndexer operation [INFO] java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "modifyThreadGroup") [INFO] at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372) [INFO] at java.security.AccessController.checkPermission(AccessController.java:559) [INFO] at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) [INFO] at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkPermission(DevAppServerFactory.java:429) [INFO] at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkAccess(DevAppServerFactory.java:454) [INFO] at java.lang.ThreadGroup.checkAccess(ThreadGroup.java:315) [INFO] at java.lang.Thread.init(Thread.java:391) [INFO] at java.lang.Thread.init(Thread.java:349) [INFO] at java.lang.Thread.(Thread.java:675) [INFO] at org.hibernate.search.batchindexing.impl.Executors$SearchThreadFactory.newThread(Executors.java:98) [INFO] at java.util.concurrent.ThreadPoolExecutor$Worker.(ThreadPoolExecutor.java:610) [INFO] at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:924) [INFO] at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1360) [INFO] at org.hibernate.search.batchindexing.impl.BatchCoordinator.doBatchWork(BatchCoordinator.java:133) [INFO] at org.hibernate.search.batchindexing.impl.BatchCoordinator.run(BatchCoordinator.java:105) [INFO] at org.hibernate.search.impl.MassIndexerImpl.startAndWait(MassIndexerImpl.java:204) [INFO] at com.missing.controllers.AjaxEndPoints.testConnection(AjaxEndPoints.java:116) [INFO] at com.missing.controllers.AjaxEndPoints.fileNewReport(AjaxEndPoints.java:63) [INFO] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [INFO] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [INFO] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [INFO] at java.lang.reflect.Method.invoke(Method.java:606) [INFO] at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:115) [INFO] at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:214) [INFO] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132) [INFO] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) [INFO] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:748) [INFO] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689) [INFO] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) [INFO] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945) [INFO] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876) [INFO] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:931) [INFO] at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:833) [INFO] at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) [INFO] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:807) [INFO] at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) [INFO] at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) [INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) [INFO] at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74) [INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) [INFO] at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:127) [INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) [INFO] at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34) [INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) [INFO] at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:63) [INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) [INFO] at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) [INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) [INFO] at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125) [INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) [INFO] at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:366) [INFO] at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:349) [INFO] at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116) [INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) [INFO] at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) [INFO] at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) [INFO] at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) [INFO] at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) [INFO] at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) [INFO] at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:98) [INFO] at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) [INFO] at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:491) [INFO] at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) [INFO] at org.mortbay.jetty.Server.handle(Server.java:326) [INFO] at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) [INFO] at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938) [INFO] at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755) [INFO] at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218) [INFO] at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) [INFO] at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409) [INFO] at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

1

1 Answers

1
votes

The Hibernate Search mass indexer works highly parallel and for that creates multiple threads. AFAIK this is not allowed on the Google App Engine. For this reason, the mass indexer is a no go in this scenario.

You could try manual indexing as described here - http://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#search-batchindex-flushtoindexes. Basically you are relying in FullTextSession#index. From the docs:

fullTextSession.setFlushMode(FlushMode.MANUAL);
fullTextSession.setCacheMode(CacheMode.IGNORE);
transaction = fullTextSession.beginTransaction();
//Scrollable results will avoid loading too many objects in memory
ScrollableResults results = fullTextSession.createCriteria( Email.class )
    .setFetchSize(BATCH_SIZE)
    .scroll(ScrollMode.FORWARD_ONLY);
int index = 0;
while(results.next()) {
    index++;
    fullTextSession.index(results.get(0)); //index each element
    if (index % BATCH_SIZE == 0) {
        fullTextSession.flushToIndexes(); //apply changes to indexes
        fullTextSession.clear(); //free memory since the queue is processed
    }
}
transaction.commit();