back to API     back to index     prev     next  

Handling Non-Functional Exceptions in ProActive

What are Non-Functional Exceptions ?

A few years ago, Aspect-oriented Programming defined non-functional properties (security, persistence, transaction...) to produce separation of concerns (for information and more, see AspectJ website). Because of its transparency in ProActive, distribution can be seen as a non-functional property. However, exceptions occuring in a distributed environment are raised from lower non-functional levels (i.e. network or Java RMI) to higher functional levels (functional code) with usually no other choice than stopping application. Such exceptions, raised from a non-functional property, are called non-functional exceptions and should not be propagated outside the scope of non-functional property. The handlers mechanism developed within ProActive is a reliable solution. As this model has been subject to intensive work, a complete article can be found here.

Non-functional exceptions signal abnormal behavior of non-functional property, such as distribution. Thus, we defined a complete hierarchy adapted to distribution and used by our own handling mechanism (see forward).

Figure 1 : Hierarchy of Non-Functional Exceptions for Distribution

Those exceptions can be found in the following packages :

  • Communication exceptions : org.objectweb.proactive.core.exceptions.communication
  • Creation exceptions : org.objectweb.proactive.core.exceptions.creation
  • Group exceptions : org.objectweb.proactive.core.exceptions.group
  • Migration exceptions : org.objectweb.proactive.core.exceptions.migration
  • Security exceptions : org.objectweb.proactive.core.exceptions.security
  • Service exceptions : org.objectweb.proactive.core.exceptions.service
  • Mechanism of Handlers and API

    Handlers are dedicated exception managers dealing with non-functional exceptions. Every handler implements the interface HandlerInterface in order to provide methods to handle exceptions. Here is the interface :

         // Is the exception managed by the current handler ?
      public boolean isHandling(Exception e);
    
         // Provide a treatment for handled exception(s)
      public void handle(Exception e);
    

    Then, handlers are associated to static and dynamic structures and provide different levels according to the desired behavior. The following levels are ordered from lower to higher priority :

  • Default : this level is static and initialized in core code. Static handlers provide basic handling for every distributed exception.
  • Virtual Machine : dynamic handlers allow the configuration of a general handling behavior for every VM.
  • Active Object : Such objects can have their own handlers.
  • Proxy : References to active object can also have their own handlers.
  • Future : Results of asynchronous calls can require a specific treatment.
  • Code : Sometimes handlers are set punctually in the code.
  • Default handlers provide a basic handling strategy which avoid intensive use of dynamic handlers. Construction and configuration happen during initialization of ProActive. Default level contains only static handlers which are provided for every class of distributed exception. VM and higher levels contain dynamic handlers to improve and adapt fault tolerance strategies defined at default level. This is particularly useful when different versions of a distributed middleware (Peer to Peer, Client/Server or Desktop/Mobile applications) derive from a common source. Such dynamic handlers are created at runtime and added to appropriate level (VM, active object, proxy, future or temporary code levels). \emph{A standard strategy, common to every distributed application, is provided with the default level while more specific strategies are achieved with dynamic levels}. Of course, as configuration change from application to application, or even from execution ton execution, dynamic handling offers obviously much more possibilities than static handling. Handlers are modified or exchanged according to the context of environment.

    The API consists of three major static functions.

      public static void setExceptionHandler(HashMap hash, HandlerInterface handler, ProActiveException ex);
      public static HandlerInterface unsetExceptionHandler(HashMap hash, ProActiveException ex);
      public static boolean searchExceptionHandler(HashMap handlerList, ProActiveException ex);
    

    SetExceptionHandler binds one handler with a class of exception at a specific level.
    UnsetExceptionHandler removes from level the handler associated with the given class of exception.
    SearchExceptionHandler searches a correct handler forn a class of exception and apply the handling method to the raised exception.

    Dealing with Exceptions in ProActive Contributions : Static Handlers at Default Level and Dynamic Handlers

    Default handlers, being part of the default level, are statically created when ProActive runtime is executing. They should not be removed or overloaded. We don't advise any modification at runtime because of its use to produce specific safety behavior. Dynamic handlers from VM and higher level are provided to improve fault tolerance behavior. The default level gives a general behavior for exception handling while VM and higher level provides its specialization. This is particularly useful if different versions of ProActive (ex : Peer to Peer application, Client/Server or Desktop/Mobile) are planed. By constructing specific behavior statically, most of the configuration can be avoided at runtime.

    Here is how default and VM levels are declared and initialized.

         // The two lower levels of exception handling
      static public HashMap defaultLevel;
      static public HashMap VMLevel;
     
         // Static initialization of ProActive
      static {
    	
           // Creation of main handlers levels
        defaultLevel = new HashMap();	
        VMLevel = new HashMap();
    	
           // We set default handlers to use at default level
           // VM and higher level remain empty from any handler
        setExceptionHandler(defaultLevel, "HandlerProActiveException", "ProActiveException");
        setExceptionHandler(defaultLevel, "HandlerCommunicationException", "ProActiveCommunicationException");
        setExceptionHandler(defaultLevel, "HandlerCreationException", "ProActiveCreationException");
        setExceptionHandler(defaultLevel, "HandlerGroupException", "ProActiveGroupException");
        setExceptionHandler(defaultLevel, "HandlerMigrationException", "ProActiveMigrationException");
        setExceptionHandler(defaultLevel, "HandlerSecurityException", "ProActiveSecurityException");
        setExceptionHandler(defaultLevel, "HandlerServiceException", "ProActiveServiceException");
    
        // Other initializations follow...
      }
    

    Other levels are created and configurated along with their associated objects.

         // Creation of a remote and mobile object
      RO ro = (RO) ProActive.newActive("RO", params);
    
         // Set a specific handler for communication
      setExceptionHandler(ro.remoteObjectLevel,
                          "CommunicationHandler",
                          "CommunicationException");
    
         // Remote method calls are now protected
      ro.foo();
    

    The following code shows how to search a specific handler when an exception is raised. Keep in mind that the search starts from higher priority levels as seen previously.

      try {
     
         // Reified method call as founded in the core of ProActive 
         sendRequest(methodCall, null);
    
      catch (ProActiveException e) {
    
           // We search a reliable handler in levels for the given exception
        HandlerInterface handler = searchExceptionHandler(e);
    
           // Then we handle exception 
        handler.handle(e);
      }
    

    To summarize, here are the most important points to customize handlers mechanism :

  • Define a Distributed Exception within the hierarchy of non-functional exceptions.
  • Create a reliable handler from scratch or from an existing one.
  • Register handler during initialization or at runtime with setExceptionHandler.
  • Adapt try/catch construction with searchExceptionHandler.
  • Example of a Complete Strategy within a ProActive Application

    Coming soon...



    Copyright © April 2004 INRIA All Rights Reserved.