Home » Eclipse Projects » Riena » ISaveable vs. Riena: Why supporting the Eclipse Jobs API might not be enough(Problem with supporting JFace-style long-running operations from within Riena)
ISaveable vs. Riena: Why supporting the Eclipse Jobs API might not be enough [message #550257] |
Thu, 29 July 2010 16:08 |
Christian Kesselheim Messages: 59 Registered: June 2010 |
Member |
|
|
Hello everyone,
we've recently bumped into a slight nuisance associated with the way that (in our petty interpretation) Riena currently supports long-running interpretation.
The problem comes-in when you or the underlying framework component try to leverage the basic JFace support (i.e. "org.eclipse.jface.operation.IRunnableWithProgress" and friends) for long-running applications.
For example, the following code will work for any basic Eclipse RCP application: but not for those built on top of Riena (at least, thats how it looks to us at the moment):
IRunnableWithProgress runnable = new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
System.out.println("Do some work");
if (monitor.isCanceled())
return;
System.out.println("Do some more work");
}
};
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
window.run(true, true, runnable);
The same is true for any standard Eclipse facilities that uses the JFace operations instead of the high-level Eclipse Jobs API to schedule and visualize its background operations. For example, any ViewPart implementing ISaveable2 will cause something similar to the following NullPointerException to be triggered as soon as a user hits "Save" (the standard Eclipse command):
java.lang.NullPointerException
at org.eclipse.jface.action.StatusLineManager$1.isCanceled(StatusLineManager.java:180)
at org.eclipse.ui.internal.SaveableHelper$5.run(SaveableHelper.java:279)
at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464)
at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372)
at org.eclipse.jface.window.ApplicationWindow$1.run(ApplicationWindow.java:759)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
at org.eclipse.jface.window.ApplicationWindow.run(ApplicationWindow.java:756)
at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2600)
at org.eclipse.ui.internal.SaveableHelper.runProgressMonitorOperation(SaveableHelper.java:285)
at org.eclipse.ui.internal.SaveableHelper.runProgressMonitorOperation(SaveableHelper.java:264)
at org.eclipse.ui.internal.SaveableHelper.savePart(SaveableHelper.java:156)
at org.eclipse.ui.internal.EditorManager.savePart(EditorManager.java:1369)
at org.eclipse.ui.internal.WorkbenchPage.savePart(WorkbenchPage.java:3334)
at org.eclipse.ui.internal.SaveAction.run(SaveAction.java:68)
at org.eclipse.jface.action.Action.runWithEvent(Action.java:498)
at org.eclipse.jface.commands.ActionHandler.execute(ActionHandler.java:119)
at org.eclipse.core.commands.Command.executeWithChecks(Command.java:476)
at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508)
at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:169)
at org.eclipse.ui.internal.handlers.SlaveHandlerService.executeCommand(SlaveHandlerService.java:241)
at org.eclipse.ui.menus.CommandContributionItem.handleWidgetSelection(CommandContributionItem.java:820)
at org.eclipse.ui.menus.CommandContributionItem.access$19(CommandContributionItem.java:806)
at org.eclipse.ui.menus.CommandContributionItem$5.handleEvent(CommandContributionItem.java:796)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4066)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3657)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2629)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2593)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2427)
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:670)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:663)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.riena.navigation.ui.swt.application.SwtApplication.createView(SwtApplication.java:63)
at org.eclipse.riena.navigation.ui.application.AbstractApplication.start(AbstractApplication.java:64)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:619)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574)
at org.eclipse.equinox.launcher.Main.run(Main.java:1407)
at org.eclipse.equinox.launcher.Main.main(Main.java:1383)
What I think happens is that...:
- ...Riena doesn't use the standard Eclipse status bar widget (org.eclipse.jface.action.StatusLine) for implementing the application's status bar, but relies on its own implementation (org.eclipse.riena.ui.swt.Statusline) instead.
- ...in any Eclipse RCP or standalone JFace application, either the ApplicationWindow or WorkbenchWindow (via the presentation factory) will make sure that an instance of org.eclipse.jface.action.StatusLineManager (the class in charge of managing both the status bar itself as well as its contributions/decorations) gets created as soon as the window itself is initialized. Please note that this is NOT true for the widget itself, since at least in a Riena-based application no-one ever actually calls StatusLineManager.createControl(...).
- ...any subsequent invocation of ApplicationWindow.run(...) will then to to use this StatusLineManager to visualize the progress of the tasks it executes. Since in a Riena-based application, there's no actual control bound to the manager at this point in time, a NullPointerException is raised .
- ...Riena (at presents) only supports the use of the Eclipse Jobs API for scheduling & execution of long-runnings tasks (via its org.eclipse.riena.ui.core.uiprocess.ProgressProviderBridge). At least I haven't found any similar integration of JFace operations API so far.
My first question therefore is: Is my reasoning above correct? Are there any known workaround for using at least ISaveable2 in a Riena-driven application?
Secondly (assuming that the answer is "no"), I'd grateful to any committer of the Riena UI project who could outline a possible implementation strategy of this feature to me.
With my limited knowledge of Riena internals, I assume this would be something along the lines of:
- Create a sub-class of StatusLineManager that integrates with org.eclipse.riena.ui.core.uiprocess.IProgressVisualizer in a way that is similar to what org.eclipse.riena.ui.core.uiprocess.ProgressProviderBridge and org.eclipse.riena.ui.core.uiprocess.UICallbackDispatcher are currently doing for the Eclipse Jobs API.
- Adapt either the AbstractApplication, PresentationFactory or WorkbenchWindowAdvisor class to use this custom StatusLineManager implementation in place of the existing one coming from Eclipse itself.
What do you think? Any suggestions?
Thanks & kind regards,
Chris
|
|
|
Re: ISaveable vs. Riena: Why supporting the Eclipse Jobs API might not be enough [message #550422 is a reply to message #550257] |
Fri, 30 July 2010 10:33 |
Christian Campo Messages: 597 Registered: July 2009 |
Senior Member |
|
|
Am 29.07.10 18:08, schrieb Christian Kesselheim:
> Hello everyone,
>
> we've recently bumped into a slight nuisance associated with the way
> that (in our petty interpretation) Riena currently supports long-running
> interpretation.
>
> The problem comes-in when you or the underlying framework component try
> to leverage the basic JFace support (i.e.
> "org.eclipse.jface.operation.IRunnableWithProgress" and friends) for
> long-running applications.
>
> For example, the following code will work for any basic Eclipse RCP
> application: but not for those built on top of Riena (at least, thats
> how it looks to us at the moment):
>
>
> IRunnableWithProgress runnable = new IRunnableWithProgress() {
> @Override
> public void run(IProgressMonitor monitor) throws
> InvocationTargetException, InterruptedException {
> System.out.println("Do some work");
> if (monitor.isCanceled())
> return;
> System.out.println("Do some more work");
> }
> };
> IWorkbenchWindow window =
> PlatformUI.getWorkbench().getActiveWorkbenchWindow();
> window.run(true, true, runnable);
>
>
> The same is true for any standard Eclipse facilities that uses the JFace
> operations instead of the high-level Eclipse Jobs API to schedule and
> visualize its background operations. For example, any ViewPart
> implementing
> http://help.eclipse.org/helios/index.jsp?topic=/org.eclipse. platform.doc.isv/reference/api/org/eclipse/ui/ISaveablePart2 .html
> will cause something similar to the following NullPointerException to be
> triggered as soon as a user hits "Save" (the standard Eclipse command):
>
>
> java.lang.NullPointerException
> at
> org.eclipse.jface.action.StatusLineManager$1.isCanceled(Stat usLineManager.java:180)
>
> at org.eclipse.ui.internal.SaveableHelper$5.run(SaveableHelper. java:279)
> at
> org.eclipse.jface.operation.ModalContext.runInCurrentThread( ModalContext.java:464)
>
> at org.eclipse.jface.operation.ModalContext.run(ModalContext.ja va:372)
> at
> org.eclipse.jface.window.ApplicationWindow$1.run(Application Window.java:759)
>
> at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator .java:70)
> at
> org.eclipse.jface.window.ApplicationWindow.run(ApplicationWi ndow.java:756)
> at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow. java:2600)
> at
> org.eclipse.ui.internal.SaveableHelper.runProgressMonitorOpe ration(SaveableHelper.java:285)
>
> at
> org.eclipse.ui.internal.SaveableHelper.runProgressMonitorOpe ration(SaveableHelper.java:264)
>
> at org.eclipse.ui.internal.SaveableHelper.savePart(SaveableHelp er.java:156)
> at org.eclipse.ui.internal.EditorManager.savePart(EditorManager .java:1369)
> at org.eclipse.ui.internal.WorkbenchPage.savePart(WorkbenchPage .java:3334)
> at org.eclipse.ui.internal.SaveAction.run(SaveAction.java:68)
> at org.eclipse.jface.action.Action.runWithEvent(Action.java:498 )
> at org.eclipse.jface.commands.ActionHandler.execute(ActionHandl er.java:119)
> at org.eclipse.core.commands.Command.executeWithChecks(Command. java:476)
> at
> org.eclipse.core.commands.ParameterizedCommand.executeWithCh ecks(ParameterizedCommand.java:508)
>
> at
> org.eclipse.ui.internal.handlers.HandlerService.executeComma nd(HandlerService.java:169)
>
> at
> org.eclipse.ui.internal.handlers.SlaveHandlerService.execute Command(SlaveHandlerService.java:241)
>
> at
> org.eclipse.ui.menus.CommandContributionItem.handleWidgetSel ection(CommandContributionItem.java:820)
>
> at
> org.eclipse.ui.menus.CommandContributionItem.access$19(Comma ndContributionItem.java:806)
>
> at
> org.eclipse.ui.menus.CommandContributionItem$5.handleEvent(C ommandContributionItem.java:796)
>
> at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java :84)
> at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
> at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.ja va:4066)
> at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java :3657)
> at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.jav a:2629)
> at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2593)
> at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:24 27)
> at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:670)
> at
> org.eclipse.core.databinding.observable.Realm.runWithDefault (Realm.java:332)
>
> at
> org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Work bench.java:663)
> at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.j ava:149)
> at
> org.eclipse.riena.navigation.ui.swt.application.SwtApplicati on.createView(SwtApplication.java:63)
>
> at
> org.eclipse.riena.navigation.ui.application.AbstractApplicat ion.start(AbstractApplication.java:64)
>
> at
> org.eclipse.equinox.internal.app.EclipseAppHandle.run(Eclips eAppHandle.java:196)
>
> at
> org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher .runApplication(EclipseAppLauncher.java:110)
>
> at
> org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher .start(EclipseAppLauncher.java:79)
>
> at
> org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseS tarter.java:369)
>
> at
> org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseS tarter.java:179)
>
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
> at java.lang.reflect.Method.invoke(Unknown Source)
> at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java: 619)
> at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574)
> at org.eclipse.equinox.launcher.Main.run(Main.java:1407)
> at org.eclipse.equinox.launcher.Main.main(Main.java:1383)
>
> What I think happens is that...:
>
>
> ...Riena doesn't use the standard Eclipse status bar widget
> (org.eclipse.jface.action.StatusLine) for implementing the application's
> status bar, but relies on its own implementation
> (org.eclipse.riena.ui.swt.Statusline) instead.
> ...in any Eclipse RCP or standalone JFace application, either the
> ApplicationWindow or WorkbenchWindow (via the presentation factory) will
> make sure that an instance of org.eclipse.jface.action.StatusLineManager
> (the class in charge of managing both the status bar itself as well as
> its contributions/decorations) gets created as soon as the window itself
> is initialized. Please note that this is NOT true for the widget itself,
> since at least in a Riena-based application no-one ever actually calls
> StatusLineManager.createControl(...).
> ...any subsequent invocation of ApplicationWindow.run(...) will then to
> to use this StatusLineManager to visualize the progress of the tasks it
> executes. Since in a Riena-based application, there's no actual control
> bound to the manager at this point in time, a NullPointerException is
> raised :?.
> ...Riena (at presents) only supports the use of the Eclipse Jobs API for
> scheduling & execution of long-runnings tasks (via its
> org.eclipse.riena.ui.core.uiprocess.ProgressProviderBridge). At least I
> haven't found any similar integration of JFace operations API so far.
>
>
> My first question therefore is: Is my reasoning above correct? Are there
> any known workaround for using at least ISaveable2 in a Riena-driven
> application?
>
> Secondly (assuming that the answer is "no"), I'd grateful to any
> committer of the Riena UI project who could outline a possible
> implementation strategy of this feature to me.
>
> With my limited knowledge of Riena internals, I assume this would be
> something along the lines of:
>
>
> Create a sub-class of StatusLineManager that integrates with
> org.eclipse.riena.ui.core.uiprocess.IProgressVisualizer in a way that is
> similar to what
> org.eclipse.riena.ui.core.uiprocess.ProgressProviderBridge and
> org.eclipse.riena.ui.core.uiprocess.UICallbackDispatcher are currently
> doing for the Eclipse Jobs API.
> Adapt either the AbstractApplication, PresentationFactory or
> WorkbenchWindowAdvisor class to use this custom StatusLineManager
> implementation in place of the existing one coming from Eclipse itself.
>
>
> What do you think? Any suggestions?
>
> Thanks & kind regards,
>
> Chris
>
>
>
>
Hi Chris,
with my limited knowledge, I think its as simple as to say that we support Eclipse Jobs API and have never thought of
doing the same for JFace operations. (I believe I wasnt aware that it exists).
So question no 1 would be, why dont you use Eclipse Jobs API and everything is good ? :-) (maybe too simple but compelling).
As you probably know we also have something Riena-specific called UIProcess that is even higher level than Eclipse Jobs
API and supplies some nice hooks for UI interaction while running the job.
I suggest you open a bug (enhancement) to support JFace Operations. We never thought of it and would have to investigate
what it means. Or if it is at all possible.
Maybe you can also also explain a little what you expect from ISaveable2 in your app.
cheers
christian
|
|
|
Re: ISaveable vs. Riena: Why supporting the Eclipse Jobs API might not be enough [message #550428 is a reply to message #550422] |
Fri, 30 July 2010 10:48 |
Christian Kesselheim Messages: 59 Registered: June 2010 |
Member |
|
|
Hi Christian,
we make these views implement ISaveablePart2 so that the underlying framework is actually aware of pending (unsaved changes) and can react accordingly in a number of situations.
For example,
a) It will prompt the user to either save or explicitly withdraw his pending changes whenever the application is asked to quit or the view is being closed.
b) It will support the use of standard "Save" & "Save as" commands as provided by Eclipse and automatically trigger their "enabled" state depending on whether or not there are still some changes pending.
Effectively, having a view implement ISaveablePart2 brings your view a tiny bit closer to the "editor" semantics as seen in a plain RCP application .
Fortunately, we ourselves are already using Jobs API for representing any long-running task as triggered by our own application, so no problem there.
So the million dollar question would be: Why is the Eclipse platform itself still bypassing Jobs API in a number of places ? I'm far, far from being a guru on Eclipse RCP myself, so perhaps another explanation would be that my current reasoning above is utterly flawed beyond repair .
I'll try to find the time to create a new bugzilla and attach a first (POC-style) patch for feature this over the next few days. Since I'm not much familiar with Riena's internal workings, don't expect anything production-ready/inline with your current coding conventions/architecture, though ...
Regards,
Chris
[Updated on: Fri, 30 July 2010 10:51] Report message to a moderator
|
|
| |
Re: ISaveable vs. Riena: Why supporting the Eclipse Jobs API might not be enough [message #586640 is a reply to message #550422] |
Fri, 30 July 2010 10:48 |
Christian Kesselheim Messages: 59 Registered: June 2010 |
Member |
|
|
Hi Christian,
we make these views implement ISaveable2 so that the underlying framework is actually aware of pending (unsaved changes) and can react accordingly in a number of situations.
For example,
a) It will prompt the user to either save or explicitly withdraw his pending changes whenever the application is asked to quit or the view is being closed.
b) It will support the use of standard "Save" & "Save as" commands as provided by Eclipse and automatically trigger their "enabled" state depending on whether or not there are still some changes pending.
Fortunately, we ourselves are already using Jobs API for representing any long-running task as triggered by our own application, so no problem there.
So the million dollar question would be: Why is the Eclipse platform itself still bypassing Jobs API in a number of places :)? I'm far, far from being a guru on Eclipse RCP myself, so perhaps another explanation would be that my current reasoning above is utterly flawed beyond repair :d.
I'll try to find the time to create a new bugzilla and attach a first (POC-style) patch for feature this over the next few days. Since I'm not much familiar with Riena's internal workings, don't expect anything production-ready/inline with your current coding conventions/architecture, though :)...
Regards,
Chris
|
|
| |
Goto Forum:
Current Time: Thu Mar 28 17:52:50 GMT 2024
Powered by FUDForum. Page generated in 0.02727 seconds
|