-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 
Author Message
 Post subject: Hibernate Search ReIndex from within JBoss (with Seam)
PostPosted: Mon Mar 24, 2008 11:40 am 
Newbie

Joined: Mon Oct 18, 2004 4:18 pm
Posts: 4
I'm trying to get a FullTextSession in my SessionBean in the JBoss Container to allow me to reindex the Hibernate Search Records based on the records and mappings I have in the database.

This is a maintenance function to be run if the indexes get corrupted or otherwise out of sync.

The documentation for Hibernate Search (page 37) has some recommendations, but they all require a FullTextSession. I'm running this within a JBoss Server using EJB 3.0 and JPA.

I can't figure out how to extract this FullTextSession from the EntityManager that is injected into the Session Bean. I can cast the EntityManager to a FullTextEntityManager but, I can't get a Session from that because the HibernateEntityManager interface hasn't been implemented against the FullTextEntityManager.

Any suggestions?

Using JBoss 4.2.2, Seam 2.0.1, Hibernate Search 3.0.1


Last edited by dstreev on Wed Mar 26, 2008 10:51 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 25, 2008 7:09 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
from the documentation:
Code:
FullTextEntityManager fullTextEntityManager =
    org.hibernate.hibernate.search.jpa.Search.createFullTextEntityManager(em);

and then use the FullTextEntityManager, it offers you the same functionality as FullTextSession.
Quote:
I can cast the EntityManager to a FullTextEntityManager

really? that's interesting.. do you get a FullTextEntityManager instance when you inject the em?


Top
 Profile  
 
 Post subject: Hibernate Search ReIndex from within JBoss (with Seam)
PostPosted: Wed Mar 26, 2008 10:50 am 
Newbie

Joined: Mon Oct 18, 2004 4:18 pm
Posts: 4
I already have the FullTextEntityManager via Seam injection. If Hibernate Search is available, Seam will inject a FullTextEntityManager instead of the HibernateEntityManager.

FullTextEntityManager doesn't offer ALL the same functionality as a FullTextSession.

IE: (From the documention in Hibernate Search)

Code:
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 ).scroll( ScrollMode.FORWARD_ONLY );
int index = 0;
while( results.next() ) {
    index++;
    fullTextSession.index( results.get(0) ); //index each element
    if (index % batchSize == 0) s.clear(); //clear every batchSize since the queue is processed
}
transaction.commit();


You don't have access to setFlushMode, cache and createCriteria to retrieve ScrollableResults.

FullTextEntityManager implements the javax.persistence.EntityManager, not HibernateEntityManager which provides access to the "Session".

It would be nice to have access to the "Session" from the FullTextEntityManager and the getSession method return a Session interface that can be cast to a FullTextSession.

Note: This is done in the app server with JTA. Unfortunately, the docs don't truly address this. They examples are theoretical.

I'd like to know how others are "ReIndexing" their Hibernate Search FROM WITHIN THE APP SERVER. I've thought of doing it outside the app server, but I'm afraid that would require bringing the server down for maintenance because of concurrent access to the indexes. Not really an option if you reindexing process could take a long time.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 26, 2008 12:22 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
You're right; for normal usage the API is the same but, as usual, for finetuning the Session version offers more functionality.

You could get the Session by casting:
Code:
Session s = (Session)fullTextEM.getDelegate();

and then using usual methods to create a FullTextSession.
Code:
FullTextSession fullTextSession = Search.createFullTextSession(session);



I guess it would be more intuitive if the getDelegate() returned the FullTextSession directly.

I am doing a lot of batch reindexing from the app server, and have developed much custom code; It's a bit outdated now and I'm currently investigating how fast it would be to use the current Search code, as providing my own code would require a lot of changes. I need some numbers to back a proposal to change the API, but I could also prove that some documentation updates could suffice.. still testing.

I can currently say that the documented version to rebuilding the index is not performing bad; In any case, it works well from within the container.

regards,
Sanne


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 27, 2008 8:37 am 
Newbie

Joined: Mon Oct 18, 2004 4:18 pm
Posts: 4
Thanks for the suggestion. It's work, for the most part. I get it to reindex everything, but it throws an exception from the SeamPhaseListener after the method exists. I'm sure it has to do with the long running transaction.

Here's the resulting solution, thus far:

Code:
import java.util.Date;

import javax.ejb.*;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.hibernate.*;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.jboss.annotation.ejb.TransactionTimeout;
import org.jboss.seam.annotations.*;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.log.Log;

// No need to carry state since the methods are self contained.
@Stateless
@Name("manage")
public class ManageBean implements ManageLocal {

  // When Hibernate Search is present, seam will inject a FullTextEntityManager
  @PersistenceContext
  private EntityManager entityManager;
 
  @Logger
  private Log log;
 
  @In
  FacesMessages facesMessages;

  // Need this to override the default timeout of 3 minutes for JBoss Transactions.
  // You'll need the jboss-annotations-ejb3.jar in classpath to compile.
  @TransactionTimeout(86400)
  // Start new transaction for this method.
  @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  public void reIndex() {

    // Extract Session from EntityManager
    Session lclSession = (Session)entityManager.getDelegate();
    log.info("Starting ReIndexing Routine");

    // Create a FullTextSession, so we can setup a scrollable cursor
    // to keep the memory footprint down while we iterate through the
    // list of objects.
    FullTextSession ftSession = Search.createFullTextSession(lclSession);

    ftSession.setFlushMode(FlushMode.MANUAL);
    ftSession.setCacheMode(CacheMode.IGNORE);

    Date start = new Date();
    log.info("Getting Scrollable Cursor for Change Requests...");

    //Scrollable results will avoid loading too many objects in memory
    ScrollableResults results = ftSession.createCriteria( XXXX.class ).scroll( ScrollMode.FORWARD_ONLY );
    log.info("Cursor retrieved... Start Indexing...");
    int index = 0;
    while( results.next() ) {
        index++;
        ftSession.index( results.get(0) ); //index each element
        // The "25" matches the value established in the persistence.xml used to
        // control batch sizes for Hibernate Search.
        /**
             <property name="hibernate.search.worker.batch_size" value="25"/>
         *
         */
        if (index % 25 == 0) {
          // clear the session contents to keep memory footprint down.
          ftSession.clear();
          log.info("Records Indexed: " + index);
        }
    }
    Date end = new Date();
    long diff = end.getTime() - start.getTime();
    log.info("ReIndexing Complete... # of records Indexed: " + index + " in " + diff + " ms.");
    facesMessages.add("ReIndexed - Complete");
  }

}


And the calling xhtml page segment:
Code:
        <h:form id="reIndexForm">
       
            <h:commandButton id="reIndex" value="ReIndex!"
                             action="#{manage.reIndex}"/>           
       
        </h:form>



If anybody has a suggestion how to stop the exception thrown at the end, please post it here. Thanks.

My Exception:
Code:
08:09:54,702 INFO  [ManageBean] Records Indexed: 36050
08:09:54,910 INFO  [ManageBean] ReIndexing Complete... # of records Indexed: 36074 in 914981 ms.
08:09:55,366 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_40] - Abort called on already aborted atomic action a613ee4:c282:47eb89f9:52
08:09:55,367 ERROR [SeamPhaseListener] uncaught exception
java.lang.IllegalStateException: Could not commit transaction
   at org.jboss.seam.jsf.SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:602)
   at org.jboss.seam.jsf.SeamPhaseListener.handleTransactionsAfterPhase(SeamPhaseListener.java:330)
   at org.jboss.seam.jsf.SeamPhaseListener.afterServletPhase(SeamPhaseListener.java:231)
   at org.jboss.seam.jsf.SeamPhaseListener.afterPhase(SeamPhaseListener.java:182)
   at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:280)
   at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
   at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
   at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
   at org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:68)
   at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
   at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:85)
   at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
   at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
   at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
   at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
   at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
   at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:141)
   at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:281)
   at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:60)
   at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
   at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
   at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
   at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
   at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
   at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
   at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
   at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
   at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
   at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
   at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
   at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
   at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
   at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.IllegalStateException: [com.arjuna.ats.internal.jta.transaction.arjunacore.inactive] [com.arjuna.ats.internal.jta.transaction.arjunacore.inactive] The transaction is not active!
   at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.rollbackAndDisassociate(TransactionImple.java:1473)
   at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.rollback(BaseTransaction.java:163)
   at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.rollback(BaseTransactionManagerDelegate.java:126)
   at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.rollback(ServerVMClientUserTransaction.java:148)
   at org.jboss.seam.transaction.UTTransaction.rollback(UTTransaction.java:66)
   at org.jboss.seam.jsf.SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:597)
   ... 43 more



Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 02, 2008 4:51 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
Hi,
sorry for the delay, I'm still interested in your topic.

Try this on the Bean:
Code:
@Stateless
@Name("manage")
@TransactionManagement(TransactionManagementType.BEAN)
@TransactionAttribute(TransactionAttributeType.NEVER)

you should get full control on your transactions;
remember to begin one, as indexing is faster when in a transaction!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 03, 2008 8:42 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

I had a similar problem once where I could not index all my entities within a single transaction. I also choose to control the transactions during indexing myself and it solved the problem.

However, it might also help to just set the hibernate.search.worker.batch_size property (http://www.hibernate.org/hib_docs/search/reference/en/html_single/#search-batchindex).

--Hardy

Ups, sorry - seems you are already using hibernate.search.worker.batch_size.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 07, 2008 5:39 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
out of curiosity
I think

@In FullTextSession session

should inject you the ftSession

Otherwise from the em. I'm pretty sure getDelegate() returns a FullTextSession, so the cast should be possible

All this work in JBoss Seam only

_________________
Emmanuel


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.