Griffon
  1. Griffon
  2. GRIFFON-328

UncaughtExceptionHandler support in Griffon core

    Details

    • Type: New Feature New Feature
    • Status: Closed Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 0.9.2
    • Component/s: rt
    • Labels:
      None
    • Number of attachments :
      0

      Description

      This is a feature request to have pluggable UncaughtExceptionHandler support in Griffon rt core, so plugin developers can develop pluggable error handling mechanism to handle uncaught exceptions regardless the threading condition. In other words, handler should be invoked whenever an uncaught exception is discovered whether its in a controller closure method or doLater or execAsync closure. It will also be useful for application developers to use to release resources or reset app state.

        Activity

        Hide
        Andres Almiray added a comment - - edited

        It turns out Griffon already has an UncaughtExceptionHandler (griffon.util.GriffonExceptionHandler), so we can extend its functionality to trigger app events when an application is caught by it. For example

        import groovy.transform.Synchronized
        
        class SampleController {
            private lastCaughtException
        
            @Synchronized
            void onUncaughtRuntimeException(RuntimeException e) {
                lastCaughtException = e
                println "Got a RuntimeException -> $e"
            }
        
            @Synchronized
            void onUncaughtExceptionThrown(e) {
                if(lastCaughtException == e) return
                lastCaughtException = e
                println "OH NOES! $e"
            }
        }
        

        Events will be triggered following these conventions:

        • trigger onUncaught<shortClassName(exception.class)>(exception)
        • trigger onUncaughtExceptionThrown(exception)

        This means that an uncaught RuntimeException will trigger two events. SampleController will handle it with onUncaughtRuntimeException but onUncaughtExceptionThrown should skip it (due to synchronization and memoizing of the last exception caught). Any other Exception should be handled by onUncaughtExceptionThrown. This mechanism does not support inheritance, i.e, throwing an IllegalArgumentException wont be handled by onUncaughtRuntimeException.

        Show
        Andres Almiray added a comment - - edited It turns out Griffon already has an UncaughtExceptionHandler (griffon.util.GriffonExceptionHandler), so we can extend its functionality to trigger app events when an application is caught by it. For example import groovy.transform.Synchronized class SampleController { private lastCaughtException @Synchronized void onUncaughtRuntimeException(RuntimeException e) { lastCaughtException = e println "Got a RuntimeException -> $e" } @Synchronized void onUncaughtExceptionThrown(e) { if (lastCaughtException == e) return lastCaughtException = e println "OH NOES! $e" } } Events will be triggered following these conventions: trigger onUncaught<shortClassName(exception.class)>(exception) trigger onUncaughtExceptionThrown(exception) This means that an uncaught RuntimeException will trigger two events. SampleController will handle it with onUncaughtRuntimeException but onUncaughtExceptionThrown should skip it (due to synchronization and memoizing of the last exception caught). Any other Exception should be handled by onUncaughtExceptionThrown . This mechanism does not support inheritance, i.e, throwing an IllegalArgumentException wont be handled by onUncaughtRuntimeException .
        Hide
        Hamlet D'Arcy added a comment -

        why not keep it simple? If a controller implements UncaughtExceptionHandler then make sure that method gets called on an unhandled exception:
        http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.UncaughtExceptionHandler.html

        There is a Java interface... just use that. Then you get Java interop for free. No reason to reinvent the wheel.

        Show
        Hamlet D'Arcy added a comment - why not keep it simple? If a controller implements UncaughtExceptionHandler then make sure that method gets called on an unhandled exception: http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.UncaughtExceptionHandler.html There is a Java interface... just use that. Then you get Java interop for free. No reason to reinvent the wheel.
        Hide
        Andres Almiray added a comment -

        Actually you can do that regardless of GriffonExceptionHandler, as long as you attach the controller to the current ThreadGroup you'll be fine. However you'll loose the ability to handle exceptions in the EDT, that's another job GriffonExceptionHandler does for the developer.

        Show
        Andres Almiray added a comment - Actually you can do that regardless of GriffonExceptionHandler , as long as you attach the controller to the current ThreadGroup you'll be fine. However you'll loose the ability to handle exceptions in the EDT, that's another job GriffonExceptionHandler does for the developer.
        Hide
        Nick Zhu added a comment -

        Andres your proposal is exactly how I implemented using AST but only nicer, so far it works great for the app I developed. One thing I would like to mention is any exception thrown by the exception handlers should be ignored since otherwise there is a chance to trigger infinite loops (something I ran into while working on my app

        Hamlet, IMO using Thread.UncaughtExceptionHandler is more repurposing than resuing which might not be a good idea. Personally I think Andres' proposal blend itself better into the Griffon framework and it is also more versatile since it already has the filtering built-in by using the exception type.

        Show
        Nick Zhu added a comment - Andres your proposal is exactly how I implemented using AST but only nicer, so far it works great for the app I developed. One thing I would like to mention is any exception thrown by the exception handlers should be ignored since otherwise there is a chance to trigger infinite loops (something I ran into while working on my app Hamlet, IMO using Thread.UncaughtExceptionHandler is more repurposing than resuing which might not be a good idea. Personally I think Andres' proposal blend itself better into the Griffon framework and it is also more versatile since it already has the filtering built-in by using the exception type.
        Hide
        Andres Almiray added a comment -

        Right. GriffonExceptionHandler is aware of any exceptions that might arise when triggering the event for handling an uncaught exception. When that happens the code will use a logger and optionally, print the error to the console.

        Other advantages of GriffonExceptionHandler are:

        • it does not interfere with AST injections
        • any instance can react to uncaught Exceptions if registered as an app event listener
        • uncaught exceptions are automatically sanitized (full stacktrace is configurable too)
        Show
        Andres Almiray added a comment - Right. GriffonExceptionHandler is aware of any exceptions that might arise when triggering the event for handling an uncaught exception. When that happens the code will use a logger and optionally, print the error to the console. Other advantages of GriffonExceptionHandler are: it does not interfere with AST injections any instance can react to uncaught Exceptions if registered as an app event listener uncaught exceptions are automatically sanitized (full stacktrace is configurable too)

          People

          • Assignee:
            Andres Almiray
            Reporter:
            Nick Zhu
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: