Restart Eclipse 4 RCP application before it gets visible - eclipse

I'm developing an Eclipse 4 RCP application and I need it to do some tasks before it gets visible, then restart.
I'm running an application that checks a P2 repository and automatically updates/installs/uninstalls certain plugins. I want this step to be transparent to the user, so I am running this in the "postContextCreate" method, using the LifeCycleURI property.
Once this is done, I need the application to restart (in order to correctly load the plugins), but I can't inject the workbench here since it's not yet created. I would appreciate any suggestions or ideas.
Thanks in advance!

Probably the earliest you can get the workbench is by subscribing to the application startup complete event UIEvents.UILifeCycle.APP_STARTUP_COMPLETE with the event broker. However this does not fire until just after the UI is displayed.
Update:
The event handler would be something like:
private static final class AppStartupCompleteEventHandler implements EventHandler
{
private final IEclipseContext _context;
AppStartupCompleteEventHandler(final IEclipseContext context)
{
_context = context;
}
#Override
public void handleEvent(final Event event)
{
IWorkbench workbench = _context.get(IWorkbench.class);
workbench.restart();
}
}
Subscribe to this event in the #PostContextCreate method.
#PostContextCreate
public void postContextCreate(IEclipseContext context, IEventBroker eventBroker)
{
eventBroker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE, new AppStartupCompleteEventHandler(context));
}

Related

Eclipse job with UI access

I have one situation.
I have one Eclipse job with following code:
private class ExecutionJob extends Job {
public static final String MY_FAMILY = "myJobFamily";
public ExecutionJob(String name) {
super(name);
}
#Override
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask("executing ...... ", IProgressMonitor.UNKNOWN);
methodForExecution();
monitor.done();
return Status.OK_STATUS;
}
#Override
public boolean belongsTo(Object family) {
return family == MY_FAMILY;
}
}
And this methodForExecution() has code as below :
public void methodForExecution(){
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView("view_id");
}
Now, the situation is, job opens up something like progressmonitor, and my method is trying to access UI which is actually behind this job's progressmonitor. And it gives NullPointerException as the progress monitor does not have ActiveWorkbenchWindow.
I can not use UIJob, as I have to execute this methodForExecution() asynchronously.
Can someone please help me resolving this.
The code you want to run must run in the UI thead.
If most of the work in the job is updating the UI and there is no long running non-UI code then you should use UIJob to run this. This is still scheduled as a job but the runInUIThread method is executed in the UI thread.
If you have a lot of non-UI code especially long running code then use a normal Job but you will have to use Display.asyncExec to run the method in the UI thread:
Display.getDefault().asyncExec(new Runnable()
{
#Override
public void run()
{
methodForExecution();
}
});
In Java 8 you could do:
Display.getDefault().asyncExec(this::methodForExecution);
You can also use syncExec instead of asyncExec to wait for the UI to update.
If the showView is all you want to do you could just do the asyncExec without using a Job.

#ProxyCodeSplit how exactly it works?

I am new to GWT and GWTP. I know what is GWT Code Split and GWTP Proxy Code Split. I've already red:
http://www.gwtproject.org/doc/latest/DevGuideCodeSplitting.html
http://dev.arcbees.com/gwtp/core/presenters/creating-places.html
I assumed that I understand it. So I've like to used.:
I have application with Administration panel, where only part of users can access. So there is no need to download Administration panel related code for all. So in Administration Presenter I've added #ProxyCodeSplit like follow:
public class AdminAreaPresenter extends Presenter<AdminAreaPresenter.MyView, AdminAreaPresenter.MyProxy> {
#ProxyCodeSplit
#NameToken(Routing.Url.admin)
#UseGatekeeper(IsAdminGatekeeper.class)
public interface MyProxy extends TabContentProxyPlace<AdminAreaPresenter> {}
#TabInfo(container = AppPresenter.class)
static TabData getTabLabel(IsAdminGatekeeper adminGatekeeper) {
return new MenuEntryGatekeeper(Routing.Label.admin, 1, adminGatekeeper);
}
public interface MyView extends View {}
AppPresenter appPresenter;
#Inject
AdminAreaPresenter(EventBus eventBus, MyView view, MyProxy proxy, AppPresenter appPresenter) {
super(eventBus, view, proxy, AppPresenter.SLOT_TAB_CONTENT);
this.appPresenter = appPresenter;
}
}
In other Presenters I have #ProxyStandard instead of #ProxyCodeSplit.
I've run app and log in. then I've opened Network tab in chrome's developer console:
And after opening Administation Panel in application:
As You can see, there is no new resources added to application.
My main app presenter AppPresenter implements interfaces AsyncCallStartHandler, AsyncCallFailHandler, AsyncCallSucceedHandler from: com.gwtplatform.mvp.client.proxy. and I override those methods:
#ProxyEvent
#Override
public void onAsyncCallStart(AsyncCallStartEvent event) {
Window.alert("Async start");
getView().setTopMessage("Loading...");
}
#ProxyEvent
#Override
public void onAsyncCallFail(AsyncCallFailEvent event) {
Window.alert("Async fail");
getView().setTopMessage("Oops, something went wrong...");
}
#ProxyEvent
#Override
public void onAsyncCallSucceed(AsyncCallSucceedEvent event) {
Window.alert("Async success");
getView().setTopMessage(null);
}
And when I enter AdmininArea I am getting to allerts: "Async start", "Async success". So I think that everythink work, but unfortunatelly I don't see any changes in resources. Please help. Am I doing something wrong or what?
Code splitting is disabled in SuperDevMode because it is not compatible with the incremental compiler and would also slow down compilation (see this issue).
To test code splitting, compile your GWT application (mvn clean install gwt:compile) and test it in production mode (take war file from target directory and put it in f.e.: Tomcat server catalog: webapps).

Is there any way i can get the current Display object from a background thread(jobs) in RAP

we need to get the the current display object in RAP 2.3 from inside a job for updating the UI. what is the suggested way to do that?
The Threads in RAP articles gives a thorough explanation about how threads and sessions interrelate in RAP.
To gain access to the Display from a Job, the Job needs to know which Display it is assigned to. Hence you need to pass the Displya to the Job.
If the Job is scheduled from the UI thread, typical code may look like this:
static class DisplayJob extends Job {
private final Display display;
private DisplayJob( Display display ) {
super( "Job with UI Access" );
this.display = display;
}
#Override
protected IStatus run( IProgressMonitor monitor ) {
display.asyncExec( new Runnable() {
#Override
public void run() {
}
} );
return Status.OK_STATUS;
}
}
Button button = new Button( ...
button.addListener( SWT.Selection, new Listener() {
#Override
public void handleEvent( Event event ) {
new DisplayJob( event.display ).schedule();;
}
} );
Don't forget to check if the widgets aren't disposed before accessing them in the run() method given to asyncExec() - or use a helper therefore.
Note that the thread/session relation isn't specific to RAP but applies to all multi-user environments that have the concept of a session.

Add System Tray and Active Workbech Shell reference in E4 application

I am new in E4 application development. I add System tray icon in RCP 3.7.x successfully.
to add a system tray icon in e4 application. I am using the e4 application life cycle to add a system tray icon in this way:
public class LifeCycleManager {
#PostContextCreate
void postContextCreate(IApplicationContext appContext, Display display) {
SystemNotifier icon= new SystemNotifier(shell);
SystemNotifier.trayItem = icon.initTaskItem(shell);
if (SystemNotifier.trayItem != null) {
icon.hookPopupMenu();
}
}
}
How to get reference of Active Workbench Shell in e4 application.
Which annotation use of e4 application life cycle to add System Tray
The application shell is not available when #PostContextCreate runs. You need to wait for the application startup complete event, something like:
#PostContextCreate
void postContextCreate(IEclipseContext context, IEventBroker eventBroker)
{
eventBroker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE, new AppStartupCompleteEventHandler(eventBroker, context));
}
private static final class AppStartupCompleteEventHandler implements EventHandler
{
private final IEventBroker _eventBroker;
private final IEclipseContext _context;
AppStartupCompleteEventHandler(IEventBroker eventBroker, IEclipseContext context)
{
_eventBroker = eventBroker;
_context = context;
}
#Override
public void handleEvent(final Event event)
{
_eventBroker.unsubscribe(this);
Shell shell = (Shell)_context.get(IServiceConstants.ACTIVE_SHELL);
... your code ...
}
}

Is there a way to have Eclipse flash its taskbar icon once a time consuming task finishes?

I often minimize Eclipse to read or work on something else for a few minutes while I wait for it to do something (e.g., run a large JUnit test suite, synchronize a huge number of files with a repo, run a long Ant build, etc.). I have to check back every 30 seconds or so to see if it's finished yet. I would like Eclipse to alert me, preferably by blinking its taskbar icon, after it finishes a time consuming operation. Are there any settings or plugins that can make this happen?
I believe is you have Mylyn installed, this should be enabled by default for Windows 7. See here and here. Regarding the post-build actions, I do not know of any existing Eclipse plugins that do this. However, I have not exhaustively searched the marketplace. However, this could be accomplished with existing Eclipse APIs but it would require someone to author a new Eclipse plugin.
The Eclipse Platform jobs framework has an API called IJobManager. A developer could write a new Eclipse plugin that could use this API to listen for job changes and do the following:
Create an eclipse plugin, register a listener to IJobManager on startup.
Once any interesting job is completed, it could fire off some external task/script using normal java process execution API in the JDK
This all could be accomplished in one Java file, probably less than 500 lines long.
You could use this template to setup a basic Eclipse plugin project including build system and have it built and ready to install into your existing Eclipse.
Update I just found a maven archetype for building eclipse plugins with tycho here. It would be my recommendation for someone new to building an eclipse feature/updatesite.
You can create a new plugin project and create this kind of functionality for yourself. The
IJobchangeListener from the Eclipse Jobs API is probably very interesting for you.
The IJobChangeListener is an interface where you can receive notifications for the different type of job states.
I have created a class called JobListener which adds the IJobchangeListener to the JobManager. With the action SampleAction you can register or unregister the listener. that means, if the listener is registered and your application is minimized you will be notified with a MessageDialog (no blinking taskbar).
I found a link where someone made his swing application blink. This functionality should be included in the method public void done(final IJobChangeEvent event). I haven't done this in my test class.
You can also get additional information about the Job with
event.getJob();
Here you are able to check the Job name:
String jobName = event.getJob().getName();
The name of the Job is human readable, for example "Collecting garbage", "Update for Decoration Completion", "Building workspace", etc.
The JobListener class.
/**
* A job listener which may be added to a job manager
*/
public class JobListener {
private MyJobListener listener = null;
private IWorkbenchWindow window = null;
private boolean active = false;
public JobListener(IWorkbenchWindow window) {
this.window = window;
}
/**
* register the job listener
*/
public void register() {
listener = new MyJobListener(window);
IJobManager jobMan = Job.getJobManager();
jobMan.addJobChangeListener(listener);
active = true;
}
/**
* unregister the job listener
*/
public void unregister() {
IJobManager jobMan = Job.getJobManager();
jobMan.removeJobChangeListener(listener);
active = false;
}
public boolean isActive() {
return active;
}
class MyJobListener implements IJobChangeListener {
private IWorkbenchWindow window;
public MyJobListener(IWorkbenchWindow window) {
this.window = window;
}
#Override
public void sleeping(IJobChangeEvent event) {
}
#Override
public void scheduled(IJobChangeEvent event) {
}
#Override
public void running(IJobChangeEvent event) {
}
#Override
public void done(final IJobChangeEvent event) {
window.getShell().getDisplay().asyncExec(new Runnable() {
#Override
public void run() {
if(window.getShell().getMinimized()) {
MessageDialog.openInformation(
window.getShell(),
"Test",
"Job " + event.getJob().getName() + " done.");
}
}
});
}
#Override
public void awake(IJobChangeEvent event) {
}
#Override
public void aboutToRun(IJobChangeEvent event) {
System.out.println("About to run: " + event.getJob().getName());
}
}
}
I called this class from a class called SampleAction.java
public class SampleAction implements IWorkbenchWindowActionDelegate {
private IWorkbenchWindow window;
private JobListener listener;
/**
* The constructor.
*/
public SampleAction() {
}
public void run(IAction action) {
if(listener.isActive()) {
listener.unregister();
MessageDialog.openInformation(
window.getShell(),
"Lrt",
"Unregistered");
}
else {
listener.register();
MessageDialog.openInformation(
window.getShell(),
"Lrt",
"Registered");
}
}
public void selectionChanged(IAction action, ISelection selection) {
}
public void dispose() {
}
public void init(IWorkbenchWindow window) {
this.window = window;
this.listener = new JobListener(window);
}
You can get started with eclipse plugin development by creating a new plugin project:
File > New > Project > Plugin Project
I used the Hello World plugin project template to test the code above.