Hi Mohamed, On Wed, 3 Jul 2013, Mohamed Tleis wrote:
> On 07/02/2013 07:49 PM, Johannes Schindelin wrote: > > > > On Tue, 2 Jul 2013, Johannes Schindelin wrote: > > > > > On Tue, 2 Jul 2013, Mohamed Tleis wrote: > > > > > > > I wanted to test the HelloWorld Plugin from the tutorials. I named > > > > it HelloWorld_Plugin and copied the compiled class to the plugins > > > > folder. I have Hello World Plugin in the Plugins Menu now, but it > > > > does nothing upon clicking. > > > > > > > > [...] > > > > > > > > 2. Why Hello World dialog message doens't display upon accessing > > > > from the menu? > > > > > > Did you have a look at the console output? > > > > Just to make sure that nothing silly is happening, I did this (you > > might want to explain in as much detail what you did in the future): > > > > 1) I made sure that my imagej-tutorials is up-to-date > > > > 2) I used Maven to build (this is by far the easiest thing to do): > > > > mvn > > > > You could use your development environment of choice (Eclipse, > > Netbeans, IntelliJ, etc) to build it, too. > > > > 3) I copied the generated .jar file (which is called > > simple-command-1.0.0-SNAPSHOT.jar) from simple-command/target/ to my > > ImageJ.app/plugins/ > > > > 4) I started ImageJ2 via ImageJ.app/ImageJ-linux64 > > > > 5) I started the command launcher by hitting the 'L' key > > > > 6) I typed "Hello" in the search box > > > > 7) I called the "Hello, World!" plugin > > > > It did show a message box, greeting the whole world. So basically I have > > no clue what went wrong on your side, but I am sure we can find out > > together if you provide every bit of useful information you can extract > > from your trial. FWIW in the future you could spare everyone reading your reply a couple of minutes by culling the part from the quoted mail that you did not address in your reply. If you think about the number of readers, multiply that by those couple of minutes, you get the idea how much time you asked others to spend on your mail. If you can spend less than that to reduce that overall time, well, maybe you want to do that? > I followed the exact steps as you did, and noticed the path of > HelloWorldPlugin is in the Help Menu. and it is working fine now, Good. > although I am wondering how to change the menu path. As so often, the answer is in the source code. Asking the web browser to search for "Help" in the page on GitHub found me this gem: https://github.com/imagej/imagej-tutorials/blob/master/simple-command/src/main/java/HelloWorldPlugin.java#L39 It is the "menuPath" attribute of the @Plugin annotation. > Building the HelloWorldPlugin.java alone, and copying the > HelloWorldPlugin.class into the Plugins folder did nothing. Yes. ImageJ2 does not support bare .class files in the plugins/ folder (except insofar necessary for backwards-compatibility). Allowing that encourages sloppy development, and it is all-too-easy for infrequent programmers to forget the intricacies: the name must contain an underscore, the class must be in the default package, or in a one-level package and the file in a subdirectory, but not two-level package, or the class must be in the default package and the file in a one-level subdirectory of plugins/, but not in a two-level directory, etc. Also, it was quite often the case that you got single .class files that were missing crucial other .class files to run. A completely inefficient and annoying back-and-forth had to ensue until everything was in place to finally run the plugin. This is particularly true for .java files defining more than one class. I am not talking about theoretical problems here, have a look at famous plugins such as TurboReg. Therefore, ImageJ2 only supports fully self-contained .jar files. They contain everything that you need to run the plugin, can contain resources such as icons, information that is put there at compile time, and a lot more. Also, .jar files are much more space-efficient than unpacked .class files will ever be. And once you have more than two plugins in your plugins/ folder, it should be a no-brainer to see that two .jar files are much easier to organize than a couple of possibly-interrelated .class files, possibly scattered over multiple directories (because you cannot import classes from the default package). > However compiling it as HelloWorld_Plugin.class did indeed show the > HelloWorld Plugin in the Plugins Menu but clicking it performs nothing, > and not even in the console output (by running ImageJ-linux64 from > terminal). Well, ImageJ 1.x does not look at the contents of the .class file -- ever! -- to determine whether it is a plugin or not. All it does is to look at the underscore. If it is present, it must be a plugin, right? And since ImageJ2 aims to be as backwards-compatible as possible, it inherits that plugin via the legacy layer. Now, there is some very, very obscure feature in ImageJ 1.x: if you have a class whose name contains an underscore but which does not implement the PlugInFilter nor the PlugIn interface, it is *still* constructed. In fact, quite a few "plugins" use that feature to perform all their computation in the constructor! So ImageJ2 handed off to ImageJ 1.x in your case, which faithfully applied that obscure feature and constructed the plugin. And that was that. It just constructed it and then did nothing with it. It is safe to say that this feature -- encouraging all the computation of the plugin to happen in the constructor (which is intended to *initialize* the plugin in preparation for the computation) -- contradicts pretty much everything you will learn about object-oriented programming and best practices, and for a very good reason: it opens a can of problems such as the absence of proper error handling (there is only one way the plugin can fail: it throws an exception, but of course from then on every internal state of the plugin is lost!), the plugin's complete inability to interact with the ImageJ core (once the constructor is done, it cannot tell ImageJ what it did, and the plugin cannot do anything else from now on), ImageJ's complete absence of knowledge what the plugin is expected to do (Does it work on images? Does it create new windows? Is it supposed to perform a computation?), basically every technique developed in the object-oriented paradigm to help establishing a structure that helps develop robust software, fast, cannot be applied. Another problem it causes is that you cannot tell whether the plugin did something or not because the constructor's purpose is to *prepare* the plugin for execution, not to execute it. Needless to say, it is not our intention to encourage such bad practices (because after all, we will be stuck with helping scientists debug their code which gets really boring really fast when the code makes exactly that debugging hard). Another rather big down-side of bare class files in plugins/ is that you could not easily put it into a different location (for example, to unclutter the already overloaded Plugins menu). Sure, you could put it into a submenu of Plugins, but not, say, into Help. This is different with ImageJ2 plugins where the @Plugin annotation determines the menuPath, but it is easy to see how confused people would be if the menu location did not change when they moved a .class into a subdirectory of plugins/, no? Your case is probably the best demonstration for yet another reason why it would be a bad idea to support ImageJ2 plugins as bare .class files in the plugins/ directory: Due to above-mentioned obscure ImageJ 1.x' feature, ImageJ2 would have to spend an substantial amount of time at startup to determine whether it is an ImageJ2 or ImageJ1 plugin. Let's keep things simple and easy instead: all ImageJ2 plugins require are @Plugin annotations, and that they are bundled in .jar files. That's it. Ciao, Johannes _______________________________________________ ImageJ-devel mailing list ImageJ-devel@imagej.net http://imagej.net/mailman/listinfo/imagej-devel