0

I'd like to install the following triggers with Liquigraph changeset:

<changeset id="create_decision_characteristic_value_relationship_trigger">
    <query>CALL apoc.trigger.add('HAS_VALUE_ON_ADD_TO_INDEX', 'UNWIND {createdRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(ch:Characteristic) CALL apoc.index.addRelationship(r, keys(r)) RETURN count(*)', {phase:'after'});</query>
    <query>CALL apoc.trigger.add('HAS_VALUE_ON_REMOVE_FROM_INDEX', "UNWIND {deletedRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(Characteristic) CALL apoc.index.removeRelationshipByName('HAS_VALUE_ON', r) RETURN count(*)", {phase:'after'});</query>
</changeset>

but the application fails with the following exception:

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:107)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:242)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'neo4jAuditionBeanFactoryPostProcessor': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [com/decisionwanted/domain/configuration/Neo4jConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.neo4j.ogm.session.SessionFactory]: Factory method 'sessionFactory' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquigraph' defined in class path resource [org/liquigraph/spring/starter/LiquigraphAutoConfiguration$LiquigraphConfiguration.class]: Invocation of init method failed; nested exception is java.lang.RuntimeException: java.sql.SQLException: Some errors occurred : 
[Neo.ClientError.Statement.SyntaxError]:Invalid input 'H': expected whitespace, '.', node labels, '[', "=~", IN, STARTS, ENDS, CONTAINS, IS, '^', '*', '/', '%', '+', '-', '=', "<>", "!=", '<', '>', "<=", ">=", AND, XOR, OR, ',' or ')' (line 1, column 189 (offset: 188))
"CALL apoc.trigger.add('HAS_VALUE_ON_REMOVE_FROM_INDEX', 'UNWIND {deletedRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(Characteristic) CALL apoc.index.removeRelationshipByName('HAS_VALUE_ON', r) RETURN count(*)', {phase:'after'});"
                                                                                                                                                                                             ^

    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:729)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1270)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:238)
    at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:709)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:534)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:388)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:327)
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:138)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117)
    ... 26 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [com/decisionwanted/domain/configuration/Neo4jConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.neo4j.ogm.session.SessionFactory]: Factory method 'sessionFactory' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquigraph' defined in class path resource [org/liquigraph/spring/starter/LiquigraphAutoConfiguration$LiquigraphConfiguration.class]: Invocation of init method failed; nested exception is java.lang.RuntimeException: java.sql.SQLException: Some errors occurred : 
[Neo.ClientError.Statement.SyntaxError]:Invalid input 'H': expected whitespace, '.', node labels, '[', "=~", IN, STARTS, ENDS, CONTAINS, IS, '^', '*', '/', '%', '+', '-', '=', "<>", "!=", '<', '>', "<=", ">=", AND, XOR, OR, ',' or ')' (line 1, column 189 (offset: 188))
"CALL apoc.trigger.add('HAS_VALUE_ON_REMOVE_FROM_INDEX', 'UNWIND {deletedRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(Characteristic) CALL apoc.index.removeRelationshipByName('HAS_VALUE_ON', r) RETURN count(*)', {phase:'after'});"
                                                                                                                                                                                             ^

    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:587)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1250)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:815)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:721)
    ... 44 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.neo4j.ogm.session.SessionFactory]: Factory method 'sessionFactory' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquigraph' defined in class path resource [org/liquigraph/spring/starter/LiquigraphAutoConfiguration$LiquigraphConfiguration.class]: Invocation of init method failed; nested exception is java.lang.RuntimeException: java.sql.SQLException: Some errors occurred : 
[Neo.ClientError.Statement.SyntaxError]:Invalid input 'H': expected whitespace, '.', node labels, '[', "=~", IN, STARTS, ENDS, CONTAINS, IS, '^', '*', '/', '%', '+', '-', '=', "<>", "!=", '<', '>', "<=", ">=", AND, XOR, OR, ',' or ')' (line 1, column 189 (offset: 188))
"CALL apoc.trigger.add('HAS_VALUE_ON_REMOVE_FROM_INDEX', 'UNWIND {deletedRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(Characteristic) CALL apoc.index.removeRelationshipByName('HAS_VALUE_ON', r) RETURN count(*)', {phase:'after'});"
                                                                                                                                                                                             ^

    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:579)
    ... 57 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquigraph' defined in class path resource [org/liquigraph/spring/starter/LiquigraphAutoConfiguration$LiquigraphConfiguration.class]: Invocation of init method failed; nested exception is java.lang.RuntimeException: java.sql.SQLException: Some errors occurred : 
[Neo.ClientError.Statement.SyntaxError]:Invalid input 'H': expected whitespace, '.', node labels, '[', "=~", IN, STARTS, ENDS, CONTAINS, IS, '^', '*', '/', '%', '+', '-', '=', "<>", "!=", '<', '>', "<=", ">=", AND, XOR, OR, ',' or ')' (line 1, column 189 (offset: 188))
"CALL apoc.trigger.add('HAS_VALUE_ON_REMOVE_FROM_INDEX', 'UNWIND {deletedRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(Characteristic) CALL apoc.index.removeRelationshipByName('HAS_VALUE_ON', r) RETURN count(*)', {phase:'after'});"
                                                                                                                                                                                             ^

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1710)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:583)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.resolveBeanReference(ConfigurationClassEnhancer.java:392)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:364)
    at com.decisionwanted.domain.configuration.Neo4jConfig$$EnhancerBySpringCGLIB$$7e91e1f.configuration(<generated>)
    at com.decisionwanted.domain.configuration.Neo4jConfig.sessionFactory(Neo4jConfig.java:42)
    at com.decisionwanted.domain.configuration.Neo4jConfig$$EnhancerBySpringCGLIB$$7e91e1f.CGLIB$sessionFactory$3(<generated>)
    at com.decisionwanted.domain.configuration.Neo4jConfig$$EnhancerBySpringCGLIB$$7e91e1f$$FastClassBySpringCGLIB$$cc165cbf.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:361)
    at com.decisionwanted.domain.configuration.Neo4jConfig$$EnhancerBySpringCGLIB$$7e91e1f.sessionFactory(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    ... 58 more
Caused by: java.lang.RuntimeException: java.sql.SQLException: Some errors occurred : 
[Neo.ClientError.Statement.SyntaxError]:Invalid input 'H': expected whitespace, '.', node labels, '[', "=~", IN, STARTS, ENDS, CONTAINS, IS, '^', '*', '/', '%', '+', '-', '=', "<>", "!=", '<', '>', "<=", ">=", AND, XOR, OR, ',' or ')' (line 1, column 189 (offset: 188))
"CALL apoc.trigger.add('HAS_VALUE_ON_REMOVE_FROM_INDEX', 'UNWIND {deletedRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(Characteristic) CALL apoc.index.removeRelationshipByName('HAS_VALUE_ON', r) RETURN count(*)', {phase:'after'});"
                                                                                                                                                                                             ^

    at com.google.common.base.Throwables.propagate(Throwables.java:241)
    at org.liquigraph.core.io.ChangelogGraphWriter.executeStatement(ChangelogGraphWriter.java:102)
    at org.liquigraph.core.io.ChangelogGraphWriter.write(ChangelogGraphWriter.java:79)
    at org.liquigraph.core.api.MigrationRunner.writeApplicableChangesets(MigrationRunner.java:109)
    at org.liquigraph.core.api.MigrationRunner.runMigrations(MigrationRunner.java:80)
    at org.liquigraph.core.api.Liquigraph.runMigrations(Liquigraph.java:63)
    at org.liquigraph.spring.SpringLiquigraph.afterPropertiesSet(SpringLiquigraph.java:52)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1769)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1706)
    ... 80 more
Caused by: java.sql.SQLException: Some errors occurred : 
[Neo.ClientError.Statement.SyntaxError]:Invalid input 'H': expected whitespace, '.', node labels, '[', "=~", IN, STARTS, ENDS, CONTAINS, IS, '^', '*', '/', '%', '+', '-', '=', "<>", "!=", '<', '>', "<=", ">=", AND, XOR, OR, ',' or ')' (line 1, column 189 (offset: 188))
"CALL apoc.trigger.add('HAS_VALUE_ON_REMOVE_FROM_INDEX', 'UNWIND {deletedRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(Characteristic) CALL apoc.index.removeRelationshipByName('HAS_VALUE_ON', r) RETURN count(*)', {phase:'after'});"
                                                                                                                                                                                             ^

    at org.neo4j.jdbc.http.HttpNeo4jStatement.execute(HttpNeo4jStatement.java:58)
    at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:95)
    at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java)
    at org.liquigraph.core.io.ChangelogGraphWriter.executeChangesetQueries(ChangelogGraphWriter.java:110)
    at org.liquigraph.core.io.ChangelogGraphWriter.executeStatement(ChangelogGraphWriter.java:96)
    ... 87 more

This is strange because I'm able to install successfully these triggers manually, for example via Neo4j Web Browser.

How to properly install these triggers via Liquigraph changeset ?

UPDATED

The following trigger declaration is causing the issue.

<query>CALL apoc.trigger.add('HAS_VALUE_ON_REMOVE_FROM_INDEX', "UNWIND {deletedRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(Characteristic) CALL apoc.index.removeRelationshipByName('HAS_VALUE_ON', r) RETURN count(*)", {phase:'after'});</query>

The first trigger works fine with Liquigraph.

I have also tried the solution with CDATA:

<query><![CDATA[CALL apoc.trigger.add('RELATIONSHIP_INDEX_ADD_HAS_VALUE_ON', 'UNWIND {createdRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(ch:Characteristic) CALL apoc.index.addRelationship(r, keys(r)) RETURN count(*)', {phase:'after'});]]></query>
<query><![CDATA[CALL apoc.trigger.add('RELATIONSHIP_INDEX_REMOVE_HAS_VALUE_ON', "UNWIND {deletedRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(ch:Characteristic) CALL apoc.index.removeRelationshipByName('HAS_VALUE_ON', r) RETURN count(*)", {phase:'after'});]]></query>

but it still doesn't work with the same issue.

Please note that the first trigger:

 <query>CALL apoc.trigger.add('HAS_VALUE_ON_ADD_TO_INDEX', 'UNWIND {createdRelationships} AS r MATCH (d:Decision)-[r:HAS_VALUE_ON]->(ch:Characteristic) CALL apoc.index.addRelationship(r, keys(r)) RETURN count(*)', {phase:'after'});</query>

works fine even without CDATA section so looks like Liquigraph doesn't like something with the second trigger declaration.

alexanoid
  • 24,051
  • 54
  • 210
  • 410

1 Answers1

1

You must wrap your queries in <![CDATA[ and ]]>, otherwise the relationship arrows will be interpreted by the XML parser.

Update: the underlying JDBC driver for HTTP had a bug regarding query sanitization, which is now merged: https://github.com/neo4j-contrib/neo4j-jdbc/pull/129. You can build branch 3.3 of the JDBC HTTP driver and then the master branch of Liquigraph if you want to test the fix before the next release.

fbiville
  • 8,407
  • 7
  • 51
  • 79
  • please see my updated question. I tried CDATA section but it still doesn't work with the same issue. Looks like Liquigraph doesn't like something with the second trigger declaration. – alexanoid Mar 12 '18 at 16:33
  • Hi @alexanoid, have you been able to try the fix? You can build https://github.com/neo4j-contrib/neo4j-jdbc/tree/3.3 locally and try! – fbiville Apr 06 '18 at 04:51
  • Hi, @Rolf Unfortunately I'm still waiting for neo4j-jdbc release in order to verify the fix. Do you have an idea when it can be released in Maven central? – alexanoid Apr 08 '18 at 16:20