Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
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)
icon5.gif  ISaveable vs. Riena: Why supporting the Eclipse Jobs API might not be enough [message #550257] Thu, 29 July 2010 16:08 Go to next message
Christian Kesselheim is currently offline Christian KesselheimFriend
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 Confused.
  • ...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 Go to previous messageGo to next message
Christian Campo is currently offline Christian CampoFriend
Messages: 590
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 Go to previous messageGo to next message
Christian Kesselheim is currently offline Christian KesselheimFriend
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 Smile.

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 Smile? 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 Very Happy.

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 Smile...

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 #558349 is a reply to message #550428] Sat, 11 September 2010 12:54 Go to previous message
Roland Tepp is currently offline Roland TeppFriend
Messages: 336
Registered: July 2009
Senior Member
30.07.2010 13:48, Christian Kesselheim kirjutas:
> 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.

Jobs API is in no way better or preferrable to Jobs API.

In my experience I've started to slowly steer away from Jobs api as it
has some serious drawbacks compared to using much simpler
IRunnableWithProgress api.

Jobs api is a bit too complex at times and should (in my opinion) be
generally used only for tasks that can or should be performed in the
background.

Heavily UI dependent processes (saving a resource is a good example)
whose progress needs to be monitored, should use much more lightweight
IRunnableWithProgress instead.

In any case, the key abstraction here is an implementation of
IProgressMonitor, which apparently returns NPE on isCancelled. In my
book this is BAD :)

--
Roland Tepp
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 Go to previous message
Christian Kesselheim is currently offline Christian KesselheimFriend
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
Re: ISaveable vs. Riena: Why supporting the Eclipse Jobs API might not be enough [message #586822 is a reply to message #586640] Sat, 11 September 2010 12:54 Go to previous message
Roland Tepp is currently offline Roland TeppFriend
Messages: 336
Registered: July 2009
Senior Member
30.07.2010 13:48, Christian Kesselheim kirjutas:
> 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.

Jobs API is in no way better or preferrable to Jobs API.

In my experience I've started to slowly steer away from Jobs api as it
has some serious drawbacks compared to using much simpler
IRunnableWithProgress api.

Jobs api is a bit too complex at times and should (in my opinion) be
generally used only for tasks that can or should be performed in the
background.

Heavily UI dependent processes (saving a resource is a good example)
whose progress needs to be monitored, should use much more lightweight
IRunnableWithProgress instead.

In any case, the key abstraction here is an implementation of
IProgressMonitor, which apparently returns NPE on isCancelled. In my
book this is BAD :)

--
Roland Tepp
Previous Topic:treeridget - the child nodes name not visible
Next Topic:riena security
Goto Forum:
  


Current Time: Thu Dec 18 23:11:13 GMT 2014

Powered by FUDForum. Page generated in 0.07458 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software