lunes, 3 de mayo de 2010

BlazeDS: NetConnection.Call.Failed

Bueno como ya había comentado antes, durante las últimas semanas, he tenido una "batalla" con BlazeDS, y parece que finalmente a acabado con un resultado algo inesperado, quedando BlazeDS totalmente exonerado.

El problema consiste en la perdida de conexión entre el cliente y el servidor (Java). Tras realizar una llamada a un servicio si esté se demora mucho (o si colocamos un breakpoint) se pierde la conexión con el servidor y tras el timeout se informa al cliente, con un evento NetStatusEvent con el código NetConnection.Call.Failed, el cuál vuelve a realizar la llamada teniendo así varios hilos ejecutando la misma llamada.

He pasado mucho tiempo comprobando los logs (tanto de servidor como de cliente), variando las configuraciones del BlazeDS, depurando el código de BlazeDS, el código de la librería RPC del FLEX SDK (en varias versiones) sin encontrar un motivo aparente del error, ya que realmente el funcionamiento era correcto. En este proceso siempre llegaba al mismo punto que era la serialización del AMF Request, pero realmente la hacía bien, pero en ese punto era cuando perdía la conexíon.

La sorpresa salta cuando probando en otro entorno con un servidor de aplicaciones Tomcat no se reproduce el error, por lo que decidimos revisar el servidor de aplicaciones Jetty que usamos en desarrollo y encontramos que se debe a una actualización del servidor Jetty que hasta al fecha funcionaba correctamente, pero que había sido actualizado.

El problema radica en la versión 6.1.24 de Jetty, el cuál ha modificado la forma en que se tratan los request HTTP (probablemente exista algún bug). No he profundizado en el tema pues las versiones anteriores de Jetty funcionan correctamente y nos hemos pasado a una anterior, pero creo que el problema anda por la clase HttpParser la cual se encarga de leer (parsear) los request.

Saludos.

sábado, 1 de mayo de 2010

Charles (Proxy Depurador Web)

Buenas a tod@s.

Esta semana he tenido una guerra particular con el BlazeDS (de la cuál hablaré en otro momento cuando tenga más tiempo), y en tales circunstancias he encontrado una herramienta que me ha sido bastante útil. Se trata de Charles, una aplicación que sirve de proxy para las peticiones web y que te permite tanto ver los request/response como depurar las peticiones.

Es cierto que para ver las peticiones del BlazeDS tan sólo s necesario activar el login, pero obviamente es menos legible, y ademas Charles te da cierta información acerca de que está sucediendo y porqué.

lunes, 12 de abril de 2010

Desaparecen los imports en Flex Builder 3

Hace un tiempo que un compañero se encontro con este problema y hasta hace poco no sabía porque se daba este comportamiento extraño. El problema en cuestión es que al usar el asistente de código (con Ctrl + Espacio) el Flex builder elimina algunos imports, sobre todo los del paquete flash. Esta situación es bastante molesta, ya que obliga al desarrollador a tener que asegurarse de si los imports están correctos antes de cada guardado suponiendo una falta de eficiencia y una fuente inmensa de errores. Otra problema que se puede apreciar es que no encuentra algunas clases al usar el asitente de código y ni siquiera podemos ver sus métodos.

Indagando un poco he encontrado el porque de éste problema y su solución. El problema realemente es una combinación de circunstancias un poco peculiar, pero que se da con frecuencia.

Por un lado tenemos la opción de "organizar los import" y "eliminar los imports no usados", las cuales las encontramos en "Window->preferences->Flex-> actionScript Code". Dichas opciones suelen estar activadas y yo recomiendo que sigan así. En algunos foros he leíio que hay quien las ha desactivado para evitar el problema, pero de esta forma sólo conseguiremos evitar que elimine los imports pero el problema seguirá "latente", ya que seguiremos sin poder usar el asistente de código.

Por el otro lado tenemos el SDK que usamos en la aplicación, que es el verdadero causante de este problema. Este error suele surgir cuando hemos cambiado de SDK o cuando se crea un proyecto nuevo con un SDK superior al 3.2 y estamos compilando para la maquina Flash Player 10. Se debe a que han cambiado la ruta en la que se encuentra la libreria playerglobal.swc, para tener compatibilidad con la máquina Flash 9 y 10, esto es lo que hace que no se carguen las clases y por tanto no aparezcan el el asistente de código y asímismo, dado que no encuentra las clases, elimina sus imports por no estar siendo utilizados.

Por tanto para solucionarlo tenemos que asegurarnos que se cargue la libreria playerglobal.swc correspondiente a la máquina Flash Player con la que trabajemos. Esto podemos hacerlo de varias formas:

Opción 1
En las propiedades del proyecto ir a "Flex Build Path" -> "Library Path" y eliminamos dicha librería del SDK, para luego añadirla manualmente.

Opción 2

Modificar el fichero ${FLEX_SDK}/frameworks/flex-config.xml para configurarlo correctamente para la la Flash player 10.
  1. Editar el tag <target-player>, reemplazando 9.x.x por 10.0.0:
    <target-player>10.0.0</target-player>
  2. En el tag , editar el "path-elelment" para el playerglobal.swc reemplazando 9 por 10
    <external-library-path>
    <path-element>libs/player/10/playerglobal.swc</path-element>
    </external-library-path>
  3. Hacer lo mismo con el tag <library-path>
    <library-path>
    <path-element>libs</path-element>
    <path-element>libs/player/10</path-element>
    <path-element>locale/{locale}</path-element>
    </library-path>

Si queremos alternar el uso de las versiones 9 y 10 de Flash Player podemos hacerlo reemplazando el 10 por {targetPlayerMajorVersion}, con lo que el usara el "major version" del flash Player que establezcamos en el compilador.

Desde mi punto de vista recomiendo la segunda opción ya que la primera aunque parezca más simple habría que repetirla en cada proyecto que tengamos y nadie garatiza que no se quede alguno atras.

Pueden ver más en el sitio oficial de adobe aqui.

miércoles, 24 de marzo de 2010

Cumplimos un año

El próximo domingo (28/03/2010) se cumple un año desde que empezara a escribir este blog, y por ese motivo me gustaría hacer un pequeño repaso de lo que ha sido este año.

Inicialmente empecé a escribir con la idea de compartir, ya que creo firmemente en la máxima de Compartir el conocimiento. Si la informática ha llegado a ser lo que es hoy es gracias a dicha máxima ("Si yo se sumar y te enseño, quizás tu mañana me enseñes a multiplicar.").

Durante el año se han escrito 27 entradas (contando ésta última), me gustaría haber escrito algunas más pero nunca tengo el tiempo suficiente. Se han tocado diversos temas : Optimización, Flex, Java, Frameworks, etc. tratando siempre de enfocarlos de manera práctica y sencilla, además siempre he querido publicar "todo aquello que en su día busqué y no encontré", claro esta esto no es aplicable a todos los artículos, hay cosas de cosecha propia y otras que ido aprendiendo con el tiempo.

En cuanto al seguimiento del blog, decir que el número de visitas ha superado lo que yo esperaba en el primer año. Esperaba tener pocas visitas ya que los temas tratados son bastantes especializados y encima lo he escrito en español, pero justamente eso es lo que quería, ya que casi todo esta en inglés y quiero que quede bien claro que los hispano-hablantes también sabemos de esto (XD). Lo que no ha sino muy alto es la participación externa (via comentarios, en el grupo, etc), cosa que me gustaría mejorar para el año que viene, así que os animo a participar, ya sabeís que "El conocimiento es lo único bien que crece cuando se comparte".

Ahora les dejo unos datos (actualizados hasta el 23/03/2010):



Saludos.

jueves, 18 de febrero de 2010

Mejorar el rendimiento de las aplicaciones.

Todo el que haya trabajado con una aplicación con un tamaño considerable se da cuenta en algún momento de que ciertas acciones provocan cierto "stress" en el sistema, es decir, hay acciones que sobrecargan el sistema y tardan mucho en ejecutarse. Este hecho no sólo provoca una pérdida de tiempo productivo para el usuario, sino que ve mermada seriamente la experiencia de usuario (del ingles User Experience). Por tanto es necesario optimizar nuestro código para que no sólo funcione sino que lo haga de forma óptima.

A continuación desglosaremos unos cuantos aspectos que pueden ayudar a mejorar el rendimiento de nuestra aplicación :

1) Limpiar todo lo que dejemos a nuestro paso.

Siempre es buena idea mantener nuestro código limpio y no tan solo en el sentido de mantenerlo legible y formateado. Todos los objetos que creemos deberán ser destruidos cuando dejemos de utilizarlos, de no ser así podremos crear "fugas de memoria" (memory leaks) importantes.

En lenguajes antiguos como C++ existían los destructores (en contraposición a los Constructores que instancian un objeto), que se encargaban de liberar la memoria., en Java podemos sobreescribir el método finalize (pero este depende de cuando se ejecute el garbage collector), como norma general podemos decir que deberíamos limpiar manualmente tras finalizar el uso de un objeto, para ello podemos poner las instancias a nulo.

Asimismo, es importante eliminar los listeners de eventos que tengamos una vez que no se vayan a usar. En sistemas que usen garbage collector como Flex y Java, si mantenemos un listener de un evento que ya no existe puede provocar que el garbage collector no elimine ciertos objetos, dado que su contador de referencias no está a cero (pueden leer un poco más sobre el garbage collecctor en un post anterior "Introducción a Flex Profiler"). Como nota práctica decir que en Flex podemos definir los listener con "weak references" lo cuál aliviará este problema.

En el caso de Flex,cada vez que usemos los cargadores (loaders), para cargar un fichero SWF, una imagen, etc. es altamente recomendable descargar el objeto una vez que ya no se use, para ello podemos usar la función unloadAndStop.

2) Evitar acciones innecesarias.
¿Para que vamos a hacer acciones que no se usan para nada?.

a)Tener mucho cuidado con el manejo de las colecciones:
  • Tener mucho cuidado al iterar en las colecciones (ya hablé de esto en otro post).
  • Si tenemos la colección bindada o asociada a un evento, y se ejecuta cierto código cada vez añadimos, eliminamos o actualizamos un elemento, quizás sea recomendable realizar todas las operaciones que deseemos y luego lanzar el evento o ejecutar el binding. Supongamos que tenemos una colección en la que insertamos 1000 objetos, y cada vez que se inserte un objeto se ejecuta un binding para mostrar los datos en una tabla, el código para mostrar se ejecutará 1000 veces, cuando s. En Flex podemos usar la función disableAutoUpdate para que no se lancen los bindings mientras iteramos.
b) Podemos usar la instanciación aplazada (deferred instantiation), que consiste en no instanciar los objetos (como contenedores, tabNavigators, etc), hasta que realmente sean necesarios. En Flex podemos usar la propiedad creationPolicy para que los hijos se creen en diferentes momentos, pero esto es muy delicado. Otra opción es no crear los hijos en el constructor y sobreescribir el método createChildren() para que nuestros componentes creándose de forma aplazada.

c) Reciclar objetos. Es menos costoso reusar un objeto ya instanciado que crear uno nuevo.

d) No invalidar y revalidar los objetos si nada ha cambiado, es decir ¿para que repintamos una pantalla que se va a mantener igual?. En flex, podemos hacer uso de los métodos para invalidar (invalidateProperties, invalidateSize e InvalidateDisplayList), para forzar una invalidación y que tenga que revalidarse el componente, esto es útil en algunas circunstancias, como cuando cambia de tamaño.

En Flex, cada vez que se invalida un componente debemos realizar el proceso de validación en el cuál debemos realizar tres pasadas sobre la jerarquía de componentes, esto supone que para una jerarquía muy grande el tiempo de computo es considerable, en estos casos debemos ser muy cuidadoso y tener en cuenta los aspectos antes mencionaos (a,b y c), asimismo debemos eliminar los objetos y contenedores intermedios que realmente no se estén usando, ya que muchas veces se anidan Box, VBox y HBox, para simplificar la forma en la que escribimos nuestros componentes, de esta forma podemos eliminar complejidad de la jerarquía de objetos.

3) Consideraciones sobre las propiedades

Otro factor a tener en cuenta es usar las propiedades correctas, a la hora de ocultar/visualizar objetos, ya que una práctica común poco acertada es establecer el valor alfa para que no sea visible, pero esto no deshabilita la interacción del componente, en mi opinión lo más acertado es hacer uso de las propiedades visible e includeInLayout, la primera aparte de no visualizar el objeto deshabilita la interacción con el usuario, y la segunda hace que el componente no este en el displayList (la jerarquía de objetos en pantalla), y por tanto no se tendrá en cuenta al recorre dicha jerarquía.


Bueno espero que estos consejos les sirvan, y no haberme liado mucho al explicarlos, ya que he tratado de separarlos un poco pero están íntimamente relacionados.