jueves, julio 12, 2007

Frameworks para RIAs

En esta cuarta entrega del desarrollo basado en Ajax, nos vamos a centrar en los diferentes frameworks existentes que nos pueden ayudar en nuestros desarrollos. Si no os habéis leído los posts anteriores, os recomiendo que os los leáis para entender mejor este:
En este post vamos a ver diferentes alternativas de las que disponemos para agilizar nuestra tarea (otra gente se ha pegado con el teclado por nosotros). Vamos a ver, aunque existen muchísimos más, los siguientes:
  • YUI: Yahoo User Interface, framework de Yahoo (que listo soy) para aplicaciones ricas de internet (RIA: Rich Internet Application). Muy completo y con un montón de ejemplos y documentación.
  • Dojo: Framework de la Dojo Foundation. Es también muy completo, quizás un poco más sencillo de utilizar que el de Yahoo y menos pesado para el explorador, aunque con menos documentación.
  • GWT: Google Web Toolkit. Es la implementación que da Google para Ajax sobre Java. En realidad, la filosofía de GWT es la de programar en Java y él interpreta el código Java para generar las páginas con los controles AJAX.
  • AJAX ASP.NET: La implementación para asp.net de AJAX. Incluye, aparte del core de librerías de comunicación una librería de controles llamada Atlas Control Toolkit. Se puede utilizar aunque no se utilice asp.net.
Todas estas librerías son de libre distribución. Por supuesto, existen muchas librerías de pago con controles flipantes que casi te programan la aplicación solas, pero los currelas de a pié, nos conformaremos con éstas (de hecho son muy buenas todas). Personalmente, la que más uso (todos los días) es la de ASP.NET, que hace cosas muy chulas. Tened en cuenta que en lo que más dan estos frameworks son controles para hacer nuestras aplicaciones más interactivas. Pero, vamos al tajo:

Yahoo User Interface:
Esta fue la primera librería que utilicé en mis pruebas. Tiene varias cosas muy buenas a tener en cuenta:
  • Una documentación muy buena con unas cheatsheets muy curradas.
  • Un mogollón de ejemplos con el código bien puesto.
  • Muchos controles
  • El respaldo de una gran empresa que soporta el proyecto (no te van a dejar tirado).
Cosas negativas que he visto y comprobado:
  • Puede llegar a ser bastante pesado para el cliente (las librerías javascript)
  • Es el framework más complejo con el que trabajar debido a que puedes hacer lo que quieras con él.
Este conjunto de librerías las puedes utilizar donde quieras porque son Javascript puro. De hecho, puedes mezclar diferentes librerías. ¿Os acordáis del ejemplo que puse en una de las entregas en el que se ponía el nombre y el servidor devolvía "Te devuelvo tu nombre: " y el nombre? Os acordéis o no, aquí tenéis ese mismo ejemplo pero implementado con YUI:

http://www.nidea-soluciones.com/PruebasAjax/YUI/yui1.html

El código javascript utilizado se divide en dos partes: primero tenemos que importar los scripts de YUI que vayamos a utilizar (lo miramos en su web para saberlo) y después realizamos nuestros propios scritps:







Los scripts a importar dependerán de qué es lo que vamos a utilizar de la librería de controles de Yahoo. En la página web se indica para cada caso cuáles son necesarios. La parte de programación es la siguiente:
















El meollo se encuentra en la línea YAHOO.util.Connect.AsyncRequest() que es la que crea el objeto XMLHttpRequest y realiza la llamada. Se le pasa el método, la url y una variable que contiene toda la información relativa a la función si va todo bien, la función si no va bien, los argumentos, etc. Es muy importante el orden, no podemos definir la variable callback antes de las funciones que manejarán las respuestas, ni podemos definir la variable callback después de la llamada al servidor.

Utilizamos también uno de los controles de YUI, el container en su versión panel. La programación con YUI se puede realizar de dos maneras distintas, por marcación o por Javascript. Todos los controles se pueden definir directamente en Javascript (caso del ejemplo) o definir en HTML (Markup). Al definir por HTML, cuando se llama al método render, la librería busca determinadas clases css y las convierte en controles. El mismo panel que se define en el ejemplo con HTML sería:











La librería lee las clases y las renderiza en pantalla en forma de panel.

Framework Dojo:
Este es el siguiente framework con el que trabajé. Tiene otras ventajas e inconvenientes que el YUI. Los que encontré fueron los siguientes:

Cosas buenas:
  • Un montón de controles
  • Definición en la programación más intuitiva que la de YUI.
  • Menos importaciones a nuestras páginas
Cosas malas:
  • La documentación es mucho peor.
  • Existen menos ejemplos en la utilización de los diferentes controles.
Veamos un ejemplo. Os he puesto el mismo ejemplo que con YUI pero programado con Dojo. Lo podéis ver en:

http://www.nidea-soluciones.com/PruebasAjax/Dojo/dojo1.html

El estilo de programación varía ligeramente entre ambos frameworks. En ambos disponemos de una parte de inicialización de dependencias que en el caso de YUI es mediante la incorporación de scripts y mediante Dojo se realiza más al estilo Java o C#:







Lo primero es importar la librería base dojo.js y después utilizamos la sentencia para importar aquellas partes que vayamos a utilizar. Podemos utilizar una sintaxis del tipo dojo.require() dojo.require("dojo.widget.*"); para importar todos los widgets. En este caso, como sólo vamos a utilizar el tipo Dialog pues lo importamos. La sentencia djConfig = {isDebug:true}; nos permite sacar mensajes de debug o de error en la librería por pantalla.

Dojo se diferencia de YUI en que al definir los elementos HTML, introducimos un nuevo parámetro llamado dojotype en el que le indicamos qué tipo de elemento dojo va a ser. De esta forma al inicializar el elemento en Javascript, la mayoría de la definición se encuentra en el elemento HTML. Vayamos por pasos: paso 1, el código HTML:
























En el código definimos tres divs a los que les decimos que son dojotype="dialog". De esta forma, Dojo sabe que tiene que renderizarlos como diálogos. Además les definimos una serie de características propias de Dojo (las subrayadas en rojo): bgcolor(color de fondo de la pantalla no del div), bgOpacity(opacidad del fondo de la pantalla), toogle (forma en la que aparece o desaparece la pantalla) y toogleDuration (duración del efecto de aparecer y desaparecer).

El resto del código es html normal. Veamos cómo se definen los diálogos y las funciones (ved que llamo a dos funciones Javascript CargarNombre() y Empezar()).
























He dividido el Javascript en trozos. En la primera parte tenemos las definiciones de las variables que vamos a utilizar después, los tres diálogos, y las dos funciones manejadoras de los eventos de respuesta correcta y respuesta incorrecta, hasta aquí todo igual que antes. Tenemos también la función init, que se ejecuta al cargar la página que define el primer diálogo que aparece en pantalla. La definición es muy simple, solamente utilizamos la sentencia dojo.widget.byId() y le pasamos el id del div que va a ser el diálogo (ese div tiene que tener el dojotype="dialog"). Le definimos el botón que va a ocultar el diálogo con la sentencia setCloseControl(). Ved que podemos utilizar con los diálogos las sentencias show() y hide() para mostrarlos u ocultarlos desde cualquier parte del código. ¿Y las llamadas a servidor cómo se hacen? Pues veamos el resto del código:
















Tenemos la función CargarNombre() que muestra el diálogo de espera y llama al servidor. Con Dojo, las llamadas se realizan utilizando el método dojo.io.bind al que le pasamos parámetros. Los más comunes y necesarios (algunos) son: url (dirección a la que llamar), load (método que controlará la respuesta correcta del servidor), error (método que manejará la respuesta de error del servidor), mimetype (mimetype de los datos de la llamada).

Dojo también permite realizar llamadas cross-domain mediante el método bind(), pero hay que importar el espacio dojo.require("dojo.io.XhrIframeProxy"), proque la llamada se realiza mediante un iFrame Proxy. Esto está aún en pruebas así que os aconsejo que vayáis a la documentación y os lo leáis.


Conclusión (hasta la próxima):
Como se me está haciendo demasiado largo el post, dejaremos los dos frameworks restantes para el siguiente. Sólo comentaros mi experiencia con ambos: personalmente prefiero el framework de Dojo que es bastante más intuitivo de utilizar, aunque YUI tenga más documentación (es realmente buena), cuando empiezas a trabajar con Dojo y te empiezas a enterar de cómo funciona, es más liviano. De todas formas, al ser frameworks completamente independientes de plataformas, siempre podéis conjugarlos y utilizar aquellas partes que más os gusten de uno y de otro.

Proximamente: GWT y ASP.NET AJAX

miércoles, julio 11, 2007

Noticiones Varios

Actualización:
Ya he arreglado el bug del mapa, así que podéis disfrutar de él todo lo que queráis. ¿Qué os parece?


Bueno chavales, hemos cambiado nuestra página web, dándole un nuevo aspecto. La podéis visitar en http://www.nidea-soluciones.com.

Aunque todavía tenemos que darle un último retoque, os recomiendo visitar la parte de contacto y abrid el mapa. Nos hemos integrado con el API de Google MAPS y ha quedado resultón. He detectado un pequeño bug que corregiré en breve.

Por otro lado, SUPER NOTICIA, Producciones Porunbujero ha empezado su actividad como estudio de grabación y productora de vídeos. Estamos trabajando en su página web, podéis visitarla (sólamente está la portada) para obtener los datos de contacto. Su dirección es: http://www.porunbujero.com

Os doy sus datos de todas maneras:

Producciones Porunbujero
Tejuela 25, Alcalá la Real
605978242

domingo, julio 08, 2007

Creación de un EJB(I): Session Bean

Bueno, después de este pequeño traspiés con la nueva versión de J2EE, voy a ir contándoos lo que voy haciendo para crear un bean de sesión desde donde lo dejé. Recordemos que en el primer post hablamos sobre la tecnología J2EE y en el segundo post habíamos instalao nuestro servidor de aplicaciones de Sun. Por lo que me comentó Manolo, existe también otro servidor de aplicaciones llamado JBOSS que parece ser que es más eficiente, pero como yo ya había trabajao con una versión previa de éste, os voy a contar cómo se hace ésto. También he visto por ahí que hay un proyecto open source llamado GlashFish que creo que también es un servidor de aplicaciones y tiene buena pinta pero eso es arena de otro costal que ya urgaremos cuando proceda. Yo voy a lo mío.

Después de instalar el servidor de aplicaciones, en la nueva versión, necesitamos para desplegar nuestras aplicaciones un pack para Netbeans o un plugin para eclipse que se ofrecen junto con el servidor de aplicaciones en la página de Sun. Ésas eran las herramientas que se descargaban si en vez de pulsar en Download with JDK pulsábamos en Download with Tools. Como por entonces no tenía ni idea de que ya no existía la herramienta de despliegue deploytool, pues yo ya tengo mi servidor de aplicaciones instalao en mi máquina. No todo está perdido. Yo he escogido hacerlo con NetBeans como reto personal porque ya conocía Eclipse y tenía ganas de ver qué tal era NetBeans, pero vosotros podéis hacerlo con lo que elijáis.

Bien, para empezar nos vamos a la página de descarga de Sun y pinchamos en un link que hay a la derecha en un div azul titulado Related Resources y que se llama NetBeans. Ahí podemos descargarnos tanto el propio IDE NetBeans como el Enterprise Pack. Descargad agusto. Luego la instalación es bastante simple. Hacemos un chmod +x fichero_binario y luego un ./fichero_binario. Con ésto se nos abre un instalador gráfico bastante intuitivo al que la máxima información que tendremos que aportarle será el sitio donde queremos que lo instale cuando se trate del IDE o del sitio donde hemos instalao el IDE cuando se trate del Enterprise Pack. Habrá un momento de la instalación que nos preguntará si queremos instalar un servidor de aplicaciones o si queremos usar una instalación preexistente. Obviamente aquí usaremos el servidor que habíamos instalao en el post anterior y para ello tendremos que darle el nombre de usuario y la contraseña de administrador que nos creamos en su momento.

Aparte de ésto, lo demás no os creará problemas. Y bien, ahora tenemos nuestro servidor de aplicaciones perfectamente sincronizao con nuestro IDE NetBeans que hemos instalao para el desarrollo de nuestros beans y sólo nos queda desarrollar las aplicaciones.


Creación de un Bean de Sesión - El meollo.

Vamos a crearnos un Bean de Sesión que a partir de un día, mes y año de nacimiento calcule la edad que debe tener la persona. Además posteriormente y para ver la funcionalidad de ésto, nos vamos a crear una página JSP que haga uso de este Bean para recoger la información introducida por un usuario, mandársela al bean, recoger el resultado y mostrarlo por pantalla. Al lío pues.

Arrancamos NetBeans si no lo hemos hecho ya y pinchamos en Archivo -> Nuevo Proyecto -> Nueva Aplicación Empresarial. Rellenamos los campos necesarios. En nuestro caso le vamos a poner de nombre CalculadorEdad. Ponemos la carpeta donde queremos que se guarde y seleccionamos la versión de J2EE que queremos usar. En este primer post vamos a usar J2EE 1.4 que es la versión que yo había trabajado, pero a ver si más adelante os puedo escribir cómo hacerlo con J2EE 5 para que veáis la diferencia. Aseguráos antes de darle a "Terminar" de que marcáis las casillas de "Crear módulo EJB" y "Crear módulo de aplicación Web" y dejad sin marcar la de "Crear módulo de aplicación Web" de abajo que se refiere a un cliente de aplicación web que nosotros no necesitaremos, sólo los dos primeros. Debería quedar parecido a lo que sigue:

Pinchad en "Terminar".

Ahora creamos el nuevo Session Bean. Para ello le damos al botón derecho en CalculadorEdad-ejb -> Nuevo -> Bean de sesión.
Introducimos el nombre que será CalculadorEdad, ponemos el nombre de un paquete, que será por ejemplo "calculadoredad". Marcamos "sin estado" puesto que vamos a hacer un Stateless Session Bean, ponemos el tick en las dos interfaces, remota y local y pinchamos en Terminar. En realidad podríamos valernos sólo con la Remota, ya que la local es para optimizar accesos desde local pero vamos a ponerlo todo y así vemos todas las interfaces en pleno rendimiento. El resultado será que nos creará automáticamente las clases que necesitamos e implementará él sólo el código aburrido de los métodos de ciclo de vida y demás asuntos escabrosos. A nosotros nos tocará entonces implementar los métodos de negocio que son los específicos de nuestro bean. La intención es crear una aplicación que introduciendo una fecha de nacimiento calcule los años que tiene la persona dada. Así pues, nuestro método de negocio lo llamaremos edad y recibirá como parámetros 3 int representando el día, mes y año de nacimiento. Además le diremos que lanza una excepción que llamaremos PeroQueInventoEsEsteException y que extiende de Exception para indicar cuando alguien ha introducido una fecha no válida (ya se que aún no la hemos creado, lo haremos a continuación).

Si le damos al botón derecho en la clase CalculadorEdadBean , y seleccionamos métodos EJB -> Agregar método Business podremos añadir nuestro método de negocio que os describía arriba y el código se implementa sólo. Jurch, estos IDEs...dentro de poco no habrá que saber programar para programar :).

Justo después de haber puesto todo lo que arriba decíamos vamos a crearnos nuestra excepción especial. Para eso nos vamos dentro de CalculadorEdad-ejb al apartado de "Paquetes de orígen". Le damos al botón derecho encima y decimos Nuevo -> Clase java. Como nombre le damos PeroQueInventoEsEsteException y le decimos que la cree. A continuación la abrimos haciendo doble click en ella y añadimos a su declaración de clase el código "extends Exception" para que tenga las propiedades de una excepción normal y corriente. Luego en el constructor por defecto metemos como código "super();" y nos creamos un constructor con un String como parámetro que tenga por código "super(motivo);" siendo motivo el nombre del String del parámetro. Ya tenemos nuestra excepción.

Ahora vamos a implementar el código de nuestro método de negocio. Para ello nos vamos a la clase CalculadorEdadBean que es quien tiene que implementar el código de nuestro bean y picamos código. Mi implementación to perrillera del método que calcula la edad es la que os pongo aquí.

public int edad(int dia, int mes, int anho) throws PeroQueInventoEsEsteException{
//Obtenemos un objeto java.util.Date con la fecha actual y un objeto java.sql.Date con la fecha que ha introducido el usuario
java.sql.Date fecha = java.sql.Date.valueOf(new Integer(anho).toString()+"-"+new Integer(mes).toString()+"-"+new Integer(dia).toString());
hoy = new Date();
//Para compararlos obtengo el número de milisegundos desde "The Epoch"
long nacimiento = fecha.getTime();
long actual = hoy.getTime();

//Si se ha introducido una fecha futura...
if(nacimiento>actual){
throw new PeroQueInventoEsEsteException("¿Tu tas creído que somos unos pardillos o qué? ¿usease que aún no has nacío no?");
}

//Calculamos el tiempo en milisegundos que la persona lleva viviendo y hayamos su edad averiguando cuántos años son esos milisegundos. Hay un error obvio debido a los años bisiestos pero no lo contemplaremos aquí.
long tiempoDeVida = actual-nacimiento;
int edad = (int)(((tiempoDeVida/1000)/3600)/24)/365;

return edad;
}


Hago uso de java.util.Date (que está importada en el inicio de la clase con un simple "import java.util.Date") y de java.sql.Date por la facilidad de uno para crear objetos Date a partir de Strings y la facilidad del otro para crear objetos Date representando la fecha actual. Como ambos tienen un método getTime() que devuelve el número de milisegundos desde "The Epoch" que es como se conoce a las 00:00h del 1 de enero de 1970, mediante una simple resta puedo tener los milisegundos de vida de la persona que ha introducido su fecha de nacimiento. Paso los milisegundos a años y voilà, ya tenemos su edad. Está claro que no estoy contemplando los bisiestos y ésto sería un problema, pero como la propia implementación es bastante perrillera no me voy a centrar en que el código sea bonito o que cumpla bien con su cometido, sino en que veáis una implementación de un EJB. Además la aproximación es bastante cercana, y sólo fallará en días próximos a nuestro cumpleaños así que lo podemos considerar aceptable para un ejemplo :). De toas formas sí, ya se que es un código un tanto perrillero, pero weno, qué le vamos a hacer.

Lo único que nos queda por hacer con el Bean es darle un nombre de referencia en el servidor para que pueda ser encontrado por nuestra página web (que crearemos a continuación) cuando vaya a buscarlo. Ésto es fácil. Nos vamos al menú de la izquierda, donde está nuestro CalculadorEdad-ejb. Desplegamos el submenú "Archivos de configuración" y hacemos doble click encima de "sun-ejb-jar.xml". Ese fichero es en realidad un xml, pero nuestro querido IDE NetBeans nos lo mostrará como cajitas y menús tó wapos (si es que vivimos en una puta metáfora con las interfaces gráficas ;) ). Veréis que debajo de "Configuración Sun" tenéis un submenú llamado CalculadorEdadBean, pues pinchad en él, y veréis algo como ésto:


Rellenadlo como véis en la imágen, poniendo "ejb/CalculadorEdadBean" en el campo de "Nombre JNDI". Ya tenemos nuestro bean programado y reconocido por el servidor para que pueda ser llamado por otras aplicaciones, servlets, beans o JSPs.

Ahora nos vamos a crear una página JSP. En realidad esta página ya está creada. Se creó automáticamente cuando marcamos la casilla de "Crear módulo de aplicación Web" cuando creamos el proyecto. Para verla, id en el menú de la izquierda a "CalculadorEdad-war" y desplegad su submenú. De ahí nos vamos a páginas web y veréis que hay una que se llama "index.jsp". Ésta es la que nuestro servidor de aplicaciones mostrará cuando ejecutemos la aplicación y entremos en localhost:8080/CalculadorEdad-war. Pinchad dos veces sobre ella y se os abrirá a la derecha. Ahora la vamos a editar. Os voy a enseñar el código en dos trozos pa ir explicándooslo poco a poco. Primer cacho:


De lo que veis, llamaros la atención sobre unas pocas cosas:
  • No os olvidéis de importar las clases necesarias para el funcionamiento de vuestra página JSP, además de las clases de las interfaces del Bean que váis a usar.
  • Cread un contexto inicial como se ve en el código.
  • Fijáos en la forma de obtener una referencia a nuestro Bean. Primero se obtiene una referencia al interfaz de inicio o interfaz Home de nuestro Bean sobre la que llamaremos a su método create(). Lo hacemos con el método lookup(String) sobre nuestro contexto inicial y le preguntaremos por "java:comp/env/" + el nombre que le dimos a la referencia del EJB. ¿Os acordáis? Lo que sí recordaréis seguro es que en los Session Beans el bean nace y muere con el cliente, así que aquí no tendría mucho sentido obtener la referencia de otra forma. La creamos cada vez y punto.

Ahora pasamos al segundo cacho:


Aquí está la chicha de nuestra página. Quitando el código que es meramente HTML, lo más importante quizás sea lo que está a partir de la línea 47. Tened en cuenta que cuando llamemos a nuestra página JSP lo podremos hacer pasándole parámetros en la propia URL del tipo dia=4&mes=5&anho=1984. Ésta es la forma de funcionar de una petición "GET". Para recuperar esos parámetros en nuestro JSP tendremos siempre el objeto request siempre inicializado y que indica la petición, y si llamamos a su método getParameter("parametro"), éste nos podrá devolver o el valor del parámetro, o bien null, y debemos contemplar esa posibilidad. También contemplamos la posibilidad de que el usuario pinche sobre el botón sin haber introducido nada (se hace en las comprobaciones noseque.length()>0) por lo que se estará enviando una cadena vacía. Una vez capturados los parámetros con los que se ha llamado a nuestra página JSP mediante nuestro formulario que generaba peticiones "GET" sobre la propia página, los transformamos en el tipo de dato que necesitábamos, para ello apoyándonos en la clase java.lang.Integer y llamamos al método de negocio edad(int,int,int) que nos habíamos creado usando la referencia que obtuvimos en el primer cacho de código. Al realizar la llamada tenemos que encapsularla por un try-catch que recoja las excepciones que se puedan producir, que en nuestro caso será la excepción especial cachonda que nos habíamos creao. Y finalmente, si la excepción no se ha producido sólo tenemos que mostrar el mensaje con el resultado de la llamada a nuestro bean. ¿A que no es complicao?

Por último, vamos a crear una referencia al EJB en nuestro módulo de aplicación web. Cosa sencillica. Nos vamos al menú de la izquierda de NetBeans. Desplegamos el menú de "CalculadorEdad-war" y dentro de él el submenú de "Archivos de configuración". Hacemos doble click sobre web.xml. Aquí pasa como antes, que pese a que es un fichero xml, nuestro IDE nos lo muestra de forma bonica (si queréis ver su forma real podéis pinchar en el botón "XML" que os lo enseñará perfectamente). Ya trastearéis un poquillo por este fichero para descubrir que se pueden configurar muchísimas cosas, como por ejemplo el tiempo que dura una sesión o temas de seguridad y demás, pero lo que a nosotros nos importa lo conseguimos pinchando en el botón de "Referencias". Ahí desplegaremos "Referencias EJB" y pincharemos sobre "Agregar". Ahí se os mostrará algo como:


Rellenadlo como ahí pongo. Aquí fijáos que en el nombre de la referencia tiene que haber una coherencia con el nombre que configuramos antes en el servidor al EJB. Luego, dado que hemos metido las distintas clases de nuestro EJB en un paquete llamado calculadoredad, fijáos en que al indicar las interfaces de inicio y remota hemos puesto delante calculadoredad.*, es importante. Una vez que hayáis hecho ésto, pinchamos en guardar y tocad la madera más cercana porque se supone que ya lo tenemos todo listo para desplegar nuestra aplicación. Lo que sigue es fácil. Le damos al botón derecho encima de "CalculadorEdad", que es la raíz de nuestro menú de la izquierda y seleccionamos "Ejecutar Proyecto". Nos saldrán un chorro de letras por abajo, os pedirá el nombre de usuario y contraseña de administrador y parecerá que nuestra máquina esté intentando calcular todos los números de pi, pero cuando lleve un rato leeréis algo así como "GENERACIÓN CORRECTA" y sabréis que todo este tiempo habrá merecido la pena :). Que no os lleve a engaños, este mensaje aparece también cuando la mayoría de las cosas fallan. Depende del tipo de fallo que se produzca. Si las referencias las habéis puesto mal o el código no rula como debería de rular, el mensaje os aparecerá, pero cuando intentéis entrar en vuestra página lo que salga o cómo funcione la aplicación...eso ya será otro rollo.

Para comprobar que la cosa rula abrimos un navegador y metemos la dirección
http://localhost:8080/CalculadorEdad-war/
Si todo ha ido medianamente bien debería de mostrársenos algo como ésto...


Ahora introducimos un día de nacimiento, mes y año correctos, por ejemplo Día: 4, Mes: 5, Año: 1984, y pinchamos en "Submit". Nos debería salir algo como...

Es correcto. Pero, ¿qué pasa si introducimos una fecha en el futuro? ¿cómo manejará nuestra página aquella PeroQueInventoEsEsteException que nos inventamos? ¡Probémoslo! El resultado debería parecerse a éste...


Wapo ¿verdad?. En realidad, seguramente no queráis hacer una aplicación de un servidor de aplicaciones que maneje una página que te calcula tu edad con un cierto márgen de error de días según bisiestos...es mu probable que no, pero hacer un calculador de edad es lo mismo que hacer cualquier otra cosa, sólo cambiad el código y número de los métodos de negocio y fenómeno. Se que es un poco tedioso, pero también hay que tener en cuenta que en este ejemplo nosotros hemos hecho todo el trabajo. En un servidor de aplicaciones real seguramente no tuviéramos que hacerlo. Ahí es donde entra el reparto de roles que contempla este tipo de programación. El desarrollador no tiene por qué ser el mismo que el desplegador, que a su vez no hace falta ni que conozca a quien montó el servidor de aplicaciones. Por eso os enseñé en el anterior post cómo arrancar y parar el servidor desde línea de comandos, pues puede que os toque símplemente hacer ésto y no desarrollar nada encima. Una vez montado el sistema, ya es sólo cuestión de hacer correr distintas aplicaciones sobre él y si somos listos al cliente le cambiaremos muy poco la interfaz para no hacerle la picha un lío, como al fin y al cabo lo que va por debajo no le importa, sólo tenemos que añadir métodos de negocio y añadir nuevas funcionalidades en nuestra interfaz que nunca cambia :). Todo ventajas. Inconveniente: ésto es java, así que ya se sabe, el procesador echando humo y la memoria derrochándose. Pero weno, dejemos eso para otro momento.

El desarrollo de un EJB de sesión con estado es bastante similar al del sin estado que hemos desarrollado así que el siguiente post lo dedicaré a crear un EJB de entidad (con una bonita base de datos derby). Espero no haberos aburrido mucho y que ésto os pueda servir para introduciros en cómo hacer lo que ya sabéis que queréis hacer.

martes, julio 03, 2007

AJAX PARA SUPERCAMPEONES o ¿Sabremos alguna vez qué es AJAX? (III)

Hala, de vuelta con el tema Ajax (la verdad es que da mucho juego el tema...). En esta tercera entrega de esta serie nos vamos a centrar en los siguientes dos temas:
  • Llamadas simultáneas: es decir, realizar múltiples llamadas a diferentes sitios a la vez.
  • Llamadas asíncronas secuenciales: este es un tema importante, saber cómo hacer llamadas asíncronas de forma ordenada.
Si no os habéis leído los posts anteriores, os recomiendo que lo hagáis:
Como sé que ya te los has leído, Nacho, puedes seguir con el siguiente punto ;P. En este post, terminamos la serie de AJAX PARA CAMPEONES o AJAX A PELO o AJAX KAMIKAZE, es decir, ajax para frikies.

Llamadas simultáneas
Una de los beneficios más importantes de trabajar con hebras de ejecución es que podemos crear tantas como nos permita el entorno (hardware, línea de comunicación, etc.) y el objeto XMLHttpRequest no es menos. Trabajando con AJAX podremos, por lo tanto, lanzar mútliples hilos de comunicación de forma simultánea que ejecutarán tareas distintas. Tendremos que tener cuidado de manejar correctamente las respuestas, de forma que sepamos siempre de quién es cada una.

En el ejemplo que os pongo aquí, podéis realizar tres llamadas simultáneas para que se carguen en los divs inferiores la página web que hayáis puesto. No es que esté demasiado currado pero menos es nada.

Ejemplo: http://www.nidea-soluciones.com/PruebasAjax/PruebaAjax5.html

Existen ciertas peculiaridades para que este ejemplo funcione:
  • Se ha creado una nueva función EnviarPeticionConParametro que además de realizar la petición le pasa un parámetro a la función que maneja la respuesta (aparte del objeto XMLHttpRequest).
  • Se ha implementado un Proxy al que llama la página para que se puedan hacer llamadas asíncronas CROSS-DOMAIN. Ésto lo explicaré otro día.
El código de la nueva función es el siguiente:










Como veis, introducimos un nuevo argumento llamado "parametro" que se le pasará a la función callback. Con este parámetro podremos decirle a la función callback qué objeto es el que ha realizado la llamada y ha respondido. Lo marco porque es muy importante ya que cada llamada tardará el tiempo que sea y devolverá el resultado en orden aleatorio. Tenemos que disponer de algún método que asocie la llamada con la respuesta.

Para entenderlo mejor, veamos el código de la página y cómo se realiza la llamada:



















En este caso, tenemos la función CargaURL(posicion), donde en posición se le pasa un 1, un 2 o un 3, dependiendo de qué botón es el pulsado. En base a ese número, se leerá el input correspondiente y se mostrará el panel de espera asociado. Finalmente se llama a la función EnviaPeticionConParametro y se le pasa la posición como parámetro final.

A la función que maneja la respuesta le llega el parámetro de la posición por lo que es capaz de poner la respuesta en el div correcto y oculta el div de espera correspondiente. De esta forma podemos tener una sola función que gestiona todas las llamadas y otra función que gestiona todas las respuestas. Si no lo hiciésemos así tendríamos que asociarle una función diferente a cada respuesta.

Os pongo un dibujo que como sabéis me molan y en el post anterior no tuve oportunidad de poner ninguno:











Las peticiones se envían al servidor, el cual las gestionará y tardará un tiempo x. Al ser asíncronas, las peticiones se evaluarán de forma simultánea y a medida que las vaya resolviendo irá mandando la respuesta. El orden de evaluación y respuesta no es fijo por lo que el orden de llegada de las peticiones no tiene por qué tener relación con el de salida. Es muy típico equivocarse con este concepto y escribir lo siguiente:

function MiFuncionQueRealizaMuchasCosas(){
// Primera accion asíncrona
ActualizaDatos();
MuestraDatosActualizados();
}

Error, al ser la función ActualizaDatos una llamada asíncrona a servidor, perderemos ese hilo de ejecución hasta que lo recoja el manejador de la respuesta. Por esto, la función MuestraDatosActualizados() no mostrará esos datos.

Llamadas asíncronas secuenciales
Por fin, el último ejemplo, lo último del AJAX PARA CAMPEONES. Este ejemplo se lo dedico con mucho cariño a Nacho porque sé que es tela de friki del Linux y en especial de Kubuntu y Ubuntu. Espero que te guste.

Como ya estaba harto de páginas html guarras con el texto a pelote decidí currarme un poquillo más este último ejemplo del post. En este ejemplo se realizan seis llamadas a servidor secuenciales, hasta que no se recibe la contestación de una no se realiza la siguiente. Podéis ver el ejemplo en la siguiente dirección (funciona mejor con Firefox porque el IE, a partir de la segunda vez, se pasa por el forro el delay que le tengo puesto en servidor):

http://www.nidea-soluciones.com/PruebasAjax/PruebaAjax6.html

Mola cantidad, eh? Por lo menos le damos un poco de aqué al tema. En fin, vamos al lío. ¿Cómo se hace esto? Aparte del tema gráfico (cada uno lo pone como más le gusta), la secuenciación de llamadas se realiza de la siguiente manera (os lo pongo en tres imágenes porque no me cabía en una):


















































Lo que hacemos es lo siguiente:
  1. Cuando el usuario pulsa sobre el botón, mostramos el divProgreso y le ponemos la primera imagen grande y su texto. Llamamos a la url Codigos/PruebaAjax6.aspx para ir a servidor.
  2. Cuando se recibe la respuesta, se pone la imagen en pequeño, se pone en grande la siguiente y la descripción de la acción y se realiza la llamada a la página con el parámetro del siguiente paso.
  3. Así sucesivamente hasta que en la última llamada, invocamos a la página redireccion.html. Obtenemos su código html y lo metemos dentro del div wrapper que engloba a toda la página.
Viéndolo en un dibujillo:















Es en las funciones callback donde realizamos la siguiente llamada.

El finaaaal deeeel veraaanooooo, llegoooo.....
Como todo, en algún momento hemos de llegar al final e igual que el verano todo acaba. Creo que con esta serie de ejemplos cubrimos la base de la comunicación asíncrona y del AJAX PARA CAMPEONES. Como os habréis percatado, el manejo del Javascript es fundamental (por Dios, nooooo), aunque, como veremos en posts posteriores, existen frameworks que nos ayudarán en nuestro cometido (un poco). Es importante que os deis cuenta que es indiferente el lenguaje de programación que utilicéis (yo lo he hecho todo en html plano), simplemente debe permitir hacer llamadas a funciones Javascript.

En próximos capítulos:
  • Frameworks Ajax
  • Llamadas Cross-Domain
Se me está ocurriendo hacer también algún post con el tema de los Mash-Ups.

lunes, julio 02, 2007

Instalación del Servidor de Aplicaciones

Actualización 04/07/07: Tras escribir este post, me he dao cuenta que la última versión del servidor de aplicaciones de Sun y de los EJB presentan algunas diferencias clave con respecto a la versión que yo había manejado y de la que os iba a hablar. Para empezar, hasta la versión anterior a la que os he indicao como instalar, se proporcionaba con ella una herramienta de despliegue llamada "deploytool" que en la nueva versión ha sido sustituída por un pack para NetBeans 5.5 u opcionalmente un pluguin para Eclipse, trastearé con ellos antes de escribir cómo hacerlo. También, la programación de los EJB 3.0 presenta algunas diferencias con respecto a su versión anterior en cuanto al número de interfaces a implementar por el/la programador/a y alguna notación específica a utilizar. Dejadme un tiempecillo que lo trastee todo y ya os escribo más adelante.


Y vamos al lío. Ya vimos en el anterior post la teoría mínima sobre J2EE y EJB's que nos iba a hacer falta para saber qué tenemos entre manos, pero sólo con la teoría, y más aún en este caso, no se puede saber de qué se está hablando concretamente, hace falta algo de código, así que en este post la intención era que desarrolláramos y desplegaremos un bean de sesión...peeeeeero, cuando me he puesto a escribir este post me he dao cuenta que ya se hacía demasiao largo sólo con la instalación y configuración del servidor de aplicaciones así que he decidío pasar al siguiente post el desarrollo de nuestro primer bean.

Lo primero de todo será pues arrancar nuestro servidor de aplicaciones. Pero...¿qué servidor es ese?
Bien, vamos a descargárnoslo de la página de Sun. Yo voy a hacer todo el proceso bajo GNU/Linux, concretamente sobre una Kubuntu 7.04, pero ésto es extrapolable de forma inmediata a cualquier otro sistema Linux y descargándose la versión correcta, también a cualquier sistema Windows. No os recomiendo usar Windows, pero allá vosotros/as :).

Entramos en http://java.sun.com y vamos hasta la página de descarga de la última versión de Java EE SDK disponible, junto con el JDK. Para ahorraros la tarea, aquí tenéis un link http://java.sun.com/javaee/downloads/index.jsp. Ahí pincháis en Download with JDK, luego en Accept License Agreement y finalmente sobre la versión de nuestro SO, lo que descargará un fichero autoinstalable donde elijamos. Este fichero contiene entre otras cosas el Java EE SDK y el servidor de aplicaciones de Sun, que son los dos elementos que nos hacen falta.

Una vez lo tenemos en nuestro sistema de ficheros, le damos permisos de ejecución con un simple chmod +x nombre_del_ejecutable. Para ejecutarlo hacemos ./nombre_del_ejecutable y se lanzará un instalador gráfico muy intuitivo. Ya sabéis, siguiente, siguiente, siguiente, meto el sitio donde quiero instalarlo, acepto lincencia, siguiente, siguiente... :). Haciendo eso llegaremos a una pantalla donde tenemos que meter el nombre de usuario del administrador y su contraseña. Importante que os acordéis de este nombre y contraseña. Como siempre, no lo apuntéis en ningún lao salvo que estéis pensando en comeros el papel donde se apunte en breves o que se trate de una región cifrada de vuestro sistema de ficheros. La cosa se vería tal que así:


Como veis, también tendréis que meter los puertos en los que escuchará nuestro servidor de aplicaciones. Si los puertos por defecto los tenéis ocupados por otra aplicación cambiadlos a vuestro gusto o símplemente por el hecho de añadir un poco más de seguridad al asunto colocándolos en puertos que no sean los habituales (sí, ya se que herramientas como nmap permiten escanear alegremente los puertos activos de una máquina, pero está bien poner las cosas un poco más complicás siempre). Yo como voy a instalarlo y desinstalarlo hoy mismo, voy a dejarlo por defecto. El siguiente paso, pulsar en Install now. Lo siguiente ya lo conocéis, una barra de progreso de 0% a 100%, algo como...


y que cuando acabe nos mostrará la página final que además contiene información útil...


La información que ahí aparece es especialmente útil porque indica cuál es la orden para arrancar el servidor, que vendrá a ser algo así como...
/sitio/donde/lo/hayais/instalao/bin/asadmin start-domain domain1 (por defecto se crea el dominio llamado domain1)
...pero antes deberíamos establecer una variable de entorno llamada JAVA_HOME que apuntara al sitio donde tengamos instalao un JDK (Java Development Kit). Si hemos escogío la opción de descarga que os dije tenéis uno en el subdirectorio jdk dentro de la nueva instalación. A continuación incluiremos la subcarpeta JAVA_HOME/bin dentro de la variable PATH de nuestro sistema. Dependiendo del tipo de intérprete que usemos ésto se hará escribiendo en un terminal:
export JAVA_HOME=/sitio/donde/lo/hayais/instalao/jdk
export PATH=${PATH}:${JAVA_HOME}/bin
...ó...
setenv JAVA_HOME /sitio/donde/lo/hayais/instalao/jdk
setenv PATH ${PATH}:${JAVA_HOME}/bin

Además también deberíamos de introducir en el PATH una variable que apunte a la localización de los scripts de nuestro servidor, que se habrán instalado en una subcarpeta /bin de nuestra instalación, algo así como...
export J2EE_HOME=/sitio/donde/lo/hayais/instalao
export PATH=${PATH}:${J2EE_HOME}/bin

...ó...
setenv JAVA_HOME /sitio/donde/lo/hayais/instalao
setenv PATH ${PATH}:${JAVA_HOME}/bin


Y finalmente dado que nuestro servidor de aplicaciones necesitará de una base de datos, vamos a establecer la variable CLASSPATH apuntando a un fichero *.jar que permite manejar la BBDD Derby que viene con la instalación de nuestro servidor. Lo tendréis en una subcarpeta llamada /javadb o similar. Ésta variable también tendrá que apuntar al fichero *.jar de J2EE así como al fichero *.jar que apunte a las utilidades de derby. Ésto lo hacemos con un...
export CLASSPATH=${J2EE_HOME}/lib/j2ee.jar:${J2EE_HOME}/javadb/lib/derbyclient.jar:${J2EE_HOME}/javadb/lib/derbytools.jar
...ó...
setenv CLASSPATH ${J2EE_HOME}/lib/j2ee.jar:${J2EE_HOME}/javadb/lib/derbyclient.jar:${J2EE_HOME}/javadb/lib/derbytools.jar

Personalmente os recomiendo que para no tengáis que hacer ésto siempre que queráis arrancarlo, os creéis un pequeño script que os lo haga automáticamente, de hecho, ya que ésto lo haréis cuando vayáis a arrancar el servidor de aplicaciones, lo mejor es que en el mismo script también arranquéis el servidor con la orden que ya vimos anteriormente. Éste script podría lucir algo así como...


Con ésto establecer las variables necesarias y arrancar o parar nuestro servidor sería tan fácil como llamar a nuestro script de la forma adecuada. Imaginemos que nuestro script lo hemos llamao servidor.sh.
Para arrancar nuestro servidor de aplicaciones haríamos...
source servidor.sh arrancar
...y para pararlo haríamos...
source servidor.sh parar
¿fácil no?

Si nuestra máquina fuese a funcionar de servidor de aplicaciones de forma permanente podríamos introducir este script en el runlevel adecuado del arranque de nuestro sistema GNU/Linux para que siempre que arranque la máquina se llame a este script y de forma automática se arranque el servidor. Si lo vamos a usar en un PC de escritorio para pruebas, podríamos crear un lanzador en nuestro entorno gráfico para que con un click se arrancase. Si lo vamos a arrancar y parar de forma periódica a determinadas horas se puede colocar una llamada al script en el cron de la máquina, etc, etc, etc...y así podéis buscar mil formas para facilitar la tarea y no tener que hacer ésto ná más que una vez.

El pantallazo de arranque podía ser éste que os muestro a continuación.


Para comprobar que hemos arrancado bien nuestro servidor, abrimos un navegador y entramos en http://localhost:8080. Deberíamos ver algo como ésto.


Por último, para entrar en la herramienta de administración, entraremos desde nuestro navegador en la dirección http://localhost:4848 y veremos algo como ésto.


Aquí es donde entra en juego el nombre de usuario y la contraseña que escribisteis en un papel para ahora coméroslo. Metéis nombre de usuario de administrador, que en mi caso era admin, contraseña, y os saldrá la página de administración del servidor de aplicaciones, que tendrá una pinta parecida a ésta.


Por supuesto, si hemos cambiado los puertos de administración o web al instalar el servidor, tendremos que coherentemente cambiar las URLs a las que accedemos para ello.

Por último, vamos a parar el servidor porque ya nos hemos hartao de tenerlo encendío y no lo vamos a usar más. El resultado de llamar a nuestro script con el parámetro "parar" será tan escueto como éste que sigue.

Y nada más. Espero que después de ésto tengáis en vuestra máquina un bonito servidor de aplicaciones J2EE activo y preparao pal desarrollo de vuestros beans. Ahora sólo nos falta configurarlo a nuestro gusto, pero eso es algo que haremos en el siguiente post para el desarrollo de nuestro primer bean.

A descansar chavalinos/as que ya os estamos dando mucho curro entre Manolo y yo (como si no supiera que el único que va a leer ésto vas a ser tú, Manolo ;) ).

AJAX para CAMPEONES o ¿Qué es eso del AJAX? (Segunda Parte)

Como su nombre indica, en este post continuo con el anterior de ¿Qué es eso del AJAX?. Si no lo habéis leido, leedlo para cogerle el hilo a este. En este post vamos a tratar el tema del que denominé como AJAX PARA CAMPEONES, es decir, la programación a pelo, vía Javascript, de las llamadas asíncronas y de toda nuestra lógica del lado de cliente. Empecemos pues.

Lo primero: las herramientas
Si empezasteis a trastear un poco con el ejemplo del post anterior, os daríais cuenta que la programación con Javascript es muy puñetera, cualquier mínimo fallo en una letra y nada funciona y a ver quién es el guapo que sabe dónde está el fallo. Javascript adolece de falta de herramientas para trabajar con él y nos podemos tirar horas delante de un código sin saber que leñe falla y sin la menor ayuda. Sin embargo (aquí vengo en plan salvador de los programadores) existen varias herramientas que nos pueden ayudar en nuestra ardua tarea:

  • Firebug: extraordinario complemento de Firefox que nos permite inspeccionar todo el HTML, el Javascript, el DOM, las hojas de estilo. Podemos depurar el código Javascript, ponerle puntos de interrupción, etc. Una herramienta indispensable para los campeones del AJAX.
  • Aptana IDE: un entorno de desarrollo, aunque también existe como plugin de Eclipse para el desarrollo de Javascript. Es magnífico y tiene un puñado de funcionalidades buenísimas: autocompletado, ayuda dinámica, nos dice la compatibilidad de exploradores para cada método, depuración, etc. También incluye las librerías YUI, Dojo, Mochikit, Rico y AFLAX listas para trabajar con ellas (de esto hablaremos en un post posterior).
Por supuesto, antes de empezar, tened dispuesto Internet para consultar las múltiples dudas que os vayan saliendo.

En fin, no queda más remedio, vamos al lío
En el post anterior vimos un pequeño ejemplo de una llamada básica a servidor para obtener un fichero de texto. En ese caso, lo único que hacíamos era llamar al servidor y poner el texto en un div. Vamos a extender un poco este concepto con otro ejemplo. En este caso ponemos una caja de texto donde el usuario introduce el nombre, pulsa el botón y se realiza una llamada a servidor que devuelve "Te devuelvo tu nombre:" seguido del nombre. Este ejemplo tiene tres particularidades:
  1. Cuando el usuario pulsa el botón aparece un cartel de espera, indicando al usuario que se está cargando la página
  2. He introducido un delay en servidor de 2 segundos para que se aprecie el cartel de espera.
  3. Se han mejorado las funciones de creación del objeto XMLHttpRequest y la de envio de la petición (ahora veremos en qué).
El ejemplo lo podéis ver aquí:
http://www.nidea-soluciones.com/PruebasAJAX/PruebaAjax2.html

En este caso he llevado las funciones generales (la de creación del objeto y envío de la petición) a un fichero javascript independiente llamado FuncionesAJAX.js. Veamos en primer lugar este fichero y cómo han cambiado las funciones:

























La función ObjetoAjax() la hemos cambiado en el sentido de que ahora contempla todas las posibles inicializaciones que existen. La función EnviarPetición acepta ahora 5 argumentos:
  • objetoAjax: será el objeto que inicialicemos con la función anterior. Se inicializa fuera de esta función para que podamos lanzar múltiples comunicaciones a la vez a través de objetos distintos.
  • método: tendremos que poner si queremos hacer un "GET" o un "POST".
  • url: dirección del servicio web o página o recurso con el que queremos comunicarnos.
  • async: true si queremos que la llamada sea asíncrona o false en el caso que no. Si es asíncrona tendremos que definir un método que maneje la vuelta.
  • callback: nombre del método que manejará la vuelta. La función EnviarPetición se encargará de enganchar la petición con este manejador y pasarle como parámetro el objeto XMLHttpRequest utilizado.
Como veis, esta función es mucho más general que la anterior y con ella podremos hacer mejor las cosas.

Veamos ahora el código de la página PruebaAjax2.html, la primera parte, dentro de la etiqueta HEAD es:
















En esta parte incluimos el script FuncionesAJAX.js y seguidamente definimos dos funciones:
  • CargaURL(): esta función es la que inicializa el objeto Ajax, pone visible el panel de espera y llama al método EnviarPeticion. Como veis, llamamos a una página .aspx pasándole como parámetro el nombre. La página devuelve un flujo con el texto. Esta llamada se podría realizar a cualquier página o servicio web que hubiésemos programado nosotros en cualquier lenguaje. Cuidado con intentar llamar directamente a páginas de otro dominio diferente de donde tengáis las páginas u os saltará un error al abrir la conexión. Esto se llama LLAMADAS CROSS-DOMAIN, y no se pueden hacer directamente, hay que utilizar un proxy o elementos intermedios.
  • FinCargaURL(objeto): es la función que maneja la respuesta del servidor. Cuando nos responde el servidor, esconderemos el panel de espera y pondremos el texto en el div correspondiente. Ved cómo se pasa como argumento el objeto Ajax encargado de la comunicación.

La parte del BODY de la página es:















En esta parte definimos únicamente la disposición de los elementos. Tenemos el div pnlEspera que contiene la etiqueta de espera, al que le ponemos en el estilo display:none para que inicialmente no se vea. Este ejemplo está bien porque, por lo menos, le ponemos un cartel al usuario diciéndole que algo estamos haciendo (sin demasiada información, pero bueno). Por supuesto esto es muy mejorable y remarco los siguientes aspectos:
  • El usuario puede volver a pulsar sobre el botón mientras se está haciendo la llamada. En determinadas circunstancias esto no debe poderse hacer. Imaginad una operación crítica que se realiza varias veces porque el usuario le ha dado al botón sin parar.
  • La información proporcionada en el cartel no es demasiado explícita. Habrá determinados momentos en los que se realicen operaciones largas, de varios pasos, y haya que informar al usuario de por donde va el tema.
Por esto, pasamos al siguiente ejemplo.

Por Dios, más no, por favor
Pues si, un poco más de Javascript a pelo. En este ejemplo (el tercero del total si no me falla la cuenta), deshabilitamos el botón que realiza la llamada mientras estamos en ello. Podéis ver el ejemplo en la siguiente url:

http://www.nidea-soluciones.com/PruebasAjax/PruebaAjax3.html

Mola, verdad? Lo único que hacemos es deshabilitar el botón en la función CargaURL y habilitarlo en la función FinCargaURL. Veamos el código:




















Le ponemos la propiedad "disabled" a true y luego la volvemos a cambiar a false. Ya empezamos a darle un poquillo de forma al tema, cuidando un poco los detalles, aunque, pequeños saltamontes, el camino aún no ha terminado y es largo y duro.

En el siguiente ejemplo, le hemos incluido un contador de tiempo, que se inicia de forma que el usuario sabe cuánto tiempo tarda en volver la información. Lo podéis ver en:

http://www.nidea-soluciones.com/PruebasAjax/PruebaAjax4.html

Aunque no tiene mucha utilidad si que sirve para ilustrar que podemos mostrar información en pantalla mientras se realiza la llamada, de verdad es asíncrona. En este caso hemos puesto un contador, pero podría ser cualquier tipo de información. En un ejemplo posterior veremos cómo ir diciéndole al usuario en qué estado se encuentra la operación (para poder darle más información). El código Javascript de esta página se complica un poco más:
























Jugamos en este caso con la función setInterval de Javascript que ejecuta cada x milisegundos la función que le pasemos como argumento. La función clearInterval para este ciclo.

Final, por ahora...
Como, otra vez, se me está haciendo demasiado largo el post, finalizo aquí. En posteriores post trataremos los siguientes casos:
  • Múltiples llamadas a la vez
  • Información del estado al usuario
  • Llamadas Cross-Domain
  • Utilización de Frameworks que nos ayuden en nuestro camino con AJAX.


domingo, julio 01, 2007

J2EE, programación de servidores de aplicaciones

¿Qué? ¿cómo andamos?

Se que dije que el siguiente post sería de XMLSchema pero voy a dejarlo pa más tarde y me dedicaré hoy a hablar un poquillo por encima de la tecnología J2EE (Java 2, Enterprise Edition). Haré una introducción teórica en este primer post de una serie de 4 post en los que trataré lo que os quiero presentar de la siguiente forma:
  1. Introducción teórica a vista de pájaro de Java 2, Enterprise Edition (J2EE) y sus Enterprise Java Beans (EJB).
  2. Creación de un EJB (I): Session Bean.
  3. Creación de un EJB (II): Entity Bean.
  4. Creación de un EJB (III): Message-Driven Bean.

J2EE

Si tuviéramos que, como en el colegio, hacer teoría de conjuntos y ver qué conjuntos es menor que cuál o está contenido en o chorrás desas, tendríamos que decir que:
J2ME < J2SE < J2EE
Y es que si bien J2ME no es exactamente un subconjunto de J2SE o J2EE puesto que puede tener elementos que no aparecen en éstos, sí que cuanto menos es una edición mucho más reducida del entorno de desarrollo.

Los objetivos básicos con los que surge J2EE son:
  • Abstraer las tareas críticas y repetitivas mediante servicios con una interfaz uniforme.
  • Preparar una infraestructura uniforme y de una arquitectura software basada en ella para aplicaciones empresariales.
La tecnología de J2EE utiliza la filosofía de la programación basada en componentes, más que la orientada a objetos. En este tipo de programación, un componente es algo más amplio que un mero objeto, y más asociado a la aplicación.

Además, una aplicación compleja basada en componentes a su vez se subdivide en niveles lógicos, de forma que cada nivel cubra un área de tareas y que pueden componer una o varias partes. Así obtenemos "Thin Clients", frente a los "Fat Clients" de la arquitectura Cliente/Servidor, ya que en los niveles intermedios se delega parte de la responsabilidad del servidor. Cada nivel se comunica sólo con los niveles contiguos mediante interfaces bien definidas.


EJB's

Pero pasemos de to este movidón teórico y metámonos en más teoría pero por lo menos un poco más próxima a la práctica. Veamos el concepto de beans. Los beans son nuestros colegas, nuestras "habichuelas", las entidades mínimas de nuestro diseño de aplicaciones...y de servidores de aplicaciones. En esencia son clases java con unas ciertas propiedades que permitirán darnos algunas prestaciones en función de nuestras necesidades, o más técnicamente son componentes que pueden ser usados para construcción de aplicaciones distribuídas y que encapsulan una parte de la lógica de negocio de una aplicación. Un EJB accede a otros gestores de recursos como bases de datos u otros EJB's y puede ser accedido por otros EJB's, aplicaciones, servlets y aplicaciones cliente. el EJB reside en un contenedor que le provee de servicios de seguridad, transacciones, gestión del ciclo de vida, gestión de concurrencia y despliegue.

Un EJB (salvo en el especial caso de los Message-Driven Beans) tiene varias partes:
  • La interfaz cliente. Permite el uso síncrono por parte de los clientes de los procesos de negocio que modela el EJB. Consta de dos clases de tipo interface. La Home Interface que debe extender la clase EJBHome y controla los métodos del ciclo de vida y la Remote Interface que debe extender la clase EJBObject y controla el acceso a los métodos de negocio remotamente.
  • La clase Enterprise Bean. Implementa el Bean en sí, su funcionamiento interno, las llamadas a las BBDD necesarias, los métodos de negocio, ciclo de vida, etc.
  • El descriptor de despliegue. Proporciona al contenedor toda la información que éste necesita sobre el EJB (nombre, nombre de sus interfaces, tipo de EJB, servicios que se esperan del contenedor, etc). Se trata de un fichero XML, y debido a su complejidad y su extensión se suelen utilizar herramientas de despliegue que lo creen a partir de la selección de opciones en un interfaz gráfico por parte del desplegador.

Lo que nuestros coleguitas beans pretenden ayudarnos a modelar son lo que llamamos "entidades de negocio" y "procesos de negocio", que viene a ser una forma empresarial de llamar a información de nuestra aplicación y métodos de acceso y modificación de esa información. Para que nos entendamos, las entidades de negocio son las bases de datos donde los procesos de negocio son los métodos/funciones/procedimientos que acceden a esas bases de datos y leen o modifican lo que en ellas hay.

Y para eso, ¿en qué nos ayudan los beans? Pues bien, tenemos beans para cada una de nuestras necesidades en una apliación...beans a la carta. En esencia tenemos:

Beans de Sesión (Session Beans):
Se encargan de la parte del lado servidor de la lógica de negocio de una aplicación.
Se crean instancias de un Session Bean cuando se produce una petición de un cliente y su tiempo de vida es el de el proceso abierto. Podemos tenerlos de dos tipos:
  • Beans de sesión sin estado (Stateless Session Beans)
    No guardan información del cliente. Todos los Stateless Session Beans instanciados tienen la misma identidad.

  • Beans de sesión con estado (Statefull Session Beans)
    Presentan diferentes estados en función del cliente, estado que se pierde cuando se deja de usar el Session Bean. Como consecuencia, cada objeto Session Bean tiene distinta identidad.
Algunas propiedades
  • Su estado se mantiene en memoria principal durante una transacción pero pasa a almacenamiento secundario tras desactivarse. Además su estado es inaccesible para otros programas, aunque pueda ser sincronizado para las transacciones.
  • Sólo puede usarse por un mismo cliente, no puede ser compartida su referencia.
  • Frente a fallos no se garantiza que una referencia a un objeto Session Bean siga valiendo.
Los Session Beans son especialmente adecuados para encargarse...
...de la lógica de sesión de una aplicación web...


...o también para encargarse de la lógica de sesión de una aplicación de tres capas.



Beans de Entidad (Entity Beans):
Este tipo de beans son los que nos modelan aquéllos conceptos u objetos de negocio cuyos datos deben ser persistentes, para lo que se suele usar una base de datos. Se pueden usar por varios clientes de forma conjunta y simultánea. Su identidad es tan simple como la clave primaria de la base de datos usada. Son tan persistentes que incluso llegan a sobrevivir a caídas de la máquina o de la máquina virtual de Java. En función de quién controle esta persistencia, se clasifican en dos tipos distintos:
  • Persistencia manejada por el bean (Bean Managed Persistence)
    El programador del bean debe programar los métodos que aseguran la persistencia, que vienen a ser los métodos que guardan los datos en la base de datos, así como crear la base de datos y mapear variables con columnas de la base de datos.

  • Persistencia manejada por el contenedor (Container Managed Persistence)
    El programador queda liberado de la tarea de programar la persistencia teniendo únicamente que indicar al contenedor qué variables van a asociadas a qué columnas de la base de datos para que éste controle la persistencia. Todo este mapeo se reflejará en el fichero xml descriptor del bean.
Algunas propiedades:
  • El estado de un Entity Bean es mantenido en una BBDD, con caché en memoria durante una transacción. Por consiguiente, cualquier programa externo puede acceder a él mediante queries SQL. Además su estado se cambia con transacciones y se puede recuperar en cualquier momento.
  • Un objeto Entity Bean puede ser compartido por múltiples clientes pasándose la referencia sin problemas.
  • Frente a fallos, caídas del contenedor o de la máquina, las referencias a los objetos siguen siendo válidas.

Beans controlados por mensajes (Message-driven Beans):
Este tipo de beans permiten a las aplicaciones J2EE procesar mensajes asíncronos, lo que los diferencia de los anteriores cuya llamada era síncrona. En última instancia no son más que escuchadores de mensajes JMS. Su estructura de hecho es similar a la de los escuchadores de eventos de java, sólo que éstos lo que escuchan son mensajes.
La principal diferencia a nivel de uso de éste tipo de bean con los anteriores es que el acceso a ellos no se realiza mediante interfaces, sino por:
  • Mensajes enviados por algún componente J2EE (una aplicación cliente, otro EJB o un componente web).
  • Mensajes enviados por una aplicación o sistema JMS que no use la tecnología J2EE.
También a diferencia de los demás beans, los MDB sólo se componen de una clase java, ya que no tienen interfaces.
describamos entonces algunas de las propiedades de este tipo de EJB's:
  • Una instancia a un MDB no almacena datos o estado conversacional de ningún cliente.
  • Todas las instancias de MDB tienen la misma identidad, por lo que la asignación de una instancia a un cliente es indiferente de qué instancia sea.
  • Un único MDB puede procesar mensajes procedentes de múltiples clientes.
Cuando un mensaje llega, el contenedor de nuestro EJB llama a su método onMessage(), que típicamente lo primero que debe tener programado es la clasificación de este mensaje según pertenezca a cada uno de los 5 tipos de mensajes JMS, para luego procesarlo según la lógica de negocio de nuestra aplicación.

Y bueno, yo creo que como introducción a J2EE y EJB's ya se ha hecho demasiao larga, pero weno, espero haberos ayudao en familiarizaros en esta tecnología. El siguiente post irá dedicao a programar y desplegar un Session Bean pa que le echéis un ojo a su código y veáis que hacerlo es más o menos sencillico aunque un poco coñazo. Además usaremos alguna herramienta de despliegue de EJBs que provee Sun. ya os contaré.

+info:
http://java.sun.com/javaee/5/docs/tutorial/doc/
http://java.sun.com/javaee/5/docs/firstcup/doc/toc.html
http://java.sun.com/javaee/index.jsp