Archive for May, 2011

May 29, 2011

Improved ExceptionHandling with GWT RequestFactory

by Stefan

Server Side Exceptions

The default setting for handling exceptions in the server is not optimal. An exception on the server-side is caught and handled by the class DefaultExceptionHandler. Only the exception message is transferred to the client but nothing is logged. As this happens inside an http 200 response, the web app container doesn’t notice that something went wrong. The default behavior can be changed by replacing the DefaultExceptionHandler during the initialization of the RequestFactory servlet.

Therefore, a custom servlet that extends from the default RequestFactoryServlet needs to be defined to pass a custom exception handler in the constructor.

package cleancodematters.server;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.web.bindery.requestfactory.server.ExceptionHandler;
import com.google.web.bindery.requestfactory.server.RequestFactoryServlet;
import com.google.web.bindery.requestfactory.shared.ServerFailure;

public class CustomRequestFactoryServlet extends RequestFactoryServlet {

  static class LoquaciousExceptionHandler implements ExceptionHandler {
    private static final Logger LOG = LoggerFactory.getLogger( LoquaciousExceptionHandler.class );

    @Override
    public ServerFailure createServerFailure( Throwable throwable ) {
      LOG.error( "Server error", throwable );
      return new ServerFailure( throwable.getMessage(), throwable.getClass().getName(), null, true );
    }
  }

  public CustomRequestFactoryServlet() {
    super( new LoquaciousExceptionHandler() );
  }
}

read more »

Advertisements
May 19, 2011

GWT RequestFactory with GIN

by Stefan

Creating GWT RequestFactory instances requires a GWT.create() call. These calls should be outside of your classes under test, as GWT.create() internally invokes native JavaScript code. This causes a ExceptionInInitializerError when run as a plain JUnit test.

A very elegant solution is to use Dependency Injection with GIN and let the framework create and assemble both the RequestFactory and corresponding RequestContext instances. In general, using DI is a good idea for all layers of business application, and GIN brings the well-known concepts of Guice into the GWT world.

read more »

May 12, 2011

Testing asynchronous services with Mockito

by Stefan

Programming asynchronous services can be really challenging. Examples are asynchronous webservices, GWT server calls or event-based systems like widget toolkits. Usually, clients have to pass a callback to the service on which a method is called on success or error containing the data to proceed or an error message.
A typical asynchronous system is your local pizza service:

package cleancodematters;

public class PizzaService {

  public interface PizzaEvent {
    void pizzaAvailable( Pizza pizza );
  }

  public void orderPizza( String name, PizzaEvent event ) {
    // some async processing, calls event on finish
  }
}

read more »

May 9, 2011

Having fun with GWT EntityProxies in JUnit tests

by Stefan

GWT comes with a nice feature called RequestFactory that provides a high level abstraction of client-server communication. This includes a mechanism for entity conversion which allows you to have, for instance, JPA-mapped entities in the backend and independent DataTransferObjects (called Entity Proxy)  in the presentation layer. The definition of the Entity Proxies looks like this:

package cleancodematters;

import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.ProxyFor;

@ProxyFor(Pizza.class)
public interface PizzaProxy extends EntityProxy {
  void setName( String name );
  String getName();

  void setPrice( Double price );
  Double getPrice();

  boolean isOrdered();
  void setOrdered( boolean ordered );
}

Entity + Interface + Tests = Trouble

As you can see, the entities are in fact interfaces (and created and populated by the framework for you). This has some advantages. For example, GWT can internally track changes and only send deltas over the wire. However, things get complicated when it comes to testing. If you want to create an entity and populate it with two parameters you find yourself writing code like this for every test case:

	PizzaProxy pizza = mock( PizzaProxy.class );
	when( pizza.getName() ).thenReturn( "Funghi" );
	when( pizza.getPrice() ).thenReturn( Double.valueOf(6.99) );

read more »

Tags: , ,