Ticket #1641 (closed defect: wontfix)

Opened 7 years ago

Last modified 6 years ago

Bypassing pre and post processors problematic

Reported by: bdezonia Owned by: curtis
Priority: major Milestone: imagej2-b10-compatibility
Component: Plugin Framework Version:
Severity: serious Keywords:
Cc: Blocked By:
Blocking: #1696

Description

ImageJ2 supports multiple methods of Command invokation. One supported method is by direct Java calls bypassing the command services. This method bypasses pre and post processors. Unfortunately one of the preprocessors is the InitPreprocessor which is responsible for initializing Commands with annotated initializers. These Commands do not get initialized correctly.

Ideally we would be able to always run initializers when the api user calls some method of Command. An initial approach would be in setContext() (of both ContextCommand and DynamicCommand). However ctrueden sees a double initialization issue here.

Change History

comment:1 Changed 7 years ago by bdezonia

Note that I discovered this issue by converting NewImage plugin to a DynamicCommand from a ContextCommand. The code in InvokeCommandTest had to be recompiled and after the change running the plugin would cause a NPE. I hacked the initialization code in NewImage to avoid this case (and documented well what was being done). If we fix this bug in a general way we should cleanup NewImage a little and make sure to test that InvokeCommandTest works.

comment:2 Changed 7 years ago by curtis

The real difficulty is that InitPreprocessor is not the only desirable preprocessor that someone may want to execute on their command, prior to running it. In particular, many initialization methods require other parameters to have been populated earlier in the chain: Services in particular, but also Datasets, DatasetViews and ImageDisplays, via the ActiveDisplayPreprocessor and ActiveImagePreprocessor. There is also a UIPreprocessor that populates UserInterface inputs, and other similar preprocessors could exist for other sorts of inputs—ImageJ2's extensibility makes this very possible.

Intuitively, it seems to me that a suitable subset of the preprocessors need to be flagged somehow for execution in the programmatic context. In other words, we should get rid of the hack in ContextCommand#setContext(ImageJ) which calls CommandService#populateServices(ContextCommand), and instead have a CommandService#selectivePreprocess or some such, that applies only those preprocessors matching the suitability criteria. This could be as simple as a boolean flag of the @Plugin annotation, or we could have some other way of deciding.

Another issue is whether such preprocessing should fire any events. Our current approach with populating the services is not to do so, but it seems strange to apply an extensible set of suitable preprocessors without telling anyone about it.

Thoughts?

comment:3 Changed 7 years ago by bdezonia

  • Priority changed from major to review

comment:4 Changed 7 years ago by bdezonia

  • Priority changed from review to major

comment:5 Changed 7 years ago by bdezonia

  • Owner changed from curtis to bdezonia
  • Status changed from new to reviewing

comment:6 Changed 7 years ago by curtis

  • Owner changed from bdezonia to curtis
  • Status changed from reviewing to accepted
  • Milestone changed from imagej2-b7-ndim-data to imagej2-b10-compatibility

comment:7 Changed 7 years ago by curtis

  • Component changed from Core to Plugin Framework
  • Blocking 1696 added; 1357 removed

comment:8 Changed 6 years ago by curtis

Note that InvokeCommandTest has been removed in favor of an ImageJ tutorial showing how to execute commands (which now uses OpenFile for simplicity and to avoid this issue). However, this issue still needs to be fixed.

comment:9 Changed 6 years ago by curtis

  • Status changed from accepted to closed
  • Resolution set to wontfix

A  recent thread on imagej-devel touched on many related issues, including the initialization of modules. We concluded that for use cases where the pre- and post-processing steps are omitted, it is the responsibility of the caller to call initialize manually before executing the module. This greatly simplifies matters, because I see no general way of ensuring that initialize gets called by the module framework when the framework itself is being largely bypassed.

Last edited 6 years ago by curtis (previous) (diff)
Note: See TracTickets for help on using tickets.