Mandala compared to other frameworks

Mandala vs RMI

HelloWorld overview

Unavailable Unavailable

"Real" code overview

We want to implement a business class with a login(user, passwd) method which returns true if the user can log into the system and false otherwise.

Two possibilities must be considered depending on the availability of this businness class we will call business.Login:

First case: coding from scratch

In this case, using RMI involves many steps:

  1. defining the remote interface:
              package business;
     
              public interface Login extends java.rmi.Remote {
    
                  boolean login(String user,
                                String passwd) throws java.remi.RemoteException;
              }
    
            
  2. implementing this interface:
              package business;
    
              public class LoginImpl extends java.rmi.server.UnicastRemoteObject
                                     implements Login {
                  private java.util.Random random = new java.util.Random();
    
                  public boolean login(String user, 
                                       String passwd) throws java.remi.RemoteException {
                      // Bad logic ?!
                      Thread.sleep(random.nextInt(10000));
                      return random.nextBoolean();
                  }
              }
    
            

    As you see, their is no logic in this business method, but this implementation will simulate an access to a database for our example. Note that if the class does not extend java.rmi.server.UnicastRemoteObject the code is still valid for the compiler since types are correct but will not have the behavior we want.

  3. Creates the method which runs the server (in the business class or anywhere else) and bind it somewhere using a registry service such as JNDI or rmiregistry:
               try{
                   business.Login loginService = new business.Login();
    
                   // bind(loginService) do the hardwork of binding...
                   bind(loginService); 
               }catch(RemoteException e) {
                   log.error(e, "Can't instantiate the Login service");
                   System.exit();
               }
            
  4. implementing the client.

    First, the client must perform a lookup on the registry service the loginService have been binded to:

                // lookup() do the hardwork of looking up...
                business.Login loginService = lookup(bindName);
    
                // Use the service:
    
                try{
                    boolean ok = loginService.login(userName, passwd);
    
                    if (!ok) {
                        displayErrorMessage(...);
                        return;
                    }
    
                    // continue...
                }catch(RemoteException re) {
                    // handle the remote exception (hard job !)
                }
            
    Notice how the code is populated with non business code (RMI code).
Mandala involves few steps:
  1. implementing the business class:
            package business;
    
            public class Login {
                  private java.util.Random random = new java.util.Random();
    
                  public boolean login(String user, String passwd) {
                      // Bad logic ?!
                      Thread.sleep(random.nextInt(10000));
                      return random.nextBoolean();
                  }
              }
            

    As you see, no more interface to implement, no class to extend, no exception to throw. Just a standard business class. Mandala allows the developer to concentrate on its business logic only. The next step is to insert an instance of our Login class into a remote ActiveMap and to bind our service to a registry in order for clients to lookup our service. We may instantiate our class locally and then insert it into the active map (using put() directly or SORFactory.getInstance() indirectly), but in order for this to be possible, our class needs to be serializable which is not the case. Note that this is not efficient if you have to use many stored objects. The other solution is to directly instantiate our class remotely. This can be done directly using the Instanciator class or indirectly using the SORFactory.newInstance() method. In fact, a simpler approach is available, you just invoke a jayac generated constructor, and it will do the job for you !

  2. Insertion into a remote active map:
            // gets a proxy on a remote active map
            ActiveMap activeMap = null;
            try{
                activeMap = (mandala.jacob.remote.RemoteActiveMap) 
                    new javax.naming.InitialContext().lookup(bindName);
            }catch(NamingException ne) {
                logger.error(ne, "Can't find " + bindName);
                return;
            }
    
            // Instanciate a Login object remotely into the active map
            jaya.business.Login proxy = 
                        new jaya.business.Login(new SORFactory(activeMap));
    
            // bind(proxy) do the hardwork of binding...        
            bind(broxy);
    
            

    Notice that since Login just contains business code, it is not concerned with remote access. So, it must be inserted into a remote server to become remotely accessible.
    Note also that this operation can be performed directly from the client so there is no need to bind anything if you are the only client of a given server!

  3. implementing the client.

    Client uses the service as any other RAMI object:

                // lookup() do the hardwork of looking up...
                jaya.business.Login proxy = lookup(bindName);
    
                // Use the service:
    
                boolean ok = proxy.login(userName, passwd);
    
                if (!ok) {
                    displayErrorMessage(...);
                    return;
                }
    
               // continue...
            

    Notice how the code is no more polluted with non business code. Note also that you can perform easily an asynchronous remote method invocation in order to compute something during the login() execution:

                // lookup() do the hardwork of looking up...
                jaya.business.Login proxy = lookup(bindName);
    
                // Use the service:
    
                FutureClient future = proxy.rami_login(userName, passwd);
    
    
                doSomethingElse(); (during the remote execution of login())
    
    
                boolean ok = false;
    
                try{
                    ok = ((Boolean) future.waitForResult()).booleanValue();
                }catch(Throwable t) {
                    logger.warning(t, "Exception during a remote asychnonous call");
                    ok = false;
                }
    
                if (!ok) {
                    displayErrorMessage(...);
                    return;
                }
    
               // continue...
            

Dynamic Remote Accessibility

Suppose you already have a business.Login class, that you must use, but you don't have the source code. How would you render this class remotely accessible

In the RMI world, several steps are necessary using the adapter pattern.

Using Mandala, since objects do not have to be designed specifically to be accessed remotely (and asynchronously), you use exactly the same steps as in the from scratch case. The only difference is that you didn't produce the business code. But as far as the client (the one who use a given class) is concerned, it doesn't matter.