使用Lucene的Web项目有一个奇怪的问题。 我编写了一个bean,它将业务对象的数据写入Lucene。业务数据由Web前端提供。一切都很好。 但在一些很少的情况下,业务对象不会添加到索引中。似乎这种情况发生在多个用户访问bean的情况下。
我的bean使用静态方法创建Lucene IndexWriter并在我的业务对象的基础上创建Lucene文档。 我认为使所有方法静态足以成为线程保存。但现在我想知道是否有必要使我的更新方法也同步'避免与其他线程冲突? 在没有将对象写入索引的情况下,没有从lucene抛出的异常。所以我不能说我的图层背后会发生什么。
我的更新方法如下所示:
public static boolean updateWorklist(ItemCollection workitem) throws PluginException {
IndexWriter awriter = null;
// try loading imixs-search properties
Properties prop = loadProperties();
if (prop.isEmpty())
return false;
try {
awriter = createIndexWriter(prop);
// create term
Term term = new Term("$uniqueid", workitem.getItemValueString("$uniqueid"));
// test if document should be indexed or not
if (matchConditions(prop, workitem)) {
logger.fine("add workitem '" + workitem.getItemValueString(EntityService.UNIQUEID) + "' into index");
awriter.updateDocument(term, createDocument(workitem));
} else {
logger.fine("remove workitem '" + workitem.getItemValueString(EntityService.UNIQUEID) + "' into index");
awriter.deleteDocuments(term);
}
} catch (IOException luceneEx) {
// close writer!
logger.warning(" Lucene Exception : " + luceneEx.getMessage());
throw new PluginException(LucenePlugin.class.getSimpleName(), INVALID_INDEX,
"Unable to update search index", luceneEx);
} finally {
if (awriter != null) {
logger.fine(" close writer");
try {
awriter.close();
} catch (CorruptIndexException e) {
throw new PluginException(LucenePlugin.class.getSimpleName(), INVALID_INDEX,
"Unable to update search index", e);
} catch (IOException e) {
throw new PluginException(LucenePlugin.class.getSimpleName(), INVALID_INDEX,
"Unable to update search index", e);
}
}
}
logger.fine(" update worklist successfull");
return true;
}
.....
public static IndexWriter createIndexWriter(Properties prop)
throws IOException {
/**
* Read configuration
*/
// String sLuceneVersion = prop.getProperty("Version", "LUCENE_45");
String sIndexDir = prop.getProperty("lucence.indexDir");
String sFulltextFieldList = prop
.getProperty("lucence.fulltextFieldList");
String sIndexFieldListAnalyse = prop
.getProperty("lucence.indexFieldListAnalyze");
String sIndexFieldListNoAnalyse = prop
.getProperty("lucence.indexFieldListNoAnalyze");
logger.fine("IndexDir:" + sIndexDir);
logger.fine("FulltextFieldList:" + sFulltextFieldList);
logger.fine("IndexFieldListAnalyse:" + sIndexFieldListAnalyse);
logger.fine("IndexFieldListNoAnalyse:" + sIndexFieldListNoAnalyse);
// compute search field list
StringTokenizer st = new StringTokenizer(sFulltextFieldList, ",");
searchFieldList = new ArrayList<String>();
while (st.hasMoreElements()) {
String sName = st.nextToken().toLowerCase();
// do not add internal fields
if (!"$uniqueid".equals(sName) && !"$readaccess".equals(sName))
searchFieldList.add(sName);
}
// compute Index field list (Analyze)
st = new StringTokenizer(sIndexFieldListAnalyse, ",");
indexFieldListAnalyse = new ArrayList<String>();
while (st.hasMoreElements()) {
String sName = st.nextToken().toLowerCase();
// do not add internal fields
if (!"$uniqueid".equals(sName) && !"$readaccess".equals(sName))
indexFieldListAnalyse.add(sName);
}
// compute Index field list (Analyze)
st = new StringTokenizer(sIndexFieldListNoAnalyse, ",");
indexFieldListNoAnalyse = new ArrayList<String>();
while (st.hasMoreElements()) {
String sName = st.nextToken().toLowerCase();
// do not add internal fields
if (!"$uniqueid".equals(sName) && !"$readaccess".equals(sName))
indexFieldListNoAnalyse.add(sName);
}
/**
* Now create a IndexWriter Instance
*/
Directory indexDir = createIndexDirectory(prop);
Analyzer analyzer = new StandardAnalyzer();
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(
Version.LATEST, analyzer);
// set the WriteLockTimeout to wait for a write lock (in milliseconds)
// for this instance. 10 seconds!
indexWriterConfig.setWriteLockTimeout(10000);
return new IndexWriter(indexDir, indexWriterConfig);
}
....
public static boolean matchConditions(Properties prop, ItemCollection aworktiem) {
String typePattern = prop.getProperty("lucence.matchingType");
String processIDPattern = prop.getProperty("lucence.matchingProcessID");
String type = aworktiem.getItemValueString("Type");
String sPid = aworktiem.getItemValueInteger("$Processid") + "";
// test type pattern
if (typePattern != null && !"".equals(typePattern) && !type.matches(typePattern)) {
logger.fine("Lucene type '" + type + "' did not match pattern '" + typePattern + "'");
return false;
}
// test $processid pattern
if (processIDPattern != null && !"".equals(processIDPattern) && !sPid.matches(processIDPattern)) {
logger.fine("Lucene $processid '" + sPid + "' did not match pattern '" + processIDPattern + "'");
return false;
}
return true;
}
.... 编辑20.Jan: 我在代码示例中添加了IndexWriter方法。我的属性文件为空,并未向IndexWriter提供任何lucene设置
编辑21.Jan: 我添加了matchConditions方法
答案 0 :(得分:0)
正如@ maksim07所解释的,我实现的问题是使用静态变量和方法。因此,createDocument方法可以观察到空的searchFieldList,indexFieldListAnalyse,indexFieldListNoAnalyse集合,因为存在竞争条件。
最后,我通过使用单独的模式和单独的init()方法重新实现了代码,其中我初始化了我的成员变量的所有值。 使用Singleton EJB可以非常轻松地使用单例模式,并保证所有方法调用都通过EJB容器的默认行为进行同步。