Random thoughts on Java, AJAX, Databases, REST, GWT, HTTP4e.

GWT Dynamic Exception Handling

Having explored the GWT RPC exception limitations, on this post we will take another approach of simplifying GWT exception handling for known business types. Assuming our application has few known runtime errors we would like to be able to throw those exception without having to declare them on the RPC methods. At the same time we expect our client code to capture those errors gracefully.

The solution is a combination of steps from overriding GWT RemoteServiceServlet to injecting our supported business exceptions.

Hooking the business exception / Injecting it into GWT SerializationPolicy.

When an error is being propagated within a GWT service this error needs to be declared within the RPC method signature, otherwise GWT SerilizablePolicy marshaling will complain about the type not being recognized. Well we could easily overcome this limitation by creating a dummy hook method with only purpose of white-listing the business exception type within the given RPC signature Serialization policy:


interface AbstractRemoteServiceAsync {
   void hookException(AsyncCallback<Void> callback);
}

interface AbstractRemoteService extends RemoteService {
   void hookException() throws MyException;
}

class AbstractRemoteServiceServlet extends RemoteServiceServlet
                 implements AbstractRemoteService {
   /**
    * This method reson vivre is to hook our business MyException type into
    * GWT Serialization policy
    */
   @Override
   public String hookException() throws MyException {
      // Blank
   }
}
/**
 * The business exception
 */
public class MyException extends RuntimeException {
	private static final long serialVersionUID = 1L;
}

Overriding RemoteServiceServlet default exception flow.

Let’s open the RemoteServiceServlet implementation. One of the many things this class do is, capturing any failures and handling them appropriately. Well this is exactly what we need – change the default exception handler. Luckily GWT team designed this class to follow a template method pattern with hook methods ready for extending. What we will acomplish is extending RemoteServiceServlet class and inject a behaviour handling our business exceptions (code in red).

And this is my humble contribution to GWT community. All sources and project are hosted at Google Code:

/**
 * This class overrides RemoteServiceServlet to provide automatic exception
 * handling for known business exceptions
 */
public class AbstractRemoteServiceServlet extends RemoteServiceServlet
    implements AbstractRemoteService {

  /**
   * Overriding method so we can inject business exception type discovery
   * and handling
   */
  @Override
  public String processCall(String payload) throws SerializationException {
    try {
      RPCRequest rpcRequest = RPC.decodeRequest(payload, this.getClass(),
          this);
      return handleProcessCall(this, rpcRequest);
    } catch (IncompatibleRemoteServiceException ex) {
      log("Incompatible error was thrown while processing this call.", ex);
      return RPC.encodeResponseForFailure(null, ex);
    }
  }
  /**
   * Tis method digest the given throwable and tries to find any know business
   * exception. When a known business error is found it is being flushed (the
   * business type) to response stream, thus client callback receives the known
   * type but not the default GWT UnexpectedException.
   */
  @Override
  protected void doUnexpectedFailure(Throwable e) {
    discoverAndWriteError(e, e);
  }

  /**
   * This method reson vivre is to hook the recognized MyException type into
   * GWT Serialization policy
   */
  @Override
  public void hookException() throws MyException {
    // Blank
  }
  /**
   * Method handles GWT RPC call and on failure it digests the error,
   * finds supported business exception and handles them gracefully.
   */
  private String handleProcessCall(Object target, RPCRequest rpcRequest)
      throws SerializationException {

    Method serviceMethod = rpcRequest.getMethod();
    Object[] params = rpcRequest.getParameters();
    SerializationPolicy serializationPolicy = rpcRequest
        .getSerializationPolicy();
    try {
      return RPC.invokeAndEncodeResponse(target, serviceMethod, params,
          serializationPolicy);
    } catch (UnexpectedException ex) {
      Throwable cause = ex.getCause();
      // This could be a list of supported types ..etc..
      // Leaving it up to your imagination
      if (cause.getClass().equals(MyException.class)) {
        throw new MyException();
      }
      return encodeResponse(cause.getClass(), cause, true,
          serializationPolicy);
    }
  }

  /**
   * This method recursively iterates through given 'masterError'
   * finding any supported failures and handling the latter
   * appropriately.
   */
  private void discoverAndWriteError(Throwable masterError, Throwable e) {
    if (e == null) {
      writeError(new UnexpectedException(masterError.getMessage(),
          masterError));
      return;
    }

    Throwable cause = e.getCause();
    if (cause == null) {
      writeError(new UnexpectedException(masterError.getMessage(),
          masterError));
      return;
    }
    // This could be a list of supported types, etc..
    // Leaving it up to your imagination
    if (cause.getClass().equals(MyException.class)) {
      writeError(new MyException());
      return;
    } else {
      // continue with 'recursion' cause discovery
      discoverAndWriteError(masterError, cause);
    }
  }

  /**
   * This method writes known business exception the response HTTP packet
   * Code borrowed from com.google.gwt.user.server.rpc.RPCServletUtils
   */
  private void writeError(Throwable cause) {
    // Send SC_OK/200 status, serialize the gwt error, flush it to response,
    // and let the client deal with the business error
    HttpServletResponse resp = getThreadLocalResponse();
    try {
      resp.setContentType("text/plain");
      resp.setStatus(HttpServletResponse.SC_OK);
      String excMsg = RPC.encodeResponseForFailure(null, cause);
      resp.getWriter().write(excMsg);

    } catch (IOException e) {
      log("Failed to send failure to client", e);

    } catch (SerializationException e) {
      log("Failed to send failure to client", e);
    }
  }

  /**
   * Borrowed from RPC.java. Returns a string that encodes the results of an
   * RPC call. Private overload that takes a flag signaling the preamble of
   * the response payload.
   */
  private static String encodeResponse(Class responseClass, Object object,
      boolean wasThrown, SerializationPolicy serializationPolicy)
      throws SerializationException {

    ServerSerializationStreamWriter stream = new
              ServerSerializationStreamWriter(serializationPolicy);
    stream.prepareToWrite();
    if (responseClass != void.class) {
      stream.serializeValue(object, responseClass);
    }
    String bufferStr = (wasThrown ? "//EX" : "//OK") + stream.toString();
    return bufferStr;
  }
}

With the new RemoteService classes being created above, our GWT Services will derive from them as bellow:


@RemoteServiceRelativePath("greet")
interface GreetingService extends AbstractRemoteService {
  /* Notice, no exception is being declared*/
  String greetServer(String name);
}

interface GreetingServiceAsync extends AbstractRemoteServiceAsync {
  /* Notice, no exception is being declared*/
  void greetServer(String input, AsyncCallback callback);
}

class GreetingServiceImpl extends AbstractRemoteServiceServlet implements
    GreetingService {
  /* Notice, no exception is being declared*/
  public String greetServer(String input) {
    {
      throw new MyException();
    }
  }
}

The last piece of course is executing the service and see it in real browser:

Feel free to explore project sources at Google Code.

GWT Exception Handling Limitations

While developing GWT Remote Procedure Calls(RPC), many of you have experienced the limitations of the default GWT exception handling model. I will demonstrate this with a sample application. If you create the default GWT hello world application you will notice three RPC service classes being created for you:


interface GreetingServiceAsync {
   void greetServer(String input, AsyncCallback<String> callback)
          throws IllegalArgumentException;
}

@RemoteServiceRelativePath("greet")
interface GreetingService extends RemoteService {
   String greetServer(String name) throws IllegalArgumentException;
}

class GreetingServiceImpl extends RemoteServiceServlet
                 implements GreetingService {
   public String greetServer(String input) throws IllegalArgumentException {
      { // let's just throw an error for demonstration
         throw new IllegalArgumentException ("Bad arguments passed");
      }
   }
}

So, the error handling works this way. GreetingServiceImpl captures an error and throws a runtime failure, in our case IllegalArgumentException. So far so good. But, what if we need to throw a different error. Let’s say MyIllegalArgumentException? Well by design (GWT design), we need to declare it on each three RPC methods:


interface GreetingServiceAsync {
   void greetServer(String input, AsyncCallback<String> callback)
            throws MyIllegalArgumentException;
}

@RemoteServiceRelativePath("greet")
interface GreetingService extends RemoteService {
   String greetServer(String name) throws MyIllegalArgumentException;
}

class GreetingServiceImpl extends RemoteServiceServlet
                 implements GreetingService {
   public String greetServer(String input) throws MyIllegalArgumentException{
      { // let's just throw an error for demonstration
         throw new MyIllegalArgumentException("Bad arguments passed");
      }
   }
}

But as you may notice, this is quite cumbersome. You need to declare the exception on each RPC method in 3 places – the Service, ServiceAsync and ServiceImp classes. To make the matter even worse as long as you have multiple methods and variety of exception types you end up into the exception over-declaring hell with methods looking this way myMethod() throws Exception1, Exception2, Exception3, Exception4 (and don’t forget this requires to be declared into three places – 3 RPC classes).

Being curious (and lazy) you may wonder what will happen if:

A. We simply skip declaring the errors from the method signature:
/* no exception being declared*/
greetServer(String input, AsyncCallback<String> callback)
B. Or derive and throw a business failure from the declared Exception. We create a derived exception from IllegalArgumentException and the method throws the child error, while the method signature has the parent one:

class AnotherBusinessException extends IllegalArgumentException {
   ..
}
class GreetingServiceImpl extends RemoteServiceServlet
                 implements GreetingService {
   public String greetServer(String input) throws IllegalArgumentException{
      { // let's just throw an error for demonstration
         throw new AnotherBusinessException("Bad arguments passed");
      }
   }
Testing those cases against GWT RPC results with:
  • A.   HTTP/1.1 500 Internal Error
    [WARN] Exception while dispatching incoming RPC call com.google.gwt.user.server.rpc.UnexpectedException: Service method ‘public abstract java.lang.String GreetingService.greetServer(java.lang.String)’ threw an unexpected exception: java.lang.IllegalArgumentException..
  • B.    HTTP/1.1 500 Internal Error
    [WARN] Exception while dispatching incoming RPC call com.google.gwt.user.client.rpc.SerializationException: Type ‘org.roussev.hello.client.AnotherBusinessException’ was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized…
Which is not very promising. GWT not just complains but throws 500 Server Errors. In case A, GWT complained about an exception type GWT doesn’t recognize and GWT defaults to UnexpectedException. In case B. GWT kinda liked the type, but refused to load it for security purposes.

All said, GWT exception handling forces us to declare all those business errors as part of the method signatures on all three RPC classes. And this is a tedious, error prone and repetitive process. Instead we (the lazy developers) are looking for more dynamic approach. We are looking for an approach where:

  1. An RPC Service method should not have to declare any runtime business failures.
  2. The server should handle the runtime business failures gracefully with 200 OK, instead of 500 Error
  3. And lastly, UI should receive the exact error type (not some gwt StatusCodeException or an UnexpectedException) directly into the consuming callback void onFailure(Throwable e).
More to come. Stay tuned..
Digging into WebDriver today an interesting question popped up.  How does WebDriver interact with browser?! Only thing I knew that it was using JNI to connect to native DLL’s.
So I decided to attach my Eclipse debugger to WebDriver sources and execute a WebDriver Hello World test. The first thing I noticed was this interesting packet being sent:
{
   "response": "Unable to locate element: {"method":"id","selector":"q"}",
   "context": "{711c552c-4fac-473c-83ce-dc767ff37ff2} ",
   "commandName": "findElement",
   "isError": true
}
Which is nothing else but JSON. This increased even more my curiosity. Well, JSON being used by WebDriver to sent messages to browser, then who is the server and who is the client? What is the protocol? I ended up finding the answer here JsonWireProtocol.
And the FirefoxDriver source class too:
public class FirefoxDriver implements WebDriver ... {
   protected Object executeCommand(Class<RuntimeException> throwOnFailure,
                             Command command) {
      Response response = extension.sendMessageAndWaitForResponse(
                     throwOnFailure, command);
      context = response.getContext();
      response.ifNecessaryThrow(throwOnFailure);
......
So what is actually happening is:
1. When a WebDriver test is being created and executed.
2. This test makes an HTTP call to Firefox (or any browser) using JNI (I am still puzzled here how this exactly works)
2. And the listener (the server) is the actual browser. Quite confusing eh?
3. The listener(the browser) receives the HTTP request from WebDriver and responds back with a JSON HTTP packet.
4. WebDriver digest the response packet and either calls back the command OR fails the execution.

I am constantly experiencing this bug since I got my Vaio for more than 3 years already. Whenever I quickly move images, copy/paste fast enough over the folders (and I am very quick typer), Windows Explorer crashes and ask me to report to Windows. Well, this problem is a know issue for years. 1.3 million people are screaming for help. Odd enough seems Windows 7 is plaged by the same problem?! Anyone at Microsoft paying attention? And what is the purpose of reporting this problem when when it never gets fixed.

Anyhow, being frustrated with the Windows experience I looked for my favorite Ubuntu file manager called Dolphin. After installing KDE I am happy camper with:

  • NON crashing Dolphin
  • More logical folder structure.
  • Bookmarking

Thank you Windows. Next time try better. Meanwhile I am switching to Mac OS.

Open to new opportunities

The Bad:

I was laid off from indicee. Bad economy, no sales, go figure… Yet, I had a chance to meet great people there. Anyway, Good luck indicee. Thanks for giving me the chance to be on your team.

The Good:

Suddenly I have time. And I am open for new challenges.

Hey Recruiters & Headhunters. I am open to new contract or long term opportunities.

IE browser is bellow 60% !

Drum Rolls… IE goes bellow 60% for a first time since Netscape4. Good job Firefox and Chrome! With this trend IE will cross the 50% line well before end of 2010.

The usage share of web browsers from wikipedia.
Internet Explorer (59.21%; )
Mozilla Firefox (28.29%; )
Google Chrome (5.02%)
Safari (4.54%)
Opera (1.68%)
Other (1.26%)

Google phases out support for IE6

http://news.bbc.co.uk/2/hi/technology/8488751.stm

Meaning “Goodbye GIF” and “Hello PNG”. I am waiting for this moment since 2003!!

Great fonts for programming

If you are looking for a neat readable font for your development machine, you may consider those two.:

Inconsolata:
http://www.levien.com/type/myfonts/inconsolata.html

Bitstream Vera
http://www.gnome.org/fonts/

After switching to those, my previous Eclipse Courier started looking as a old Russian car.

Enjoy it.

TechCrunch News:  http://www.techcrunch.com/2009/11/04/indicee-raises-6-million-for-cloud-based-business-intelligence-reporting-tool/

The fastest way to mash data and get answers.

Great video from Indicee.

Combine data from different business systems, files and spreadsheets to create and share reports in minutes. No IT expertise required.

Indicee web2.0 business intelligence