8/27/2012

How to Run JBoss Jandex

Jandex is a tool that processes Java annotations within a directory or jar file, and saves the resulting metadata in an index file. This is similar to what a jar file index is to a classloader.

There are 3 ways to run jandex tool:

  1. java -jar command
  2. ant task
  3. jandex maven plugin
In JBoss AS7, jandex jar is located at $JBOSS_HOME/modules/org/jboss/jandex/main/jandex-1.0.3.Final.jar

To display the usage message,
java -jar jandex-1.0.3.Final.jar

Usage: jandex [-v] [-m] [-o file-name] <directory> | <jar>
-or-
jandex [-d] <index-file-name>
Options:
-v verbose output
-m modify directory or jar instead of creating an external index file
-o name the external index file file-name
-d dump the index file index-file-name

The default behavior, with no options specified, is to autogenerate an external index file

To scan a WAR file, adding the result to WAR's META-INF/jandex.idx (not WEB-INF/jandex.idx):
java -jar jandex-1.0.3.Final.jar -v -m /tmp/test.war

Indexed test.TestBean (2 annotations)
Indexed test.TestIF (0 annotations)
Indexed test.TestServlet (2 annotations)
Wrote META-INF/jandex.idx in 0.0710 seconds (3 classes, 4 annotations, 4 instances, 257 bytes)

To scan a WAR file and put result in the default result file in the same directory as the WAR file:
java -jar jandex-1.0.3.Final.jar /tmp/test.war

Wrote /tmp/test.war.idx in 0.0280 seconds (3 classes, 4 annotations, 4 instances, 257 bytes)

To view the content of an index file:
java -jar jandex-1.0.3.Final.jar -d /tmp/test.war.idx

Annotations:
javax.ejb.Stateless:
Class: test.TestBean
javax.ejb.EJB:
Field: test.TestIF test.TestServlet.testBean
javax.ejb.Local:
Class: test.TestBean
(value = [test.TestIF])
javax.servlet.annotation.WebServlet:
Class: test.TestServlet
(urlPatterns = ["/*"])
Subclasses:
javax.servlet.http.HttpServlet:
test.TestServlet
java.lang.Object:
test.TestBean
test.TestIF

Read test.war.idx in 0.0030 seconds

To scan a directory and save the result in a custom output file (-o option currently does not work with jar file input):
java -jar jandex-1.0.3.Final.jar -v -o /tmp/ann.dat $HOME/ws/test/

Indexed test.TestBean (2 annotations)
Indexed test.TestIF (0 annotations)
Indexed test.TestServlet (2 annotations)
Wrote /tmp/ann.dat in 0.0180 seconds (3 classes, 4 annotations, 4 instances, 257 bytes)

jandex.jar comes with an ant task, org/jboss/jandex/JandexAntTask. To run jandex with ant, first create a build.xml:
<?xml version="1.0"?>
<project name="test" default="jandex.modify" basedir=".">
<property environment="env" />
<taskdef name="jandex" classname="org.jboss.jandex.JandexAntTask"
classpath="${env.JBOSS_HOME}/modules/org/jboss/jandex/main/jandex-1.0.3.Final.jar" />

<target name="jandex.modify">
<jandex run="true" verbose="true" modify="true">
<fileset dir="${env.HOME}/ws/test" />
</jandex>
</target>

<target name="jandex.newjar">
<jandex run="true" verbose="true" newJar="true">
<fileset dir="${env.HOME}/ws/test" />
</jandex>
</target>
</project>
To process all "*.jar" files within a directory (recursively, adding the index file to the original jar:

ant jandex.modify

To process all "*.jar" files within a directory (recursively), and create a new index jar file (a jar file that only contains the generated index: META-INF/jandex.idx) for each source jar:

ant jandex.newjar

JandexAntTask (at least this version) filters on file name "*.jar", so any other types of jar files (*.war, *.ear, *.rar, etc) will not be included.

Jandex maven plugin project page has all the source and usages. With this plugin, jandex processes application annotations directly at build time, instead of post-processing the archives as in the 2 other methods. I tried the basic usage by copying the plugin element to one of the quickstart project pom.xml. After running mvn clean install, I can see the console output showing jandex being invoked as part of process-classes phase:
[INFO] --- jandex-maven-plugin:1.0.1:jandex (make-index) @ jboss-as-ejb-in-war ---
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ jboss-as-ejb-in-war ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
...
To verify the index has been generated into target/classes and packaged into war file:
ls -l target/classes/META-INF/jandex.idx

jar tvf target/jboss-as-ejb-in-war.war | grep jandex

289 Tue Aug 28 10:09:40 EDT 2012 WEB-INF/classes/META-INF/jandex.idx
In the above output jandex.idx seems to have been packaged into the wrong directory inside the WAR. It should be in META-INF/jandex.idx. Could be a bug in jandex plugin?

Jandex can be used on jars or directories of any java application classes or libraries. For instance, the following command runs jandex on JDK classes.jar:
sudo java -jar jandex-1.0.3.Final.jar $JAVA_HOME/../Classes/classes.jar

Wrote /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/../Classes/classes-jar.idx
in 2.4900 seconds (20723 classes, 36 annotations, 1381 instances, 678046 bytes)

ls -l $JAVA_HOME/../Classes/*idx
-rw-r--r-- 1 root wheel 678046 Aug 28 10:45 /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/../Classes/classes-jar.idx