A question about the behavior of java annotations and the SciJava annotation processor

scijava
imagej
plugin

#1

When I compile (javac) a plugin, it appears that I need to have a
specific (possibly empty) file, org.scijava.plugin.Plugin, available.
But then the compilation process creates a deeply-nested
sub-directory tree that contains the “real” org.scijava.plugin.Plugin,
leaving the original empty.

Could someone offer a few words of explanation about how
the SciJava plugin framework fits together, and why I see this
unexpected behavior?

Specifically, I have the test plugin class, AnnotationTest.java:

package test;

import org.scijava.command.Command;
import org.scijava.log.LogService;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;

/**

  • test annotation framework
    */

@Plugin(type = Command.class, menuPath = “test>annotation”)
public class AnnotationTest implements Command {

@Parameter
private LogService log;

@Override
public void run() {
log.info (“annotation test”);
}

}

I compile it against the jars in a stock fiji installation:

javac -cp .:<path_to_fiji_installation>/Fiji.app/jars/* AnnotationTest.java

When I do this I get the error:

error: java.nio.file.NoSuchFileException: <path_to_build_directory>/org.scijava.plugin.Plugin

So I create the (empty) file: touch org.scijava.plugin.Plugin

The compilation now runs, but I get a goofy nested sub-directory:

<path_to_build_directory>/file:/<path_to_build_directory>/META-INF/json

(Lots of new inodes in my file system!)

containing the “real” org.scijava.plugin.Plugin, presumably created
by the SciJava annotation processor:

{“class”:“test.AnnotationTest”,“values”:{“menuPath”:“test>annotation”,“type”:“org.scijava.command.Command”}}

So, I suppose that the SciJava annotation processor is responsible
for populating the plugin json file. I guess that there is a global json
file that the annotation processor appends to, and the annotation
processor errors out if it can’t find it. This reasonably makes sense.
But why then doesn’t it use the (empty) json file that I created, and
instead creates its own way down yonder in the deeply-nested
sub-directory?

I would appreciate any help understanding how this all works.

Thanks, mm.


#2

Hi @mountain_man,
is there a specific reason you are using plain javac to compile your plugin? The whole SciJava ecosystem is build around using maven to do the heavy lifting (in fancy: project life-cycle management) for us, be it dependency management, running the annotation preprocessor and much more. Have you taken a look at the https://imagej.net/Writing_plugins page on the wiki yet? It explains how to get started developing ImageJ plugins and how to setup your project correctly.
If there are any points where the wiki or the tutorial linked within it are unclear, please tell us about so we can improve it.


#3

Hello Gabriel,

Yes, using good, old javac to compile / build my test plugin is a
conscious decision on my part. (I have discovered by dint of hard
experience that, when learning a complicated framework, avoiding
layers of tooling pays dividends in the long run even if downloading
a bunch of “stuff” and clicking “run” might be the shortest path to
executing “hello world.”)

I have looked at the Writing_plugins wiki page (but not gone through
it in depth). No issues with it at this point.

I do intend to use the whole tooling system – maven, and all – for
any “real” fiji development.

It does appear from my experiments that the “annotation
preprocessor” system is a built-in part of javac. (That is, that javac
knows how to discover and run custom annotation processors in
the classpath.) Although maybe something in the official maven
project knows to create the empty org.scijava.plugin.Plugin
json file (and maybe even retrieve it from its deeply-nested
sub-directory).

Thank you for your follow-up, mm