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

Curtis Rueden ctrueden at wisc.edu
Mon Aug 25 13:03:30 CDT 2014


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 <ctrueden at wisc.edu> 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:
>
> https://github.com/scijava/scijava-common/commit/852f05cf1dbfb3ce99ccd416fee64573a0692764
>
> 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 <pietzsch at mpi-cbg.de>
> wrote:
>
>> Hi Curtis,
>>
>> On 22 Aug 2014, at 16:51, Curtis Rueden <ctrueden at wisc.edu> 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 <pietzsch at mpi-cbg.de>
>> wrote:
>>
>>> Hi Johannes,
>>>
>>> On 22 Aug 2014, at 09:04, Johannes Schindelin <
>>> Johannes.Schindelin at gmx.de> 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 fiji-devel+unsubscribe at googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>>
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://imagej.net/pipermail/imagej-devel/attachments/20140825/fe6e0fd5/attachment.html>


More information about the ImageJ-devel mailing list