Pārlūkot izejas kodu

SDK:
- Move Exception repoting to ApplicationLogHandler / NotifyUtil
- TODO: Change Exceptions.printStackTrace(throwable); -> logger.log(Level.SEVERE, "Message", throwable); across SDK

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10257 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

nor..67 12 gadi atpakaļ
vecāks
revīzija
6a5473f779

+ 3 - 0
jme3-core/src/com/jme3/gde/core/Installer.java

@@ -65,6 +65,9 @@ public class Installer extends ModuleInstall {
     }
 
     static {
+        //set exception report levels
+        System.setProperty("netbeans.exception.report.min.level", "99999");
+        System.setProperty("netbeans.exception.alert.min.level", "99999"); 
         //set http agent
         System.setProperty("http.agent", NbBundle.getBundle("org.netbeans.core.windows.view.ui.Bundle").getString("CTL_MainWindow_Title")
                 + " (" + System.getProperty("os.name") + "/" + System.getProperty("os.version") + ")");

+ 15 - 7
jme3-core/src/com/jme3/gde/core/scene/ApplicationLogHandler.java

@@ -36,9 +36,11 @@ import com.jme3.gde.core.util.notify.NotifyUtil;
 import com.jme3.util.JmeFormatter;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.util.concurrent.Callable;
 import java.util.logging.Handler;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
+import javax.swing.JButton;
 import org.openide.windows.IOProvider;
 import org.openide.windows.InputOutput;
 
@@ -46,7 +48,7 @@ import org.openide.windows.InputOutput;
  *
  * @author normenhansen
  */
-public class ApplicationLogHandler extends Handler {
+public class ApplicationLogHandler extends Handler implements Callable<JButton> {
 
     InputOutput io = IOProvider.getDefault().getIO("Application", true);
     JmeFormatter formatter = new JmeFormatter();
@@ -65,31 +67,37 @@ public class ApplicationLogHandler extends Handler {
         if (record.getLevel().equals(Level.SEVERE)) {
             Throwable thrown = record.getThrown();
             if (thrown != null) {
-                NotifyUtil.error("Exception!", formatter.formatMessage(record), thrown, false);
+                NotifyUtil.error(thrown);
+                thrown.printStackTrace(io.getErr());
             } else {
-                NotifyUtil.show("Error!", formatter.formatMessage(record), MessageType.ERROR, listener, 10000);
+                NotifyUtil.show("Error", formatter.format(record), MessageType.ERROR, listener, 10000);
+                io.getErr().println(formatter.formatMessage(record));
             }
-            io.getErr().println(formatter.formatMessage(record));
         } else if (record.getLevel().equals(Level.WARNING)) {
             io.getErr().println(formatter.formatMessage(record));
             NotifyUtil.show("Warning", formatter.formatMessage(record), MessageType.WARNING, listener, 5000);
         } else if (record.getLevel().equals(Level.INFO)) {
-//            NotifyUtil.show("Message", formatter.formatMessage(record), MessageType.INFO, listener, 3000);
+            io.getOut().println(formatter.formatMessage(record));
+        } else if (record.getLevel().intValue()>800) {
+            //larger than INFO:
+            NotifyUtil.show("Info", formatter.formatMessage(record), MessageType.INFO, listener, 3000);
             io.getOut().println(formatter.formatMessage(record));
         } else {
             io.getOut().println(formatter.formatMessage(record));
         }
     }
 
+    public JButton call() throws Exception {
+        return new JButton("Report");
+    }
+
     @Override
     public void flush() {
-//        throw new UnsupportedOperationException("Not supported yet.");
     }
 
     @Override
     public void close() throws SecurityException {
         io.getOut().close();
         io.getErr().close();
-//        throw new UnsupportedOperationException("Not supported yet.");
     }
 }

+ 133 - 119
jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java

@@ -67,6 +67,7 @@ import java.net.URL;
 import java.util.Iterator;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 import org.netbeans.api.progress.ProgressHandle;
 import org.netbeans.api.progress.ProgressHandleFactory;
@@ -74,9 +75,7 @@ import org.netbeans.spi.project.LookupProvider;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
 import org.openide.NotifyDescriptor.Confirmation;
-import org.openide.NotifyDescriptor.Message;
 import org.openide.awt.HtmlBrowser;
-import org.openide.awt.StatusDisplayer;
 import org.openide.loaders.DataObject;
 import org.openide.util.Exceptions;
 import org.openide.util.HelpCtx;
@@ -91,6 +90,8 @@ import org.openide.util.lookup.Lookups;
 @SuppressWarnings("unchecked")
 public class SceneApplication extends Application implements LookupProvider {
 
+    private static final Logger logger = Logger.getLogger(SceneApplication.class.getName());
+    private static boolean failMessageShown = false;
     private PointLight camLight;
     private static SceneApplication application;
 
@@ -126,6 +127,7 @@ public class SceneApplication extends Application implements LookupProvider {
     private ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Opening SceneViewer..");
     private String lastError = "";
     private boolean started = false;
+    private boolean initFailed = false;
     private AwtPanel panel;
     private ViewPort overlayView;
     boolean useCanvas = false;
@@ -135,6 +137,7 @@ public class SceneApplication extends Application implements LookupProvider {
     private FakeApplication fakeApp;
 
     public SceneApplication() {
+        Logger.getLogger("com.jme3").addHandler(logHandler);
         progressHandle.start(7);
         useCanvas = "true".equals(NbPreferences.forModule(Installer.class).get("use_lwjgl_canvas", "false"));
         try {
@@ -148,8 +151,6 @@ public class SceneApplication extends Application implements LookupProvider {
             }
             setSettings(newSetting);
 
-            Logger.getLogger("com.jme3").addHandler(logHandler);
-
             setPauseOnLostFocus(false);
 
             if (useCanvas) {
@@ -164,10 +165,8 @@ public class SceneApplication extends Application implements LookupProvider {
                 start();
             }
         } catch (Exception e) {
-            Exceptions.printStackTrace(e);
             showStartupErrorMessage(e);
         } catch (Error e) {
-            Exceptions.printStackTrace(e);
             showStartupErrorMessage(e);
         } finally {
             getProgressHandle().finish();
@@ -220,116 +219,125 @@ public class SceneApplication extends Application implements LookupProvider {
 
     @Override
     public void initialize() {
-        thread = Thread.currentThread();
-        fakeApp.startFakeApp();
-        try {
-            super.initialize();
-            {
-                overlayView = getRenderManager().createMainView("Overlay", cam);
-                overlayView.setClearFlags(false, true, false);
-                guiViewPort.setClearFlags(false, false, false);
+        if (!initFailed) {
+            try {
+                super.initialize();
+                thread = Thread.currentThread();
+                fakeApp.startFakeApp();
+                {
+                    overlayView = getRenderManager().createMainView("Overlay", cam);
+                    overlayView.setClearFlags(false, true, false);
+                    guiViewPort.setClearFlags(false, false, false);
+                }
+                getProgressHandle().progress("Setup Camera Controller", 2);
+                //create camera controller
+                camController = new SceneCameraController(cam, inputManager);
+                //create preview view
+                getProgressHandle().progress("Setup Preview Scene", 3);
+
+                previewProcessor = new ScenePreviewProcessor();
+                previewProcessor.setupPreviewView();
+
+                getProgressHandle().progress("Prepare Camera", 4);
+                camLight = new PointLight();
+                camLight.setColor(ColorRGBA.White);
+
+                getProgressHandle().progress("Prepare Stats View", 5);
+                guiNode.setQueueBucket(Bucket.Gui);
+                guiNode.setCullHint(CullHint.Never);
+                loadFPSText();
+                loadStatsView();
+                getProgressHandle().progress("Attach Scene to Viewport", 6);
+                viewPort.attachScene(rootNode);
+                viewPort.attachScene(toolsNode);
+                guiViewPort.attachScene(guiNode);
+                cam.setLocation(new Vector3f(0, 0, 10));
+
+                getProgressHandle().progress("Create", 6);
+                wireProcessor = new WireProcessor(assetManager);
+                getProgressHandle().finish();
+
+                inputManager.addMapping("MouseAxisX", new MouseAxisTrigger(MouseInput.AXIS_X, false));
+                inputManager.addMapping("MouseAxisY", new MouseAxisTrigger(MouseInput.AXIS_Y, false));
+                inputManager.addMapping("MouseAxisX-", new MouseAxisTrigger(MouseInput.AXIS_X, true));
+                inputManager.addMapping("MouseAxisY-", new MouseAxisTrigger(MouseInput.AXIS_Y, true));
+                inputManager.addMapping("MouseWheel", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false));
+                inputManager.addMapping("MouseWheel-", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true));
+                inputManager.addMapping("MouseButtonLeft", new MouseButtonTrigger(0));
+                inputManager.addMapping("MouseButtonMiddle", new MouseButtonTrigger(2));
+                inputManager.addMapping("MouseButtonRight", new MouseButtonTrigger(1));
+                started = true;
+            } catch (Throwable e) {
+                showStartupErrorMessage(e);
+                initFailed = true;
+                if (fakeApp != null) {
+                    fakeApp.stopFakeApp();
+                }
+            } finally {
+                getProgressHandle().finish();
             }
-            getProgressHandle().progress("Setup Camera Controller", 2);
-            //create camera controller
-            camController = new SceneCameraController(cam, inputManager);
-            //create preview view
-            getProgressHandle().progress("Setup Preview Scene", 3);
-
-            previewProcessor = new ScenePreviewProcessor();
-            previewProcessor.setupPreviewView();
-
-            getProgressHandle().progress("Prepare Camera", 4);
-            camLight = new PointLight();
-            camLight.setColor(ColorRGBA.White);
-
-            getProgressHandle().progress("Prepare Stats View", 5);
-            guiNode.setQueueBucket(Bucket.Gui);
-            guiNode.setCullHint(CullHint.Never);
-            loadFPSText();
-            loadStatsView();
-            getProgressHandle().progress("Attach Scene to Viewport", 6);
-            viewPort.attachScene(rootNode);
-            viewPort.attachScene(toolsNode);
-            guiViewPort.attachScene(guiNode);
-            cam.setLocation(new Vector3f(0, 0, 10));
-
-            getProgressHandle().progress("Create", 6);
-            wireProcessor = new WireProcessor(assetManager);
-            getProgressHandle().finish();
-
-            inputManager.addMapping("MouseAxisX", new MouseAxisTrigger(MouseInput.AXIS_X, false));
-            inputManager.addMapping("MouseAxisY", new MouseAxisTrigger(MouseInput.AXIS_Y, false));
-            inputManager.addMapping("MouseAxisX-", new MouseAxisTrigger(MouseInput.AXIS_X, true));
-            inputManager.addMapping("MouseAxisY-", new MouseAxisTrigger(MouseInput.AXIS_Y, true));
-            inputManager.addMapping("MouseWheel", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false));
-            inputManager.addMapping("MouseWheel-", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true));
-            inputManager.addMapping("MouseButtonLeft", new MouseButtonTrigger(0));
-            inputManager.addMapping("MouseButtonMiddle", new MouseButtonTrigger(2));
-            inputManager.addMapping("MouseButtonRight", new MouseButtonTrigger(1));
-            started = true;
-        } catch (Exception e) {
-            Exceptions.printStackTrace(e);
-            showStartupErrorMessage(e);
-        } catch (Error e) {
-            Exceptions.printStackTrace(e);
-            showStartupErrorMessage(e);
-        } finally {
-            getProgressHandle().finish();
         }
     }
 
     @Override
     public void destroy() {
         fakeApp.stopFakeApp();
+        initFailed = false;
         super.destroy();
     }
 
     @Override
     public void update() {
         if (!started) {
-            return;
-        }
-        try {
-            super.update();
-            FakeApplication fakap = fakeApp;
-            if (fakap != null) {
-                fakap.runQueuedFake();
+            try {
+                runQueuedTasks();
+            } catch (Exception e) {
+                getStateManager().update(0);
+                logger.log(Level.INFO, "Exception calling Tasks:", e);
             }
-            float tpf = timer.getTimePerFrame();
-            camLight.setPosition(cam.getLocation());
-            secondCounter += tpf;
-            int fps = (int) timer.getFrameRate();
-            if (secondCounter >= 1.0f) {
-                fpsText.setText("Frames per second: " + fps);
-                secondCounter = 0.0f;
-            }
-            getStateManager().update(tpf);
-            toolsNode.updateLogicalState(tpf);
-            if (fakap != null) {
-                fakap.updateFake(tpf);
-                fakap.updateExternalLogicalState(rootNode, tpf);
-                fakap.updateExternalLogicalState(guiNode, tpf);
-                fakap.updateExternalGeometricState(rootNode);
-                fakap.updateExternalGeometricState(guiNode);
-            } else {
-                rootNode.updateLogicalState(tpf);
-                guiNode.updateLogicalState(tpf);
-                rootNode.updateGeometricState();
-                guiNode.updateGeometricState();
-            }
-            toolsNode.updateGeometricState();
-            if (fakap != null) {
-                fakap.renderFake();
+        } else {
+            try {
+                super.update();
+                FakeApplication fakap = fakeApp;
+                if (fakap != null) {
+                    fakap.runQueuedFake();
+                }
+                float tpf = timer.getTimePerFrame();
+                camLight.setPosition(cam.getLocation());
+                secondCounter += tpf;
+                int fps = (int) timer.getFrameRate();
+                if (secondCounter >= 1.0f) {
+                    fpsText.setText("Frames per second: " + fps);
+                    secondCounter = 0.0f;
+                }
+                getStateManager().update(tpf);
+                toolsNode.updateLogicalState(tpf);
+                if (fakap != null) {
+                    fakap.updateFake(tpf);
+                    fakap.updateExternalLogicalState(rootNode, tpf);
+                    fakap.updateExternalLogicalState(guiNode, tpf);
+                    fakap.updateExternalGeometricState(rootNode);
+                    fakap.updateExternalGeometricState(guiNode);
+                } else {
+                    rootNode.updateLogicalState(tpf);
+                    guiNode.updateLogicalState(tpf);
+                    rootNode.updateGeometricState();
+                    guiNode.updateGeometricState();
+                }
+                toolsNode.updateGeometricState();
+                if (fakap != null) {
+                    fakap.renderFake();
+                }
+                getStateManager().render(renderManager);
+                renderManager.render(tpf, context.isRenderable());
+                getStateManager().postRender();
+            } catch (NullPointerException e) {
+                handleError("NullPointerException: " + e.getMessage(), e);
+            } catch (Exception e) {
+                handleError(e.getMessage(), e);
+            } catch (Error e) {
+                handleError(e.getMessage(), e);
             }
-            getStateManager().render(renderManager);
-            renderManager.render(tpf, context.isRenderable());
-            getStateManager().postRender();
-        } catch (NullPointerException e) {
-            handleError("NullPointerException: " + e.getMessage(), e);
-        } catch (Exception e) {
-            handleError(e.getMessage(), e);
-        } catch (Error e) {
-            handleError(e.getMessage(), e);
         }
     }
 
@@ -382,6 +390,10 @@ public class SceneApplication extends Application implements LookupProvider {
      * @param request
      */
     public void openScene(final SceneRequest request) {
+        if (failMessageShown) {
+            NotifyUtil.show("Error starting OpenGL context!", "Click here to go to troubleshooting web page.", MessageType.EXCEPTION, lst, 0);
+            return;
+        }
         closeScene(currentSceneRequest, request);
         java.awt.EventQueue.invokeLater(new Runnable() {
             public void run() {
@@ -618,32 +630,34 @@ public class SceneApplication extends Application implements LookupProvider {
     public void handleError(String msg, Throwable t) {
         progressHandle.finish();
         if (msg == null) {
-            return;
+            msg = t.getMessage();
         }
         if (!started) {
             showStartupErrorMessage(t);
-            Exceptions.printStackTrace(t);
-        } else {
-            if (lastError != null && !lastError.equals(msg)) {
-                StatusDisplayer.getDefault().setStatusText("Error in Scene, check application log");
-                Exceptions.printStackTrace(t);
-                lastError = msg;
-            }
+        } else if (lastError != null && !lastError.equals(msg)) {
+            logger.log(Level.SEVERE, msg, t);
+            lastError = msg;
         }
     }
 
     public static void showStartupErrorMessage(Throwable exception) {
-        ActionListener lst = new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                try {
-                    HtmlBrowser.URLDisplayer.getDefault().showURL(new URL("http://jmonkeyengine.org/wiki/doku.php/sdk:troubleshooting"));
-                } catch (MalformedURLException ex) {
-                    Exceptions.printStackTrace(ex);
-                }
+        if (failMessageShown) {
+            logger.log(Level.INFO, exception.getMessage(), exception);
+            return;
+        }
+        failMessageShown = true;
+        NotifyUtil.show("Error starting OpenGL context!", "Click here to go to troubleshooting web page.", MessageType.EXCEPTION, lst, 0);
+        logger.log(Level.INFO, exception.getMessage(), exception);
+    }
+    private static ActionListener lst = new ActionListener() {
+        public void actionPerformed(ActionEvent e) {
+            try {
+                HtmlBrowser.URLDisplayer.getDefault().showURL(new URL("http://jmonkeyengine.org/wiki/doku.php/sdk:troubleshooting"));
+            } catch (MalformedURLException ex) {
+                Exceptions.printStackTrace(ex);
             }
-        };
-        NotifyUtil.show("Error starting OpenGL context!", exception.getMessage() + " - Click here to go to troubleshooting web page.", MessageType.EXCEPTION, lst, 0);
-    }
+        }
+    };
 
     @Override
     public RenderManager getRenderManager() {

+ 0 - 14
jme3-core/src/com/jme3/gde/core/sceneviewer/SceneViewerTopComponent.java

@@ -28,29 +28,17 @@ import com.jme3.gde.core.filters.FilterExplorerTopComponent;
 import com.jme3.gde.core.icons.IconList;
 import com.jme3.gde.core.scene.SceneApplication;
 import com.jme3.gde.core.scene.SceneRequest;
-import com.jme3.gde.core.util.notify.MessageType;
-import com.jme3.gde.core.util.notify.NotifyUtil;
 import com.jme3.input.awt.AwtKeyInput;
 import com.jme3.input.event.KeyInputEvent;
 import java.awt.Component;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
 import java.awt.event.MouseWheelEvent;
 import java.awt.event.MouseWheelListener;
-import java.net.MalformedURLException;
-import java.net.URL;
 import java.util.concurrent.Callable;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Logger;
 import org.netbeans.api.settings.ConvertAsProperties;
-import org.openide.DialogDisplayer;
-import org.openide.NotifyDescriptor;
-import org.openide.NotifyDescriptor.Message;
-import org.openide.awt.HtmlBrowser;
 import org.openide.awt.UndoRedo;
-import org.openide.util.Exceptions;
 import org.openide.util.HelpCtx;
 import org.openide.util.ImageUtilities;
 import org.openide.util.Lookup;
@@ -93,10 +81,8 @@ public final class SceneViewerTopComponent extends TopComponent {
             oGLPanel.add(oglCanvas);
 
         } catch (Exception e) {
-            Exceptions.printStackTrace(e);
             SceneApplication.showStartupErrorMessage(e);
         } catch (Error err) {
-            Exceptions.printStackTrace(err);
             SceneApplication.showStartupErrorMessage(err);
         }
         //TODO: camera tools (see SwitchFrontViewAction)

+ 1 - 1
jme3-core/src/com/jme3/gde/core/util/notify/MessageUtil.java

@@ -67,7 +67,7 @@ public class MessageUtil {
     * @param exception
     */
     public static void showException(String message, Throwable exception) {
-        getDialogDisplayer().notify(new NotifyDescriptor.Exception(exception, message));
+        getDialogDisplayer().notifyLater(new NotifyDescriptor.Exception(exception, message));
     }
 
     /**

+ 59 - 24
jme3-core/src/com/jme3/gde/core/util/notify/NotifyUtil.java

@@ -33,7 +33,11 @@ package com.jme3.gde.core.util.notify;
 
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import javax.swing.Timer;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
 import org.openide.awt.Notification;
 import org.openide.awt.NotificationDisplayer;
 
@@ -49,12 +53,18 @@ public class NotifyUtil {
     /**
      * Show message with the specified type and action listener
      */
-    public static void show(String title, String message, MessageType type, ActionListener actionListener, int timeout) {
+    public static Notification show(String title, String message, MessageType type, ActionListener actionListener, final int timeout) {
+        if (message == null) {
+            message = "null";
+        }
+        if (title == null) {
+            title = "null";
+        }
         final Notification n = (Notification) NotificationDisplayer.getDefault().notify(title, type.getIcon(), message, actionListener);
         if (timeout > 0) {
             java.awt.EventQueue.invokeLater(new Runnable() {
                 public void run() {
-                    Timer timer = new Timer(10000, new ActionListener() {
+                    Timer timer = new Timer(timeout, new ActionListener() {
                         public void actionPerformed(ActionEvent e) {
                             n.clear();
                         }
@@ -64,13 +74,14 @@ public class NotifyUtil {
                 }
             });
         }
+        return n;
     }
 
     /**
      * Show message with the specified type and a default action which displays
      * the message using {@link MessageUtil} with the same message type
      */
-    public static void show(String title, final String message, final MessageType type, int timeout) {
+    public static Notification show(String title, final String message, final MessageType type, int timeout) {
         ActionListener actionListener = new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent e) {
@@ -78,7 +89,7 @@ public class NotifyUtil {
             }
         };
 
-        show(title, message, type, actionListener, timeout);
+        return show(title, message, type, actionListener, timeout);
     }
 
     /**
@@ -86,8 +97,8 @@ public class NotifyUtil {
      *
      * @param message
      */
-    public static void info(String title, String message) {
-        error(title, message, true);
+    public static Notification info(String title, String message) {
+        return error(title, message, true);
     }
 
     /**
@@ -95,26 +106,34 @@ public class NotifyUtil {
      *
      * @param message
      */
-    public static void info(String title, String message, boolean clear) {
-        show(title, message, MessageType.INFO, 3000);
+    public static Notification info(String title, String message, boolean clear) {
+        return show(title, message, MessageType.INFO, clear ? 3000 : 0);
     }
 
     /**
-     * Show an exception
+     * Show an error notification
      *
-     * @param exception
+     * @param message
      */
-    public static void error(Throwable exception) {
-        error("Exception in SDK!", exception.getMessage(), exception, true);
+    public static Notification error(String title, String message, boolean clear) {
+        return show(title, message, MessageType.ERROR, clear ? 10000 : 0);
     }
 
     /**
-     * Show an error notification
+     * Show an exception
      *
-     * @param message
+     * @param exception
      */
-    public static void error(String title, String message, boolean clear) {
-        show(title, message, MessageType.ERROR, 10000);
+    public static Notification error(Throwable exception) {
+        return error("Exception", exception.getMessage(), exception, false);
+    }
+
+    public static Notification error(String title, Throwable exception) {
+        return error(title, exception, false);
+    }
+
+    public static Notification error(String title, Throwable exception, boolean clear) {
+        return error(title, exception.getMessage(), exception, clear);
     }
 
     /**
@@ -123,16 +142,27 @@ public class NotifyUtil {
      * @param message
      * @param exception
      */
-    public static void error(String title, final String message, final Throwable exception, boolean clear) {
+    public static Notification error(String title, String message, final Throwable exception, boolean clear) {
+        final NoteKeeper keeper = new NoteKeeper();
+        if (message == null) {
+            message = exception.getMessage();
+        }
+        if (title == null) {
+            message = exception.getMessage();
+        }
         ActionListener actionListener = new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent e) {
-//                ErrorManager.getDefault().notify(exception);
-                MessageUtil.showException(message, exception);
+                StringWriter out = new StringWriter();
+                exception.printStackTrace(new PrintWriter(out));
+                String exception = out.toString();
+                DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message(exception, NotifyDescriptor.ERROR_MESSAGE));
+                keeper.note.clear();
             }
         };
 
-        show(title, message, MessageType.EXCEPTION, actionListener, 10000);
+        keeper.note = show(title, message, MessageType.EXCEPTION, actionListener, clear ? 10000 : 0);
+        return keeper.note;
     }
 
     /**
@@ -140,8 +170,8 @@ public class NotifyUtil {
      *
      * @param message
      */
-    public static void warn(String title, String message, boolean clear) {
-        show(title, message, MessageType.WARNING, 5000);
+    public static Notification warn(String title, String message, boolean clear) {
+        return show(title, message, MessageType.WARNING, clear ? 5000 : 0);
     }
 
     /**
@@ -149,7 +179,12 @@ public class NotifyUtil {
      *
      * @param message
      */
-    public static void plain(String title, String message, boolean clear) {
-        show(title, message, MessageType.PLAIN, 5000);
+    public static Notification plain(String title, String message, boolean clear) {
+        return show(title, message, MessageType.PLAIN, clear ? 3000 : 0);
+    }
+
+    private static class NoteKeeper {
+
+        Notification note;
     }
 }