creating io.scif.img.ImgOpener currently fails in Fiji

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

creating io.scif.img.ImgOpener currently fails in Fiji

Tobias Pietzsch
Hi,

Currently
new io.scif.img.ImgOpener();
fails with
java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.LegacyAppEventService

To reproduce run
new io.scif.img.ImgOpener();
in Beanshell interpreter.

The exception displayed in Beanshell interpreter is a bit non-helpful.
Benjamin Schmid noticed the error, when it occurred in BigDataViewer’s ExportSpimSequencePlugIn.
Here is the exception from that, which is a bit more detailed

java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.LegacyAppEventService
        at org.scijava.service.ServiceHelper.createExactService(ServiceHelper.java:280)
        at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:231)
        at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:194)
        at org.scijava.service.ServiceHelper.loadServices(ServiceHelper.java:166)
        at org.scijava.Context.<init>(Context.java:244)
        at org.scijava.Context.<init>(Context.java:203)
        at org.scijava.Context.<init>(Context.java:142)
        at org.scijava.Context.<init>(Context.java:128)
        at io.scif.img.AbstractImgIOComponent.<init>(AbstractImgIOComponent.java:57)
        at io.scif.img.ImgOpener.<init>(ImgOpener.java:94)
        at bdv.ij.export.imgloader.StackImageLoader.<init>(StackImageLoader.java:52)
        at bdv.ij.export.SpimRegistrationSequence.createImageLoader(SpimRegistrationSequence.java:109)
        at bdv.ij.export.SpimRegistrationSequence.<init>(SpimRegistrationSequence.java:56)
        at bdv.ij.ExportSpimSequencePlugIn.getParameters(ExportSpimSequencePlugIn.java:490)
        at bdv.ij.ExportSpimSequencePlugIn.run(ExportSpimSequencePlugIn.java:52)
        at ij.IJ.runUserPlugIn(IJ.java:202)
        at ij.IJ.runPlugIn(IJ.java:166)
        at ij.Executer.runCommand(Executer.java:131)
        at ij.Executer.run(Executer.java:64)
        at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.DefaultLegacyService
        at org.scijava.service.ServiceHelper.createExactService(ServiceHelper.java:280)
        at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:231)
        at org.scijava.service.ServiceHelper.createServiceRecursively(ServiceHelper.java:340)
        at org.scijava.service.ServiceHelper.createExactService(ServiceHelper.java:269)
        ... 19 more
Caused by: java.lang.UnsupportedOperationException: Cannot instantiate more than one DefaultLegacyService
        at net.imagej.legacy.DefaultLegacyService.checkInstance(DefaultLegacyService.java:606)
        at net.imagej.legacy.DefaultLegacyService.initialize(DefaultLegacyService.java:411)
        at org.scijava.service.ServiceHelper.createServiceRecursively(ServiceHelper.java:353)
        at org.scijava.service.ServiceHelper.createExactService(ServiceHelper.java:269)
        ... 22 more
Caused by: java.lang.Throwable: Initialized here:
        at net.imagej.legacy.DefaultLegacyService.initialize(DefaultLegacyService.java:429)
        at org.scijava.service.ServiceHelper.createServiceRecursively(ServiceHelper.java:353)
        at org.scijava.service.ServiceHelper.createExactService(ServiceHelper.java:269)
        at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:231)
        at org.scijava.service.ServiceHelper.createServiceRecursively(ServiceHelper.java:340)
        at org.scijava.service.ServiceHelper.createExactService(ServiceHelper.java:269)
        at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:231)
        at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:194)
        at org.scijava.service.ServiceHelper.loadServices(ServiceHelper.java:166)
        at org.scijava.Context.<init>(Context.java:244)
        at org.scijava.Context.<init>(Context.java:203)
        at org.scijava.Context.<init>(Context.java:142)
        at org.scijava.Context.<init>(Context.java:98)
        at org.scijava.Context.<init>(Context.java:86)
        at net.imagej.ImageJ.<init>(ImageJ.java:82)
        at net.imagej.Main.launch(Main.java:61)
        at net.imagej.Main.main(Main.java:73)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at net.imagej.launcher.ClassLauncher.launch(ClassLauncher.java:258)
        at net.imagej.launcher.ClassLauncher.run(ClassLauncher.java:184)
        at net.imagej.launcher.ClassLauncher.main(ClassLauncher.java:76)

best regards,
Tobias


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel

signature.asc (465 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: creating io.scif.img.ImgOpener currently fails in Fiji

dscho
Administrator
Hi Tobias,

On Fri, 22 Aug 2014, Tobias Pietzsch wrote:

> Currently
> new io.scif.img.ImgOpener();
> fails with
> java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.LegacyAppEventService

Yep, the explanation is very easy:

> [...]
> Caused by: java.lang.UnsupportedOperationException: Cannot instantiate more than one DefaultLegacyService
> [...]

There is already a context, including a legacy service. Unfortunately, the
best way to get at this context from an *ImageJ 1.x plugin* that I could
come up with is:

        import org.scijava.Context;

        ...

        final Context context = (Context)
                IJ.runPlugIn(Context.class.getName(), "");
        final ImgOpener opener = new ImgOpener(context);

(There is no way to make that more convenient without letting SCIFIO
depend on ImageJ 1.x, which is of course a big no-no).

Of course, you could also turn your plugin into an ImageJ2 plugin -- which
is handled properly in Fiji thanks to Fiji Just Being ImageJ2 -- and then
it would become as easy as:

                @Parameter
                private IOService io;

                ...
                        // use the IOService (which lets SCIFIO handle
                        // things) to open your dataset

Ciao,
Johannes

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: [fiji-devel] creating io.scif.img.ImgOpener currently fails in Fiji

Tobias Pietzsch
Hi Johannes,

On 22 Aug 2014, at 09:04, Johannes Schindelin <[hidden email]> wrote:

Hi Tobias,

On Fri, 22 Aug 2014, Tobias Pietzsch wrote:

Currently
new io.scif.img.ImgOpener();
fails with
java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.LegacyAppEventService

Yep, the explanation is very easy:

[...]
Caused by: java.lang.UnsupportedOperationException: Cannot instantiate more than one DefaultLegacyService
[…]

I missed that...


There is already a context, including a legacy service. Unfortunately, the
best way to get at this context from an *ImageJ 1.x plugin* that I could
come up with is:

import org.scijava.Context;

...

final Context context = (Context)
IJ.runPlugIn(Context.class.getName(), "");
final ImgOpener opener = new ImgOpener(context);

(There is no way to make that more convenient without letting SCIFIO
depend on ImageJ 1.x, which is of course a big no-no).

The problem with this solution you suggested is that it does not work in Eclipse:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.DefaultLegacyService

As much as I understand the need for the runtime service discovery used by the scijava stack, there are certainly downsides to it.
My feeling is that in some ways it undermines the advantages that we have gained by switching to maven.
I can import a maven project into my Eclipse, and all the dependencies are there, explicitly and automatically, which is really very convenient.
Except now all dependencies are not there anymore because now there are non-obvious (to me) implicit runtime dependencies.
I find this unfortunate.

That being said, I found a solution that works for now, both in Eclipse and in Fiji
    final ImgOpener opener = new ImgOpener( new Context( SCIFIOService.class, AppService.class, StatusService.class ) );
This avoids requiring the net.imagej.legacy.LegacyAppEventService.
It seems to work, but I’m not sure: Are there any downsides to that?

best regards,
Tobias


Of course, you could also turn your plugin into an ImageJ2 plugin -- which
is handled properly in Fiji thanks to Fiji Just Being ImageJ2 -- and then
it would become as easy as:

@Parameter
private IOService io;

...
// use the IOService (which lets SCIFIO handle
// things) to open your dataset

Ciao,
Johannes

--
--
Please avoid top-posting, and please make sure to reply-to-all!

Mailing list web interface: http://groups.google.com/group/fiji-devel

---
You received this message because you are subscribed to the Google Groups "Fiji-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel

signature.asc (465 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [fiji-devel] creating io.scif.img.ImgOpener currently fails in Fiji

Curtis Rueden
Hi Tobias,

> java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.LegacyAppEventService
>         at org.scijava.service.ServiceHelper.createExactService(ServiceHelper.java:280)
...
>         at org.scijava.Context.<init>(Context.java:128)
>         at io.scif.img.AbstractImgIOComponent.<init>(AbstractImgIOComponent.java:57)
>         at io.scif.img.ImgOpener.<init>(ImgOpener.java:94)

Actually, this problem is a known bug, for which I am already working on a fix:


It is not a problem in your code, Tobias.

Basically, the problem comes down to this "AppEventService" and how the design of it works. I have a strategy in mind for a new design that avoids the "cascade" of service dependencies which end up pulling in a LegacyService into a pure SCIFIO context, which is what causes this error.

Feel free to comment on the PR if you wish to follow the progress.

Regards,
Curtis


On Fri, Aug 22, 2014 at 9:35 AM, Tobias Pietzsch <[hidden email]> wrote:
Hi Johannes,

On 22 Aug 2014, at 09:04, Johannes Schindelin <[hidden email]> wrote:

Hi Tobias,

On Fri, 22 Aug 2014, Tobias Pietzsch wrote:

Currently
new io.scif.img.ImgOpener();
fails with
java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.LegacyAppEventService

Yep, the explanation is very easy:

[...]
Caused by: java.lang.UnsupportedOperationException: Cannot instantiate more than one DefaultLegacyService
[…]

I missed that...


There is already a context, including a legacy service. Unfortunately, the
best way to get at this context from an *ImageJ 1.x plugin* that I could
come up with is:

import org.scijava.Context;

...

final Context context = (Context)
IJ.runPlugIn(Context.class.getName(), "");
final ImgOpener opener = new ImgOpener(context);

(There is no way to make that more convenient without letting SCIFIO
depend on ImageJ 1.x, which is of course a big no-no).

The problem with this solution you suggested is that it does not work in Eclipse:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.DefaultLegacyService

As much as I understand the need for the runtime service discovery used by the scijava stack, there are certainly downsides to it.
My feeling is that in some ways it undermines the advantages that we have gained by switching to maven.
I can import a maven project into my Eclipse, and all the dependencies are there, explicitly and automatically, which is really very convenient.
Except now all dependencies are not there anymore because now there are non-obvious (to me) implicit runtime dependencies.
I find this unfortunate.

That being said, I found a solution that works for now, both in Eclipse and in Fiji
    final ImgOpener opener = new ImgOpener( new Context( SCIFIOService.class, AppService.class, StatusService.class ) );
This avoids requiring the net.imagej.legacy.LegacyAppEventService.
It seems to work, but I’m not sure: Are there any downsides to that?

best regards,
Tobias


Of course, you could also turn your plugin into an ImageJ2 plugin -- which
is handled properly in Fiji thanks to Fiji Just Being ImageJ2 -- and then
it would become as easy as:

@Parameter
private IOService io;

...
// use the IOService (which lets SCIFIO handle
// things) to open your dataset

Ciao,
Johannes

--
--
Please avoid top-posting, and please make sure to reply-to-all!

Mailing list web interface: http://groups.google.com/group/fiji-devel

---
You received this message because you are subscribed to the Google Groups "Fiji-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.



_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: [fiji-devel] creating io.scif.img.ImgOpener currently fails in Fiji

Curtis Rueden
In reply to this post by Tobias Pietzsch
Hi Tobias,

> Except now all dependencies are not there anymore because now there
> are non-obvious (to me) implicit runtime dependencies.
>
> I find this unfortunate.

I agree that this is a two-edged sword. We have more types of plugins now, which can alter the runtime behavior in more ways, so of course it becomes possible for ill-behaved plugins to bring down the system.

This is already true in ImageJ 1.x though, because it is extensible at runtime: any plugin class could have a static initializer block that hoses up the JVM however it can imagine. It is just easier to do now.

IMO, it would not be worth it to eliminate these powerful extension points just because of this possibility. The flexibility gained outweighs any disadvantages.

We have already taken great pains to mitigate the issue with services in the context: when you create a new ImgOpener without specifying an SJC context, it uses _only_ relevant service types: things that implement the SciJavaService and SCIFIOService interfaces. In other words: _not_ ImageJServices or other service types. The reason LegacyService is being (erroneously!) pulled in here is due to a bug in the design of the SJC AppEventService, as I said. I introduced a "LegacyAppEventService" which is a SciJavaService but depends on the ImageJ LegacyService. Hence, any Context that asks for SciJavaServices now pulls in a DefaultLegacyService whenever the LegacyAppEventService is on the classpath. The fix is to stop doing that.

Anyway, if it still bothers you that any ol' developer can add something to the classpath which hoses up your programs, then you can stop it: create a more carefully controlled SJC Context and pass that to the ImgOpener. Alternately, we could change ImgOpener to be even more conservative in which services it uses. Of course, there are downsides there: any additional file format plugins, codec plugins, etc., might not be work properly if they do not have access to the services they need.

I am very open to ideas for mitigating the extensibility issues here.

Regards,
Curtis


On Fri, Aug 22, 2014 at 9:35 AM, Tobias Pietzsch <[hidden email]> wrote:
Hi Johannes,

On 22 Aug 2014, at 09:04, Johannes Schindelin <[hidden email]> wrote:

Hi Tobias,

On Fri, 22 Aug 2014, Tobias Pietzsch wrote:

Currently
new io.scif.img.ImgOpener();
fails with
java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.LegacyAppEventService

Yep, the explanation is very easy:

[...]
Caused by: java.lang.UnsupportedOperationException: Cannot instantiate more than one DefaultLegacyService
[…]

I missed that...


There is already a context, including a legacy service. Unfortunately, the
best way to get at this context from an *ImageJ 1.x plugin* that I could
come up with is:

import org.scijava.Context;

...

final Context context = (Context)
IJ.runPlugIn(Context.class.getName(), "");
final ImgOpener opener = new ImgOpener(context);

(There is no way to make that more convenient without letting SCIFIO
depend on ImageJ 1.x, which is of course a big no-no).

The problem with this solution you suggested is that it does not work in Eclipse:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.DefaultLegacyService

As much as I understand the need for the runtime service discovery used by the scijava stack, there are certainly downsides to it.
My feeling is that in some ways it undermines the advantages that we have gained by switching to maven.
I can import a maven project into my Eclipse, and all the dependencies are there, explicitly and automatically, which is really very convenient.
Except now all dependencies are not there anymore because now there are non-obvious (to me) implicit runtime dependencies.
I find this unfortunate.

That being said, I found a solution that works for now, both in Eclipse and in Fiji
    final ImgOpener opener = new ImgOpener( new Context( SCIFIOService.class, AppService.class, StatusService.class ) );
This avoids requiring the net.imagej.legacy.LegacyAppEventService.
It seems to work, but I’m not sure: Are there any downsides to that?

best regards,
Tobias


Of course, you could also turn your plugin into an ImageJ2 plugin -- which
is handled properly in Fiji thanks to Fiji Just Being ImageJ2 -- and then
it would become as easy as:

@Parameter
private IOService io;

...
// use the IOService (which lets SCIFIO handle
// things) to open your dataset

Ciao,
Johannes

--
--
Please avoid top-posting, and please make sure to reply-to-all!

Mailing list web interface: http://groups.google.com/group/fiji-devel

---
You received this message because you are subscribed to the Google Groups "Fiji-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.



_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: [fiji-devel] creating io.scif.img.ImgOpener currently fails in Fiji

dscho
Administrator
In reply to this post by Tobias Pietzsch
Hi Tobias,

On Fri, 22 Aug 2014, Tobias Pietzsch wrote:

>     final ImgOpener opener = new ImgOpener( new Context(
>     SCIFIOService.class, AppService.class, StatusService.class ) );

Why do you create a new Context everytime? That's a bit wasteful...

Ciao,
Johannes

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: [fiji-devel] creating io.scif.img.ImgOpener currently fails in Fiji

Tobias Pietzsch
Hi Johannes,

On 22 Aug 2014, at 17:53, Johannes Schindelin <[hidden email]> wrote:

Hi Tobias,

On Fri, 22 Aug 2014, Tobias Pietzsch wrote:

   final ImgOpener opener = new ImgOpener( new Context(
   SCIFIOService.class, AppService.class, StatusService.class ) );

Why do you create a new Context everytime? That's a bit wasteful…

That is true, but I’m not sure how to improve it.

The problem is that I know too little about how the infrastructure around Context works.
I assume in Fiji there is only one Context that is used by everything? An I get it the way you described?
In Eclipse, for testing, I have a main() method that just says
new ExportSpimSequencePlugIn().run( null );
so there is no Fiji that has a Context.
How would I make something that works in both cases?

best regards,
Tobias


Ciao,
Johannes


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel

signature.asc (465 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [fiji-devel] creating io.scif.img.ImgOpener currently fails in Fiji

Tobias Pietzsch
In reply to this post by Curtis Rueden
Hi Curtis,

On 22 Aug 2014, at 16:51, Curtis Rueden <[hidden email]> wrote:

Hi Tobias,

> Except now all dependencies are not there anymore because now there
> are non-obvious (to me) implicit runtime dependencies.
>
> I find this unfortunate.

I agree that this is a two-edged sword. We have more types of plugins now, which can alter the runtime behavior in more ways, so of course it becomes possible for ill-behaved plugins to bring down the system.

This is already true in ImageJ 1.x though, because it is extensible at runtime: any plugin class could have a static initializer block that hoses up the JVM however it can imagine. It is just easier to do now.

IMO, it would not be worth it to eliminate these powerful extension points just because of this possibility. The flexibility gained outweighs any disadvantages.

I agree that it is very powerful and I’m not proposing to eliminate it.

I’m happy that my problem is just a quirk and that I will be able to continue just calling new ImgOpener(), in blissfull ignorance of what is going on behind the scenes.

We have already taken great pains to mitigate the issue with services in the context: when you create a new ImgOpener without specifying an SJC context, it uses _only_ relevant service types: things that implement the SciJavaService and SCIFIOService interfaces. In other words: _not_ ImageJServices or other service types. The reason LegacyService is being (erroneously!) pulled in here is due to a bug in the design of the SJC AppEventService, as I said. I introduced a "LegacyAppEventService" which is a SciJavaService but depends on the ImageJ LegacyService. Hence, any Context that asks for SciJavaServices now pulls in a DefaultLegacyService whenever the LegacyAppEventService is on the classpath. The fix is to stop doing that.

Anyway, if it still bothers you that any ol' developer can add something to the classpath which hoses up your programs, then you can stop it: create a more carefully controlled SJC Context and pass that to the ImgOpener. Alternately, we could change ImgOpener to be even more conservative in which services it uses. Of course, there are downsides there: any additional file format plugins, codec plugins, etc., might not be work properly if they do not have access to the services they need.

I am very open to ideas for mitigating the extensibility issues here.

I currently have only limited knowledge of the workings of scijava-common so I admit that I have no ideas here.

I imagine that in many cases it would be helpful to somehow produce an explicit list of transitive (runtime) dependencies at compile time. But this is probably not possible because these dependencies are specified as interfaces and there is no way of knowing beforehand the dependencies of the implementing class that will be used at runtime.
In the present case it is even worse, because, if I understand correctly, simply put the problem was not a missing dependency is missing but additional stuff being present?

best regards,
Tobias


Regards,
Curtis


On Fri, Aug 22, 2014 at 9:35 AM, Tobias Pietzsch <[hidden email]> wrote:
Hi Johannes,

On 22 Aug 2014, at 09:04, Johannes Schindelin <[hidden email]> wrote:

Hi Tobias,

On Fri, 22 Aug 2014, Tobias Pietzsch wrote:

Currently
new io.scif.img.ImgOpener();
fails with
java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.LegacyAppEventService

Yep, the explanation is very easy:

[...]
Caused by: java.lang.UnsupportedOperationException: Cannot instantiate more than one DefaultLegacyService
[…]

I missed that...


There is already a context, including a legacy service. Unfortunately, the
best way to get at this context from an *ImageJ 1.x plugin* that I could
come up with is:

import org.scijava.Context;

...

final Context context = (Context)
IJ.runPlugIn(Context.class.getName(), "");
final ImgOpener opener = new ImgOpener(context);

(There is no way to make that more convenient without letting SCIFIO
depend on ImageJ 1.x, which is of course a big no-no).

The problem with this solution you suggested is that it does not work in Eclipse:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.DefaultLegacyService

As much as I understand the need for the runtime service discovery used by the scijava stack, there are certainly downsides to it.
My feeling is that in some ways it undermines the advantages that we have gained by switching to maven.
I can import a maven project into my Eclipse, and all the dependencies are there, explicitly and automatically, which is really very convenient.
Except now all dependencies are not there anymore because now there are non-obvious (to me) implicit runtime dependencies.
I find this unfortunate.

That being said, I found a solution that works for now, both in Eclipse and in Fiji
    final ImgOpener opener = new ImgOpener( new Context( SCIFIOService.class, AppService.class, StatusService.class ) );
This avoids requiring the net.imagej.legacy.LegacyAppEventService.
It seems to work, but I’m not sure: Are there any downsides to that?

best regards,
Tobias


Of course, you could also turn your plugin into an ImageJ2 plugin -- which
is handled properly in Fiji thanks to Fiji Just Being ImageJ2 -- and then
it would become as easy as:

@Parameter
private IOService io;

...
// use the IOService (which lets SCIFIO handle
// things) to open your dataset

Ciao,
Johannes

--
--
Please avoid top-posting, and please make sure to reply-to-all!

Mailing list web interface: http://groups.google.com/group/fiji-devel

---
You received this message because you are subscribed to the Google Groups "Fiji-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.




_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel

signature.asc (465 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [fiji-devel] creating io.scif.img.ImgOpener currently fails in Fiji

Curtis Rueden
Hi Tobias,

> I imagine that in many cases it would be helpful to somehow produce an
> explicit list of transitive (runtime) dependencies at compile time.
> But this is probably not possible because these dependencies are
> specified as interfaces and there is no way of knowing beforehand the
> dependencies of the implementing class that will be used at runtime.

Actually, you can do it either way. If you ask for an interface, it adds all concrete service plugins that implement that interface. If you ask for a concrete class, you get that concrete class only. But it is true that whenever you ask for an interface, you will also transitively bring in all dependencies of all implementing classes.

> In the present case it is even worse, because, if I understand
> correctly, simply put the problem was not a missing dependency is
> missing but additional stuff being present?

Right. There was an additional AppEventService that had a dependency on the most problematic and limited ImageJ service: the DefaultLegacyService.

Another way I plan to (eventually!) mitigate that is to make the DefaultLegacyService less crabby: I want it to be possible to have more than one, that simply ends up referencing the same instance of ImageJ 1.x. This shouldn't be too hard to do but haven't had to time explore that yet. This would "paper over" the problem you had in that you wouldn't have received an exception, but still would have brought in a whole bunch of unneeded service dependencies for the purposes of ImgOpener.

The real fix here is to retool the AppEvent API as described here:

This is a critical bug in SJC which I will work on resolving today if possible.

Regards,
Curtis



On Fri, Aug 22, 2014 at 11:45 AM, Tobias Pietzsch <[hidden email]> wrote:
Hi Curtis,

On 22 Aug 2014, at 16:51, Curtis Rueden <[hidden email]> wrote:

Hi Tobias,

> Except now all dependencies are not there anymore because now there
> are non-obvious (to me) implicit runtime dependencies.
>
> I find this unfortunate.

I agree that this is a two-edged sword. We have more types of plugins now, which can alter the runtime behavior in more ways, so of course it becomes possible for ill-behaved plugins to bring down the system.

This is already true in ImageJ 1.x though, because it is extensible at runtime: any plugin class could have a static initializer block that hoses up the JVM however it can imagine. It is just easier to do now.

IMO, it would not be worth it to eliminate these powerful extension points just because of this possibility. The flexibility gained outweighs any disadvantages.

I agree that it is very powerful and I’m not proposing to eliminate it.

I’m happy that my problem is just a quirk and that I will be able to continue just calling new ImgOpener(), in blissfull ignorance of what is going on behind the scenes.

We have already taken great pains to mitigate the issue with services in the context: when you create a new ImgOpener without specifying an SJC context, it uses _only_ relevant service types: things that implement the SciJavaService and SCIFIOService interfaces. In other words: _not_ ImageJServices or other service types. The reason LegacyService is being (erroneously!) pulled in here is due to a bug in the design of the SJC AppEventService, as I said. I introduced a "LegacyAppEventService" which is a SciJavaService but depends on the ImageJ LegacyService. Hence, any Context that asks for SciJavaServices now pulls in a DefaultLegacyService whenever the LegacyAppEventService is on the classpath. The fix is to stop doing that.

Anyway, if it still bothers you that any ol' developer can add something to the classpath which hoses up your programs, then you can stop it: create a more carefully controlled SJC Context and pass that to the ImgOpener. Alternately, we could change ImgOpener to be even more conservative in which services it uses. Of course, there are downsides there: any additional file format plugins, codec plugins, etc., might not be work properly if they do not have access to the services they need.

I am very open to ideas for mitigating the extensibility issues here.

I currently have only limited knowledge of the workings of scijava-common so I admit that I have no ideas here.

I imagine that in many cases it would be helpful to somehow produce an explicit list of transitive (runtime) dependencies at compile time. But this is probably not possible because these dependencies are specified as interfaces and there is no way of knowing beforehand the dependencies of the implementing class that will be used at runtime.
In the present case it is even worse, because, if I understand correctly, simply put the problem was not a missing dependency is missing but additional stuff being present?

best regards,
Tobias


Regards,
Curtis


On Fri, Aug 22, 2014 at 9:35 AM, Tobias Pietzsch <[hidden email]> wrote:
Hi Johannes,

On 22 Aug 2014, at 09:04, Johannes Schindelin <[hidden email]> wrote:

Hi Tobias,

On Fri, 22 Aug 2014, Tobias Pietzsch wrote:

Currently
new io.scif.img.ImgOpener();
fails with
java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.LegacyAppEventService

Yep, the explanation is very easy:

[...]
Caused by: java.lang.UnsupportedOperationException: Cannot instantiate more than one DefaultLegacyService
[…]

I missed that...


There is already a context, including a legacy service. Unfortunately, the
best way to get at this context from an *ImageJ 1.x plugin* that I could
come up with is:

import org.scijava.Context;

...

final Context context = (Context)
IJ.runPlugIn(Context.class.getName(), "");
final ImgOpener opener = new ImgOpener(context);

(There is no way to make that more convenient without letting SCIFIO
depend on ImageJ 1.x, which is of course a big no-no).

The problem with this solution you suggested is that it does not work in Eclipse:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.DefaultLegacyService

As much as I understand the need for the runtime service discovery used by the scijava stack, there are certainly downsides to it.
My feeling is that in some ways it undermines the advantages that we have gained by switching to maven.
I can import a maven project into my Eclipse, and all the dependencies are there, explicitly and automatically, which is really very convenient.
Except now all dependencies are not there anymore because now there are non-obvious (to me) implicit runtime dependencies.
I find this unfortunate.

That being said, I found a solution that works for now, both in Eclipse and in Fiji
    final ImgOpener opener = new ImgOpener( new Context( SCIFIOService.class, AppService.class, StatusService.class ) );
This avoids requiring the net.imagej.legacy.LegacyAppEventService.
It seems to work, but I’m not sure: Are there any downsides to that?

best regards,
Tobias


Of course, you could also turn your plugin into an ImageJ2 plugin -- which
is handled properly in Fiji thanks to Fiji Just Being ImageJ2 -- and then
it would become as easy as:

@Parameter
private IOService io;

...
// use the IOService (which lets SCIFIO handle
// things) to open your dataset

Ciao,
Johannes

--
--
Please avoid top-posting, and please make sure to reply-to-all!

Mailing list web interface: http://groups.google.com/group/fiji-devel

---
You received this message because you are subscribed to the Google Groups "Fiji-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.





_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: [fiji-devel] creating io.scif.img.ImgOpener currently fails in Fiji

Curtis Rueden
Hi Tobias,

> This is a critical bug in SJC which I will work on resolving today if
> possible.

Latest released versions of the SciJava software stack now have this bug fixed.

You can get the needed component versions by using pom-imagej 2.49 as parent.

Regards,
Curtis


On Fri, Aug 22, 2014 at 11:51 AM, Curtis Rueden <[hidden email]> wrote:
Hi Tobias,

> I imagine that in many cases it would be helpful to somehow produce an
> explicit list of transitive (runtime) dependencies at compile time.
> But this is probably not possible because these dependencies are
> specified as interfaces and there is no way of knowing beforehand the
> dependencies of the implementing class that will be used at runtime.

Actually, you can do it either way. If you ask for an interface, it adds all concrete service plugins that implement that interface. If you ask for a concrete class, you get that concrete class only. But it is true that whenever you ask for an interface, you will also transitively bring in all dependencies of all implementing classes.

> In the present case it is even worse, because, if I understand
> correctly, simply put the problem was not a missing dependency is
> missing but additional stuff being present?

Right. There was an additional AppEventService that had a dependency on the most problematic and limited ImageJ service: the DefaultLegacyService.

Another way I plan to (eventually!) mitigate that is to make the DefaultLegacyService less crabby: I want it to be possible to have more than one, that simply ends up referencing the same instance of ImageJ 1.x. This shouldn't be too hard to do but haven't had to time explore that yet. This would "paper over" the problem you had in that you wouldn't have received an exception, but still would have brought in a whole bunch of unneeded service dependencies for the purposes of ImgOpener.

The real fix here is to retool the AppEvent API as described here:

This is a critical bug in SJC which I will work on resolving today if possible.

Regards,
Curtis



On Fri, Aug 22, 2014 at 11:45 AM, Tobias Pietzsch <[hidden email]> wrote:
Hi Curtis,

On 22 Aug 2014, at 16:51, Curtis Rueden <[hidden email]> wrote:

Hi Tobias,

> Except now all dependencies are not there anymore because now there
> are non-obvious (to me) implicit runtime dependencies.
>
> I find this unfortunate.

I agree that this is a two-edged sword. We have more types of plugins now, which can alter the runtime behavior in more ways, so of course it becomes possible for ill-behaved plugins to bring down the system.

This is already true in ImageJ 1.x though, because it is extensible at runtime: any plugin class could have a static initializer block that hoses up the JVM however it can imagine. It is just easier to do now.

IMO, it would not be worth it to eliminate these powerful extension points just because of this possibility. The flexibility gained outweighs any disadvantages.

I agree that it is very powerful and I’m not proposing to eliminate it.

I’m happy that my problem is just a quirk and that I will be able to continue just calling new ImgOpener(), in blissfull ignorance of what is going on behind the scenes.

We have already taken great pains to mitigate the issue with services in the context: when you create a new ImgOpener without specifying an SJC context, it uses _only_ relevant service types: things that implement the SciJavaService and SCIFIOService interfaces. In other words: _not_ ImageJServices or other service types. The reason LegacyService is being (erroneously!) pulled in here is due to a bug in the design of the SJC AppEventService, as I said. I introduced a "LegacyAppEventService" which is a SciJavaService but depends on the ImageJ LegacyService. Hence, any Context that asks for SciJavaServices now pulls in a DefaultLegacyService whenever the LegacyAppEventService is on the classpath. The fix is to stop doing that.

Anyway, if it still bothers you that any ol' developer can add something to the classpath which hoses up your programs, then you can stop it: create a more carefully controlled SJC Context and pass that to the ImgOpener. Alternately, we could change ImgOpener to be even more conservative in which services it uses. Of course, there are downsides there: any additional file format plugins, codec plugins, etc., might not be work properly if they do not have access to the services they need.

I am very open to ideas for mitigating the extensibility issues here.

I currently have only limited knowledge of the workings of scijava-common so I admit that I have no ideas here.

I imagine that in many cases it would be helpful to somehow produce an explicit list of transitive (runtime) dependencies at compile time. But this is probably not possible because these dependencies are specified as interfaces and there is no way of knowing beforehand the dependencies of the implementing class that will be used at runtime.
In the present case it is even worse, because, if I understand correctly, simply put the problem was not a missing dependency is missing but additional stuff being present?

best regards,
Tobias


Regards,
Curtis


On Fri, Aug 22, 2014 at 9:35 AM, Tobias Pietzsch <[hidden email]> wrote:
Hi Johannes,

On 22 Aug 2014, at 09:04, Johannes Schindelin <[hidden email]> wrote:

Hi Tobias,

On Fri, 22 Aug 2014, Tobias Pietzsch wrote:

Currently
new io.scif.img.ImgOpener();
fails with
java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.LegacyAppEventService

Yep, the explanation is very easy:

[...]
Caused by: java.lang.UnsupportedOperationException: Cannot instantiate more than one DefaultLegacyService
[…]

I missed that...


There is already a context, including a legacy service. Unfortunately, the
best way to get at this context from an *ImageJ 1.x plugin* that I could
come up with is:

import org.scijava.Context;

...

final Context context = (Context)
IJ.runPlugIn(Context.class.getName(), "");
final ImgOpener opener = new ImgOpener(context);

(There is no way to make that more convenient without letting SCIFIO
depend on ImageJ 1.x, which is of course a big no-no).

The problem with this solution you suggested is that it does not work in Eclipse:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.DefaultLegacyService

As much as I understand the need for the runtime service discovery used by the scijava stack, there are certainly downsides to it.
My feeling is that in some ways it undermines the advantages that we have gained by switching to maven.
I can import a maven project into my Eclipse, and all the dependencies are there, explicitly and automatically, which is really very convenient.
Except now all dependencies are not there anymore because now there are non-obvious (to me) implicit runtime dependencies.
I find this unfortunate.

That being said, I found a solution that works for now, both in Eclipse and in Fiji
    final ImgOpener opener = new ImgOpener( new Context( SCIFIOService.class, AppService.class, StatusService.class ) );
This avoids requiring the net.imagej.legacy.LegacyAppEventService.
It seems to work, but I’m not sure: Are there any downsides to that?

best regards,
Tobias


Of course, you could also turn your plugin into an ImageJ2 plugin -- which
is handled properly in Fiji thanks to Fiji Just Being ImageJ2 -- and then
it would become as easy as:

@Parameter
private IOService io;

...
// use the IOService (which lets SCIFIO handle
// things) to open your dataset

Ciao,
Johannes

--
--
Please avoid top-posting, and please make sure to reply-to-all!

Mailing list web interface: http://groups.google.com/group/fiji-devel

---
You received this message because you are subscribed to the Google Groups "Fiji-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.






_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: [fiji-devel] creating io.scif.img.ImgOpener currently fails in Fiji

Tobias Pietzsch
Awesome! Thank you!
Tobias

On 25 Aug 2014, at 20:03, Curtis Rueden <[hidden email]> wrote:

Hi Tobias,

> This is a critical bug in SJC which I will work on resolving today if
> possible.

Latest released versions of the SciJava software stack now have this bug fixed.

You can get the needed component versions by using pom-imagej 2.49 as parent.

Regards,
Curtis


On Fri, Aug 22, 2014 at 11:51 AM, Curtis Rueden <[hidden email]> wrote:
Hi Tobias,

> I imagine that in many cases it would be helpful to somehow produce an
> explicit list of transitive (runtime) dependencies at compile time.
> But this is probably not possible because these dependencies are
> specified as interfaces and there is no way of knowing beforehand the
> dependencies of the implementing class that will be used at runtime.

Actually, you can do it either way. If you ask for an interface, it adds all concrete service plugins that implement that interface. If you ask for a concrete class, you get that concrete class only. But it is true that whenever you ask for an interface, you will also transitively bring in all dependencies of all implementing classes.

> In the present case it is even worse, because, if I understand
> correctly, simply put the problem was not a missing dependency is
> missing but additional stuff being present?

Right. There was an additional AppEventService that had a dependency on the most problematic and limited ImageJ service: the DefaultLegacyService.

Another way I plan to (eventually!) mitigate that is to make the DefaultLegacyService less crabby: I want it to be possible to have more than one, that simply ends up referencing the same instance of ImageJ 1.x. This shouldn't be too hard to do but haven't had to time explore that yet. This would "paper over" the problem you had in that you wouldn't have received an exception, but still would have brought in a whole bunch of unneeded service dependencies for the purposes of ImgOpener.

The real fix here is to retool the AppEvent API as described here:

This is a critical bug in SJC which I will work on resolving today if possible.

Regards,
Curtis



On Fri, Aug 22, 2014 at 11:45 AM, Tobias Pietzsch <[hidden email]> wrote:
Hi Curtis,

On 22 Aug 2014, at 16:51, Curtis Rueden <[hidden email]> wrote:

Hi Tobias,

> Except now all dependencies are not there anymore because now there
> are non-obvious (to me) implicit runtime dependencies.
>
> I find this unfortunate.

I agree that this is a two-edged sword. We have more types of plugins now, which can alter the runtime behavior in more ways, so of course it becomes possible for ill-behaved plugins to bring down the system.

This is already true in ImageJ 1.x though, because it is extensible at runtime: any plugin class could have a static initializer block that hoses up the JVM however it can imagine. It is just easier to do now.

IMO, it would not be worth it to eliminate these powerful extension points just because of this possibility. The flexibility gained outweighs any disadvantages.

I agree that it is very powerful and I’m not proposing to eliminate it.

I’m happy that my problem is just a quirk and that I will be able to continue just calling new ImgOpener(), in blissfull ignorance of what is going on behind the scenes.

We have already taken great pains to mitigate the issue with services in the context: when you create a new ImgOpener without specifying an SJC context, it uses _only_ relevant service types: things that implement the SciJavaService and SCIFIOService interfaces. In other words: _not_ ImageJServices or other service types. The reason LegacyService is being (erroneously!) pulled in here is due to a bug in the design of the SJC AppEventService, as I said. I introduced a "LegacyAppEventService" which is a SciJavaService but depends on the ImageJ LegacyService. Hence, any Context that asks for SciJavaServices now pulls in a DefaultLegacyService whenever the LegacyAppEventService is on the classpath. The fix is to stop doing that.

Anyway, if it still bothers you that any ol' developer can add something to the classpath which hoses up your programs, then you can stop it: create a more carefully controlled SJC Context and pass that to the ImgOpener. Alternately, we could change ImgOpener to be even more conservative in which services it uses. Of course, there are downsides there: any additional file format plugins, codec plugins, etc., might not be work properly if they do not have access to the services they need.

I am very open to ideas for mitigating the extensibility issues here.

I currently have only limited knowledge of the workings of scijava-common so I admit that I have no ideas here.

I imagine that in many cases it would be helpful to somehow produce an explicit list of transitive (runtime) dependencies at compile time. But this is probably not possible because these dependencies are specified as interfaces and there is no way of knowing beforehand the dependencies of the implementing class that will be used at runtime.
In the present case it is even worse, because, if I understand correctly, simply put the problem was not a missing dependency is missing but additional stuff being present?

best regards,
Tobias


Regards,
Curtis


On Fri, Aug 22, 2014 at 9:35 AM, Tobias Pietzsch <[hidden email]> wrote:
Hi Johannes,

On 22 Aug 2014, at 09:04, Johannes Schindelin <[hidden email]> wrote:

Hi Tobias,

On Fri, 22 Aug 2014, Tobias Pietzsch wrote:

Currently
new io.scif.img.ImgOpener();
fails with
java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.LegacyAppEventService

Yep, the explanation is very easy:

[...]
Caused by: java.lang.UnsupportedOperationException: Cannot instantiate more than one DefaultLegacyService
[…]

I missed that...


There is already a context, including a legacy service. Unfortunately, the
best way to get at this context from an *ImageJ 1.x plugin* that I could
come up with is:

import org.scijava.Context;

...

final Context context = (Context)
IJ.runPlugIn(Context.class.getName(), "");
final ImgOpener opener = new ImgOpener(context);

(There is no way to make that more convenient without letting SCIFIO
depend on ImageJ 1.x, which is of course a big no-no).

The problem with this solution you suggested is that it does not work in Eclipse:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid service: net.imagej.legacy.DefaultLegacyService

As much as I understand the need for the runtime service discovery used by the scijava stack, there are certainly downsides to it.
My feeling is that in some ways it undermines the advantages that we have gained by switching to maven.
I can import a maven project into my Eclipse, and all the dependencies are there, explicitly and automatically, which is really very convenient.
Except now all dependencies are not there anymore because now there are non-obvious (to me) implicit runtime dependencies.
I find this unfortunate.

That being said, I found a solution that works for now, both in Eclipse and in Fiji
    final ImgOpener opener = new ImgOpener( new Context( SCIFIOService.class, AppService.class, StatusService.class ) );
This avoids requiring the net.imagej.legacy.LegacyAppEventService.
It seems to work, but I’m not sure: Are there any downsides to that?

best regards,
Tobias


Of course, you could also turn your plugin into an ImageJ2 plugin -- which
is handled properly in Fiji thanks to Fiji Just Being ImageJ2 -- and then
it would become as easy as:

@Parameter
private IOService io;

...
// use the IOService (which lets SCIFIO handle
// things) to open your dataset

Ciao,
Johannes

--
--
Please avoid top-posting, and please make sure to reply-to-all!

Mailing list web interface: http://groups.google.com/group/fiji-devel

---
You received this message because you are subscribed to the Google Groups "Fiji-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.







_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel

signature.asc (465 bytes) Download Attachment