Path problem?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Path problem?

Bob Loushin
I recently started using ImageJ and Java (I am an experienced C++ programmer).  I am working on WinXP, SP3, ImageJ 1.42q, and Java 1.6.0_16.  I wrote my first plugin, and that went smoothly.  When I wrote the second plugin, I needed methods from the first plugin, so I imported it.  When I try to compile it, I get the error message "Package XYZ_ does not exist", pointing to the import line.  I am guessing the problem is that the compiler cannot find the XYZ_.class file.  I have added the path to the folder containing the file to the system variable PATH, but this did not resolve the problem.  Does anybody know how to get the compiler to link this file?

Thanks to anyone who can help.
Reply | Threaded
Open this post in threaded view
|

Re: Path problem?

Stephan Saalfeld
Put either the sources together in one path or give a package
declaration to your first plugin (the equivalent to a namespace in C++).
For non-trivial plugins this is anyway the better idea.

You can then import that plugin by

import mynamespace.FirstPlugin;

similar to

using mynamespace::FirstPlugin;

to announce mynamespace.FirstPlugin to ImageJ, you need a hack called
plugins.config in the jar file that contains it or in the plugins folder
alternatively to define what to call under which menu point.
Explanation here:

http://rsbweb.nih.gov/ij/plugins/jar-demo.html

Best,
Stephan



On Sun, 2010-01-17 at 16:28 -0600, Bob wrote:
> I recently started using ImageJ and Java (I am an experienced C++ programmer).  I am working on WinXP, SP3, ImageJ 1.42q, and Java 1.6.0_16.  I wrote my first plugin, and that went smoothly.  When I wrote the second plugin, I needed methods from the first plugin, so I imported it.  When I try to compile it, I get the error message "Package XYZ_ does not exist", pointing to the import line.  I am guessing the problem is that the compiler cannot find the XYZ_.class file.  I have added the path to the folder containing the file to the system variable PATH, but this did not resolve the problem.  Does anybody know how to get the compiler to link this file?
>
> Thanks to anyone who can help.
Reply | Threaded
Open this post in threaded view
|

Re: Path problem?

Volker Baecker
In reply to this post by Bob Loushin
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello,
for ImageJ the plugin (i.e. the class that implements the PlugIn
interface) must not be in any package. Therefore it can not be imported
from anywhere else.
IMHO the best thing to do is to put the code into another class that can
be in a package and to import this package into the two plugins.
Volker

Bob wrote:
> I recently started using ImageJ and Java (I am an experienced C++ programmer).  I am working on WinXP, SP3, ImageJ 1.42q, and Java 1.6.0_16.  I wrote my first plugin, and that went smoothly.  When I wrote the second plugin, I needed methods from the first plugin, so I imported it.  When I try to compile it, I get the error message "Package XYZ_ does not exist", pointing to the import line.  I am guessing the problem is that the compiler cannot find the XYZ_.class file.  I have added the path to the folder containing the file to the system variable PATH, but this did not resolve the problem.  Does anybody know how to get the compiler to link this file?
>
> Thanks to anyone who can help.
>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAktUJisACgkQ0gXPLVKexCcbkQCfc8hWquZiG8UYATtBzM6X8y5B
NpIAmgOdR8QaB/8HRk5V1YOsUiYFSPpb
=3WDY
-----END PGP SIGNATURE-----

--
passerelle antivirus du campus CNRS de Montpellier
--
Reply | Threaded
Open this post in threaded view
|

Re: Path problem?

Michael Doube
Hi Bob,

I've had similar problems in the past but now:

1) Implement PlugIn within packages
2) Call methods from other PlugIn classes in other sub-packages
3) Call methods and use classes from imported .jars

This is really very convenient and means I can reuse code between my
plugins, as well as have some non-PlugIn utility classes (but my code
is, shall we say, a bit "agricultural")

(Though I now better understand Volker's preference to have the PlugIns
in the root directory, calling classes in the packages - the PlugIn
classes talk to ImageJ's API and the other classes, which "do the work".
http://n2.nabble.com/plugins-config-Plugin-or-class-not-found-exception-tp2245232p2245464.html).

The special sauce is in plugins.config (which is sensitive to whitespace
incidentally, you must use space and not tab).

A PlugIn in the root directory of my jar is referred to in
plugins.config like this:
Plugins>BoneJ, "Fit Sphere", Fit_Sphere

It gets the menu item Plugins->BoneJ->Fit Sphere

A plugin in a package directory is referred to like this:
Plugins>BoneJ, "Moments 3D", org.doube.bonej.Moments

It gets the menu item Plugins->BoneJ->Moments 3D

I think Stephan covered the rest; importing classes for use in your new
PlugIn goes like:
import org.doube.util.ResultInserter;

I hope these tips help,

Michael


On 18/01/2010 09:13, Volker Baecker wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hello,
> for ImageJ the plugin (i.e. the class that implements the PlugIn
> interface) must not be in any package. Therefore it can not be imported
> from anywhere else.
> IMHO the best thing to do is to put the code into another class that can
> be in a package and to import this package into the two plugins.
> Volker
>
> Bob wrote:
>> I recently started using ImageJ and Java (I am an experienced C++ programmer).  I am working on WinXP, SP3, ImageJ 1.42q, and Java 1.6.0_16.  I wrote my first plugin, and that went smoothly.  When I wrote the second plugin, I needed methods from the first plugin, so I imported it.  When I try to compile it, I get the error message "Package XYZ_ does not exist", pointing to the import line.  I am guessing the problem is that the compiler cannot find the XYZ_.class file.  I have added the path to the folder containing the file to the system variable PATH, but this did not resolve the problem.  Does anybody know how to get the compiler to link this file?
>>
>> Thanks to anyone who can help.
>>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
>
> iEYEARECAAYFAktUJisACgkQ0gXPLVKexCcbkQCfc8hWquZiG8UYATtBzM6X8y5B
> NpIAmgOdR8QaB/8HRk5V1YOsUiYFSPpb
> =3WDY
> -----END PGP SIGNATURE-----
>
Reply | Threaded
Open this post in threaded view
|

Re: Path problem?

Chris Mawata
In reply to this post by Bob Loushin
Bob wrote:
> I recently started using ImageJ and Java (I am an experienced C++ programmer).  I am working on WinXP, SP3, ImageJ 1.42q, and Java 1.6.0_16.  I wrote my first plugin, and that went smoothly.  When I wrote the second plugin, I needed methods from the first plugin, so I imported it.  When I try to compile it, I get the error message "Package XYZ_ does not exist", pointing to the import line.  I am guessing the problem is that the compiler cannot find the XYZ_.class file.  I have added the path to the folder containing the file to the system variable PATH, but this did not resolve the problem.  Does anybody know how to get the compiler to link this file?
>
> Thanks to anyone who can help.
>
>  
Classes are searched for on the CLASSPATH (rather than PATH). You could
make a system variable called path but it is better to define the
classpath in your IDE.
Reply | Threaded
Open this post in threaded view
|

Re: Path Problem?

Bob Loushin
In reply to this post by Bob Loushin
I'd like to thank everyone who responded.  Mr. Saalfeld seems to have pointed me down the right path, but I haven't had success following it.  In particular, the following works:

Experiment 1:

test_1.java:
//package my_stuff;

import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.*;

public class test_1 implements PlugIn {

 public void run(String arg) { shared_method(); }

 public void shared_method() { IJ.showMessage("test_1","Hello world!"); }
}


plugins.config:

# Name: Test_Plugin

# Author: Bob
# Version: 1.0
# Date: 1/18/10
# Requires: ImageJ 1.31s

Plugins>Test, "Test 1", test_1("run")

I compile a .class out of the java file using ImageJ>Plugins>Compile and Run..., wrap the whole thing in a .jar using the command

jar cvfM Test.jar test_1.class test_1.java plugins.config

I put this in the plugins folder, fired up ImageJ, and Test 1 was there and ran as expected.

Experiment 2:  Then I uncommented the first line of the .java file and changed the last line of the plugins.config to read

Plugins>Test, "Test 1", my_stuff.test_1("run")

I compile the .class, but of course when I do the Compile and Run..., the run part fails, because now my class is inside a package.  But it still compiled, and the .class should be good, so I proceed.  I use the same jar command as before, restart ImageJ, and try to run it.  Unfortunately, it again fails.  Apparently, there is still a detail I do not understand.

Experiment 3:  The ultimate goal is to be able to write a test_2.java which will look like the following:

test_2.java:
//package my_stuff;

import test_1.*;  //This line may not be necessary, or it might need to be import test_1; my Java knowledge is weak on this point, but I'll experiment.
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.*;

public class test_2 implements PlugIn {

 public void run(String arg) {
     test_1 temp;
     temp.shared_method();
   }

}

I can't try this until I can get Experiment 2 to work.

Can anyone tell me where I've gone wrong?

Thanks!

Bob
Reply | Threaded
Open this post in threaded view
|

Re: Path Problem?

Stephan Saalfeld
Your problems are on Java syntax, not ImageJ ;)---read:

http://java.sun.com/docs/books/tutorial/java/index.html

I your case, what you're trying is to use an instance method in a static
way.  In Java, an object is not instantiated just by declaring it, you
have to use new.  So either:

test_1.java:

public class test_1 implements PlugIn {

 public void run(String arg) { shared_method(); }

 static public void shared_method() { IJ.showMessage("test_1","Hello world!"); }
}

or leaving test_1 as you had it before:

test_2.java:

public class test_2 implements PlugIn {

 public void run(String arg) {
     test_1 temp = new test_1();
     temp.shared_method();
   }

}

The previous test_1/test_2 combination shouldn't have been compilable.

Best,
Stephan
Reply | Threaded
Open this post in threaded view
|

Re: Path Problem?

Bob Loushin
Stephan,

You're right, of course, I should have used a new in my test_2.java example
(it is in the original code, but didn't survive when I rewrote the
simplified illustration).  But where I'm stuck is at the point before test_2
enters the picture.  Basically, I can't get experiment 2 (which only
involves the packaged version of test_1) to work.  You're also correct that
this may be a Java problem, not an ImageJ problem, since I'm new to both.
To focus a bit more clearly on my current stopper, this fails:

test_1.java:
package my_stuff;

import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.*;

public class test_1 implements PlugIn {

 public void run(String arg) { shared_method(); }

 public void shared_method() { IJ.showMessage("test_1","Hello world!"); }
}


plugins.config:

# Name: Test_Plugin

# Author: Bob
# Version: 1.0
# Date: 1/18/10
# Requires: ImageJ 1.31s

Plugins>Test, "Test 1", my_stuff.test_1("run")

The issue may be in the way I compile, by just using the "Compile and
Run..." in ImageJ to generate test_1.class, and then manually making the
.jar file using "jar cvfM Test.jar test_1.class test_1.java plugins.config".
However, it seems more likely to me that I have the syntax wrong in the last
line of plugins.config.  The error message I am getting is:  "Plugin or
class not found: 'my_stuff.test_1' (java.lang.ClassNotFoundException:
my_stuff.test_1)"


> Your problems are on Java syntax, not ImageJ ;)---read:
>
> http://java.sun.com/docs/books/tutorial/java/index.html
>
> I your case, what you're trying is to use an instance method in a static
> way.  In Java, an object is not instantiated just by declaring it, you
> have to use new.  So either:
>
> test_1.java:
>
> public class test_1 implements PlugIn {
>
> public void run(String arg) { shared_method(); }
>
> static public void shared_method() { IJ.showMessage("test_1","Hello
> world!"); }
> }
>
> or leaving test_1 as you had it before:
>
> test_2.java:
>
> public class test_2 implements PlugIn {
>
> public void run(String arg) {
>     test_1 temp = new test_1();
>     temp.shared_method();
>   }
>
> }
>
> The previous test_1/test_2 combination shouldn't have been compilable.
>
> Best,
> Stephan
Reply | Threaded
Open this post in threaded view
|

Re: Path Problem?

Michael Doube
Bob,

You don't have to put ("run") at the end of your plugins.config lines.

Plugins>Test, "Test 1", my_stuff.test_1

should work.

Michael


Bob wrote:

> Stephan,
>
> You're right, of course, I should have used a new in my test_2.java example
> (it is in the original code, but didn't survive when I rewrote the
> simplified illustration).  But where I'm stuck is at the point before test_2
> enters the picture.  Basically, I can't get experiment 2 (which only
> involves the packaged version of test_1) to work.  You're also correct that
> this may be a Java problem, not an ImageJ problem, since I'm new to both.
> To focus a bit more clearly on my current stopper, this fails:
>
> test_1.java:
> package my_stuff;
>
> import ij.*;
> import ij.process.*;
> import ij.gui.*;
> import java.awt.*;
> import ij.plugin.*;
>
> public class test_1 implements PlugIn {
>
>  public void run(String arg) { shared_method(); }
>
>  public void shared_method() { IJ.showMessage("test_1","Hello world!"); }
> }
>
>
> plugins.config:
>
> # Name: Test_Plugin
>
> # Author: Bob
> # Version: 1.0
> # Date: 1/18/10
> # Requires: ImageJ 1.31s
>
> Plugins>Test, "Test 1", my_stuff.test_1("run")
>
> The issue may be in the way I compile, by just using the "Compile and
> Run..." in ImageJ to generate test_1.class, and then manually making the
> .jar file using "jar cvfM Test.jar test_1.class test_1.java plugins.config".
> However, it seems more likely to me that I have the syntax wrong in the last
> line of plugins.config.  The error message I am getting is:  "Plugin or
> class not found: 'my_stuff.test_1' (java.lang.ClassNotFoundException:
> my_stuff.test_1)"
>
>
>> Your problems are on Java syntax, not ImageJ ;)---read:
>>
>> http://java.sun.com/docs/books/tutorial/java/index.html
>>
>> I your case, what you're trying is to use an instance method in a static
>> way.  In Java, an object is not instantiated just by declaring it, you
>> have to use new.  So either:
>>
>> test_1.java:
>>
>> public class test_1 implements PlugIn {
>>
>> public void run(String arg) { shared_method(); }
>>
>> static public void shared_method() { IJ.showMessage("test_1","Hello
>> world!"); }
>> }
>>
>> or leaving test_1 as you had it before:
>>
>> test_2.java:
>>
>> public class test_2 implements PlugIn {
>>
>> public void run(String arg) {
>>     test_1 temp = new test_1();
>>     temp.shared_method();
>>   }
>>
>> }
>>
>> The previous test_1/test_2 combination shouldn't have been compilable.
>>
>> Best,
>> Stephan

--
Dr Michael Doube  BPhil BVSc PhD MRCVS
Research Associate
Department of Bioengineering
Imperial College London
South Kensington Campus
London  SW7 2AZ
United Kingdom
Reply | Threaded
Open this post in threaded view
|

Re: Path Problem?

Stephan Saalfeld
In reply to this post by Bob Loushin
It seems that either Java or ImageJ show us their ugly face here ;)

The path matters!  Never thought about this because I always followed
the main stream and did that...

If test_1 is in package my_stuff, it also has to be in a folder my_stuff
respectively.  The content of your jar must thus be minimally:

$ jar -vtf Test_.jar
   471 Tue Jan 19 17:58:14 CET 2010 my_stuff/test_1.class
   132 Tue Jan 19 17:40:20 CET 2010 plugins.config


Add the source if you like.  The jar must have an underscore in its name
for announcing itself as a plugin to ImageJ (e.g. Test_.jar)

In your example, the package declaration was missing thus the code
should be:

$ cat my_stuff/test_1.java
package my_stuff;

import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.*;

public class test_1 implements PlugIn {

public void run(String arg) { shared_method(); }

  public void shared_method() { IJ.showMessage("test_1","Hello world!");
}
}

I compiled that with:

$ javac -cp /wherever/you/have/imagej/ij.jar my_stuff/*.java

then

$ jar cvfM Test_.jar my_stuff/* plugins.config

Runs for me.

Best,
Stephan



On Tue, 2010-01-19 at 09:36 -0600, Bob wrote:

> Stephan,
>
> You're right, of course, I should have used a new in my test_2.java example
> (it is in the original code, but didn't survive when I rewrote the
> simplified illustration).  But where I'm stuck is at the point before test_2
> enters the picture.  Basically, I can't get experiment 2 (which only
> involves the packaged version of test_1) to work.  You're also correct that
> this may be a Java problem, not an ImageJ problem, since I'm new to both.
> To focus a bit more clearly on my current stopper, this fails:
>
> test_1.java:
> package my_stuff;
>
> import ij.*;
> import ij.process.*;
> import ij.gui.*;
> import java.awt.*;
> import ij.plugin.*;
>
> public class test_1 implements PlugIn {
>
>  public void run(String arg) { shared_method(); }
>
>  public void shared_method() { IJ.showMessage("test_1","Hello world!"); }
> }
>
>
> plugins.config:
>
> # Name: Test_Plugin
>
> # Author: Bob
> # Version: 1.0
> # Date: 1/18/10
> # Requires: ImageJ 1.31s
>
> Plugins>Test, "Test 1", my_stuff.test_1("run")
>
> The issue may be in the way I compile, by just using the "Compile and
> Run..." in ImageJ to generate test_1.class, and then manually making the
> .jar file using "jar cvfM Test.jar test_1.class test_1.java plugins.config".
> However, it seems more likely to me that I have the syntax wrong in the last
> line of plugins.config.  The error message I am getting is:  "Plugin or
> class not found: 'my_stuff.test_1' (java.lang.ClassNotFoundException:
> my_stuff.test_1)"
>
>
> > Your problems are on Java syntax, not ImageJ ;)---read:
> >
> > http://java.sun.com/docs/books/tutorial/java/index.html
> >
> > I your case, what you're trying is to use an instance method in a static
> > way.  In Java, an object is not instantiated just by declaring it, you
> > have to use new.  So either:
> >
> > test_1.java:
> >
> > public class test_1 implements PlugIn {
> >
> > public void run(String arg) { shared_method(); }
> >
> > static public void shared_method() { IJ.showMessage("test_1","Hello
> > world!"); }
> > }
> >
> > or leaving test_1 as you had it before:
> >
> > test_2.java:
> >
> > public class test_2 implements PlugIn {
> >
> > public void run(String arg) {
> >     test_1 temp = new test_1();
> >     temp.shared_method();
> >   }
> >
> > }
> >
> > The previous test_1/test_2 combination shouldn't have been compilable.
> >
> > Best,
> > Stephan
Reply | Threaded
Open this post in threaded view
|

Re: Path Problem?

Bob Loushin
Stephan,

Thank you!  It all works now, when I put the path in the .config file.  That
was the missing piece.  Yes, it was a conspiracy--ImageJ forcing things into
packages before allowing objects to call one another, and then Java having
this subtle issue with paths inside .jar files needing to match the package
structure.

I really appreciate your help.

Bob

Subject: Re: Path Problem?

> It seems that either Java or ImageJ show us their ugly face here ;)
>
> The path matters!  Never thought about this because I always followed
> the main stream and did that...
>
> If test_1 is in package my_stuff, it also has to be in a folder my_stuff
> respectively.  The content of your jar must thus be minimally:
>
> $ jar -vtf Test_.jar
>   471 Tue Jan 19 17:58:14 CET 2010 my_stuff/test_1.class
>   132 Tue Jan 19 17:40:20 CET 2010 plugins.config
>
>>SNIP<<
Reply | Threaded
Open this post in threaded view
|

Re: Path Problem?

dscho
Hi,

On Tue, 19 Jan 2010, Bob wrote:

> Thank you!  It all works now, when I put the path in the .config file.  
> That was the missing piece.  Yes, it was a conspiracy--ImageJ forcing
> things into packages before allowing objects to call one another, and
> then Java having this subtle issue with paths inside .jar files needing
> to match the package structure.

This cannot stand as you put it.

It was a concious design decision of Java to require classes to be put
into packages before they can be imported.  If you have a class that is in
the default package (i.e. none), you can use other classes from that
default package, but that is bad style anyway, as there would be too many
clashes if everybody did that.

And the alternative to letting classes be put into .jar files wherever you
like it instead of according to the package would mean an unbearable
performance impact.  Basically, _every_ _single_ class in _every_ _single_
.jar file would have to be inspected if it might be the one you might look
for (remember, you can say "import ij.*;")!

So I think that both issues you hit have a very good reason for having to
be fixed on your side instead of anywhere else.

Ciao,
Dscho

P.S.: I would be interested to know if there is any Java book out there
which fails to mention both that you should put classes into appropriate
packages (and why) and that you must put classes into directory structures
reflecting the package structure (does not matter whether they are inside
a .jar file or in a directory in the classpath).