如何在不关闭VM的情况下关闭和重新打开Spring Data Neo4J上下文

7

我正在运行一个Spring Data Neo4j应用程序(非基于Web),在正常操作期间运行良好。

如果我关闭Spring上下文“ctx.close()”,Neo4J数据库上的锁将消失。

然后,从同一应用程序实例中,如果我获取另一个上下文,我会看到锁回来了,但如果我尝试从该上下文读取/写入该数据库,则会出现错误:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.data.neo4j.config.Neo4jConfiguration#0': Unsatisfied dependency expressed through bean property 'conversionService': : Error creating bean with name 'mappingInfrastructure' defined in class org.springframework.data.neo4j.config.Neo4jConfiguration: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public final org.springframework.data.neo4j.support.MappingInfrastructureFactoryBean org.springframework.data.neo4j.config.Neo4jConfiguration$$EnhancerByCGLIB$$64cefd6f.mappingInfrastructure() throws java.lang.Exception] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'typeRepresentationStrategyFactory' defined in class org.springframework.data.neo4j.config.Neo4jConfiguration: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public final org.springframework.data.neo4j.support.typerepresentation.TypeRepresentationStrategyFactory org.springframework.data.neo4j.config.Neo4jConfiguration$$EnhancerByCGLIB$$64cefd6f.typeRepresentationStrategyFactory() throws java.lang.Exception] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'graphDatabaseService': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.neo4j.kernel.EmbeddedGraphDatabase]: Constructor threw exception; nested exception is java.lang.IllegalStateException: Unable to lock store [C:\app_data\gelato\data\neostore], this is usually a result of some other Neo4j kernel running using the same store.; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mappingInfrastructure' defined in class org.springframework.data.neo4j.config.Neo4jConfiguration: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public final org.springframework.data.neo4j.support.MappingInfrastructureFactoryBean org.springframework.data.neo4j.config.Neo4jConfiguration$$EnhancerByCGLIB$$64cefd6f.mappingInfrastructure() throws java.lang.Exception] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'typeRepresentationStrategyFactory' defined in class org.springframework.data.neo4j.config.Neo4jConfiguration: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public final org.springframework.data.neo4j.support.typerepresentation.TypeRepresentationStrategyFactory org.springframework.data.neo4j.config.Neo4jConfiguration$$EnhancerByCGLIB$$64cefd6f.typeRepresentationStrategyFactory() throws java.lang.Exception] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'graphDatabaseService': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.neo4j.kernel.EmbeddedGraphDatabase]: Constructor threw exception; nested exception is java.lang.IllegalStateException: Unable to lock store [C:\app_data\gelato\data\neostore], this is usually a result of some other Neo4j kernel running using the same store.

有没有一种方法可以在单个应用程序实例内成功关闭并重新打开应用程序上下文(即不关闭虚拟机)?

最初我在图形数据库上调用了shutdown(),但由于Michael Hunger告诉我不要这样做,因此进行了更改。

我们的问题可以在我们的领域中重现如下。

AbstractApplicationContext ctx = new FileSystemXmlApplicationContext("neo4jconfig.xml");
OurDomainService domainService = (OurDomainService) ctx.getBean(OurDomainServiceImpl.class);
// This works
domainService.save(data);
// this releases the lock
ctx.close();
// this re-creates the lock and the context looks actvive
ctx = new FileSystemXmlApplicationContext("neo4jconfig.xml");
domainService = (OurDomainService) ctx.getBean(OurDomainServiceImpl.class);
// this errors out
domainService.save(data);

这是我们用来创建上下文的XML文件。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/neo4j
http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

<context:spring-configured/>
    <context:annotation-config/>
    <context:component-scan base-package="OurData" />

    <neo4j:config storeDirectory="c:/app_data/data"/>
    <neo4j:repositories base-package="OurData"/>

</beans>

你也正确关闭了 WrappingNeoServerBootstrapper 吗? - Michael Hunger
能否在Github上分享一个测试项目,以便检查这种行为是否存在? - Michael Hunger
使用引导程序工作正常,但当我们停止服务器并复制另一个数据库以替换活动数据库时,再次启动并从中请求数据时,似乎会从旧数据库获取结果,就像缓存一样? - Link19
很高兴WrappingNeoServerBootstrapper能够正常工作。你所说的“复制另一个数据库来替换活动数据库”是什么意思? - Manish Singh
我们关闭,从文件系统中删除数据库文件,然后重新启动。 - Link19
你有没有找到解决办法? - Kevin Krumwiede
2个回答

3

您不应该这样做,在您的情况下,spring-context 应该处理生命周期。

在您的情况下,重新启动时会发生什么?

您将使用以下命令关闭应用程序上下文:

ctx.close()

您应该使用 WebApplicationContext(Utils) 通过您的 web.xml 获取配置的 Spring 上下文。如下所示:

WebApplicationContext springContext = 
    WebApplicationContextUtils.getWebApplicationContext(getServletContext()); 

我们不是在Web服务器中托管它,而是运行一个独立的应用程序。我正在使用FileApplicationContext,并通过命令行指向外部XML文件。这与之前的方式有很大的相似之处吗? - Link19
ApplicationContext接口似乎没有包含close()方法? - Link19
忽略我刚刚将ctx声明为“FileSystemXmlApplicationContext”,现在调用close方法,但当我尝试获取另一个上下文时,它会给出错误提示,就像我在已经运行服务器的情况下尝试启动服务器一样。 - Link19
算了,我获取另一个上下文,当我尝试保存节点时,我得到了这个错误:通过bean属性表达的不满足的依赖关系。 - Link19

0

看了我的最后一条评论和你的回复,我修改了我的完整答案。

以下是两个主要文件。

第一个文件使用WrappingNeoServerBootstrapper

这是Neo4j服务器的引导程序,它接受一个已经实例化的{@link org.neo4j.kernel.GraphDatabaseAPI}和可选配置,并使用该数据库启动服务器。 使用它可以从已经使用{@link EmbeddedGraphDatabase}或{@link HighlyAvailableGraphDatabase}的应用程序中启动完整的Neo4j服务器。这使您的应用程序能够充分利用服务器的REST API、Web管理界面和统计跟踪等所有优势。

package sandbox;

import org.neo4j.server.WrappingNeoServerBootstrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.support.Neo4jTemplate;

public class GalaxyServiceTest {

    private final static Logger slf4jLogger = LoggerFactory.getLogger(GalaxyServiceTest.class);
    @Autowired
    private GalaxyService galaxyService;
    @Autowired
    private Neo4jTemplate template;

    public static void main(String args[]) throws InterruptedException {
        GalaxyServiceTest main = new GalaxyServiceTest();
        ApplicationContextLoader loader = new ApplicationContextLoader();
        loader.load(main, "/spring/helloWorldContext.xml");
        // The server starts with loading of above Context.xml
        WrappingNeoServerBootstrapper neoServer = loader.getApplicationContext().getBean("serverWrapper", WrappingNeoServerBootstrapper.class);
        //process something in repository 
        main.doSomething();
        // do a graceful stop
        int stop = neoServer.stop(0);
        slf4jLogger.info("stopping Server status code {} ", stop);
        //Restart the server 
        neoServer.start();
        slf4jLogger.info("Restarting Server ");
        // Process something in Repository
        main.doSomething();

    }

    public void doSomething() {
        galaxyService.makeSomeWorlds();
        Iterable<World> allWorlds = galaxyService.getAllWorlds();
        for (World world : allWorlds) {
            slf4jLogger.info("World Name is {}", world.toString());
        }
    }
}

应用程序上下文定义 XML

   <context:annotation-config />
    <context:spring-configured/>
    <context:component-scan base-package="sandbox" />

    <bean id="transactionManager" 
          class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager">
            <bean id="jotm" class="org.springframework.data.neo4j.transaction.JotmFactoryBean"/>
        </property>
    </bean>
    <neo4j:config graphDatabaseService="graphDatabaseService" />
    <bean id="serverWrapper" class="org.neo4j.server.WrappingNeoServerBootstrapper"
          init-method="start" destroy-method="stop">
        <constructor-arg ref="graphDatabaseService" />
    </bean>

    <bean id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase" 
          destroy-method="shutdown">
        <constructor-arg value="target/test-db"/>
    </bean>
    <tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>

    <neo4j:repositories base-package="sandbox"></neo4j:repositories>

</beans>

希望这能有所帮助。


你是否意识到我正在尝试在应用程序的同一实例中停止和启动NEO服务器。也就是说,我的虚拟机不会关闭。测试应该使用ctx.close()关闭neo,然后重新启动它并能够查询/保存。 - Link19
你是否在使用neo4j的嵌入式数据库模式? - Manish Singh
但这就是问题所在,就我所知,我的问题确实都说了吧? - Link19
那么你的意思是说我们无法关闭它?也就是说有一个漏洞? - Link19
很抱歉,我不是Neo4J或Spring Data的专家,所以我需要寻求帮助。我们使用的实现是从可用资源中组合而成的,当像这样的东西不起作用时,甚至开始弄清原因都很困难。我没有理解到不同解决方案的程度,所以我无法告诉您我们使用的名称。我们的xml文件几乎没有用处,但如果有帮助的话,我会发布它。 - Link19
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接