Si l'on est sûr de recevoir une exception de type MonApplicationException côté client, il est plus facile d'afficher à l'utilisateur final un message compréhensible pour le commun des mortels.

Théorie

MonApplicationException devra être sérializable, avec un constructeur par défaut et des getter / setter pour chacun de ses attributs. On pensera à déclarer que les méthodes Rpc renvoient bien cette exception avec un throws afin de pouvoir la récupérer avec la méthode onFailure de l'AsyncCallBack. MonApplicationException devra également se trouver dans un package déclaré en module GWT afin de pouvoir être traduit en Javascript.

MonApplicationException pourra contenir divers autres attributs suivant le besoin, pour afficher une liste d'explications pour résoudre le message d'erreur par exemple. Le tout est de bien respecter les getter et les setter.

L'AOP va nous permettre d'enlever les try / catch de toutes les méthodes de traitement des appels Rpc. Ça allègera le code, qui sera plus lisible et plus rapide à écrire. Par convention, j'ai choisi de terminer toutes les classes de gestion Rpc par le pattern *Rpc, ainsi que les appels eux même. Un service Rpc est un service d'infrastructure, à bien différencier avec les services de persistence qui eux feront appel à une couche de règles métier.

Pratique

Premièrement on configure Spring avec ces quelques lignes à rajouter dans son fichier de configuration.

	<aop:aspectj-autoproxy />

	<bean id="rpcHandlerInterceptor"
		class="package.interceptor.RpcHandlerInterceptor" />

	<aop:config>
		<aop:pointcut id="pointcut4RpcExceptionHandler"
			expression="package.aop.SystemArchitectureWeb.rpcWithExceptionHandler()" />

		<aop:advisor pointcut-ref="pointcut4RpcExceptionHandler"
			advice-ref="rpcHandlerInterceptor" />

	</aop:config>

Voici un exemple simple d'implémentation d'un interceptor. On utilise ici ExceptionHelper qui est un simple Helper de transformation d'Exception, qui permet de faire un traitement spécifique pour les validator Hibernate ou pour d'autres types d'erreur bien spécifique (gestion des messages d'erreur)

/**
 * Interceptor pour les methodes des appels Rpc.
 */
public final class RpcHandlerInterceptor implements MethodInterceptor {

	/**
	 * ServiceExceptionInterceptor gere par Spring
	 */
	private RpcHandlerInterceptor() {
		super();
	}

	/**
	 * {@inheritDoc}
	 */
	public Object invoke(final MethodInvocation pMethod) throws MonApplicationException {
		Object object = null;
		try {
			object = pMethod.proceed();
			// Traitement generique des exceptions
		} catch (Throwable vThrowable) {
			throw ExceptionHelper.transform(vThrowable);
		}
		return object;
	}

}

Voici maintenant un exemple d'implémentation d'un pointCut, qui permet de dire que l'interceptor sera appliqué sur toutes les méthodes des classes se terminant par Rpc. Il n'y a que les deux annotations qui sont utilisées dans cette classe, pas besoin d'implémenter les méthodes.

/**
 * La classe tisseuse d'aspect
 */
@Aspect
public final class SystemArchitectureWeb {

  /**
   * Classe non instanciee.
   */
  private SystemArchitectureWeb() {
  }
  
  /**
   * Rpc with exception handler.
   */
  @Pointcut("execution(* package.mon.application.server..*Rpc.*(..))")  
  public void rpcWithExceptionHandler() {
  }

}

Et voici les dépendances à rajouter dans Maven, il vous suffit juste de mettre à jour le numéro de version avec le dernier sortie.

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${spring.version}</version>
		</dependency>

Attention tout de même à ne pas abuser de l'AOP qui peut transformer votre code en plat de spaghetti.