|
Re: EventBroker.post does not reach @UIEventTopic method [message #1716564 is a reply to message #1716429] |
Fri, 04 December 2015 20:27 |
Thomas Schindl Messages: 6651 Registered: July 2009 |
Senior Member |
|
|
Hi,
My wild guess (i have not looked at the handler code) is that the
context you get there is a temporary one which is only valid while the
@Execute-method is running.
You can check if this is true by adding an @PreDestroy in the MyDialog
if it is called then this means that you @UIEventTopic gets unregistered
as well.
The reason is sometimes work might be caused by GC because we are using
WeakRefs internally and so thing might not get collected immediately.
The only solution is see is that you use a context always available eg
using the one attached to MApplication / MWindow / MPart who are
guaranteed to be there while your dialog is up and running.
so your code should most likely look like this
public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart part)
throws Exception {
IEclipseContext context = part.getContext();
// ...
}
Tom
On 04.12.15 14:56, Christopher Roscoe wrote:
> I have an eclipse rcp 4 application running on Windows 8.1.
> One of my use cases is to start a asynchronous service on a remote
> backend and have a dialog that is listening on JMS messages from the
> remote backend. There are several JMS messages indicating different
> processing steps and the dialog should react on those steps and draw
> update informations.
> At some point the service is done and a last message is send indicating
> the termination of the process. The dialog can be closed. Then it is
> possible to trigger the use case again.
>
> Most of the time my solution works flawlessly.
> But there is the rare case that my dialog is opened and from the
> beginning gets no update messages. From what i see in the backend log
> the service is processed successfully.
> But for the user the whole use case seems to be broken.
>
> My solution:
>
> There is a handler, that
> 1. creates the dialog if not present (i reuse the same object)
> 2. starts a JMS listener, that post the message to the injected
> org.eclipse.e4.core.services.events.IEventBroker
> 3. calls the backend service
> 4. opens the dialog
> 5. stops the JMS listener
>
> The dialog has a method annotated with @UIEventTopic.
>
> @Inject
> @Optional
> public void notifyUpdate(@UIEventTopic(EventConstants.TOPIC) MyUpdate
> myUpdate) {
>
>
> There is no observable issue with the messaging.
> I found out that even in the broken case the
> eventBroker.post(EventConstants.TOPIC, message) is processed without
> exception,
> but the event never reaches the dialog methods.
>
> I did some tracing afterwards. The control flow after eventBroker.post
> goes into EventHandlerTracker.getHandlers to get the listeners for the
> topic. In the normal case i observe the returned set containing 2
> objects. In the broken case the returned set is empty for the same topic.
>
> public synchronized Set<EventHandlerWrapper>
> org.eclipse.equinox.internal.event.EventHandlerTracker.getHandlers(final
> String topic)
>
> I use this version org.eclipse.equinox.event_1.3.100.v20140115-1647.jar.
>
> What am i doing wrong?
>
> package demo;
>
> import java.util.function.Function;
>
> import javax.inject.Inject;
>
> import org.eclipse.e4.core.contexts.ContextInjectionFactory;
> import org.eclipse.e4.core.contexts.IEclipseContext;
> import org.eclipse.e4.core.di.annotations.Execute;
> import org.eclipse.e4.core.services.events.IEventBroker;
> import org.eclipse.jface.window.Window;
>
> public class Handler {
>
> private Function<IEclipseContext, MyDialog> dialogFactory =
> context -> ContextInjectionFactory.make(MyDialog.class,
> context);
>
> @Inject
> private IEventBroker eventBroker;
>
> private MyDialog myDialog;
>
> @Inject
> private MyService myService;
>
> private MessagingDelegate messagingDelegate;
>
> @Execute
> public void execute(IEclipseContext context) throws Exception {
>
> MyContext context = new MyContext();
>
> if (myDialog == null) {
> myDialog = dialogFactory.apply(context);
> }
>
> messagingDelegate.start(context.getQueueName(), message -> {
> eventBroker.post(EventConstants.TOPIC, message);
> });
>
> myService.start(context);
>
> myDialog.open();
>
> messagingDelegate.stop();
> }
>
> @Inject
> public void setMessagingDelegateFactory(MessagingDelegateFactory
> messagingDelegateFactory) {
> messagingDelegate =
> messagingDelegateFactory.createMessagingDelegate();
> }
> }
>
> The dialog implementation.
>
> package demo;
>
> import java.util.Objects;
>
> import javax.inject.Inject;
>
> import org.eclipse.e4.core.di.annotations.Optional;
> import org.eclipse.e4.core.services.nls.Translation;
> import org.eclipse.e4.ui.di.UIEventTopic;
> import org.eclipse.jface.dialogs.Dialog;
> import org.eclipse.jface.dialogs.IDialogConstants;
> import org.eclipse.jface.layout.GridDataFactory;
> import org.eclipse.jface.layout.GridLayoutFactory;
> import org.eclipse.swt.SWT;
> import org.eclipse.swt.events.SelectionAdapter;
> import org.eclipse.swt.events.SelectionEvent;
> import org.eclipse.swt.graphics.Point;
> import org.eclipse.swt.widgets.Button;
> import org.eclipse.swt.widgets.Composite;
> import org.eclipse.swt.widgets.Control;
> import org.eclipse.swt.widgets.Label;
> import org.eclipse.swt.widgets.ProgressBar;
> import org.eclipse.swt.widgets.Shell;
>
> public class MyDialog extends Dialog {
>
> @Inject
> @Optional
> public void notifyUpdate(@UIEventTopic(EventConstants.TOPIC)
> MyUpdate myUpdate) {
> if (myUpdate != null) {
> updateInformation(myUpdate);
> }
> }
>
> private void updateInformation(MyUpdate myUpdate) {
> label.setText(myUpdate.getInfo());
> }
> }
>
|
|
|
Powered by
FUDForum. Page generated in 0.01870 seconds