2

我们编写了一个使用 ElasticSearch 比较文档的库。它适用于 JSF 应用程序,但不适用于 Web 服务。

这两个应用程序具有相同的逻辑:首先它们创建一个存储库(构造函数从硬编码位置加载文档列表并对其进行索引),然后允许用户将自己的文档与存储库中的文档进行比较。JSF 应用程序提供了一些 GUI,但 web 服务层非常薄 - 它在启动时创建存储库(加载和索引文档),然后只是将比较请求传递给库。

更复杂的 JSF 应用程序运行时没有任何问题,而 web 服务应用程序甚至不加载(即它甚至不索引文档),存在重叠锁的问题。(请注意,我部署了一个或另一个应用程序,而不是同时部署两个应用程序。应用程序不共享任何数据。我只提到 JSF 应用程序,因为它可以工作,而另一个没有,即使它们使用相同的库。 )

JSF 应用程序和 Web 服务有什么不同,前者可以工作,而后者不能?

以下是一些细节(略微简化/修改)

网络服务:

@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 应用程序访问也创建了存储库的单例实例(使用@ApplicationScopedbean)。

我得到的网络服务的例外是:

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:]
    :

elasticsearch.yml中,我有(除其他外):

node.max_local_storage_nodes: 1
index:
    number_of_shards: 1
    number_of_replicas: 0

我尝试了 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 上)时,它就可以工作。当 jars 只是 war 文件的一部分时,它不会。

不知道发生了什么。我虽然这可能与在 java 中仅加载一个本机库实例这一事实有关,但仅将 jna 和 snappy-java jar 放在那里是不够的。

4

2 回答 2

1

不确定它是否会有所帮助,但这里有一些想法:

  • 看起来您已经加载了 Web 服务类的多个实例。您确定 Repository.getInstance() 工作正常吗?
  • 我有一个有效的演示项目(webapp - REST Webservice + 嵌入式 ES):(看看这段代码)。我在这个项目中使用了 Spring 和 Elasticsearch Spring Factory: Spring ElasticSearch

希望这可以帮助。

于 2012-11-02T03:02:29.063 回答
0

看起来您正在为 JSF 和 Web 服务应用程序调用方法或类似方法之后加载列表。在最后一个中,您应该在部署应用程序时加载数据。为此,编写一个ServletContextListener并在方法中加载数据contextInitialized

ServletContextListener在所有Servlets 加载到 Web 应用程序之前加载。通过这样做,您的所有 Web 服务方法都可以访问准备好的数据。

关于ServletContextListener

如果您需要/想要ServletContext从 Web Service 类访问,您可以通过设置这句话来实现

@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...
}
于 2012-11-02T01:26:05.573 回答