Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Gracefully Loading a Heavy Plugin

DZone's Guide to

Gracefully Loading a Heavy Plugin

· Java Zone
Free Resource

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

Here's the challenge: I have a plug-in which may take more than a few seconds to load. That's not a problem if the plug-in is loaded when the platform starts since the user waits for platform to load anyway. However, if the plug-in is loaded on-demand, after the platform is already started, the user may experience an unexplained freeze. 

To overcome this behavior, it is best to use some progress dialog with a monitor when starting your plugin. This is simple, however, the less-than-trivial question is: how to determine if the platform is starting?  

Those with some knowledge of Eclipse would simply direct me to a very simple API call:

PlatformUI.isWorkbenchRunning()

One major disadvantage.. this is useless, since it will return true when the platform is still loading as well. It is considered running at this point.

Searching in the Eclipse newsgroups portal, I came across another idea:

Bundle b = Platform.getBundle("org.eclipse.swt");
if (b==null || b.getState() != Bundle.ACTIVE) { 
   System.out.println("no UI..."); 
}

This doesn't work, since SWT is already resolved when the splash screen is shown. You can test other bundles, if you'd like, but I find it hard to believe you'll discover any well-defined and consistent difference between the two situations: loading upon launch and loading after it is complete.

My next idea was to check the visibility of the default shell. Nope, it is considered visible at startup. I tried checking for the existence of workbench visual parts and, guess what, they're already there in both cases. After some trial and error I found a very simple way of doing that. One of the distinct features when the splash screen is showing is that you don't see a menu-bar. From that I derived the following test:

Display.getCurrent().getActiveShell().getMenuBar() == null

This will return true when the platform is still launching and a splash screen is shown. Putting it all together and adding all the null checks I could think of, I wrote the following method for checking if the shell is already open and return it if it is:

private Shell findStartedShell() {
   Shell result = null;
   final Display currentDisplay = Display.getCurrent();
   if (currentDisplay != null) {
      result = currentDisplay.getActiveShell();
      if ((result != null) && (result.getMenuBar() == null)) {
         result = null;
      }
   }
   return result;
}


 

I used a ProgressMonitorDialog to show the progress and an IRunnableWithProgress to implement the lengthy startup process. Eventually, the plugin Activator start method would look like this:

public void start(final BundleContext context) throws Exception {
   super.start(context);
   plugin = this;
   final IRunnableWithProgress statupOperation = 
      new IRunnableWithProgress() {

      public void run(final IProgressMonitor monitor) throws
         InvocationTargetException, InterruptedException {
         // do your initialization here
         // use the monitor to set the task name 
         // and report progress

      }
   };

   final Shell activeShell = findStartedShell();
   if (activeShell != null) {
      final ProgressMonitorDialog progressMonitorDialog = 
         new ProgressMonitorDialog(activeShell);
      progressMonitorDialog.run(false, false, statupOperation);
   } else {
      statupOperation.run(new NullProgressMonitor());
   }
} 


The above will do exactly what we were looking for: if the platform is launching, it will proceed with normal startup (the splash screen shows the progress of loading all the plugins) and, if the platform is already loaded, it will show a progress dialog.

Found a better way of doing that?  Let me know in the comments.

From http://zvikico.typepad.com

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}