Versions:
Seam 2.1.0.CR1
hibernate-search 3.0.1.GA
I have two entities which I want to manually index, viz. Product, and ProductInfo (OneToMany relationship)
I get an exception when I index ProductInfo.
I'm getting the following exception while running a manual index operation.
Quote:
org.hibernate.search.SearchException: Unable to remove from Lucene index: class za.co.mymed.model.Product#null
at org.hibernate.search.backend.impl.lucene.LuceneWorker.remove(LuceneWorker.java:109)
at org.hibernate.search.backend.impl.lucene.LuceneWorker.performWork(LuceneWorker.java:80)
at org.hibernate.search.backend.impl.lucene.LuceneWorker.performWork(LuceneWorker.java:46)
at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueProcessor.run(LuceneBackendQueueProcessor.java:98)
at org.hibernate.search.backend.impl.BatchedQueueingProcessor.performWorks(BatchedQueueingProcessor.java:149)
at org.hibernate.search.backend.impl.TransactionalWorker.performWork(TransactionalWorker.java:45)
at org.hibernate.search.impl.FullTextSessionImpl.index(FullTextSessionImpl.java:140)
at za.co.mymed.action.IndexerBean.indexAllClasses(IndexerBean.java:91)
at za.co.mymed.action.IndexerBean.index(IndexerBean.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:31)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56)
at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:28)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.core.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:77)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.core.ConversationInterceptor.aroundInvoke(ConversationInterceptor.java:56)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.bpm.BusinessProcessInterceptor.aroundInvoke(BusinessProcessInterceptor.java:51)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.async.AsynchronousInterceptor.aroundInvoke(AsynchronousInterceptor.java:52)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:166)
at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:102)
at za.co.mymed.action.IndexerBean_$$_javassist_5.index(IndexerBean_$$_javassist_5.java)
at za.co.mymed.action.IndexerBean.startProcess(IndexerBean.java:52)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:31)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56)
at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:28)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.core.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:77)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.core.ConversationInterceptor.aroundInvoke(ConversationInterceptor.java:65)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.bpm.BusinessProcessInterceptor.aroundInvoke(BusinessProcessInterceptor.java:51)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.async.AsynchronousInterceptor.aroundInvoke(AsynchronousInterceptor.java:52)
at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:166)
at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:102)
at za.co.mymed.action.IndexerBean_$$_javassist_5.startProcess(IndexerBean_$$_javassist_5.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
at org.jboss.seam.util.Reflections.invokeAndWrap(Reflections.java:126)
at org.jboss.seam.async.AsynchronousInvocation$1.process(AsynchronousInvocation.java:62)
at org.jboss.seam.async.Asynchronous$ContextualAsynchronousRequest.run(Asynchronous.java:80)
at org.jboss.seam.async.AsynchronousInvocation.execute(AsynchronousInvocation.java:44)
at org.jboss.seam.async.ThreadPoolDispatcher$RunnableAsynchronous.run(ThreadPoolDispatcher.java:136)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:417)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:269)
at java.util.concurrent.FutureTask.run(FutureTask.java:123)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:65)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:168)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.NullPointerException
at org.apache.lucene.index.Term.compareTo(Term.java:92)
at org.apache.lucene.index.TermInfosReader.getIndexOffset(TermInfosReader.java:181)
at org.apache.lucene.index.TermInfosReader.get(TermInfosReader.java:216)
at org.apache.lucene.index.SegmentTermDocs.seek(SegmentTermDocs.java:54)
at org.apache.lucene.index.MultiSegmentReader$MultiTermDocs.termDocs(MultiSegmentReader.java:604)
at org.apache.lucene.index.MultiSegmentReader$MultiTermDocs.next(MultiSegmentReader.java:555)
at org.hibernate.search.backend.impl.lucene.LuceneWorker.remove(LuceneWorker.java:99)
... 73 more
Code:
@Name("indexer")
@Scope(ScopeType.CONVERSATION)
public class IndexerBean {
static final int BATCH_SIZE = 1000;
private boolean enabled = false;
private boolean buttonRendered = true;
private float index;
private long total;
private long percentage = -1;
@In
EntityManager entityManager;
private Stopwatch stopwatch = new Stopwatch();
@Asynchronous
public String startProcess(IndexerBean indexerBean){
indexerBean.setEnabled(true);
indexerBean.setButtonRendered(false);
indexerBean.index();
return null;
}
@Begin(join=true)
public void index() {
stopwatch.start();
Session session = (Session)entityManager.getDelegate();
session.setFlushMode(FlushMode.MANUAL); //Disable flush operations
session.setCacheMode(CacheMode.IGNORE); //Disable 2nd-level cache operations
final FullTextSession ftSession =
org.hibernate.search.Search.createFullTextSession( session );
indexAllClasses(ftSession, ProductInfo.class);
stopwatch.stop();
setButtonRendered(true);
}
@SuppressWarnings("unchecked") @End
private void indexAllClasses(FullTextSession fullTextSession, Class... entityTypes){
//First calculate the total records to index
for (Class entityType : entityTypes){
Query query = entityManager.createQuery("select COUNT(e) from "+entityType.getName()+" e");
total += (Long)query.getSingleResult();
}
//Perform indexing
for (Class entityType : entityTypes){
//read the data from the database
//Scrollable results will avoid loading too many objects in memory
ScrollableResults results = fullTextSession.createCriteria( entityType )
.scroll( ScrollMode.FORWARD_ONLY );
while( results.next() ) {
index++;
percentage = (long)((index / total) * 100);
fullTextSession.index( results.get(0) );
if (index % BATCH_SIZE == 0) {
fullTextSession.clear();
}
}
}
}
public long getPercentage() {
return percentage;
}
public long getRunningTime(){
return stopwatch.getRunningTime();
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isButtonRendered() {
return buttonRendered;
}
public void setButtonRendered(boolean buttonRendered) {
this.buttonRendered = buttonRendered;
}
}
Code:
@Entity
@Table(name="tbl_product")
@Indexed
@SuppressWarnings("serial")
public class Product implements java.io.Serializable {
@Id
@TableGenerator(name="id_generator",
pkColumnValue="tbl_product")
@GeneratedValue(generator="id_generator")
@DocumentId
private Integer id;
@Fields({
@Field(index=Index.TOKENIZED),
@Field(name="name_sort", index=Index.UN_TOKENIZED)
})
private String name;
@Lob @Field
private String description;
// Mapped Relationships
@OneToMany(mappedBy="product",fetch = FetchType.LAZY,cascade = { CascadeType.ALL })
@IndexedEmbedded
private Set<ProductInfo> productInfos = new HashSet<ProductInfo>();
}
Code:
@Entity
@Table(name="tbl_product_info")
@Indexed
@SuppressWarnings("serial")
public class ProductInfo implements java.io.Serializable {
@Id
@TableGenerator(name="id_generator",
pkColumnValue="tbl_product_info")
@GeneratedValue(generator="id_generator")
@DocumentId
private Integer id;
@Column(name="product_id",insertable=false,updatable=false)
private Integer productId;
@Lob
@Field
private String information;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({@JoinColumn(name = "product_id",referencedColumnName="id")})
@ContainedIn
private Product product;
}