Announcement Announcement Module
Collapse
No announcement yet.
@PostConstruct with Neo4j Spring Data, still not working. Show stopper for me now Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • @PostConstruct with Neo4j Spring Data, still not working. Show stopper for me now

    Hi guys, I am still having issues running my @PostConstruct method that prepopulates my Neo4j db with some seed data. It appears that there is some stuff that is needed that isn't going to be available in an init method like an @PostConstruct.

    Whether I am in an integration Junit test, or deploying in Tomcat. My init method is using my Spring Data Repositories I created. It runs without an exception, but looking at the data in the db, all the field values are null. But if I use the same code, with repositories in a unit test to insert data, it inserts the data and I am able to retrieve the data. Now it is still within the same tx context that I used to save as I do load, so it could be cached, instead of retrieving from the db.

    So my guess is that it is creating a new node in the database, but the values of my fields are not stored, just as null.

    Thanks

    Mark
    Last edited by bytor99999; Jan 13th, 2012, 03:43 PM. Reason: Further testing reveals more an issue I have, but still trying to find it.

  • #2
    This is a bit frustrating, Sometimes it stores it sometimes it doesn't. But it never saved it in the @PostConstruct. It should work in the @PostConstruct, but the closest I get that might have worked throughs exception saying there isn't a Transaction, even though that method is also annotated with @Transactional.

    If I take the approach of calling the method later, it puts the data into the database. So I have the workaround working. I think, now to try in Tomcat.

    Thanks

    Mark

    Comment


    • #3
      Did you try the depends-on ?

      I think the issue here is that postconstruct is part of the container-setup-lifecycle and not the application lifecycle. So some things are only partly set up at this moment, and with the depends-on you should try to move your component instantiation to the latest moment possible.

      Please have also a look at this issue: https://jira.springsource.org/browse/DATAGRAPH-94

      Comment


      • #4
        Originally posted by MichaelHunger View Post
        Did you try the depends-on ?
        Yes, and I posted my results a few days ago in the other thread I have. It did not work. At this point, the hack of creating a URL for populating the data is working for me and I can move on to my html css and javascript code. But the Jira you posted is exactly what I am having as an issue, but the depends on did not work for me, iirc in the other thread I posted that I got a bean not found exception when depending on @DependsOn("neo4jNodeBacking")

        Thanks Michael for your help. I know it sounds like I am harping on this, but it is really just a small thing for me right now, but is stopping my progress. Once I get my html and registration page working, I really won't need the @PostConstruct anymore. And everything else that you have done on this project is fantastic.

        Mark

        Comment


        • #5
          It looks like I didn't post the stacktrace in the other thread, but it was that it can't find neo4jNodeBacking bean. Here is the exception.

          Code:
          Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'neo4jNodeBacking' is defined
          	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:529)
          	at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1095)
          	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:277)
          	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
          	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
          	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
          	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
          	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
          	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
          	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:103)
          	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
          	at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228)
          	at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124)
          	at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)
          	... 27 more

          Comment


          • #6
            Hi,
            I ran into the same issue.
            I tried the @DependsOn({ "neo4jNodeBacking", "transactionManager" }) suggestion, but it didn't help.
            Any other suggestions?

            Comment


            • #7
              Nope. I had to do without using @PostConstruct. Basically those other beans it needs hadn't been created yet. So I went without it where I manually call my method. First way was with a URL mapping that I use in my browser which calls my Controller which calls my method. The other was in testing where I instantiate my object then call the method manually.

              Mark

              Comment


              • #8
                This should have helped, can you by chance share a minimal project setup that shows this issue?

                Thanks a lot

                Michael

                Comment


                • #9
                  Hi Michael,
                  These are the Details:

                  I have a class named "AppAdmin" which is annotated with @NodeEntity.
                  I wanted to create a service ("InitModel "), that checks on server start-up if the DB contains an AppAdmin object, and if not, create one and persist it.



                  Code:
                  @Service
                  public class InitModel {
                  
                  	@Autowired
                  	private AppAdminDao appAdminDao;
                  
                  
                  	
                  	/**
                  	 * Create an AppAdmin, if there isn't such already
                  	 */
                  	@PostConstruct
                  	private void initAppAdmin() {
                  
                  		AppAdmin admin = appAdminDao.getAppAdmin();
                  		if (admin == null) {
                  			admin = new AppAdmin("admin", "[email protected]", "123456");  //(username, email, password)
                  			admin.persist(); //this line throws NullPointerException
                  
                  		}
                  
                  	}
                  
                  }
                  This is the getAppAdmin method:
                  Code:
                      @Autowired
                  	private IAppAdminRepo appAdminRepo; //IAppAdminRepo is an interface that extends GraphRepository,RelationshipOperationsRepository
                  
                  	/**
                  	 * 
                  	 * @return the appAdmin or null if there is no appAdmin
                  	 */
                  	public AppAdmin getAppAdmin() {
                  
                  		AppAdmin admin = null;
                  		Collection<AppAdmin> admins = IteratorUtil.asCollection(appAdminRepo.findAll());
                  		List<AppAdmin> adminsList = new ArrayList<AppAdmin>(admins);
                  
                  		if (adminsList.size() == 0) {
                  
                  			log.warn("The DB doesn't contain an App-Admin!");
                  			return null;
                  
                  		} else {
                  
                  			admin = adminsList.get(0);
                  
                  			if (admins.size() > 1) {
                  				log.error("The DB contains more than one App-Admin, using the first one (" + admin.getUsername() + ")");
                  			}
                  
                  		}
                  
                  		return admin;
                  
                  	}
                  I also tried to add @DependsOn({ "neo4jNodeBacking", "transactionManager" } to InitModel service, but it didn't help.
                  When I changed the InitModel class to be a @Controller instead of @Service, everything worked well, I guess that's because the controllers are the last to be loaded.
                  Last edited by lironn; Feb 20th, 2012, 03:55 PM.

                  Comment


                  • #10
                    Temporary solution

                    Hi

                    I'm also bugged by this bug because I'm trying to have a sort of managed schema (schema on NoSQL, heresy!), but I found a workaround. Make your populator service implement ApplicationListener<ContextRefreshedEvent> and call the populate method from onApplicationEvent(ContextRefreshedEvent event). When the event is called, the context is ready for you.

                    cheers
                    Alberto

                    Comment


                    • #11
                      Good point Alberto, should probably make it into the docs, wdyt ?

                      Michael

                      Comment


                      • #12
                        For now as a workaround (with a bug ticket) perhaps, but I think the optimal solution is that bean creation in SDG should be strictly ordered in such a way that other (service-layer) beans can @DependOn. In my case, I would like to make my schema manager depend on SDG, and the business/view layer on the schema manager. With the workaround the @Controllers can start serving requests when the pre-population hasn't finished.

                        Alberto

                        Originally posted by MichaelHunger View Post
                        Good point Alberto, should probably make it into the docs, wdyt ?

                        Michael

                        Comment


                        • #13
                          I am experiencing the same issue ! I am on spring mvc 3.06.

                          I should also say that implementing InitializingBean doesnt work either for some reason. afterPropertiesSet is not being fired ...

                          Comment


                          • #14
                            Alberto,

                            thanks for sharing it. There is an open issue that will hopefully make the setup behave better when finished.

                            Cheers

                            Michael

                            Comment

                            Working...
                            X