Scanning your Java app with jQAssistant and Neo4j

Michael Hunger’s talk had an elegant solution to an actual, unsolved problem of mine

After attending a software development conference, you usually return back home with a bunch of new ideas and cool things you want to try out. But most of the time your ideas remain in experimental stage, since it’s often hard to find a problem that’s just right for all newfound solutions…

But returning from GeekOut 2014 was different – Michael Hunger’s talk “Using Ascii Art to Analyze Your Source Code with Neo4j and OSS Tools” had an elegant solution to an actual, unsolved problem of mine that had surfaced just a couple of weeks earlier. Scanning my Java app with jQAssistant and Neo4j.

Challenge

I am developing a system that uses custom source code parsing to find all concrete subclasses of a specific class, excluding inner classes. These subclasses define units where you can configure user access. If this list is incomplete, the configuration will be incomplete, which in turn means missing user access. We had just seen our first case of generics showing up in this class hierarchy, and the parser couldn’t handle that properly.

Solution

The objective is to extract all concrete subclasses of a particular class into a custom format file, and this should be part of the build. This file serves as a template for access control configuration for the scanned rich client application.

If you have a Maven project, this can be done quite easily with jQAssistant and Neo4j. Here are the basic steps:

  1. Setup jQAssistant
  2. Build your Maven project
  3. Scan your compiled classes with jQAssistant to create a Neo4j representation of your code
  4. Query the database to extract the information you need
  5. Generate the result

The steps will be described in more detail below, using this sample project. It’s a real-world example, but the actual code scanned and the custom report plugin have been replaced with sample code.

Step 1 – setting up jQAssistant

To set up jQAssistant, make sure you have the following:

  • JDK 7
  • Maven 3 and access to Maven Central Repository
  • A Maven project

Add the following to your settings.xml, located in the .m2 folder of your home directory.
This makes it easier to run jQAssistant from the command line. Now you’re good to go.

Step 2 – build your Maven project

Since jQAssistant scans bytecode, you need to build your Maven project.

Step 3 – scan your compiled classes

Before you can scan your application, you need to add the jQAssistant Maven plugin to your POM:
You configure the report writer and specify the file for writing the result.

Now you can scan your code using

Step 4 – Query the Neo4j database

With your code scanned, it’s time to write your Cypher query. The Neo4j web interface is very useful for experimenting with queries, start it by executing

Now you can browse to https://localhost:7474 and start writing and testing your queries.

First, let’s locate the base class that we want to find concrete subclasses for. In the sample code we have a hierarchy of animals, with the base class Animal. So, to find that class, we can use the following query:

Executing that query in the web interface will return one node, the Animal class:

Now, if we extend the query a little bit we can get all subclasses instead.

Clicking the nodes will reveal that we now have found some animals, but also some abstract classes such as Fish and Insect. To get rid of those, we enhance the query:

Now we only have concrete subclasses left. The final thing to get rid of is the inner class declared by GoblinShark.

Now only we have a query that returns all concrete subclasses of Animal, inner classes excluded.
To stop the server, return to the console where you started it and press Enter.
Now it’s time to create a rule file to integrate the query into the build. Rule files are XML files located in the jqassistant folder.

Step 5 – Generate the result

Now that we have a query that do the extraction from the compiled code, we just need to put that in a file. In this example, we just want to write the fully qualified name for each class found by the query. To do that, we implement a custom report writer:

When we plug in this report writer, the result from the query will be available in the Result parameter passed to the setResult method. You can retrieve the rows and write them to a file in the desired format.

To let jQAssistant know about your plugin, create a file called jqassistant-plugin.xml and place it in the META-INF folder of your report writer project.

The final step involves executing your query with jQAssistant to generate the report. This is achieved by running:

Scanning your Java app with jQAssistant and Neo4j is as simple as that.

Thanks to Michael Hunger for a great talk on jQAssistant and Neo4j at GeekOut 2014, and many thanks to Dirk Mahler for helping out, sharing knowledge and enhancing jQAssistant to allow plugging in your own custom report writer. Awesome.

For more details check out https://jqassistant.org where you’ll also find reference documentation and examples.

Mattias Olofsson

Mattias is a software developer with project management experience. He is a quick learner with excellent analytical, design and problem solving skills. He has long experience from design and development of technically challenging systems. He has also been involved in team and technical project management as well as architecture work. He is comfortable working independently or as part of a team and always strives to perform his best and deliver on time and in full.

More interesting articles…