jQAssistant / jqassistant

Your Software. Your Structures. Your Rules.
https://jqassistant.org/
GNU General Public License v3.0
198 stars 35 forks source link

scan fails with 'More than one relationship' #76

Closed stevensmi closed 9 years ago

stevensmi commented 10 years ago

Ttesting the current master (commit 624be1cfe3af8cd7e5c3fc7694032d03d9d48e51) show a failure when scanning.

Looking at the half build database with "match (s) where id(s) = 282 return s;" there is a Node[282] with the following content: [{"fqn":"de.wingas.trayport.jaxb.ActionType","name":"ActionType","fileName":"/de/wingas/trayport/jaxb/ActionType.class","visibility":"public","final":true}],"graph":{"nodes":[{"id":"282","labels":["File","Type","Enum"],"properties":{"fqn":"de.wingas.trayport.jaxb.ActionType","name":"ActionType","fileName":"/de/wingas/trayport/jaxb/ActionType.class","visibility":"public","final":true}}]

The 'OUTGOING" realtionship does not appear on this node so I not sure I am looking in the right place. Any ideas how best to debug jqassistant. I could simply bisect from the M2 release to find where problem started to occur.

[ERROR] Failed to execute goal com.buschmais.jqassistant.scm:jqassistant-maven-plugin:1.0.0-M3-SNAPSHOT:scan (default-cli) on project Gv8interop: Execution default-cli of goal com.buschmais.jqassistant.scm:jqassistant-maven-plugin:1.0.0-M3-SNAPSHOT:scan failed: More than one relationship[EXTENDS, OUTGOING] found for Node[282] -> [Help 1] org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal com.buschmais.jqassistant.scm:jqassistant-maven-plugin:1.0.0-M3-SNAPSHOT:scan (default-cli) on project Gv8interop: Execution default-cli of goal com.buschmais.jqassistant.scm:jqassistant-maven-plugin:1.0.0-M3-SNAPSHOT:scan failed: More than one relationship[EXTENDS, OUTGOING] found for Node[282] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:225) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59) at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183) at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161) at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320) at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156) at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537) at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196) at org.apache.maven.cli.MavenCli.main(MavenCli.java:141) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290) at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230) at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409) at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352) Caused by: org.apache.maven.plugin.PluginExecutionException: Execution default-cli of goal com.buschmais.jqassistant.scm:jqassistant-maven-plugin:1.0.0-M3-SNAPSHOT:scan failed: More than one relationship[EXTENDS, OUTGOING] found for Node[282] at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:110) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209) ... 19 more Caused by: org.neo4j.graphdb.NotFoundException: More than one relationship[EXTENDS, OUTGOING] found for Node[282] at org.neo4j.kernel.impl.core.NodeProxy.getSingleRelationship(NodeProxy.java:232) at com.buschmais.xo.neo4j.impl.datastore.Neo4jRelationManager.getSingleRelation(Neo4jRelationManager.java:62) at com.buschmais.xo.neo4j.impl.datastore.Neo4jRelationManager.getSingleRelation(Neo4jRelationManager.java:16) at com.buschmais.xo.impl.EntityPropertyManager.createSingleReference(EntityPropertyManager.java:172) at com.buschmais.xo.impl.EntityPropertyManager.createRelation(EntityPropertyManager.java:157) at com.buschmais.xo.impl.EntityPropertyManager.createEntityReference(EntityPropertyManager.java:39) at com.buschmais.xo.impl.proxy.entity.property.EntityReferencePropertySetMethod.invoke(EntityReferencePropertySetMethod.java:15) at com.buschmais.xo.impl.proxy.AbstractProxyMethodService.invoke(AbstractProxyMethodService.java:21) at com.buschmais.xo.impl.proxy.InstanceInvocationHandler.invoke(InstanceInvocationHandler.java:23) at com.sun.proxy.$Proxy115.setSuperClass(Unknown Source) at com.buschmais.jqassistant.plugin.java.impl.scanner.visitor.ClassSignatureVisitor$1.visitEnd(ClassSignatureVisitor.java:45) at com.buschmais.jqassistant.plugin.java.impl.scanner.visitor.AbstractTypeSignatureVisitor.visitEnd(AbstractTypeSignatureVisitor.java:62) at org.objectweb.asm.signature.SignatureReader.a(Unknown Source) at org.objectweb.asm.signature.SignatureReader.accept(Unknown Source) at com.buschmais.jqassistant.plugin.java.impl.scanner.visitor.ClassVisitor.visit(ClassVisitor.java:58) at org.objectweb.asm.ClassReader.accept(Unknown Source) at org.objectweb.asm.ClassReader.accept(Unknown Source) at com.buschmais.jqassistant.plugin.java.impl.scanner.ClassFileScannerPlugin.scan(ClassFileScannerPlugin.java:56) at com.buschmais.jqassistant.plugin.java.impl.scanner.ClassFileScannerPlugin.scan(ClassFileScannerPlugin.java:24) at com.buschmais.jqassistant.core.scanner.impl.ScannerImpl$1.map(ScannerImpl.java:43) at com.buschmais.jqassistant.core.scanner.impl.ScannerImpl$1.map(ScannerImpl.java:36) at com.buschmais.jqassistant.core.scanner.api.iterable.MappingIterable$1.next(MappingIterable.java:27) at com.buschmais.jqassistant.core.scanner.api.iterable.AggregatingIterable$1.hasNext(AggregatingIterable.java:24) at com.buschmais.jqassistant.core.scanner.api.iterable.AggregatingIterable$1.hasNext(AggregatingIterable.java:23) at com.buschmais.jqassistant.core.scanner.api.iterable.AggregatingIterable$1.hasNext(AggregatingIterable.java:23) at com.buschmais.jqassistant.core.scanner.api.iterable.MappingIterable$1.hasNext(MappingIterable.java:20) at com.buschmais.jqassistant.core.scanner.api.iterable.AggregatingIterable$1.hasNext(AggregatingIterable.java:23) at com.buschmais.jqassistant.core.scanner.api.iterable.IterableConsumer.consume(IterableConsumer.java:17) at com.buschmais.jqassistant.core.scanner.api.iterable.IterableConsumer.consume(IterableConsumer.java:13) at com.buschmais.jqassistant.plugin.maven3.impl.scanner.impl.scanner.MavenProjectMavenScannerPlugin.scanClassesDirectory(MavenProjectMavenScannerPlugin.java:183) at com.buschmais.jqassistant.plugin.maven3.impl.scanner.impl.scanner.MavenProjectMavenScannerPlugin.scan(MavenProjectMavenScannerPlugin.java:58) at com.buschmais.jqassistant.plugin.maven3.impl.scanner.impl.scanner.MavenProjectMavenScannerPlugin.scan(MavenProjectMavenScannerPlugin.java:35) at com.buschmais.jqassistant.core.scanner.impl.ScannerImpl$1.map(ScannerImpl.java:43) at com.buschmais.jqassistant.core.scanner.impl.ScannerImpl$1.map(ScannerImpl.java:36) at com.buschmais.jqassistant.core.scanner.api.iterable.MappingIterable$1.next(MappingIterable.java:27) at com.buschmais.jqassistant.core.scanner.api.iterable.AggregatingIterable$1.hasNext(AggregatingIterable.java:24) at com.buschmais.jqassistant.core.scanner.api.iterable.IterableConsumer.consume(IterableConsumer.java:17) at com.buschmais.jqassistant.core.scanner.api.iterable.IterableConsumer.consume(IterableConsumer.java:13) at com.buschmais.jqassistant.scm.maven.ScanMojo.aggregate(ScanMojo.java:41) at com.buschmais.jqassistant.scm.maven.AbstractAnalysisMojo$1.execute(AbstractAnalysisMojo.java:132) at com.buschmais.jqassistant.scm.maven.Aggregator.execute(Aggregator.java:46) at com.buschmais.jqassistant.scm.maven.AbstractAnalysisMojo.execute(AbstractAnalysisMojo.java:121) at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101) ... 20 more

DirkMahler commented 10 years ago

I've seen this problem last week, the reason was that the scanned multi-module project contained two classes with the same fully qualified name. Can you verify if this is the same cause for you?

DirkMahler commented 10 years ago

The problem can be reproduced if two enumeration classes with the same qualified name (e.g. com.buschmais.jqassistant.demo.MyEnum) exist and are scanned in the same run.

stevensmi commented 10 years ago

Thanks for the feedback. Root cause was the same. Duplicate classes with the same FQN. In this case my maven build process was includeding idetical classes in classes and test-classes!

I guess I should look at the error handling the case of duplicates and see if I can contribute a patch.

DirkMahler commented 10 years ago

Thanks for the confirmation! There are two problems with it:

  1. I don't understand why exactly this Exception happens - I'd expect that the current implementation would overwrite it without complaining. I'll analyze that.
  2. It could be a valid case that two classes with the same fully qualified name exist, i.e. if they come from different modules and are packaged into different deployable artifacts (e.g. different WAR or EAR files). Actually I don't like this idea but it might happen and could be the case if someone starts using jQAssistant on a legacy project. The implication of supporting this in a meaningful way is quite big: the data model must be changed such that references between types (e.g. EXTENDS, INVOKES, etc) are only resolved within the scope of the same artifact. Using concepts and the knowledge about deployble units the actual relations could be established later - but this makes it harder to write rules. Maybe this should be a configurable option.
DirkMahler commented 10 years ago

The exception happens because jQAssistant tries to update the EXTENDS relationship of an enum type, for some (still unknown) reason Neo4j 2.1.x reports that more than one relation already exists. After downgrading to Neo4j 2.0.3 the exception is no longer thrown, the scan finishes but the resulting node representing the enum type is a mix of both scanned classes.

DirkMahler commented 9 years ago

Types are now resolved in the context of the artifact they are contained in, this means that the same class may exist in different artifacts (e.g. JAR files)