Java web服务中使用的ElasticSearch引发重叠FileLockException
我们使用ElasticSearch编写了一个比较文档的库。它可以在JSF应用程序中工作,但不能在Web服务中工作 这两个应用程序具有相同的逻辑:首先,它们创建一个存储库(构造器从硬编码位置加载一个文档列表并为其编制索引),然后允许用户将自己的文档与存储库中的文档进行比较。JSF应用程序提供了一些GUI,但是webservice层非常薄——它在启动时创建存储库(加载和索引文档),然后将比较请求传递给库 更复杂的JSF应用程序工作起来没有任何问题,而webservice应用程序甚至不加载(即,它甚至不为文档编制索引),存在重叠锁的问题。(请注意,我部署了一个或另一个应用程序,而不是同时部署两个应用程序。这些应用程序不共享任何数据。我之所以提到JSF应用程序,是因为它可以工作,而另一个应用程序不能工作,即使它们使用相同的库。) JSF应用程序和Web服务有什么不同,前者可以工作,而后者不能工作 以下是一些细节(稍微简化/修改) 网络服务:Java web服务中使用的ElasticSearch引发重叠FileLockException,java,web-services,
elasticsearch,Java,Web Services,
elasticsearch,我们使用ElasticSearch编写了一个比较文档的库。它可以在JSF应用程序中工作,但不能在Web服务中工作 这两个应用程序具有相同的逻辑:首先,它们创建一个存储库(构造器从硬编码位置加载一个文档列表并为其编制索引),然后允许用户将自己的文档与存储库中的文档进行比较。JSF应用程序提供了一些GUI,但是webservice层非常薄——它在启动时创建存储库(加载和索引文档),然后将比较请求传递给库 更复杂的JSF应用程序工作起来没有任何问题,而webservice应用程序甚至不加载(即,它甚至
@WebService(serviceName = "RepositoryWebService")
public class RepositoryWebService {
private static Repository repository = Repository.getInstance();
// some web methods (irrelevant since I never get that far)
}
public class Repository {
private final static Repository instance = new Repository();
public static Repository getInstance() {
return instance;
}
:
}
JSF应用程序access还创建了一个存储库的单例实例(使用@ApplicationScoped
bean)
Web服务的例外情况是:
java.nio.channels.OverlappingFileLockException
at sun.nio.ch.SharedFileLockTable.checkList(FileLockTable.java:255) [rt.jar:1.7.0_04]
:
at java.nio.channels.FileChannel.tryLock(FileChannel.java:1154) [rt.jar:1.7.0_04]
at org.apache.lucene.store.NativeFSLock.obtain(NativeFSLockFactory.java:217) [lucene-core-3.6.1.jar:3.6.1 1362471 - thetaphi - 2012-07-17 12:40:12]
at org.elasticsearch.env.NodeEnvironment.<init>(NodeEnvironment.java:80) [elasticsearch-0.19.11.jar:]
at org.elasticsearch.node.internal.InternalNode.<init>(InternalNode.java:125) [elasticsearch-0.19.11.jar:]
at org.elasticsearch.node.NodeBuilder.build(NodeBuilder.java:159) [elasticsearch-0.19.11.jar:]
at org.elasticsearch.node.NodeBuilder.node(NodeBuilder.java:166) [elasticsearch-0.19.11.jar:]
at org.abc.Repository.<init>(Repository.java:56) [repository.jar:]
:
我尝试了glassfish 3.1.2和JBoss 7.1.1,得到了相同的结果。两者都在JDK 1.7.0_07 64位Windows 7上
任何关于我做错了什么的建议都将不胜感激
更新:
当我将所有依赖jar(elasticsearch*、jna*、log4j*、lucene*、snappy java*和我的jar)放入域的lib目录(在Glassfish上)时,它就可以工作了。当jar只是war文件的一部分时,它就不存在了
不知道发生了什么事。我认为这可能与java中只加载了一个本机库实例有关,但仅加载jna和snappy java JAR是不够的。对于JSF和Web服务应用程序,您似乎是在方法调用或类似调用之后加载列表。在最后一个示例中,您应该在部署应用程序时加载数据。为此,编写一个
ServletContextListener
并在contextInitialized
方法中加载数据
ServletContextListener
将在Web应用程序中加载所有Servlet
之前加载。通过这样做,您的所有web服务方法都可以访问准备好的数据
关于ServletContextListener
:
ServletContext
,可以通过设置以下语句来实现
@WebService(serviceName = "RepositoryWebService")
public class RepositoryWebService {
@Resource
private WebServiceContext wsContext;
@SuppressWarnings("unused")
private ServletContext getServletContext() {
return (ServletContext)wsContext.getMessageContext()
.get(MessageContext.SERVLET_CONTEXT);
}
//your web methods here...
}
不确定这是否有帮助,但以下是一些想法:
- 看起来您已经加载了webservice类的多个实例。您确定Repository.getInstance()工作正常吗
- 我有一个演示项目(webapp-restwebservice+embedded-ES)可以工作:(看看这个)。我在这个项目中使用了Spring和Elasticsearch Spring工厂:
希望这能有所帮助。但这就是静态变量
repository
自动执行的操作-当类加载器加载RepositoryWebService
时,它会创建repository
对象。Repository
的构造函数加载文档(确实如此,一旦索引开始,问题就会出现)。您是否试图同时加载JSF和Web服务应用程序在同一台机器上的数据?否。我部署了其中一个。JSF工作,ws不工作。谢谢。是的,我非常确定存储库只创建了一次(构造函数中有一个log语句,我在日志中只看到一条这样的日志消息)。@dadoonet,您是否尝试过运行演示项目的多个实例?它有用吗?面对同样的问题,当尝试在tomcat中部署两个war文件实例(配置不同)时。我不知道(线程太旧),但elasticsearch不再支持嵌入。
@WebService(serviceName = "RepositoryWebService")
public class RepositoryWebService {
@Resource
private WebServiceContext wsContext;
@SuppressWarnings("unused")
private ServletContext getServletContext() {
return (ServletContext)wsContext.getMessageContext()
.get(MessageContext.SERVLET_CONTEXT);
}
//your web methods here...
}