Tratamiento de excepciones de Java en Flex utilizando el paquete de integración de Spring con BlazeDS
Spring tiene un proyecto, denominado Spring BlazeDS Integration, cuyo objetivo es facilitar el desarrollo de aplicaciones ricas de internet que utilicen java y Spring en el back end y Adobe Flex en el front end. Con este proyecto podemos exponer como destinos remotos objetos gestionados por el contenedor, de modo que podamos invocar desde Flex sus métodos, hacer uso de las facilidades del Data Centric Development de Flash Builder 4 y dar tratamiento personalizado a las excepciones de Java, entre otras cosas.
Introducción
Normalmente en el código Java, y más frecuentemente en la capa de acceso a datos, se pueden generar excepciones que se propagan hasta la interfaz de usuario. Si por ejemplo utilizamos un componente RemoteObject para invocar un método de una clase Java, y éste genera una excepción durante su ejecución, podemos acceder a la información de ésta si hemos definido un manejador para el evento “fault” del componente.
Como sabemos, las excepciones de Java pueden ser disímiles, y atendiendo a la condición que las causa la cantidad de información que portan es variable. Las excepciones generadas por las operaciones de acceso a datos son por lo general muy explicativas, e incluyen prácticamente un reporte detallado de la causa, que puede ser una violación de integridad referencial, una violación de llave duplicada, etc. Esta información por lo general se encuentra fuera de dominio de los usuarios finales de la aplicación y además de abrumarlos no les aporta información útil. En estas condiciones es cuando puede ser útil un mecanismo que traduzca esas excepciones en otras que porten información útil para el usuario final.
Desarrollo
Para mostrar el funcionamiento del mecanismo de traducción de excepciones del paquete de integración de Spring con BlazeDS, desarrollaremos una pequeña aplicación de ejemplo en la que desde Flex invoquemos un método de Java que genere una excepción y veremos cómo se maneja, luego incorporaremos el mecanismo de traducción de excepciones, invocaremos nuevamente el método y compararemos los resultados.
Como entorno de trabajo utilizaremos Flash Builder 4 plug-in instalado sobre el paquete galileo del Eclipse IDE for Java EE Developers, BlazeDS 4, spring-framework-3.0.2.RELEASE y spring-flex-1.0.3.RELEASE.
Comenzaremos por crear un proyecto combinado Flex/Java:
A continuación añadiremos todo lo que tiene que ver con Spring al proyecto.
- Una vez descargado el framework spring extraemos en la carpeta ExceptionTranslationDemo\WEB-INF\lib\ el contenido de la carpeta “dist” del archivo previamente descargado.
- Descargamos “cglib-nodep-2.2.jar” y lo copiamos en ExceptionTranslationDemo\WEB-INF\lib\
- Descargamos “backport-util-concurrent.jar” y lo copiamos en ExceptionTranslationDemo\WEB-INF\lib\
- Descargamos “aopalliance.zip” y copiamos el archivo “aopalliance.jar” en ExceptionTranslationDemo\WEB-INF\lib\
- Descargamos “spring-flex-1.0.3.RELEASE.zip” y copiamos los archivos de la carpeta “dist” en ExceptionTranslationDemo\WEB-INF\lib\
Para configurar la integración de Spring con BlazeDS, modificamos el archivo “web.xml” que se encuentra en ExceptionTranslationDemo\WEB-INF para que quede de la siguiente manera:
-
<?xml version="1.0" encoding="UTF-8"?>
-
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
-
<web-app>
-
-
<display-name>BlazeDS</display-name>
-
<description>BlazeDS Application</description>
-
-
<listener>
-
<listener-class>flex.messaging.HttpFlexSession</listener-class>
-
</listener>
-
-
<servlet>
-
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
-
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
-
<init-param>
-
<param-name>contextConfigLocation</param-name>
-
<param-value>/WEB-INF/spring/web-application-config.xml</param-value>
-
</init-param>
-
<load-on-startup>1</load-on-startup>
-
</servlet>
-
-
<servlet-mapping>
-
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
-
<url-pattern>/messagebroker/*</url-pattern>
-
</servlet-mapping>
-
-
<servlet>
-
<servlet-name>RDSDispatchServlet</servlet-name>
-
<display-name>RDSDispatchServlet</display-name>
-
<servlet-class>flex.rds.server.servlet.FrontEndServlet</servlet-class>
-
<init-param>
-
<param-name>useAppserverSecurity</param-name>
-
<param-value>false</param-value>
-
</init-param>
-
<init-param>
-
<param-name>messageBrokerId</param-name>
-
<param-value>_messageBroker</param-value>
-
</init-param>
-
<load-on-startup>10</load-on-startup>
-
</servlet>
-
-
<servlet-mapping id="RDS_DISPATCH_MAPPING">
-
<servlet-name>RDSDispatchServlet</servlet-name>
-
<url-pattern>/CFIDE/main/ide.cfm</url-pattern>
-
</servlet-mapping>
-
-
<welcome-file-list>
-
<welcome-file>index.html</welcome-file>
-
<welcome-file>index.htm</welcome-file>
-
</welcome-file-list>
-
-
</web-app>
Seguidamente modificamos la sección “<services></services>” del archivo “services-config.xml” que se encuentra en ExceptionTranslationDemo\WEB-INF\flex\, y que originalmente viene así:
-
<services>
-
<service-include file-path="remoting-config.xml" />
-
<service-include file-path="proxy-config.xml" />
-
<service-include file-path="messaging-config.xml" />
-
</services>
Para que quede de esta manera:
-
<services>
-
<default-channels>
-
<channel ref="my-amf"/>
-
</default-channels>
-
</services>
Dentro de ExceptionTranslationDemo\WEB-INF creamos la carpeta “spring” y en ella creamos el archivo web-application-config.xml con el siguiente contenido:
-
<?xml version="1.0" encoding="UTF-8"?>
-
<beans xmlns="http://www.springframework.org/schema/beans"
-
xmlns:flex="http://www.springframework.org/schema/flex"
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="
-
http://www.springframework.org/schema/beans
-
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
-
http://www.springframework.org/schema/flex
-
http://www.springframework.org/schema/flex/spring-flex-1.0.xsd">
-
-
<flex:message-broker/>
-
</beans>
Lo próximo que haremos será crear una clase con un método donde se realice una operación que genera una excepción. Dentro de la carpeta “src” del proyecto crearemos el paquete “com.et.services” y dentro crearemos la clase “ExceptionTranslationService.java” con el siguiente código:
Como vemos, la línea “((String)x).concat("123");“ generará una excepción de tipo “ClassCastException”. Ahora crearemos una interface de usuario sencilla que invoque el método a través de un objeto “RemoteObject” y veremos lo que ocurre, pero primeramente registramos un objeto de tipo “ExceptionTranslationService” en Spring y lo publicamos como destino remoto. El archivo “web-application-config.xml” queda ahora de la siguiente manera:
-
<?xml version="1.0" encoding="UTF-8"?>
-
<beans xmlns="http://www.springframework.org/schema/beans"
-
xmlns:flex="http://www.springframework.org/schema/flex"
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="
-
http://www.springframework.org/schema/beans
-
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
-
http://www.springframework.org/schema/flex
-
http://www.springframework.org/schema/flex/spring-flex-1.0.xsd">
-
-
<flex:message-broker/>
-
-
<bean id="ExceptionTranslationBean" class="com.et.services.ExceptionTranslationService">
-
<flex:remoting-destination/>
-
</bean>
-
-
</beans>
Nuestra interfaz de usuario, definida en el archivo “ExceptionTranslationDemo.mxml” en la carpeta “flex-src” queda así:
-
<?xml version="1.0" encoding="utf-8"?>
-
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
-
xmlns:s="library://ns.adobe.com/flex/spark"
-
xmlns:mx="library://ns.adobe.com/flex/mx"
-
minWidth="955" minHeight="600">
-
<s:layout>
-
<s:VerticalLayout/>
-
</s:layout>
-
-
<fx:Script>
-
<![CDATA[
-
import mx.controls.Alert;
-
]]>
-
</fx:Script>
-
-
<fx:Declarations>
-
<s:RemoteObject
-
id="ExceptionTranslationRO"
-
destination="ExceptionTranslationBean"
-
showBusyCursor="true"
-
fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)"/>
-
-
<!-- Place non-visual elements (e.g., services, value objects) here -->
-
</fx:Declarations>
-
-
<s:Button label="Genera Excepcion"
-
click="ExceptionTranslationRO.generateException()"/>
-
</s:Application>
Compilamos el proyecto, desplegamos la aplicación en Tomcat y cuando la corremos y oprimimos el botón obtenemos este mensaje de error:
La información de la excepción generada por el método Java llegó a Flex a través de las propiedades “faultString” y “faultDetails” del objeto “event.fault” del manejador del evento “fault” del componente “RemoteObject”. Estas propiedades contienen la misma información que las propiedades del mismo nombre del objeto “event.message”, que es de tipo “mx.messaging.messages.ErrorMessage”, la propiedad “rootCause” de esta clase contiene toda la información del objeto “Throwable” de Java.
Lo que haremos será interceptar el objeto “Throwable” de Java (del cual heredan las excepciones) en su tránsito hacia Flex y en su lugar generar un objeto de tipo “flex.messaging.MessageException” con la información personalizada, para lo cual nos auxiliaremos del mecanismo de traducción de excepciones del paquete spring-flex.
Comenzamos por crear el paquete “com.et.exceptions” dentro de la carpeta “src” del proyecto y dentro creamos la clase “CustomExceptionTranslation.java” que implementa la interface “org.springframework.flex.core.ExceptionTranslator”:
-
package com.et.exceptions;
-
-
import org.springframework.flex.core.ExceptionTranslator;
-
-
import flex.messaging.MessageException;
-
-
public class CustomExceptionTranslation implements ExceptionTranslator {
-
-
@Override
-
public boolean handles(Class<?> arg0) {
-
// TODO Auto-generated method stub
-
return false;
-
}
-
-
@Override
-
// TODO Auto-generated method stub
-
return null;
-
}
-
}
El método “handles” indica cuándo se invoca al método “translate” ante una excepción dada, en nuestro caso el método “handles” queda así:
-
public boolean handles(Class<?> arg0) {
-
return true;
-
}
-
return false;
-
}
Y el método “translate” así:
-
MessageException result = new MessageException();
-
result.setDetails("No se puede convertir un Integer en un String");
-
result.setMessage("Error de conversion de tipo");
-
return result;
-
}
-
return null;
-
}
Finalmente registramos el objeto de tipo “CustomExceptionTranslation” en Spring e informamos al “MessageBroker” que lo use como traductor de excepciones, el archivo “web-application-config.xml” queda finalmente de la siguiente manera:
-
<?xml version="1.0" encoding="UTF-8"?>
-
<beans xmlns="http://www.springframework.org/schema/beans"
-
xmlns:flex="http://www.springframework.org/schema/flex"
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="
-
http://www.springframework.org/schema/beans
-
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
-
http://www.springframework.org/schema/flex
-
http://www.springframework.org/schema/flex/spring-flex-1.0.xsd">
-
-
-
<bean id="CustomExceptionTranslation" class="com.et.exceptions.CustomExceptionTranslation"/>
-
-
<flex:message-broker>
-
<flex:exception-translator ref="CustomExceptionTranslation"/>
-
</flex:message-broker>
-
-
<bean id="ExceptionTranslationBean" class="com.et.services.ExceptionTranslationService">
-
<flex:remoting-destination/>
-
</bean>
-
-
</beans>
Compilamos el proyecto, redesplegamos la aplicación y cuando la corremos nuevamente obtenemos lo siguiente:
Como vemos, la excepción original fue interceptada y en su lugar llegó a Flex un objeto de tipo MessageException con información personalizada, el código Flex no sufrió ninguna alteración. El proyecto final (sin el contenido de ExceptionTranslationDemo\WEB-INF\lib\) se puede bajar aqui.
Conclusiones
Hemos visto como utilizar el mecanismo de traducción de excepciones de Java a Flex que incorpora spring-flex y su utilidad utilizando una excepción “sencilla”, pero si en vez de ser una excepción de este tipo hubiera sido alguna de las generadas por la capa de acceso a datos (utilizando Hibernate, iBatis o JPA), la cantidad de información que llega al cliente es considerablemente mayor y carente de sentido para el usuario final. Por ejemplo, el siguiente mensaje se obtiene ante una excepción generada por la capa de acceso a datos en una aplicación que no usa el mecanismo de traducción:
Luego de incorporar el mecanismo de traducción de excepciones el mensaje obtenido es el siguiente:
El código Flex no fue modificado en absoluto.
Acerca de esta entrada
Usted está leyendo “Tratamiento de excepciones de Java en Flex utilizando el paquete de integración de Spring con BlazeDS,” una entrada de MadeInFlex
- Autor: Nono F. Carballo Escalona
- Publicada:
- 04.06.10 / 1am
- Categorías:
- Artículos
- Entradas relacionadas:
- BlazeDS más cerca de Spring
- Clear Toolkit ahora con soporte para Spring
- Granite Data Services 1.0.0
- Clear Toolkit para el desarrollo de aplicaciones Flex
- Número de visitas:
- 4128






4 Comentarios
Ir al formulario de comentarios | rss (comentarios) [?] | trackback url [?]