7

I'm running a spring data neo-4j application (not web based) which works fine during normal operation.

If I close the Spring Context 'ctx.close()' the lock on the neo 4J database goes away.

Then, from the same instance of the application, if I grab another Context I see the lock come back, but if I try and read / write from that database from that context I get an error:

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.

Is there a way to successfully close and then re-open the Application Context within a single instance of an application (ie without shutting down the virtual machine) ?

I was initially calling shutdown() on the graph database, but changed this as Michael Hunger told me not to do it.

our problem can be reproduced in our domain like this.

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);

Here's the XML file we use to create the context.

<?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>
Link19
  • 586
  • 1
  • 18
  • 47
  • Are you also shutting down the `WrappingNeoServerBootstrapper` correctly? – Michael Hunger Feb 20 '13 at 08:35
  • Would it be possible to share a test project that exhibits that behavior on github to check it out? – Michael Hunger Feb 20 '13 at 08:35
  • Ok using the Bootstrapper Worked, but when we stop the server, copy another database in to replace the active one. When we start it again, and request data from it, it seems like we are getting results back from the old database, like a cache maybe? – Link19 Feb 20 '13 at 14:51
  • Glad that WrappingNeoServerBootstrapper got working. What do you mean by copy another database in to replace active one ? – Manish Singh Feb 23 '13 at 16:03
  • We shut down, delete the database files from the FS, then re-start. – Link19 Feb 25 '13 at 13:03

2 Answers2

3

You shouldn't do that, in your case the spring-context should handle the lifecycle.

What happens when you restart in your case?

You shut down the application-context with

ctx.close()

You should probably use a WebApplicationContext(Utils) to get your configured Spring Context via your web.xml. Like this:

WebApplicationContext springContext = 
    WebApplicationContextUtils.getWebApplicationContext(getServletContext()); 
Michael Hunger
  • 41,339
  • 3
  • 57
  • 80
  • We aren't hosting it inside a web server, just running a stand alone, I'm using FileApplicationContext and pointing to an external xml provided by the command line. Is that much the same? – Link19 Feb 05 '13 at 12:53
  • The ApplicationContext interface doesn't seem to contain a close() method? – Link19 Feb 05 '13 at 15:13
  • Ignore that I've just declared ctx as a 'FileSystemXmlApplicationContext' instead, close is now called, but when I try to get hold of another context it gives me the error I get when I try and start a server whils one is already running. – Link19 Feb 05 '13 at 15:21
  • Scratch that, I grab another Contexts, and when I try and save a node I get: Unsatisfied dependency expressed through bean property – Link19 Feb 05 '13 at 15:38
0

Looking at my last comment and your responses have edited my complete answer.

The two main files below.

The first one uses WrappingNeoServerBootstrapper

A bootstrapper for the Neo4j Server that takes an already instantiated {@link org.neo4j.kernel.GraphDatabaseAPI}, and optional configuration, and launches a server using that database. Use this to start up a full Neo4j server from within an application that already uses the {@link EmbeddedGraphDatabase} or the {@link HighlyAvailableGraphDatabase}. This gives your application the full benefits of the server's REST API, the Web administration interface and statistics tracking.

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());
        }
    }
}

The application Context definition 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>

I hope this helps.

Manish Singh
  • 3,463
  • 22
  • 21
  • Thanks for this, we have added this stuff in and when we close the application context the lock on the database goes away, it comes back when we get another context. Then when we try and persists new nodes we get the 'Unsatisfied dependency expressed through bean property' error. – Link19 Feb 14 '13 at 09:58
  • When we try and read from it we get: "Lucene index provider has been shut down" – Link19 Feb 14 '13 at 10:23
  • I don't think the call to shutdown() is correct, the methods docs say: Shuts down Neo4j. After this method has been invoked, it's invalid to invoke any methods in the Neo4j API and all references to this instance of GraphDatabaseService should be discarded. – Link19 Feb 14 '13 at 10:41
  • Are you working on HA mode ? Can you share how you are creating index ? This might be a code issue then ... Your understanding is correct about shutdown. – Manish Singh Feb 14 '13 at 10:43
  • What's HA mode? I believe the Index is created using @Index annotation in our entities. – Link19 Feb 14 '13 at 10:49
  • No we have a single application running, it's only used on a single machine. The point is if I call Shutdown() are you saying that re-initiating the spring application context will re-start database. I understand that we are getting the lucene problem because you told us to call shutdown(). – Link19 Feb 14 '13 at 10:59
  • Do you realise that i'm trying to stop and start the NEO server within the same instance of the application. ie My virtual machine does not close. The test should have ctx.close() shutting down neo and then re-starting it and being able to query/save. – Link19 Feb 15 '13 at 11:47
  • Are you using neo4j in EmbeddedDatabase mode ? – Manish Singh Feb 15 '13 at 14:17
  • Doesn't the fact that we are using SpringData Neo4j indicate that we are using Embedded mode? Or am I miss understanding? – Link19 Feb 15 '13 at 16:12
  • To make it more clear, can you update the question with a scenario? For e.g., While starting a spring application (Non web application), Neo4j instances are started and stopped during some transactions. which results in the mentioned error. Pseudo code also might like Transaction 1 - Start neo4j Server - process repository - stop neo4j - do some process - Transaction 2 - start neo4j again - process repository - stop neo4j and exit application. Is this What you are looking for? The Context will help – Manish Singh Feb 16 '13 at 04:32
  • That's exactly it though, and as far as I can see my question does say all that? – Link19 Feb 18 '13 at 17:08
  • So you are saying that it just isn't possible to shut down our way? Ie there's a bug? – Link19 Feb 19 '13 at 09:24
  • If I would have understood your way of doing, There wouldnt have been series of responses :). Does the present answer works for use case ? – Manish Singh Feb 19 '13 at 09:59
  • I don't know, unfortunately I'm not an expert in Neo4J or Spring Data, that's why I'm asking for help. The implementation we use is one that we put together from available resources and when something like that just doesn't work it's difficult to even begin to work out why. I didn't understand the extent of different solutions, so I can't tell you the name of the one we use. Our xml file is hardly useful but I'll post that if it helps. – Link19 Feb 19 '13 at 10:30