如何在Apache Tomcat中部署Marklogic XCC库?

时间:2016-03-17 15:38:40

标签: marklogic marklogic-8

问题:
使用WAR文件(在WEB-INF / classes中)部署XCC库禁止重新部署/更新该Web应用程序,而无需重新启动整个Tomcat容器。它只是停止工作,因为仍然分配了资源,因此Tomcat无法删除一些JAR文件 在Tomcats lib目录中部署库时(作为JDBC驱动程序),Tomcat会在Tomcat日志中写入内存泄漏警告,如下所示:

17-Mar-2016 10:58:45.683 WARNING [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [api] appears to have started a thread named [Thread-4] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:  java.lang.Thread.sleep(Native Method)  com.marklogic.xcc.ContentSourceFactory$ConnectionCollector.run(ContentSourceFactory.java:449)

我发现了什么:
我做了一些调查并发现,(至少在XCC 8.0.3中)在ContentSourceFactory中启动了一个永不关闭的线程。该线程正在影响servlet的更新/重新部署并产生内存泄漏。我的快速解决方案是创建一个自定义的ContentSourceFactory,它有一个shutdown方法,当servlet停止时会调用它。

问题:
不幸的是,我没有在文档中找到任何线索。那么在servlet容器中使用XCC库(8.x)的官方方式是什么?

2 个答案:

答案 0 :(得分:2)

此线程似乎在JVM的持续时间内运行。我会为此打开一个缺陷。

基于tomcat中不同产品的类似问题的经验解决方法。数据库驱动器(特别是JDBC)在历史上一直存在问题。

将xcc.jar放入tomcat的“共享库”类路径而不是WAR中。一般不推荐这样做 - 但OTOH正是为什么存在共享库类路径 - 这允许重新部署应用程序。 XCC代码是线程安全的并且与上下文无关,只要您不自己共享活动连接对象它就可以正常工作。

同时确保您努力关闭或关闭所有响应对象,终结器可能需要很长时间才能启动。

-David

答案 1 :(得分:0)

我的临时解决方案:
正如DALDEI所说,它看起来像是XCC库中的一个开放问题。为了做一个临时的解决方法,我根据原始资源(8.0.4)编写了DisposableContentSourceFactory。代码可以在这里找到:https://gist.github.com/Mario-Eis/a16437c35d2aa097f668

这种方法也有一个优点,因为它可以平滑地集成在IoC上下文中,例如Spring IoC。

@Configuration
public class XccContext {

    @Bean(destroyMethod = "shutdown")
    public DisposableContentSourceFactory contentSourceFactory() {
        return DisposableContentSourceFactory.create();
    }

    @Bean
    public ContentSource contentSource(XccConfiguration xccConfiguration, DisposableContentSourceFactory contentSourceFactory) throws XccConfigException {
        return contentSourceFactory.newContentSource(xccConfiguration.connectionString());
    }

    @Bean(destroyMethod = "close")
    @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
    public Session marklogicSession(ContentSource contentSource) {
        return contentSource.newSession();
    }
}

为了确保对官方静态类方法的一些“兼容性”,我还包括一个静态工厂方法create()

如果有公共GIT存储库,我可以提交拉取请求。