14 Replies Latest reply on Jul 28, 2010 12:32 PM by Kurt Stam

    Referential Integrity Exception question

    Kurt Stam Master

      Hi guys,

       

      If I archive all items on a category, and then remove the category like so:

       

      {code}

              RulesRepository repo = getRepo();
              repo.loadCategory( "/" ).addCategory( "testRemoveCategoryWithArchivedCat", "a" );
              AssetItem as = repo.loadDefaultPackage().addAsset( "testRemoveCategoryWithArchivedAsset", "a", "testRemoveCategoryWithArchivedCat", "drl" );
              as.checkin( "a" );

              as.archiveItem(true);

              repo.loadCategory( "testRemoveCategoryWithArchivedCat" ).remove();
              repo.save();

      {code}

       

      then it throws a ReferentialIntegrityException:

       

      org.drools.repository.RulesRepositoryException: javax.jcr.ReferentialIntegrityException
          at org.drools.repository.RulesRepository.save(RulesRepository.java:1149)
          at org.drools.repository.CategoryItemTest.testRemoveCategoryLinkedWithArchived(CategoryItemTest.java:175)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
          at java.lang.reflect.Method.invoke(Method.java:597)
          at junit.framework.TestCase.runTest(TestCase.java:168)
          at junit.framework.TestCase.runBare(TestCase.java:134)
          at junit.framework.TestResult$1.protect(TestResult.java:110)
          at junit.framework.TestResult.runProtected(TestResult.java:128)
          at junit.framework.TestResult.run(TestResult.java:113)
          at junit.framework.TestCase.run(TestCase.java:124)
          at junit.framework.TestSuite.runTest(TestSuite.java:232)
          at junit.framework.TestSuite.run(TestSuite.java:227)
          at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
          at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
          at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
      Caused by: javax.jcr.ReferentialIntegrityException
          at org.modeshape.jcr.JcrSession.checkReferentialIntegrityOfChanges(JcrSession.java:1318)
          at org.modeshape.jcr.JcrSession.save(JcrSession.java:1330)
          at org.drools.repository.RulesRepository.save(RulesRepository.java:1140)
          ... 20 more

       

      Is this the expected behavior? Or can I add a config option to 'cascade delete'?

       

      Thx,

       

      --Kurt

        • 1. Re: Referential Integrity Exception question
          Randall Hauch Master

          It is difficult to say what is going on, since your code is using Guvnor-specific methods and not just the JCR API. For example, I don't know what as.archiveItem(true) does, and I can only assume that as.checkin("a") is a layer on top of JCR versioning.

          • 2. Re: Referential Integrity Exception question
            Kurt Stam Master

            Right, sorry about that. Yes it gets comitted to the repo on checkin, and then the archiveItem sets the archive Flag on this piece of data ('as')

             

            this.node.setProperty(CONTENT_PROPERTY_ARCHIVE_FLAG, data);

             

            This is in the http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/CategoryItemTest.java

            'testRemovecategoryLinkedWithArchived'

             

            Does this help?

            • 3. Re: Referential Integrity Exception question
              Randall Hauch Master

              Does any of this code used during the session make use of JCR 2's shareable nodes feature? If so, that might explain the referential integrity exception. For example, if the code is removing a node from a shared set, then the original are still available (so inward pointing references are still valid).

               

              But since ModeShape does not yet implement the shareable nodes feature, removing a node (that would be in a shared set) might actually result in ModeShape removing the only node with that UUID. Thus, inward pointing references to that UUID will not be valid, and ModeShape throws the ReferentialIntegrityException.

               

              WDYT?

              • 4. Re: Referential Integrity Exception question
                Randall Hauch Master

                I just committed into trunk support for the optional JCR shareable nodes feature (see MODE-794 for the details, including an outline of our design). All of the corresponding TCK unit tests pass, as do the new unit tests I wrote as part of the commit.

                 

                The tricky thing with the shareable nodes feature is that the JCR specification allows for quite a bit of the behavior to be dictated by the implementation. I tried to implement this based upon what I surmise Guvnor is doing (based upon a cursory glance at the code and unit tests) as well as what I'd like to have if I were writing an application using shareable nodes. For example, calling 'remove()' on a shareable node only removes that node; any other nodes in the shared set will remain. Also, the paths of a descendant of the shared set are determined by ModeShape to match where the shareable nodes originated.

                 

                Any chance you can get the latest from SVN, do a full build, and test with Guvnor? I'd love to see what issues (if any) we run into!

                • 5. Re: Referential Integrity Exception question
                  Kurt Stam Master

                  Very cool. I will give it a try and report back! --Kurt

                  • 6. Re: Referential Integrity Exception question
                    Kurt Stam Master

                    Hi Randall,

                     

                    When I upgrade to the latest on the trunk, my code can no longer find:

                     

                    import org.modeshape.jcr.CndNodeTypeSource;

                     

                    which in the ModeShapeRepositoryConfigurator was used for:

                     

                    CndNodeTypeSource newNodeTypes = new CndNodeTypeSource(new String[] {"/node_type_definitions/tag_node_type.cnd",
                                        "/node_type_definitions/state_node_type.cnd", "/node_type_definitions/versionable_node_type.cnd",
                                        "/node_type_definitions/versionable_asset_folder_node_type.cnd", "/node_type_definitions/rule_node_type.cnd",
                                        "/node_type_definitions/rulepackage_node_type.cnd"});

                     

                    Did it move, or am I supposed to do something else?

                     

                    Thx,

                     

                    --Kurt

                    • 7. Re: Referential Integrity Exception question
                      Randall Hauch Master

                      Woa, sorry about that. We just recently refactored that code so that it can use the public JCR API rather than requiring casting to ModeShape interfaces/classes. See MODE-827 for details.

                       

                      I believe your code was this (slight reformatted):

                       

                      {code}CndNodeTypeSource newNodeTypes = new CndNodeTypeSource(new String[] {

                           "/node_type_definitions/tag_node_type.cnd",

                           "/node_type_definitions/state_node_type.cnd",

                           "/node_type_definitions/versionable_node_type.cnd",

                           "/node_type_definitions/versionable_asset_folder_node_type.cnd",

                           "/node_type_definitions/rule_node_type.cnd",

                           "/node_type_definitions/rulepackage_node_type.cnd"});

                      ((JcrNodeTypeManager)ws.getNodeTypeManager()).registerNodeTypes(newNodeTypes);

                      {code}

                       

                      This can be replaced with this new code that does use a ModeShape-specific class to read the CND files, but the actual registration is done using the standard JCR 2.0 API:

                       

                      {code}

                      CndNodeTypeReader reader = new CndNodeTypeReader(session);

                      reader.read("/node_type_definitions/tag_node_type.cnd");

                      reader.read("/node_type_definitions/state_node_type.cnd");

                      reader.read("/node_type_definitions/versionable_node_type.cnd");

                      reader.read("/node_type_definitions/versionable_asset_folder_node_type.cnd");

                      reader.read("/node_type_definitions/rule_node_type.cnd");

                      reader.read("/node_type_definitions/rulepackage_node_type.cnd");

                      ws.getNodeTypeManager().registerNodeTypes(reader.getNodeTypeDefinitions(),false);

                      {code}

                      • 8. Re: Referential Integrity Exception question
                        Kurt Stam Master

                        Right, i think I need to use:

                         

                        CndNodeTypeReader newNodeTypes = new CndNodeTypeReader(session);

                         

                        Since the default constructor seems missing.

                         

                        --Kurt

                        • 9. Re: Referential Integrity Exception question
                          Randall Hauch Master

                          Right, i think I need to use:

                           

                          CndNodeTypeReader newNodeTypes = new CndNodeTypeReader(session);

                           

                          Since the default constructor seems missing.

                          Yup. I'll correct my post.

                          • 10. Re: Referential Integrity Exception question
                            Kurt Stam Master

                            With the 2.1-SNAPSHOT, the public void testRemoveCategoryLinkedWithArchived of the CategoryItem test is still giving me

                             

                            org.drools.repository.RulesRepositoryException: javax.jcr.ReferentialIntegrityException
                                at org.drools.repository.RulesRepository.save(RulesRepository.java:1149)
                                at org.drools.repository.CategoryItemTest.testRemoveCategoryLinkedWithArchived(CategoryItemTest.java:175)
                                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                                at java.lang.reflect.Method.invoke(Method.java:597)
                                at junit.framework.TestCase.runTest(TestCase.java:168)
                                at junit.framework.TestCase.runBare(TestCase.java:134)
                                at junit.framework.TestResult$1.protect(TestResult.java:110)
                                at junit.framework.TestResult.runProtected(TestResult.java:128)
                                at junit.framework.TestResult.run(TestResult.java:113)
                                at junit.framework.TestCase.run(TestCase.java:124)
                                at junit.framework.TestSuite.runTest(TestSuite.java:232)
                                at junit.framework.TestSuite.run(TestSuite.java:227)
                                at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
                                at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
                                at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
                                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
                                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
                                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
                                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
                            Caused by: javax.jcr.ReferentialIntegrityException
                                at org.modeshape.jcr.JcrSession.checkReferentialIntegrityOfChanges(JcrSession.java:1318)
                                at org.modeshape.jcr.JcrSession.save(JcrSession.java:1330)
                                at org.drools.repository.RulesRepository.save(RulesRepository.java:1140)
                                ... 20 more

                             

                            I will try to create a test which just uses JCR and remove the drools stuff.

                             

                            --Kurt

                            • 11. Re: Referential Integrity Exception question
                              Randall Hauch Master

                              Are you still getting a lot of exceptions?

                              • 12. Re: Referential Integrity Exception question
                                Kurt Stam Master

                                Yes most of the tests fail: Tests run: 172, Failures: 5, Errors: 128, Skipped: 0

                                 

                                So I'm trying just to just getting a few fixed, I'm hoping it will turn up something that will fix a lot of them..

                                 

                                --K

                                • 13. Re: Referential Integrity Exception question
                                  Randall Hauch Master

                                  I got the Guvnor codebase checked out and built locally, modified it with the patch to get it running against ModeShape, and was able to debug the test cases. This helped me realize an error in how shareable nodes are materialized from the persistent store, so I've reopened MODE-794 and will work on a fix first thing tomorrow. Stay tuned.