Hot questions for Using Neo4j in jqassistant

Top Java Programmings / Neo4j / jqassistant

Question:

I have used jQAssistant to fill a Neo4j database with information about java artifacts.

Now I want to find the latest version of some artifact fulfilling some conditions. At first glance, I could use max(a.version) on the version property of an artifact. But artifact versions are not ordered by the usual String order, but actually 1.10.0 is a later version than 1.2.0.

How could I implement or use a custom ordering scheme like the one described above?


Answer:

How about that for version numbers (major, minor and patch) to have their nodes? Something like that:

// Major
MERGE (M0:Semver:Major {v: 0}) 
MERGE (M1:Semver:Major {v: 1})
// Minor
MERGE (Mi0: Semver:Minor {v: 0 }) 
MERGE (Mi2: Semver:Minor {v: 2 }) 
MERGE (Mi10:Semver:Minor {v: 10})
// Patch
MERGE (P0:Semver:Patch {v:0}) 
MERGE (P2:Semver:Patch {v:2})

// Artifacts
MERGE (A1:Artifact {name:'Artifact 13afd'})
MERGE (A2:Artifact {name:'Artifact asdfk'})
MERGE (A3:Artifact {name:'Artifact 09sd2'})
MERGE (A4:Artifact {name:'Artifact skw30'})

// Versioning
MERGE (A1)-[:semver]->(M0) MERGE (A1)-[:semver]->(Mi0 ) MERGE (A1)-[:semver]->(P0)
MERGE (A2)-[:semver]->(M0) MERGE (A2)-[:semver]->(Mi0 ) MERGE (A2)-[:semver]->(P2)
MERGE (A3)-[:semver]->(M1) MERGE (A3)-[:semver]->(Mi2 ) MERGE (A3)-[:semver]->(P0)
MERGE (A4)-[:semver]->(M1) MERGE (A4)-[:semver]->(Mi10) MERGE (A4)-[:semver]->(P0)

RETURN *;

And the desired query:

MATCH  (A:Artifact)-[:semver]->(Mj:Semver:Major),
       (A         )-[:semver]->(Mi:Semver:Minor),
       (A         )-[:semver]->(Pt:Semver:Patch)
RETURN A.name,  Mj.v,     Mi.v,     Pt.v
       ORDER BY Mj.v asc, Mi.v asc, Pt.v asc

Question:

I would like to implement some naming conventions with the help of jQAssistant. All classes implementing the PropertyConverter interface should have names ending with Converter. This rule does not apply to anonymous inner classes. Now I have two queries. This one returns all classes violating the naming rule:

MATCH   (t:Type)-[:IMPLEMENTS]->(i:Type) 
WHERE   i.fqn='PropertyConverter' And
NOT     t.name =~ '.*Converter'
RETURN  t.fqn

But this query also returns inner classes which have names like ABC$1. I can find these classes with the following query:

 MATCH  (t:Type)-[:IMPLEMENTS]->(i:Type)
 WHERE  i.fqn='org.apache.tamaya.PropertyConverter'
        AND NOT t.name =~ '.*Converter'
 WITH   t
 MATCH  (h:Type)-[:DECLARES]->(t)
 RETURN distinct t.fqn, h.fqn

But I was unable to combine both queries so that I will get only the results of the first query which are not contained in the second result set.

How can I combine both queries?


Answer:

The best approach would be using the pre-defined concept to identify anonymous inner types ("java:AnonymousInnerType"). It comes with the Java plugin and would make your constraint look like this:

<constraint id="...">
  <requiresConcept refId="java:AnonymousInnerType" />
  <description>All classes implementing the PropertyConverter interface must have the suffix "Converter".</description>
  <cypher>
    MATCH 
      (t:Type)-[:IMPLEMENTS]->(i:Type)
    WHERE
      i.fqn='PropertyConverter'
      and not t:Anonymous:Inner
      and not t.name =~ '.*Converter'
    RETURN
      t.fqn
  </cypher>
</constraint>

Question:

I know that I can use something like

jqassistant.cmd scan -u maven:repository::http://ik-repo1:8084/nexus/content/repositories/releases

to incrementally scan a Maven repository and that

jqassistant.cmd server -serverAddress 123.321.0.0 -serverPort 8088

allows me to access the attached neo4j database through a server.

Now I would like to scan the repository regularly (say: once a day) and run the server all day (so that everybody can look up and query software structures).

I could not find an option to run the server as a (Windows) service. Furthermore, it seems to be impossible to run "scan" and "server" at the same time.

My best idea so far is to write a little service in java which runs the following loop:

  1. Start server and wait until midnight.
  2. Stop server.
  3. Do an incremental scan.

Any better ideas?


Answer:

The current jQAssistant runtime model is designed around invoking it as a task or plugin within a build process but not for the described "24/7 server" use case. So your described approach is currently the only solution.

Nevertheless there are user requests to support this scenario and we have some ideas in our heads how this could look like, e.g. jQAssistant as a Neo4j server extension providing REST interfaces to trigger scans and analysis tasks - discussion about this including potential use cases would be highly appreciated!

Best regards,

Dirk

Question:

I want to write a Cypher rule for jQAssistant that checks whether all public EJB methods are annoated with either @RolesAllowed or @PermitAll.

Is this possible? Since I'm new to the Cypher query language of Neo4j I have problems formulating the "not exists" condition in Cypher to find "all public methods in EJB classes (= classes that have the @Stateless annotation) that are not annotated with @RolesAllowed or @PermitAll".


Answer:

The trick is putting the not exists part in where clause, e.g.

match
  (:Stateless)-[:DECLARES]->(m:Method)
where
  m.visibility ="public"
  and not (
    (m)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(:Type{fqn:"...PermitAll")
    or
    ... 
  )
return
  m

Hope this illustrates the idea, it's quite difficult to write this stuff on a tablet. I can give you a more advanced example next week.