<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>AQuA.it</title>
	<atom:link href="http://blog.aquait.info/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.aquait.info</link>
	<description>Blog técnico de AQuA.it</description>
	<lastBuildDate>Tue, 22 Jun 2010 21:30:45 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Juegos en JME (o cómo convertir tu celular en una mini consola de video juegos)</title>
		<link>http://blog.aquait.info/2010/06/juegos-en-jme-o-como-convertir-tu-celular-en-una-mini-consola-de-video-juegos/</link>
		<comments>http://blog.aquait.info/2010/06/juegos-en-jme-o-como-convertir-tu-celular-en-una-mini-consola-de-video-juegos/#comments</comments>
		<pubDate>Thu, 17 Jun 2010 22:39:02 +0000</pubDate>
		<dc:creator>Enrique</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[j2me]]></category>
		<category><![CDATA[jme]]></category>

		<guid isPermaLink="false">http://blog.aquait.info/?p=224</guid>
		<description><![CDATA[Con el poder de procesamiento que tienen los dispositivos móviles hoy en día y en particular los celulares, se puede -con un poco de esfuerzo, paciencia y muchas ganas- implementar juegos interesantes en Java para el celular.
El “celular” de hoy en día es como una computadora con un montón de periféricos integrados: cámara, teclado, pantalla, [...]]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } --><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Con el poder de procesamiento que tienen los dispositivos móviles hoy en día y en particular los celulares, se puede -con un poco de esfuerzo, paciencia y muchas ganas- implementar juegos interesantes en Java para el celular.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">El “celular” de hoy en día es como una computadora con un montón de periféricos integrados: cámara, teclado, pantalla, teléfono celular, lector de memoria externa, wifi, gps, gsm, etc. Y todo esto en la palma de la mano.<span id="more-224"></span></span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Algunos de estos dispositivos móviles traen sistemas operativos propietarios, otros utilizan alguna versión de Windows, Linux o Symbian OS. Pero hay una características que la gran mayoría tienen en común: Java. Obviamente no es la versión de Java full power que se instala en nuestro desktop, laptop o servidor. Se trata de una versión adaptada a dispositivos móviles en los cuales no se cuenta con Gigas de RAM, o múltiples CPUs con frecuencias de reloj del orden de los Giga Hetrz.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Sorprendentemente, Java Micro Edition (JME, A.K.A. J2ME) tiene las características que la hacen una plataforma bien interesante para desarrollar aplicaciones y particularmente juegos. Y estos últimos son los que vamos a explorar.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;"><br />
</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;"><strong>Primero un poco de teoría</strong></span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Dada la cantidad de dispositivos móviles -todos con características diferentes- se inventaron los “perfiles de capacidades”: MIDP por Mobile Information Device Profile. Dependiendo de la versión de MIDP, el dispositivo va a tener más o menos capacidades de: comunicación, presentación, audio, etc.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Además de MIDP, existe otra especificación llamada CLDC por Connected Limited Device Configuration, que define capacidades de bajo nivel del dispositivo, por ejemplo, si tiene la capacidad de manejar número con punto flotante.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">MIDP se apoya en CLDC para formar la plataforma Java ME. La idea es desarrollar en la plataforma más compatible que se pueda. Hoy por hoy, la mayoría de los celulares soportan MIDP 2.0 y CLDC 1.1, pero si podemos restringirnos a CLDC 1.0 mejor. El Motorola V360 es un ejemplo de teléfono móvil con MIDP 2.0 y CLDC 1.0.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Entonces cuando empecemos a desarrollar, tenemos que elegir que versión de MIDP y CLDC vamos a utilizar. En la página de Oracle (http://java.sun.com/javame/technology/index.jsp), se puede encontrar más información y el SDK (http://java.sun.com/javame/downloads/index.jsp).</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Bien, tenemos el SDK instalado, tenemos nuestra IDE de confianza configurada. ¿Y ahora qué? ¡A programar! Bueno, no tan rápido. ¿Cómo se programa un juego? Esto es algo que los que venimos haciendo IT desde ya hace años, no tenemos muy claro. En Internet hay mucha documentación, pero la realmente buena es escasa.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Primero que nada, veremos como es el esqueleto de un juego -en pseudocódigo-:</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;"> </span></span></p>
<pre class="brush: java">proceso entrada del usuario
actualizo el estado del juego
dibujo la pantalla
goto 1
</pre>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;"> </span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Santo patrono de la informática, perdón por el goto.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">No hay nada revelador en estas 4 lineas, pero lo que si se pueden empezar a ver algunos problemas. Por ejemplo: este juego va a ejecutar a distinta velocidad según de la potencia del celular. Algo claramente no deseable. Obviamente queremos que nuestro juego funcione a la misma velocidad en cualquier celular, sin importar la potencia del mismo.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Para esto, hacemos un pequeño cambio:</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;"></p>
<pre class="brush: java">proceso entrada del usuario
actualizo el estado del juego
dibujo la pantalla
esperar X milisegundos
goto 1
</pre>
<p></span></span><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;"></span></span></p>
<ul></ul>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Ahora variando X, podemos variar la velocidad del juego. Fácil&#8230; ¿no? Queda en manos del usuario elegir X mediante, por ejemplo, el menú el juego. Pero, ¿no se podría determinar X automáticamente? Mejor aún, ¿no se podría determinar X dinámicamente en cada vuelta del ciclo?  Claro que sí. Ahora vemos como:</span></span></p>
<pre class="brush: java">ciclos_por_segundo = 30
milisegundos_por_ciclo = 1000 / ciclos_por_segundo
t_inicial = ahora()
proceso entrada del usuario
actualizo el estado del juego
dibujo la pantalla
t_ciclo = ahora() - t_inicial
si (t_ciclo &lt; milisegundos_por_ciclo) entonces
    esperar (milisegundos_por_ciclo - t_ciclo) milisegundos
goto 3
</pre>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;"> </span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Nota: La función ahora() devuelve la hora actual en milisegundos, algo como lo que hace System.currentTimeMillis() en Java.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Lo que se hace es, tomar el tiempo que toma un ciclo completo (4, 5 y 6). Si ese tiempo es menor que la cantidad de tiempo que establecimos para cada ciclo en 1 y 2, entonces esperamos esa diferencia de tiempo. Así, todos los ciclos demoran lo mismo y el tiempo de espera se ajusta dinámicamente. </span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">De esta forma logramos un rendimiento igual entre celulares de distinta potencia. Este método se puede mejorar implementando saltos de ciclos (frame skipping) cuando el celular es de muy baja potencia, pero corremos el riesgo de que el juego se vuelva injugable. Así, el juego ejecutará más lento en celulares de poca potencia, ya que todo el tiempo se consumirá en los puntos 4, 5 y 6 y nunca entrará en espera.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Es sorprendente la cantidad de cosas interesantes que se pueden hacer utilizando esta sencilla técnica.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;"><strong>A la práctica</strong></span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Vamos a implementar, con esta técnica, el “hola mundo” de los juegos: el PONG de a uno.</span></span></p>
<div id="attachment_225" class="wp-caption aligncenter" style="width: 219px"><a href="http://blog.aquait.info/wp-content/uploads/2010/06/Screenshot.png"><img class="size-full wp-image-225" title="Pong" src="http://blog.aquait.info/wp-content/uploads/2010/06/Screenshot.png" alt="Pong" width="209" height="202" /></a><p class="wp-caption-text">Pong</p></div>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Es como si fuera un Arkanoid, pero sin los ladrillos. Es verdad, no es muy divertido.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">La implementación en Java del bucle principal sería algo así:</span></span></p>
<pre class="brush: java">final int CICLOS_POR_SEGUNDO = 30;
final int MILISEGUNDOS_POR_CICLO = 1000 / CICLOS_POR_SEGUNDO;
while (true) {
    long tInicial = System.currentTimeMillis();
    procesarEntradaDelUsuario();
    actualizarEstadoDelJuego();
    dibujarLaPantalla();
    long tCiclo = System.currentTimeMillis() - tInicial;
    if (tCiclo &lt; MILISEGUNDOS_POR_CICLO) {
        Thread.sleep(MILISEGUNDOS_POR_CICLO - tCiclo);
    }
}
</pre>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Notar que hasta ahora no hay nada hecho particularmente para el PONG. Lo particular estará en las funciones procesarEntradaDelUsuario(), actualizarEstadoDelJuego() y dibujarLaPantalla().</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">La primera tiene la responsabilidad de tomar la entrada del usuario y modificar algo en el juego, en este caso sería la posición de la paleta. Sí, la paleta es ese rectángulo verde.. hay que tener imaginación <img src='http://blog.aquait.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">La segunda debe actualizar el estado interno del juego. En este juego, esta función tiene dos objetivos: a) mover la pelota y b) si la pelota se va hacia abajo, entonces el juego termina con el fatídico “Game Over”. </span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">La tercer y última función, debe tomar el estado del juego y dibujarlo en la pantalla.</span></span></p>
<p><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">El código fuente se puede bajar desde acá: <a href="http://blog.aquait.info/wp-content/uploads/2010/06/pong-scr.tar.gz">pong-scr.tar</a>. En esta implementación, nunca se pierde. Cuando la pelota se va para abajo, aparece nuevamente en el medio de la pantalla. Un buen ejercicio, sería agregarle vidas, que aumente la velocidad de la pelota, darle aceleración a la paleta, mejorar los gráficos, agregarle ladrillitos, sonidos, powerups y ponerle un nombre marketinero (que no sea Arkanoid, claro <img src='http://blog.aquait.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ) y de ahí, a la fama!</span></span></p>
<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } --><span style="font-family: Liberation Sans,sans-serif;"><span style="font-size: x-small;">Enjoy!</span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aquait.info/2010/06/juegos-en-jme-o-como-convertir-tu-celular-en-una-mini-consola-de-video-juegos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Usando SessionBeans en Grails</title>
		<link>http://blog.aquait.info/2010/03/usando-sessionbeans-en-grails/</link>
		<comments>http://blog.aquait.info/2010/03/usando-sessionbeans-en-grails/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 19:17:21 +0000</pubDate>
		<dc:creator>Alejandro</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.aquait.info/?p=204</guid>
		<description><![CDATA[¿SessionBeans y Grails?
Una de la cualidades de Grails que personalmente más me gusta es su integración con JEE. Desde Grails podemos utilizar tags JSP, Session Beans y EntityBeans como si fueran parte integral del framework.
En este post nos centraremos en como podemos invocar SessionBeans ya sean remotos o locales desde nuestro código Grails.  Esta [...]]]></description>
			<content:encoded><![CDATA[<p><strong>¿SessionBeans y Grails?</strong></p>
<p>Una de la cualidades de Grails que personalmente más me gusta es su integración con JEE. Desde Grails podemos utilizar tags JSP, Session Beans y EntityBeans como si fueran parte integral del framework.<br />
En este post nos centraremos en como podemos invocar SessionBeans ya sean remotos o locales desde nuestro código Grails. <span id="more-204"></span> Esta posibilidad junto con el manejo de los EntityBeans le aportan a Grails  adaptabilidad y escalabilidad. A que me refiero con esto, a que siendo prolijos podemos desarrollar una aplicación entera en Grails y luego más adelante pasar los modelos y los servicios a Entities y SessionBeans respectivamente. De esta forma podemos comenzar rápidamente a desarrollar nuestra aplicación haciendo uso de las ventajas de estar en un ambiente dinámico y luego cuando la aplicación está más definida y los cambios no son lo común entonces podemos pasar la capa de negocios a JEE. Este cambio no afecta a ningún otro componente de Grails como ser controladores o vistas.<br />
Para lograr esto último todo lo que debemos hacer es sustituir el código de las operaciones de los servicios por delegación a la misma operación en los SessionBeans creados.</p>
<p>A continuación veremos como se configura Grails para utilizar SessionBeans tanto para EJB3.0 como EJB2.1</p>
<p><strong>Inyectando los SessionBeans</strong><br />
Grails permite inyectar tanto en los servicios como en los controladores cualquier SB al igual que lo hace con sus servicios. Al Grails utilizar Spring en el manejo de sus componentes es posible utilizar todas las ventajas de este dentro de Grails. La forma más sencilla de configurar los objetos a ser inyectados dentro de los controladores o servicios, y en especial los SB, es utilizando el archivo resources.groovy. Este archivo es equivalente a el archivo applicationContext.xml de Spring solo que en vez de ser un archivo XML es una clase groovy que utiliza el SpringBuilder como DSL para la configuración. Por defecto el archivo resources que se encuentra en grails-app/conf/spring y tiene el siguiente contenido:</p>
<pre class="brush: groovy">// Place your Spring DSL code here
beans = {

}</pre>
<p>Dentro del closure es donde se deben agregar las definiciones de los beans.</p>
<p><strong>Configuración de servidor JNDI</strong><br />
Para poder acceder a cualquier componente que se encuentra en un servidor de aplicaciones debemos hacerlo utilizando JNDI. Para esto Spring provee una clase utilitaria la cual facilita las operaciones sobre un servidor de nombres JNDI como ser lookup y a su vez actúa como un proveedor de contexto JNDI. Para esto hay que agregar la siguiente definición en el resources.groovy</p>
<pre class="brush: groovy">	ejbJndi(org.springframework.jndi.JndiTemplate){
		environment = [
			"java.naming.factory.initial" : "org.jnp.interfaces.NamingContextFactory",
			"java.naming.provider.url" : "jnp://http://localhost:1099</pre>
<p>Donde:</p>
<ul>
<li>
<dl>
<dt>ejbJndi </dt>
</dl>
</li>
</ul>
<dl>
<dd>Es el nombre del bean el cual es de tipo <em>org.springframework.jndi.JndiTemplate</em>.  Este nombre puede ser cualquiera. Es a este nombre que se hará referencia para determinar el servidor de nombres que provee el acceso a un objeto. </dd>
</dl>
<ul>
<li>
<dl>
<dt>environment </dt>
</dl>
</li>
</ul>
<dl>
<dd>Es la propiedad de JndiTempalte la cual se configura con un Mapa que tiene las propiedades JNDI </dd>
</dl>
<p>En un archivo podrían existir tantas definiciones de JndiTemplate como proveedores JNDI se necesiten acceder.</p>
<p><strong>Configuración de servidor JNDI por ENVIRONMENT</strong><br />
Es muy probable y necesario, que el servidor JNDI requiera diferente configuración de IP y puerto según sea el ambiente desarrollo, producción o testing. Para lograr esto se debe anexar a la configuración anterior lo siguiente:</p>
<ul>
<li>Colocar el valor de la IP y puerto del JBoss en cada environment del Config.groovy.</li>
<li>Importar la clase ConfigurationHolder en el archivo resources.groovy</li>
<li>Sustituir la ip y puerto de la variable "java.naming.provider.url" por las cargadas en la configuración.</li>
</ul>
<p><em>Ejemplo</em><br />
<strong>Config.groovy</strong></p>
<pre class="brush: groovy">  ...
  environments {
    development {
        ...
        jboss.ip = "10.200.8.173"
        jboss.port = "1099"
        ...
    }
    production {
        ...
        jboss.ip = "172.16.2.105"
        jboss.port = "1099"
        ...
    }</pre>
<p><strong>Resources.groovy</strong></p>
<pre class="brush: groovy">     import org.codehaus.groovy.grails.commons.*
     ...
	ejbJndi(org.springframework.jndi.JndiTemplate){
		environment = [
			"java.naming.factory.initial" : "org.jnp.interfaces.NamingContextFactory",
			"java.naming.provider.url" : "jnp://"+ConfigurationHolder.config.jboss.ip+":"+ConfigurationHolder.config.jboss.port]
	}</pre>
<p><strong>Configuración de componentes EJB 3.0</strong><br />
Para poder inyectar componentes EJB 3.0 tenemos que agregar la siguiente configuración:</p>
<pre class="brush: groovy">	xXXServices(org.springframework.jndi.JndiObjectFactoryBean){
		jndiName = "XXXServices/remote"
		jndiTemplate = ref("ejbJndi")
	}</pre>
<p>Donde:</p>
<ul>
<li>
<dl>
<dt>xXXServices</dt>
</dl>
</li>
</ul>
<dl>
<dd>Es el nombre que se le dará a la referencia remota al SB y que será utilizado para inyectar esta en los controladores y servicios. Cualquier controlador o servicio que tenga una propiedad con nombre xXXServices se le inyectara la referencia al SB remoto definido por ese nombre en el archivo resources.groovy. La primer <strong>x</strong> es en minúscula para indicar que por convención el nombre debe comenzar en minúscula.</dd>
</dl>
<ul>
<li>
<dl>
<dt>jndiName</dt>
</dl>
</li>
</ul>
<dl>
<dd>Nombre por el cual se va a buscar la referencia al SB en el servidor JNDI</dd>
</dl>
<ul>
<li>
<dl>
<dt>jndiTemplate</dt>
</dl>
</li>
</ul>
<dl>
<dd>Nombre del bean que se va a utilizar como provider para acceder al objeto JNDI. Es el definido en el punto anterior.</dd>
</dl>
<p>Para utilizar el SB en un servicio sería:</p>
<pre class="brush: groovy">public class EjemploServices {
	def xXXServices

	void unMetodo(param1, param2) {
		xXXServices.invocoMetodoEnEJB(param1, param 2)
	}
}</pre>
<p><strong>Configuración de componentes EJB 2.1</strong><br />
Para poder inyectar componentes EJB 2.1 tenemos que agregar la siguiente configuración que es similar a la vista para EJB 3.0.</p>
<pre class="brush: groovy"> xXXServices(org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean) {
		jndiName = "EJBXXXServices"
		businessInterface = "biz.aquait.yyy.ejb.EJBXXXServices"
		jndiTemplate = ref("ejbJndi")
		refreshHomeOnConnectFailure = true
                lookupHomeOnStartup=false

	}</pre>
<p>Donde:</p>
<ul>
<li>
<dl>
<dt>xXXServices</dt>
</dl>
</li>
</ul>
<dl>
<dd>Es el nombre que se le dará a la referencia remota al SB y que será utilizado para inyectar esta en los controladores y servicios. Cualquier controlador o servicio que tenga una propiedad con nombre xXXServices a esta se le inyectara la referencia al SB remoto definido por ese nombre en el archivo resources.groovy. La primer <strong>x</strong> es en minúscula para indicar que por convención el nombre debe comenzar en minúscula.</dd>
</dl>
<ul>
<li>
<dl>
<dt>jndiName</dt>
</dl>
</li>
</ul>
<dl>
<dd>Nombre por el cual se va a buscar la referencia al SB en el servidor JNDI</dd>
</dl>
<ul>
<li>
<dl>
<dt>refreshHomeOnConnectFailure</dt>
</dl>
</li>
</ul>
<dl>
<dd>Refresca la home cuando detecta un fallo en la conexión, por ejemplo cuando se reinicia el servidor</dd>
</dl>
<ul>
<li>
<dl>
<dt>lookupHomeOnStartup</dt>
</dl>
</li>
</ul>
<dl>
<dd>Hace que la aplicación no haga el lookup a levantar sino al utilizar servicios del SB.</dd>
</dl>
<ul>
<li>
<dl>
<dt>jndiTemplate</dt>
</dl>
</li>
</ul>
<dl>
<dd>Nombre del bean que se va a utilizar como provider para acceder al objeto JNDI. Es el definido en el primer punto.</dd>
</dl>
<ul>
<li>
<dl>
<dt>businessInterface</dt>
</dl>
</li>
</ul>
<dl>
<dd>La interfaz remota del SB, es decir la que extiende EJBObject.</dd>
</dl>
<p>La forma de utilizar el SB dentro de un servicio u otro componente es la misma forma que las referencias a SB implementados  con EJB 3.0.</p>
<p><strong>Conclusión</strong></p>
<p>Siguiendo los pasos presentados arriba podemos decir que configurar Grails para utilizar  SB no es engorroso y que el uso de estos dentro del framework es transparente ya que se usan de la misma forma que un servicio de Grails.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aquait.info/2010/03/usando-sessionbeans-en-grails/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SCRUM &#8211; Cuando comprendas esta metodología de proyectos sentirás que lo sabías desde hace tiempo</title>
		<link>http://blog.aquait.info/2010/01/scrum-cuando-comprendas-esta-metodologia-de-proyectos-sentiras-que-lo-sabias-desde-hace-tiempo/</link>
		<comments>http://blog.aquait.info/2010/01/scrum-cuando-comprendas-esta-metodologia-de-proyectos-sentiras-que-lo-sabias-desde-hace-tiempo/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 19:21:34 +0000</pubDate>
		<dc:creator>Gabriel</dc:creator>
				<category><![CDATA[SCRUM]]></category>

		<guid isPermaLink="false">http://blog.aquait.info/?p=198</guid>
		<description><![CDATA[Hace nueve años comencé a gestionar procesos de desarrollo de software, utilice varias metodologías ortodoxas que me ayudaron a lograr los objetivos de mis proyectos.
En la medida que adquiría experiencia me daba cuenta que faltaba algo. Tenía la sensación que lograba las metas con un esfuerzo personal muy importante, pero mi equipo lo hacía de [...]]]></description>
			<content:encoded><![CDATA[<p>Hace nueve años comencé a gestionar procesos de desarrollo de software, utilice varias metodologías ortodoxas que me ayudaron a lograr los objetivos de mis proyectos.</p>
<p>En la medida que adquiría experiencia me daba cuenta que faltaba algo. Tenía la sensación que lograba las metas con un esfuerzo personal muy importante, pero mi equipo lo hacía de forma irregular.</p>
<p>Luego de decenas de proyectos comencé a buscar la verdadera razón del éxito. Comprendí que éste radica en la naturaleza de las personas que trabajan en él, sumado al conocimiento técnico adecuado. Por esta razón, siempre considere a mi equipo de trabajo como el “gran actor” de un proyecto y siempre intente generar el contexto más adecuado para obtener el mayor rendimiento de ellos, incluyendo la motivación personal.<br />
<span id="more-198"></span><br />
También aprendí que si quieres hacer un proyecto exitoso debes estar dispuesto a darle paso a quienes te acompañan en el trabajo cotidiano. Sin importar el nivel jerárquico, todos quieren ser reconocidos, todos quieren proponer, todos quieren aportar al objetivo. He aquí lo difícil, intentar satisfacer estas necesidades. Siempre intente hacerlo, convencido que era fundamental para lograr el objetivo.</p>
<p>Hace un par de años atrás, descubrí que muchas de esas premisas, en las cuales yo me basaba intuitivamente, estaban plasmadas en algo llamado SCRUM. Comencé a leer con ahínco, y poco a poco me daba cuenta que había encontrando lo que desde hace tiempo buscaba. Un marco de trabajo que pone por escrito el sentido común, basándose en el valor que aportan las personas, el vínculo, la creatividad, la crítica constructiva, la auto-enseñanza y la auto-organización.</p>
<p>¿Acaso alguien cree que es un buen project manager por hacer cronogramas, calcular presupuestos, hacer cumplir órdenes? Si estás o has estado desempeñando este rol, seguramente pienses que nada de lo anterior fue fundamental en el éxito de un proyecto. En mi opinión, un buen project manager es quién logra llevar a cabo un proyecto sintiendo que realmente tuvo el control del proyecto, fue el gestor, pero sabe perfectamente que sin el equipo de trabajo, solamente con su aporte individual no lograba el objetivo.</p>
<p>Del análisis anterior surge el tipo de líder que propone SCRUM,  el líder que articula, orquesta, comanda, pero prácticamente no aparece en escena. Logrando el compromiso profesional de su equipo de trabajo plasmado en productos tangibles, que agreguen valor al cliente. Todo esto, conjugado con ciclos de desarrollo cortos, permiten corregir en base al empirismo y siempre con riesgo de bajo costo.</p>
<p>Muchas veces, al hablar de metodologías ágiles, tales como SCRUM, los project manager pensamos en anarquía y poca intensidad, cuando en realidad es exactamente lo contrario. Para practicar correctamente SCRUM se exige disciplina e intensidad, sostenidas en el tiempo.</p>
<p>Podría haber escrito un artículo que explicara aburridamente SCRUM, pero iría contra la esencia de éste método, por tal razón, los invito a aprender SCRUM. Luego habrá tiempo para decidir si lo practican o no, pero no lo quiten de sus escenarios por desconocimiento. Piensen, por algo está siendo utilizado por las grandes empresas del mundo de tecnología; Google, Yahoo, Microsoft, HP, Novell, SAP, Nokia, Xerox, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aquait.info/2010/01/scrum-cuando-comprendas-esta-metodologia-de-proyectos-sentiras-que-lo-sabias-desde-hace-tiempo/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>GWT Reflection</title>
		<link>http://blog.aquait.info/2009/12/gwt-reflection/</link>
		<comments>http://blog.aquait.info/2009/12/gwt-reflection/#comments</comments>
		<pubDate>Sun, 06 Dec 2009 00:32:02 +0000</pubDate>
		<dc:creator>Enrique</dc:creator>
				<category><![CDATA[GWT]]></category>
		<category><![CDATA[AppServer]]></category>
		<category><![CDATA[Lab]]></category>

		<guid isPermaLink="false">http://blog.aquait.info/?p=188</guid>
		<description><![CDATA[
Intro
Siguiendo en la linea de la introspección, hoy vamos a ver una simple reflexión que nos va a permitir invocar sobre una instancia de una clase a métodos por su nombre.

What for?
La reflexión es una característica interesante, que se hace fundamental a la hora de diseñar componentes genéricos. Nos permite crear instancias de determinada clase [...]]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } 		A:link { so-language: zxx } --></p>
<p style="margin-bottom: 0in;">Intro</p>
<p style="margin-bottom: 0in;">Siguiendo en la linea de la introspección, hoy vamos a ver una simple reflexión que nos va a permitir invocar sobre una instancia de una clase a métodos por su nombre.</p>
<p style="margin-bottom: 0in;"><span id="more-188"></span></p>
<p style="margin-bottom: 0in;">What for?</p>
<p style="margin-bottom: 0in;">La reflexión es una característica interesante, que se hace fundamental a la hora de diseñar componentes genéricos. Nos permite crear instancias de determinada clase con el nombre de la clase o también invocar métodos sobre una instancia de una clase teniendo el nombre del método. Esto, por ejemplo, nos simplifica enormemente la implementación del patrón command.</p>
<p style="margin-bottom: 0in;">How? What?!</p>
<p style="margin-bottom: 0in;">En GWT (al menos hasta la 1.7) no hay reflexión. Lo que vamos a hacer en esta implementación de reflexión, es proveer un mecanismo para invocar métodos por nombre. Suponiendo que tenemos una clase llamada <strong>MiClase</strong> que tiene un método llamado <strong>miMetodo</strong> buscamos poder hacer algo así:</p>
<p style="margin-bottom: 0in;">
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">MiClase instancia = new MiClase();</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">String nombreMetodo = “miMetodo”;</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">Object[] parametros = new Object[]{...};</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">invocar(instancia, nombreMetodo, parametros);</span></span></pre>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">Enter generators!</p>
<p style="margin-bottom: 0in;">Lo que vamos a hacer es que GWT genere la clase MiClaseReflection. ¿Cómo? Usando generators. Esta es una característica bien interesante de GWT. El foco de este artículo no está en explicar generators, hay mucha literatura en Internet. Acá va un link: <a href="http://code.google.com/intl/es/webtoolkit/doc/1.6/DevGuideCodingBasics.html#DevGuideDeferredBinding">http://code.google.com/intl/es/webtoolkit/doc/1.6/DevGuideCodingBasics.html#DevGuideDeferredBinding</a>. Igual no hay que ser un experto para entender lo que vamos a hacer.</p>
<p style="margin-bottom: 0in;">Básicamente vamos a escribir una clase que genere el código de MiClaseReflection, que tiene un único método -invocar- que es una cadena if..elseif..else que pregunta por cada método de MiClase y si alguna coincide, se lo invoca. Sería algo como esto:</p>
<p style="margin-bottom: 0in;">
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">if (nombreMetodo.equals(“miMetodo1”)) {</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">    target.miMetodo1(params);  // void</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">} else if (nombreMetodo.equals(“miMetodo2”)) {</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">    return target.miMetodo2(params); // no void</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">} else {</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">    throw new Exception(“método no encontrador: ” + nombreMetodo);</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">}</span></span></pre>
<p style="margin-bottom: 0in;">Obviamente falta chequeos de parámetros.</p>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">Para no tener que realizar ningún paso previo a la compilación generando la clase con alguna utilidad externa vamos a usar la API que tiene GWT que permite extender el compilador (com.google.gwt.core.ext). NOTA: Los que hayan utilizado APT de Java van ver unas cuantas similitudes (<a href="http://java.sun.com/javase/6/docs/technotes/guides/apt/index.html">http://java.sun.com/javase/6/docs/technotes/guides/apt/index.html</a>).</p>
<p style="margin-bottom: 0in;">Cuando el compilador de GWT encuentra con la instrucción GWT.create(class) –que devuelve una implementación de la interfaz class– invoca al generador asociado a la interfaz class (esta asociación se declara en el gwt.xml del módulo). En este generador se “escribe” el código que implementa la interfaz class. Para escribir este código tenemos la asistencia de la API com.google.gwt.core.ext.typeinfo que recuerda mucho a la API Mirror Reflection de Java.</p>
<p style="margin-bottom: 0in;">Generate</p>
<p style="margin-bottom: 0in;">La instrucción GWT.create() toma una interfaz y devuelve una implementación de la misma. Entonces vamos definir una interfaz de marca y la vamos a llamar Reflectable. Toda clase que queramos tener soporte de reflexión va a tener que implementar esta interfaz:</p>
<p style="margin-bottom: 0in;">
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">public interface Reflectable {</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">}</span></span></pre>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">Entonces la clase MiClase:</p>
<p style="margin-bottom: 0in;">
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">public class MiClase implements Reflectable {</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">    void miMetodo1();</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">    int miMetodo2();</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">}</span></span></pre>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">Además, tenemos que tener la interfaz de idioma de la reflexión:</p>
<p style="margin-bottom: 0in;">
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">public interface Reflection&lt;I extends Reflectable&gt; {</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">    Object invoke(I target, String methodName, Object... params)</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">    throws InvocationException;</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">}</span></span></pre>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">Para obtener una reflexión y usarla suponiendo que <strong>miMetodo</strong> no tiene parámetros:</p>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">MiClase objeto = new MiClase();</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">Reflection&lt;MiClase&gt; reflection = GWT.create(MiClase.class);</span></span></pre>
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">reflection.invoke(objeto, “miMetodo”);</span></span></pre>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">Para asociar el generador con la interfaz Reflectable, agregamos el siguiente fragmento al :</p>
<p style="margin-bottom: 0in;">
<pre style="margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">    &lt;generate-with class="com.aquait.utils.gwt.rebind.ReflectionGenerator"&gt;</span></span></pre>
<pre style="margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">        &lt;when-type-assignable class="com.aquait.utils.gwt.reflection.Reflectable"/&gt;</span></span></pre>
<pre style="margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">    &lt;/generate-with&gt;</span></span></pre>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">Así, cuando el compilador de GWT encuentra GWT.create(MiClase.class), llama al generador pues la clase MiClase implementa Reflectable. Luego, tenemos una implementación de la interfaz Reflectable para la clase MiClase.</p>
<p style="margin-bottom: 0in;">Para usarlo en un proyecto, hay que agregar esto en el &lt;modulo&gt;.gwt.xml:</p>
<p style="margin-bottom: 0in;">
<pre style="margin-left: 0.49in; margin-bottom: 0in;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">&lt;inherits name="com.aquait.utils.gwt.Reflection"/&gt;</span></span></pre>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">El JAR se puede descargar de acá: <a href="http://blog.aquait.info/wp-content/uploads/2009/12/introspection-reflection4gwt.jar_.gz">introspection-reflection4gwt.jar</a></p>
<p style="margin-bottom: 0in;">Nota: Este JAR tiene una versión actualizada de la introspección que elimina los métodos getIntrospectable() y setIntrospectable() de la interfaz Introspection. Por lo tanto, los métodos getProperty() y setProperty() toman como primer parámetro al Introspectable.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aquait.info/2009/12/gwt-reflection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java AppServer-03: Configuración y código</title>
		<link>http://blog.aquait.info/2009/10/180/</link>
		<comments>http://blog.aquait.info/2009/10/180/#comments</comments>
		<pubDate>Fri, 30 Oct 2009 01:08:40 +0000</pubDate>
		<dc:creator>Enrique</dc:creator>
				<category><![CDATA[AppServer]]></category>
		<category><![CDATA[RPC]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Lab]]></category>

		<guid isPermaLink="false">http://blog.aquait.info/?p=180</guid>
		<description><![CDATA[
Este es el último artículo de esta serie. En este voy a presentar como se configura el servidor y además voy a subir el código fuente.

Estructura de directorios:
aquait-appserver/

 application/

db_connection_pool.config	Configuración del módulo pool de conexiones a la base
modules.config		Configuración de los módulos
services.config 		Configuración de los servicios
messaging.config		Configuración del módulo de mensajería
security.config 		Configuración de seguridad


 lib/

aquaitrt-bin_2009r1.jar	Runtime
mail.jar 			Servicio de mail


 [...]]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } 		A:link { so-language: zxx } --></p>
<p style="margin-bottom: 0in; font-weight: normal;">Este es el último artículo de esta serie. En este voy a presentar como se configura el servidor y además voy a subir el código fuente.</p>
<p style="margin-bottom: 0in; font-weight: normal;"><span id="more-180"></span></p>
<p style="margin-bottom: 0in; font-weight: normal;">Estructura de directorios:</p>
<p style="margin-bottom: 0in;"><strong>aquait-appserver/</strong></p>
<ul>
<li><strong> application/</strong>
<ul>
<li>db_connection_pool.config	Configuración del módulo pool de conexiones a la base</li>
<li>modules.config		Configuración de los módulos</li>
<li>services.config 		Configuración de los servicios</li>
<li>messaging.config		Configuración del módulo de mensajería</li>
<li>security.config 		Configuración de seguridad</li>
</ul>
</li>
<li><strong> lib/</strong>
<ul>
<li>aquaitrt-bin_2009r1.jar	Runtime</li>
<li>mail.jar 			Servicio de mail</li>
</ul>
</li>
<li><strong> log/</strong></li>
<li>logging.config				Configuración de logging</li>
<li>server.config				Configuración del servidor</li>
<li>start.sh</li>
<li>stop.sh</li>
<li>start.cmd				       Scripts para iniciar y detener al servidor</li>
<li>start.sh</li>
<li>stop.cmd</li>
<li>stop.sh</li>
</ul>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in;"><strong>logging.config</strong></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"> </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">java.util.logging.FileHandler.level = ALL </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">java.util.logging.FileHandler.pattern = ./log/server.%u.txt </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">java.util.logging.FileHandler.limit = 50000 </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">java.util.logging.FileHandler.count = 1 </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">java.util.logging.FileHandler.formatter = com.aquait.utils.logging.ServerFormatter </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"> </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">java.util.logging.ConsoleHandler.level = INFO </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">java.util.logging.ConsoleHandler.formatter = com.aquait.utils.logging.ServerFormatter </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">Archivo que configura el logging. El servidor usa la API estándar de Java SE para logear. El archivo por defecto define dos handlers. El primero que genera archivos y el segundo logea a la consola. Por más detalles, ver http://java.sun.com/javase/6/docs/api/java/util/logging/package-summary.html.</p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;"><strong>server.config</strong></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># Server config </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"> </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># Server listening port </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">port = 6666 </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"> </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># Worker pool size </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">workers.poolsize = 10 </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"> </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># Shutdown password </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">shutdown.password = _shut_down_now_server_ </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">Este archivo define tres parámetros del servidor. Primero el puerto TCP/IP en el cual el servidor escucha conexiones. Los clientes se deberán conectar a este puerto. El segundo parámetro define la cantidad de workers (hilos) que atienden los pedidos de los clientes. Y el tercero es la contraseña para bajar el servidor. Se baja mediante el script stop que se comunica al puerto definido y manda un mensaje especial. El servidor solamente se puede bajar desde el mismo host en donde está ejecutando.</p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;"><strong>db_connection_pool.config</strong></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># DBConnectionPoolModule configuration </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># Examples: </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">#     url = jdbc:oracle:thin:@&lt;host&gt;:&lt;port&gt;:&lt;database&gt; </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">#     driverclass = oracle.jdbc.driver.OracleDriver </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">enable = false </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">url = &lt;url&gt; </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">username = &lt;user&gt; </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">password = &lt;pass&gt; </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">driverclass = &lt;driver_class&gt; </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">autocommit = false </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">poolsize = 5 </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">maxpoolsize = 10 </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">Este archivo controla los parámetros del pool de conexiones a la base de datos.</p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;"><strong>modules.config</strong></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># Modules to load </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># Format: </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">#       module.name = &lt;module_name&gt; </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">#       module[&lt;module_name&gt;].class = &lt;module_class&gt; </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">#</span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">En este archivo se delcaran los módulos que van a desplegarse en el servidor. Cada módulo puede tener una cantidad varible de parámetros.</p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;"><strong>messaging.config</strong></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># MessagingModule configuration </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">enable = false </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">poolsize = 10 </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"> # Security realms </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># Format (&lt;n&gt; starts at 0): </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">#       security_realm[&lt;n&gt;] = &lt;security_realm_class&gt; </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">#</span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">Este archivo configura la seguridad del servidor. Se pueden definir varios realms que se ejecutan en orden  para cada pedido de los clientes.</p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;"><strong>services.config</strong></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># Services </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># Format: </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">#       service[&lt;service_name&gt;].interface = &lt;service_interface&gt; </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">#       service[&lt;service_name&gt;].implementation = &lt;service_implementation&gt; </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">#       service[&lt;service_name&gt;].parameter[&lt;param_name&gt;] = &lt;param_value&gt; </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;"># </span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">Este archivo configura los servicios que se publican en el servidor. Para cada servicio hay que configurar la interfaz y la implementación de esta. Además, opcionalmente, se pueden agregar parámetros de inicialización.</p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">Con esto finalizamos esta serie. Siempre estoy a las orden ante cualquier consulta que tengan al respecto de este servidor.</p>
<p style="margin-bottom: 0in; font-weight: normal;">Bajar código fuente: <a href="http://blog.aquait.info/wp-content/uploads/2009/10/aquaitrt_2009-10-14.tar.gz">aquaitrt_2009-10-14.tar.gz</a></p>
<p style="margin-bottom: 0in; font-weight: normal;">
]]></content:encoded>
			<wfw:commentRss>http://blog.aquait.info/2009/10/180/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java AppServer-02: DBPool + Messaging</title>
		<link>http://blog.aquait.info/2009/10/java-appserver-02-dbpool-messaging/</link>
		<comments>http://blog.aquait.info/2009/10/java-appserver-02-dbpool-messaging/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 18:17:16 +0000</pubDate>
		<dc:creator>Enrique</dc:creator>
				<category><![CDATA[AppServer]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Lab]]></category>

		<guid isPermaLink="false">http://blog.aquait.info/?p=175</guid>
		<description><![CDATA[
Siguiendo la exploración de los principales componentes de servidor, en este artículo vamos a ver el el componente de conexiones a la base de datos y el de mensajería. Los dos componentes se diseñaron e implementaron separadamente del servidor de aplicaciones, por lo que no están acoplados de ninguna forma. Para “agregarlos” al servidor, se [...]]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } --></p>
<p style="margin-bottom: 0in;">Siguiendo la exploración de los principales componentes de servidor, en este artículo vamos a ver el el componente de conexiones a la base de datos y el de mensajería. Los dos componentes se diseñaron e implementaron separadamente del servidor de aplicaciones, por lo que no están acoplados de ninguna forma. Para “agregarlos” al servidor, se implementaron módulos del servidor que los adaptan. <span id="more-175"></span></p>
<p style="margin-bottom: 0in;">Pool de conexiones a la base de datos</p>
<p style="margin-bottom: 0in;">El pool implementado es muy sencillo. Tiene una colección de conexiones con un tamaño inicial (configurable) y en caso de que el cliente (en este caso el servidor de aplicaciones) necesite más, crea hasta un máximo (también configurable).</p>
<p style="margin-bottom: 0in; text-align: center;">
<div id="attachment_176" class="wp-caption aligncenter" style="width: 570px"><a href="http://blog.aquait.info/wp-content/uploads/2009/10/Java-AppServer-02-fig1.png"><img class="size-full wp-image-176 " title="Java-AppServer-02-fig1" src="http://blog.aquait.info/wp-content/uploads/2009/10/Java-AppServer-02-fig1.png" alt="Diseño del pool de conexiónes a la BD" width="560" height="426" /></a><p class="wp-caption-text">Diseño del pool de conexiónes a la BD</p></div>
<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } --></p>
<p style="margin-bottom: 0in;">Los métodos startup() y shutdown() del módulo manejan el ciclo de vida del pool. El primero carga de un archivo de configuración -que veremos más adelante- los datos para crear el pool y el segundo mata a las conexiones activas.</p>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">Mensajería</p>
<p style="margin-bottom: 0in; font-weight: normal;">El servicio de mensajería también es sencillo, pero potente. Poseé un pool de hilos que procesan los mensajes en form asíncrona. La clase Messaging tiene un conjunto de MessageHandlers que son los responsables de procesar los mensajes. Cuando llega un mensaje, este se le pasa a todos los handlers y cada uno es responsable de si lo procesa o no.</p>
<p style="margin-bottom: 0in; text-align: center;">
<div id="attachment_177" class="wp-caption aligncenter" style="width: 634px"><a href="http://blog.aquait.info/wp-content/uploads/2009/10/Java-AppServer-02-fig2.png"><img class="size-full wp-image-177 " title="Java-AppServer-02-fig2" src="http://blog.aquait.info/wp-content/uploads/2009/10/Java-AppServer-02-fig2.png" alt="Diseño del servicio de mensajería" width="624" height="435" /></a><p class="wp-caption-text">Diseño del servicio de mensajería</p></div>
<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } --></p>
<p style="margin-bottom: 0in; font-weight: normal;">En el próximo artículo voy presentar la configuración del servidor y también voy a subir el código fuente. Hasta el próximo!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aquait.info/2009/10/java-appserver-02-dbpool-messaging/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Como elegir un framework web</title>
		<link>http://blog.aquait.info/2009/09/como-elegir-un-framework-web/</link>
		<comments>http://blog.aquait.info/2009/09/como-elegir-un-framework-web/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 02:20:23 +0000</pubDate>
		<dc:creator>Alejandro</dc:creator>
				<category><![CDATA[Arquitectura]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.aquait.info/?p=134</guid>
		<description><![CDATA[Hoy en día casi todo proyecto de desarrollo tiene alguna interfaz web como parte del producto. Esto no es ningún desafío si tenemos un equipo el cual ya ha trabajado con este tipo de  proyectos. ¿Pero que pasa si el equipo no tiene experiencia en el desarrollo de aplicaciones web?]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } --><br />
<strong><em>¿Como puedo saber cual es el mejor framework web para mi proyecto?</em></strong><em> </em></p>
<p style="margin-bottom: 0in">Hoy en día casi todo proyecto de desarrollo tiene alguna interfaz web como parte del producto. Esto no es ningún desafío si tenemos un equipo el cual ya ha trabajado con este tipo de  proyectos. ¿Pero que pasa si el equipo no tiene experiencia en el desarrollo de aplicaciones web?</p>
<p style="margin-bottom: 0in"><span id="more-134"></span></p>
<p style="margin-bottom: 0in" align="left">Por ejemplo, viene del mundo enterprise, con años de experiencia en sistema de mediano y gran porte con clientes realizados con frameworks GUIs como ser Swing.</p>
<p style="margin-bottom: 0in" align="left">Al principio seguramente subestimemos el mundo web pensando que todo es es un juego de niños que cualquiera puede hacer y que contratando a un diseñador web nuestros problemas van a estar solucionados. Pero obviamente uno está equivocado y ni bien comienza a estudiar lo básico se encuentra con una cantidad de conceptos no menores como ser  manejo de sesión, AJAX, CSS, XSS, SQL-Inyection que uno debe entender antes de poder realizar cualquier sistema.</p>
<p style="margin-bottom: 0in" align="left">Una vez que terminamos de estudiar estos conceptos y que nos volvemos a sentir seguros para comenzar es recién ahí que nuestro problema comienza. En ese momento es cuando la gran pregunta surge ¿Qué framework web (FW) es el que debo utilizar para mis proyectos?</p>
<p style="margin-bottom: 0in" align="left">Hace un par de años atrás esto no hubiera sido un problema, la respuesta probablemente hubiera  sido si estamos trabajando en Java, utiliza <strong>struts</strong><span style="font-weight: normal">. Pero hoy eso cambió debido a que solo para Java en la página </span><a href="http://java-source.net/open-source/web-frameworks">http://java-source.net/open-source/web-frameworks</a> podemos encontrar más de 40 frameworks, dentro de los cuales el que yo utilizo no está. Y ni hablar si entramos considerar FW de diferentes lenguaje de programación como ser Ruby, Python, php y .net . ¿Entonces como podemos hacer para responder semejante pregunta hoy en día?</p>
<p style="margin-bottom: 0in" align="left">A continuación voy a definir lo que IMHO son los factores que yo he utilizado para responder está pregunta y que pueden ser de ayuda a otros que se enfrenten a una situación similar. Partiremos de la base  que tenemos un equipo de desarrollo con experiencia en un lenguaje determinado el cual debemos reconvertir al desarrollo de aplicaciones web. Algunos de los puntos que se plantearán no tienen sentido por ejemplo para un desarrollador independiente o si se está armando un equipo desde cero. Cuando se trabaja con un equipo ya formado hay factores a considerar que no dependen directamente de la tecnología y que pueden determinar que el mejor FW del mundo, no sea la mejor elección, lo cual hace que la solución del vecino no siempre sea la solución adecuada para uno. Por lo tanto debemos tener sumo cuidado con nuestros pares cuando con su mejor intención nos recomiendan “él FW” ya que probablemente ellos no conozcan el contexto donde usted lo debe utilizar. Por último hay que ser realistas y saber que probablemente al finalizar el proceso de selección haya más de un FW que pueda ser utilizado y que la definición terminará siendo un tema de preferencia con un grado de incertidumbre. La respuesta final solo la sabrá luego de estar avanzado en el primer proyecto, pudiendo equivocarse y debiendo reconsiderar su decisión. Por tal motivo es importante elegir como primer experiencia un proyecto  no crítico.</p>
<p style="margin-bottom: 0in" align="left">Los puntos que voy a nombrar a continuación no están en un orden especial.</p>
<p><strong><em>Puntos a tener en cuenta a la hora de elegir un FW</em></strong><br />
<strong>Conocimientos del equipo</strong></p>
<p style="margin-bottom: 0in">Es de suma importancia evaluar en que se siente cómodo el equipo trabajando. Es decir si tengo todos programadores Java muy probablemente lo mejor sea buscar una FW dentro de Java de esta forma el equipo podrá aprender rápidamente el FW ya que no tiene que perder tiempo estudiando los detalles de otro lenguaje. Por otro lado FW buenos hay en casi todos los lenguajes así que no debería ser un problema fijar este punto. La excepción a esta regla sería si estamos trabajando con un lenguaje desactualizado como ser Clipper o Cobol. Pero en este caso estaremos ante una problema mayor que es una reconversión tecnológica de los sistemas.</p>
<p><strong>¿Necesitamos algo que solucione solo la presentación o tenemos que trabajar en todas las capas?</strong></p>
<p style="margin-bottom: 0in" align="left">Es importante determinar que grado de libertad tenemos a la hora de elegir. Es decir, estamos ante un caso en el cual tenemos un sistema ya armado al cual solo debemos darle la presentación web o estamos ante un caso en el cual podemos elegir desde la forma de presentar los datos hasta la forma de persistirlos. Dependiendo de esto nos convendrá utilizar algo que soluciones todo nuestro requerimientos o simplemente centrarnos en lo que necesitamos que es solucionar la presentación web. En base a lo anterior podemos dividir los FW dividir en dos grupos y así descartar el que no sea de nuestro interés. Los grupos serían:</p>
<p><em>Frameworks full stack</em></p>
<p style="margin-bottom: 0in" align="left">Son los que presentan una solución completa que va desde la capa de presentación hasta la capa de persistencia de la información. Los más nuevos están basados en el patrón MVC. Algunos ejemplos de estos  son:</p>
<ul>
<li>Rails en ruby y que podríamos decir que es la estrella del momento</li>
<li> Grails en Groovy</li>
<li>CakePhp en php</li>
<li>Spring Roo y SEAM en Java</li>
<li>Django en Python</li>
</ul>
<p style="margin-bottom: 0in" align="left">Detallar cada uno no es nuestra intención, simplemente me limitaré a comentar que la mayoría está basado en los principios de CoC (convention over configuration), DRY (don&#8217;t repeate yourself) y que su composición básica consta de un procesador de templates para el diseño de las vista (que generarán las páginas dinámicas), un despachador de HttpRequests que siguiendo determinadas convención decide a que servicio despachar el pedido. Para el manejo de los datos cuentan con un framework ORM que ofrece creación de consultas dinámicas y una cantidad de facilidades que simplifican el trabajo.</p>
<p><em>Solo de presentación:</em></p>
<p style="margin-bottom: 0in" align="left">Estos son aquellos que están orientados solo a la capa de presentación.</p>
<p style="margin-bottom: 0in" align="left">Ejemplos de este tipo son:</p>
<ul>
<li>GWT- Google Web Tookit:el cual genera una aplicación 100% JavaScript pero que es	programada en Java</li>
<li>JSF: Java Server Faces, es el framework de componentes oficial de Java</li>
<li>ASP.NET: que es LA opción dentro de Microsoft</li>
</ul>
<p><strong>Soporte (comunidad, fabricante, libros, certificación, perspectiva a futuro)</strong></p>
<p style="margin-bottom: 0in" align="left">Un punto importante, sobre todo en los proyectos OS, es ver la comunidad que hay al rededor del framework a utilizar. Es importante investigar si hay una empresa invirtiendo recursos en el desarrollo del producto o está movido pura y exclusivamente por la comunidad. En el último casó es cuando “el tamaño si importa” y dependiendo del tamaño de la comunidad en que se sustenta depende el soporte que podemos tener. Para esto la mejor forma es en la página del framework buscar que tantos reporte de bugs hay, que tan rápido se solucionan, cuantos desarrolladores hay corrigiendo tickets. Siguiendo en esta misma linea hay que ver cada cuanto sale una nueva versión y si hay versiones destinadas a generar una versiones estables del framework o si solo salen versiones cuando hay nuevas funcionalidades. Visto que vamos a tener que aprender a utilizar el framework hay que estudiar la calidad de la documentación de este, ver que tantos libros publicados (por ejemplo en Amazon) hay sobre el tema y si se ofrece algún tipo de certificación y/o capacitación.</p>
<p><strong>Existencia de proyectos exitosos</strong></p>
<p style="margin-bottom: 0in" align="left">Como nuestra intención es utilizar el FW para un producto que en algún momento deberá salir en producción seguramente no queramos ser los conejillos de indias. Si el FW es  mínimamente serio entonces debe tener en su sitio web referencia a  sistemas que están implementado con este.  No es una mala idea de ser posible dar una mirada a estos y ver que tan bien funcionan. Sería excelente poder encontrar un blog de uno de estos proyectos en el cual se comente la experiencia durante el desarrollo del sistema.</p>
<p><strong>Integración con la plataforma existente</strong></p>
<p style="margin-bottom: 0in" align="left">Si el proyecto va a formar parte de un ecosistema más complejo entonces hay que tomar en cuenta las posibilidades de integración que tiene el FW y si estas son aceptables dentro de la arquitectura de nuestro producto. Por ejemplo si tenemos que interactuar con un sistema JEE es importante determinar que facilidades para invocar servicios EJB me da el FW. Claro está que siempre es posible desarrollar una capa que se encargue de la interacción, pero si el FW lo soporta nativamente no solo nos ahorramos trabajo sino que estamos reutilizando algo que está probado y utilizado por otros.</p>
<p><strong>Curva de aprendizaje</strong></p>
<p style="margin-bottom: 0in" align="left">Este punto hoy en día es engañoso debido a que los FW modernos tienen una curva de aprendizaje muy rápida inicialmente pero que para llegar a niveles de expertos hay que dedicarle mucho tiempo como a cualquier otro framework. Si ha esto le sumamos que la mayoría de los FW son OS con una documentación de mala calidad, que  probablemente no exista soporte local y que para capacitarnos tengamos que viajar muchos kilómetros (por lo menos si están el el Sur como yo). Lo cual hace que la capacidad de aprendizaje del equipo sea un factor importante. En algunos casos para poder llegar a solucionar un problema será necesario estudiar el código fuente del FW. Si llegáramos a tener la suerte de que el presupuesto nos permitiera poder capacitar parte del equipo y/o de contratar soporte entonces no hay que dudarlo. Los dolores de cabeza y el tiempo que se puede ganar  seguramente lo vale.</p>
<p><strong>Probar, probar y probar</strong></p>
<p style="margin-bottom: 0in" align="left">Inevitablemente para poder determinar el FW tendremos que destinar recursos y realizar algunas pruebas antes de poder llegar a una conclusión aceptable y fundamentada. No es necesario probar todos para estar tranquilo de que estamos utilizando el mejor. Cuando evaluemos recordar que estamos buscando el adecuado para el contexto donde hay que usarlo y no el mejor en general. Con un buen análisis previo probablemente no debamos probar más de dos o tres FW. Para que la prueba sea lo más comparativa posible debemos elegir un proyecto tipo y e implementarlo con con los FW que vayamos a evaluar..</p>
<p><strong><em>¿Como comparamos los FW?</em></strong><em> </em></p>
<p style="margin-bottom: 0in" align="left">Para la comparación de los FW he utilizado una herramienta que a mi me ha ayudado a la hora de evaluar  y puede ser de ayuda para ustedes también. La herramienta es una simple tabla en la que refleja la mayoría de los puntos vistos. En esta tabla calificaremos los FW dándoles un puntaje donde para cada punto tendríamos un máximo asignable y la suma de los máximos te todos los puntos suma 100. Al definir máximos diferentes por puntos estamos priorizando los puntos a evaluar de acuerdo a nuestro contexto. Por ejemplo si estamos en un caso en el cual tenemos una cantidad de sistemas existentes con los cuales debemos interactuar seguramente la capacidad de integración del FW sea uno de los puntos más importantes a evaluar mientras que si no tenemos que interactuar con otros sistemas, tenemos tiempos tiranos y un equipo ya formado con poca experiencia web  entonces la curva de aprendizaje es un punto determinante en nuestra elección.</p>
<p style="margin-bottom: 0in" align="left">Para dejar en claro este punto vamos a ver un ejemplo:</p>
<p><!-- 		@page { margin: 0.79in } 		TD P { margin-bottom: 0in } 		TH P { margin-bottom: 0in } 		P { margin-bottom: 0.08in } --></p>
<table border="1" cellspacing="0" cellpadding="0" width="100%" rules="true" bordercolor="#555555">
<tbody>
<tr valign="top">
<th width="24%"></th>
<th width="6%">
<p align="center"><em><strong>Max</strong></em></p>
</th>
<th width="17%">
<p align="center"><em><strong>FW 1</strong></em></p>
</th>
<th width="17%">
<p align="center"><em><strong>FW 2</strong></em></p>
</th>
<th width="17%">
<p align="center"><em><strong>FW 3</strong></em></p>
</th>
<th width="17%">
<p align="center"><em><strong>FW 4</strong></em></p>
</th>
</tr>
<tr valign="top">
<td width="24%">
<p align="left"><em><strong>Soporte</strong></em></p>
</td>
<td width="6%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">25</span></p>
</td>
<td width="17%" bgcolor="#ffffff">
<p align="left">15</p>
</td>
<td width="18%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">10</span></p>
</td>
<td width="17%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">20</span></p>
</td>
<td width="18%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">5</span></p>
</td>
</tr>
<tr valign="top">
<td width="24%">
<p align="left"><em><strong>Proyecto exitoso</strong></em></p>
</td>
<td width="6%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">10</span></p>
</td>
<td width="17%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">5</span></p>
</td>
<td width="18%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">10</span></p>
</td>
<td width="17%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">10</span></p>
</td>
<td width="18%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">0</span></p>
</td>
</tr>
<tr valign="top">
<td width="24%">
<p align="left"><em><strong>Integración</strong></em></p>
</td>
<td width="6%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">50</span></p>
</td>
<td width="17%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">25</span></p>
</td>
<td width="18%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">40</span></p>
</td>
<td width="17%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">35</span></p>
</td>
<td width="18%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">45</span></p>
</td>
</tr>
<tr valign="top">
<td width="24%">
<p align="left"><em><strong>Curva aprendizaje</strong></em></p>
</td>
<td width="6%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">15</span></p>
</td>
<td width="17%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">15</span></p>
</td>
<td width="18%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">10</span></p>
</td>
<td width="17%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">10</span></p>
</td>
<td width="18%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">5</span></p>
</td>
</tr>
<tr valign="top">
<td width="24%">
<p align="left"><em><strong>Total:</strong></em></p>
</td>
<td width="6%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">100</span></p>
</td>
<td width="17%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">60</span></p>
</td>
<td width="18%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;"><strong>70</strong></span></p>
</td>
<td width="17%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;"><strong>75</strong></span></p>
</td>
<td width="18%" bgcolor="#ffffff">
<p align="left"><span style="color: #000000;">55</span></p>
</td>
</tr>
</tbody>
</table>
<p style="margin-bottom: 0in" align="left">
<p style="margin-bottom: 0in" align="left">La lectura que se pude hacer de la tabla anterior es que debemos realizar pruebas con el FW2 y el FW4 para definir cual de estos dos es el que vamos a utilizar. Gracias al estudio que realizamos redijimos por lo menos a la mitad la cantidad de FW a estudiar y tenemos una tabla que justifica nuestra elección.</p>
<p style="margin-bottom: 0in" align="left">Obviamente cuanta más filas le agreguemos a la tabla tendremos más información para justificar la elección.</p>
<p style="margin-bottom: 0in" align="left">Por las dudas aclaro que los máximos asignados son de ejemplos y ustedes deberían definir los suyos de acuerdo a sus necesidades.</p>
<p><strong>En resumen&#8230;</strong></p>
<p style="margin-bottom: 0in" align="left">En resumen a la hora de seleccionar un FW debemos seguir tres pasos:</p>
<ol>
<li>
<p style="margin-bottom: 0in; font-weight: normal;">Primero debemos evaluar 	los conocimientos del equipo y determinar que tipo de FW se quiere si uno que sea full-stack o solo presentación.</p>
</li>
<li>
<p style="margin-bottom: 0in; font-weight: normal;">Una vez tengamos esto y sabiendo el lenguaje de preferencia podemos buscar el subconjunto de FW a evaluar. Para facilitar la evaluación confeccionamos una planilla como la vista en el punto anterior.</p>
</li>
<li>
<p style="margin-bottom: 0in; font-weight: normal;">Por ultimo con los FW mejor ranqueados realizamos las pruebas las cuales se realizan con un mismo proyecto implementado en cada uno de los FW.</p>
</li>
</ol>
<p style="margin-bottom: 0in" align="left">Luego de todo esto podremos saber cual es el FW a utilizar. Parece mucho trabajo, no? Si seguro que lo es, pero es la única forma de poder tomar una decisión minimizando el riesgo de equivocarnos&#8230; y cuando la decisiones tecnológicas de una empresa depende de nosotros es bueno tener herramientas para justificar nuestras decisiones y sobro todo para asegurarnos el éxito de nuestro trabajo.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aquait.info/2009/09/como-elegir-un-framework-web/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Java AppServer-01: Intro Application Server</title>
		<link>http://blog.aquait.info/2009/09/112/</link>
		<comments>http://blog.aquait.info/2009/09/112/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 00:00:53 +0000</pubDate>
		<dc:creator>Enrique</dc:creator>
				<category><![CDATA[AppServer]]></category>
		<category><![CDATA[Lab]]></category>

		<guid isPermaLink="false">http://blog.aquait.info/?p=112</guid>
		<description><![CDATA[
Ahora que tenemos un servicio RPC podemos usarlo como base para implementar un servidor de aplicaciones, pero solamente un servicio RPC no alcanza. Por esto, vamos a implementar estos módulos/servicios:


Seguridad: 	autorización, autenticación y auditoria


Pool de 	conexiones a la base de datos


Servicio de 	mensajería asíncrona



Y, además de tener una API para agregar servicios, el servidor va [...]]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } --></p>
<p style="margin-bottom: 0in; font-weight: normal;">Ahora que tenemos un servicio RPC podemos usarlo como base para implementar un servidor de aplicaciones, pero solamente un servicio RPC no alcanza. Por esto, vamos a implementar estos módulos/servicios:</p>
<ul>
<li>
<p style="margin-bottom: 0in; font-weight: normal;">Seguridad: 	autorización, autenticación y auditoria</p>
</li>
<li>
<p style="margin-bottom: 0in; font-weight: normal;">Pool de 	conexiones a la base de datos</p>
</li>
<li>
<p style="margin-bottom: 0in; font-weight: normal;">Servicio de 	mensajería asíncrona</p>
</li>
</ul>
<p style="margin-bottom: 0in; font-weight: normal;"><span id="more-112"></span></p>
<p style="margin-bottom: 0in; font-weight: normal;">Y, además de tener una API para agregar servicios, el servidor va a proveer una API para agregar módulos del usuario. Ahora el diagrama de componentes del servidor:</p>
<p style="margin-bottom: 0in; font-weight: normal; text-align: center;">
<div id="attachment_113" class="wp-caption aligncenter" style="width: 464px"><a href="http://blog.aquait.info/wp-content/uploads/2009/09/Java-AppServer-01-fig1.png"><img class="size-full wp-image-113 " title="Java-AppServer-01-fig1" src="http://blog.aquait.info/wp-content/uploads/2009/09/Java-AppServer-01-fig1.png" alt="Diagrama de componentes" width="454" height="151" /></a><p class="wp-caption-text">Diagrama de componentes</p></div>
<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } --></p>
<p style="margin-bottom: 0in; font-weight: normal;">Los componentes de la capa superior utilizan funcionalidades de los componentes de la capa inferior. Ahora vamos a explorar cada uno de los componentes.</p>
<p style="margin-bottom: 0in; font-weight: normal;">
<p style="margin-bottom: 0in; font-weight: normal;">Security realms manager</p>
<p style="margin-bottom: 0in; font-weight: normal;">Esto es obligatorio en cualquier AppServer. En el Security Realms Manager se instalan los security realms. ¿Qué es un security realm? Conceptualmente es un componentes que controla el acceso al los servicios. Desde el punto de vista técnico, es la implementación de la interfaz:</p>
<p style="margin-bottom: 0in; font-weight: normal;">
<pre class="brush: java">public interface SecurityRealm {
    /**
     * The login method.
     * @param credentials The credentials to validate
     * @throws LoginException If an exeption ocurrs during login
     */
    void login(Credentials credentials) throws LoginException;

    /**
     * The logout method.
     * @param credentials The credentials
     */
    void logout(Credentials credentials);

    /**
     * This method returns true if and only if the service's method can be
     * executed with the given credentials.
     *
     * @param credentials the credentials of the executing user
     * @param serviceName the service name
     * @param methodName the method name to execute
     * @param params the paramenters to pass to the method
     * @throws NotExecutedException signals that the execution is not allowed for the given credentials, serviceName, methodName and params
     */
    void executionAllowed(Credentials credentials, String serviceName, String methodName, Object... params) throws NotExecutedException;
}</pre>
<p style="margin-bottom: 0in; font-weight: normal;">Son solamente tres métodos: login, logout y isExecutionAllowed. Los dos primeros refieren al concepto de autenticación y el tercero refiere al concepto de autorización, pero también se puede asociar a auditoría ya que siempre se ejecuta antes de realizar la invocación al servicio.</p>
<p style="margin-bottom: 0in; font-weight: normal;">El security realms manager utiliza el interceptor que aparece en Java RPC-07: en el método onPreExecution() se llama al método executionAllowed() del security realm y continúa la ejecución si este no da la excepción NotExecutedException. Por seguridad, tampoco ejecuta si ocurre cualquier otra excepción (o error) en el executionAllowed() y así evita que un bug quiebre el sistema de seguridad.</p>
<p style="margin-bottom: 0in; font-weight: normal;">Entonces poniendo código arbitrario en método executionAllowed() se puede autorizar o no la ejecución de un método de un servicio con determinados parámetros.</p>
<p style="margin-bottom: 0in; font-weight: normal;">El security realms manager maneja una colección de security realms. Se ejecutan todos y solamente se da por autorizada la llamada si todos autorizaron. El servidor tiene implementado un security realm abstracto que se basa en nombre de usuario y contraseña y otro security realm para hacer auditoría (logging).</p>
<pre class="brush: java">public abstract class AbstractUserPasswordSecurityRealm extends SecurityRealmAdapter {

    public AbstractUserPasswordSecurityRealm() {
    }

    public void login(Credentials c) throws LoginException {
        UserPasswordCredentials cred = (UserPasswordCredentials)c;
        if (cred != null) {
            String user = cred.getUser();
            String pass = cred.getPassword();
            validate(user, pass);
        } else {
            throw new LoginException("null credentials");
        }
    }

    public void executionAllowed(Credentials credentials, String serviceName, String methodName, Object... params) throws NotExecutedException {
        if (credentials == null) {
            throw new NotExecutedException("not logged in");
        }
    }

    public abstract void validate(String user, String pass) throws LoginException;
}</pre>
<p style="margin-bottom: 0in; font-weight: normal;">Module manager</p>
<p style="margin-bottom: 0in; font-weight: normal;">Como vimos, el servidor es extensible. ¿Pero cómo? Mediante módulos. Un módulo no es más que un bean que tiene un nombre y dos métodos para el manejo del ciclo de vida: startup() y shutdown(). Luego, el servidor tiene un método para obtener el módulo por su nombre. Como es tan simple la interfaz, es fácil adaptar cualquier servicio para incorporarlo al servidor. Por ejemplo, el servicio de mensajería asíncrona se implementó por separado y se creó un módulo para adaptarlo a este servidor de aplicaciones. Idem con el pool de conexiones a la base de datos. La interfaz:</p>
<pre class="brush: java">public interface Module {
    void setName(String name);
    String getName();

    void startup() throws Exception;
    void shutdown();
}</pre>
<p style="margin-bottom: 0in; font-weight: normal;">Para obtener un módulo desde un servicio, se lo pedimos al ServerContext:</p>
<p style="margin-bottom: 0in; font-weight: normal;" align="CENTER"><span style="font-family: Liberation Mono,monospace;"><span style="font-size: x-small;">ServerContext.getModule(moduleName);</span></span></p>
<p style="margin-bottom: 0in; font-weight: normal;">La clase ServerContext nuclea un conjunto de métodos estáticos que dan acceso a diferentes partes del servidor de aplicaciones. Los que más se desatacan son getModule() y getServerConfig(). El primero ya lo vimos. El segundo devuelve un Mapa con propiedades que se cargan de un archivo de configuración. Ya veremos la configuración en una sección dedicada a esta.</p>
<p style="margin-bottom: 0in; font-weight: normal;">Services Loader</p>
<p style="margin-bottom: 0in; font-weight: normal;">Este es el componente encargado de leer de un archivo de configuración y crear los servicios en el RPC. Está implementado como módulo así se puede reemplazar fácilmente por otro y se acopla al servidor. Básicamente lee de un archivo de configuración la descripción de los servicios con sus parámetros y los agrega al servidor.</p>
<p style="margin-bottom: 0in; font-weight: normal;">En el siguiente artículo voy a describir el pool de conexiones a la base de datos y el servicio de mensajería. También voy a describir los archivos de configuración.</p>
<p style="margin-bottom: 0in; font-weight: normal;">Hasta el próximo.</p>
<p style="margin-bottom: 0in; font-weight: normal;">
]]></content:encoded>
			<wfw:commentRss>http://blog.aquait.info/2009/09/112/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java RPC-07: Extras y rendimiento</title>
		<link>http://blog.aquait.info/2009/09/java-rpc-07-extras-y-rendimiento/</link>
		<comments>http://blog.aquait.info/2009/09/java-rpc-07-extras-y-rendimiento/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 01:07:39 +0000</pubDate>
		<dc:creator>Enrique</dc:creator>
				<category><![CDATA[RPC]]></category>
		<category><![CDATA[AppServer]]></category>
		<category><![CDATA[Lab]]></category>

		<guid isPermaLink="false">http://blog.aquait.info/?p=104</guid>
		<description><![CDATA[
En este es último artículo de la serie RPC voy explorar algunas extras que tiene el servidor que nos van a servir para implementar un servidor de aplicaciones, pero sin perder generalidad. También vamos ha realizar un test de rendimiento, viendo el througput (pedidos por segundo) que tiene el servidor.

Extras
Los servicios en el lado del [...]]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } --></p>
<p style="margin-bottom: 0in;">En este es último artículo de la serie RPC voy explorar algunas extras que tiene el servidor que nos van a servir para implementar un servidor de aplicaciones, pero sin perder generalidad. También vamos ha realizar un test de rendimiento, viendo el througput (pedidos por segundo) que tiene el servidor.</p>
<p style="margin-bottom: 0in;"><span id="more-104"></span></p>
<p style="margin-bottom: 0in;">Extras</p>
<p style="margin-bottom: 0in;">Los servicios en el lado del servidor toman parámetros de inicialización. Esto nos va a permitir pasar datos al servicio para configurarlos. Estos parámetros se acceden mediante el método getParameters() de la clase Service, que devuelve un Mapa con la configuración.</p>
<p style="margin-bottom: 0in;">Validación de servicios</p>
<p style="margin-bottom: 0in;">Antes de agregar un servicio al servidor, se realizan los siguientes chequeos:</p>
<ul>
<li>
<p style="margin-bottom: 0in;">Que la 	implementación del servicio tiene que tener un constructor sin 	parámetros</p>
</li>
<li>
<p style="margin-bottom: 0in;">Que la implementación del 	servicio debe implementar la interfaz del servicio</p>
</li>
<li>
<p style="margin-bottom: 0in;">Qué no haya sobrecarga de métodos 	en el servicio</p>
</li>
<li>
<p style="margin-bottom: 0in;">Que el tipo de retorno como los 	parámetros de los métodos sean serializables</p>
</li>
</ul>
<p style="margin-bottom: 0in;">Estos chequeos ayudan a evitar errores comunes.</p>
<p style="margin-bottom: 0in;">Autorización de ejecución</p>
<p style="margin-bottom: 0in;">Antes de efectivamente ejecutar un método de un servicio, se invoca a un interceptor: onPreExecution. Si se ejecuta correctamente, entonces se pasa a invocar al servicio, si no se sale por excepción NotExecutedException. Esto nos va a servir para implementar, por ejemplo, mecanismos de seguridad y auditoría (logging).</p>
<p style="margin-bottom: 0in;">Rendimiento</p>
<p style="margin-bottom: 0in;">Con el test de rendimiento vamos comprobar ver si el diseño que hicimos es escalable como queríamos. El test se realizó en un notebook que tiene un CPU Intel modelo T9500 (C2D 2.6GHz, 6MB de cache core Penryn) con 2GB de RAM sobre Ubuntu 9.04 32 bits y con Java6. Los resultados fueron:</p>
<dl>
<dl>
<dd>
<table border="1" cellspacing="0" cellpadding="4" width="100%" bordercolor="#000000">
<col width="37"></col>
<col width="37"></col>
<tbody>
<tr valign="top">
<td width="9%" bgcolor="#000000"><span style="color: #ffffff;">Caso</span></td>
<td width="15%" bgcolor="#000000"><span style="color: #ffffff;">Procesos cliente</span></td>
<td width="16%" bgcolor="#000000"><span style="color: #ffffff;">Hilos por cliente</span></td>
<td width="14%" bgcolor="#000000"><span style="color: #ffffff;">Pedidos por hilo</span></td>
<td width="17%" bgcolor="#000000"><span style="color: #ffffff;">Total pedidos</span></td>
<td width="15%" bgcolor="#000000"><span style="color: #ffffff;">Tiempo (segs)</span></td>
<td width="15%" bgcolor="#000000"><span style="color: #ffffff;">Pedidos/ segundo</span></td>
</tr>
<tr valign="top">
<td width="9%">
<p align="right">1</p>
</td>
<td width="15%">
<p align="right">5</p>
</td>
<td width="16%">
<p align="right">30</p>
</td>
<td width="14%">
<p align="right">2500</p>
</td>
<td width="17%">
<p align="right">375000</p>
</td>
<td width="15%">
<p align="right">207</p>
</td>
<td width="15%">
<p align="right">1811,59</p>
</td>
</tr>
<tr valign="top">
<td width="9%">
<p align="right">2</p>
</td>
<td width="15%">
<p align="right">10</p>
</td>
<td width="16%">
<p align="right">30</p>
</td>
<td width="14%">
<p align="right">2500</p>
</td>
<td width="17%">
<p align="right">750000</p>
</td>
<td width="15%">
<p align="right">229</p>
</td>
<td width="15%">
<p align="right">3275,11</p>
</td>
</tr>
</tbody>
</table>
</dd>
</dl>
</dl>
<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } --></p>
<p style="margin-bottom: 0in;">Si bien no es un test de stress muy riguroso, nos da una buena aproximación de la performance y escalabilidad del servicio: aumentando al doble la cantidad de pedidos, solamente sube el tiempo en 10,6%. También, hay un valor que se puede ajustar en la creación del servidor que es el tamaño del pool de workers de la capa Pedido que despachan pedidos a la capa Servicio. Por defecto es de tamaño 10, pero si se está ante una configuración multi CPU se puede subir este valor para obtener mejor rendimiento. En el caso del test de rendimiento se utilizó un pool de 10 workers.</p>
<p style="margin-bottom: 0in;">Un servidor de aplicaciones basado en un versión más vieja de este mecanismo de RPC está implantado hace ya varios años en uno de los bancos más importantes de Uruguay.</p>
<p style="margin-bottom: 0in;">En el próximo artículo vamos a comenzar con la introducción al servidor de aplicaciones y cuales son los componentes principales.</p>
<p style="margin-bottom: 0in;">Stay tuned!</p>
<p style="margin-bottom: 0in;">
]]></content:encoded>
			<wfw:commentRss>http://blog.aquait.info/2009/09/java-rpc-07-extras-y-rendimiento/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GWT Introspection</title>
		<link>http://blog.aquait.info/2009/09/introspeccion-en-gwt/</link>
		<comments>http://blog.aquait.info/2009/09/introspeccion-en-gwt/#comments</comments>
		<pubDate>Wed, 02 Sep 2009 18:23:27 +0000</pubDate>
		<dc:creator>Enrique</dc:creator>
				<category><![CDATA[GWT]]></category>
		<category><![CDATA[Lab]]></category>

		<guid isPermaLink="false">http://blog.aquait.info/?p=89</guid>
		<description><![CDATA[
Intro
Una de las características que más se extrañan a la hora de utilizar GWT es la capacidad de Java de realizar introspección sobre beans. La causa de esta limitación es que GWT no tiene emulación la API reflexión (java.lang.reflect). En este artículo vamos a ver como podemos implementar una suerte de introspección en GWT. También [...]]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } 		A:link { so-language: zxx } --></p>
<p style="margin-bottom: 0in;">Intro</p>
<p style="margin-bottom: 0in;">Una de las características que más se extrañan a la hora de utilizar GWT es la capacidad de Java de realizar introspección sobre beans. La causa de esta limitación es que GWT no tiene emulación la API reflexión (java.lang.reflect). En este artículo vamos a ver como podemos implementar una suerte de introspección en GWT. También vamos a explorar algunas aplicaciones de introspección, ya que en principio no es trivial su utilidad.</p>
<p style="margin-bottom: 0in;"><span id="more-89"></span></p>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">What for?</p>
<p style="margin-bottom: 0in;">Lo primero que vamos a ver es para qué queremos esto.</p>
<p style="margin-bottom: 0in;">Supongamos que queremos desarrollar un framework de componentes visuales que tenga data binding (capacidad de “enganchar” la propiedad de un objeto a un componente visual). Seguramente a todo aquel que le tocó la “maravillosa” tarea de implementar un CURD (ABM en criollo) se topó con la tediosa tarea de setear y leer de los componentes visuales al objeto y viceversa. Si te tocó hacer esto, algo malo hiciste <img src='http://blog.aquait.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Bueno, esta es una tarea tan aburrida como propensa a errores, sobre todo de Control-C + Control-V. Si pudieramos decir algo como: “este componente UI mira la propiedades tal de cual objeto”, entonces podemos aliviar bastante esta tarea ya que por ejemplo nos ahorramos todo el código de manejo de eventos.</p>
<p style="margin-bottom: 0in;">Entonces si podemos hacer esto, podemos construir un conjunto de componentes a los cuales simplemente le seteamos el bean y la propiedad que “mira” así cuando al componente se le cambia el valor, automáticamente se refleja en el bean y viceversa.</p>
<p style="margin-bottom: 0in;">Pero ¿cómo hacer esto sin introspeccion?</p>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">How? What?!</p>
<p style="margin-bottom: 0in;">Como vimos, en GWT (al menos hasta la 1.7) no hay reflexión, por lo que no nos queda más remedio que buscar otra forma de implementar introspección. Primero vamos a ver qué es la introspección en Java. Según el JavaDoc de la clase java.beans.Introspector:</p>
<p style="margin-left: 0.49in; margin-bottom: 0in;">“The Introspector class provides a standard way for tools to learn about the properties, events, and methods supported by a target Java Bean.”</p>
<p style="margin-bottom: 0in;">En español:</p>
<p style="margin-left: 0.49in; margin-bottom: 0in;">“La clase Introspector  provee una forma estándar para que herramientas descubran propiedades, eventos y métodos soportados por un Java Bean”.</p>
<p style="margin-bottom: 0in;">La parte que más nos interesa es la parte de las propiedades. O sea, queremos poder implementar un mecanismo con el cual se le pueda preguntar a un Java Bean cuales son sus propiedades y cuales son los valores de estas.</p>
<p style="margin-bottom: 0in;">La forma que vamos a implementar es creando una clase que sea la introspección para cada clase que queramos tener introspección.</p>
<p style="margin-bottom: 0in;">Entonces para la clase:</p>
<pre class="brush: java">public class Persona {
    private String nombre;
    private String direccion;
    private Date nacimiento;
    private boolean sexo;

    public Persona() {
    }

    public String getNombre() {
        return nombre;
    }
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    // ...más getters y setters...
}</pre>
<p style="margin-bottom: 0in;">Tenemos que implementar la clase de “introspección”:</p>
<pre class="brush: java">public PersonaIntrospection {
    private Persona persona;

    public PersonaIntrospeccion() {
    }

    public Persona getPersona() {
        return persona;
    }

    public Persona setPersona(Persona p) {
        persona = p;
    }

    public List&lt;String&gt; getProperties() {
        List&lt;String&gt; l = new ArrayList&lt;String&gt;();
        l.add(“nombre”);
        l.add(“direccion”);
        l.add(“nacimiento”);
        l.add(“sexo”);
    }

    public Object getProperty(String property) {
        if (“nombre”.equals(property))
            return persona.getNombre();
        else if (“direccion”.equals(property))
            return persona.getDireccion();
        else if (“nacimiento”.equals(property))
            return persona.getNacimiento();
        else if (“sexo”.equals(property))
            return persona.getSexo();
        else
            throw new IllegalArgumentException(property);
    }

    public void setProperty(String property, Object value) {
        if (“nombre”.equals(property))
            persona.setNombre((String)value);
        else if (“direccion”.equals(property))
            persona.setDireccion((String)value);
        else if (“nacimiento”.equals(property))
            persona.setNacimiento((Date)value);
        else if (“sexo”.equals(property))
            persona.setSexo((Boolean)value);
        else
            throw new IllegalArgumentException(property);
    }
}</pre>
<p style="margin-bottom: 0in;">Más allá de las optimizaciones que se le pueden hacer al código (como cachear la lista de propiedades), la idea es que se entienda de por qué esta clase nos da introspección sobre un objeto persona. Como ya se deben estar imaginando, la gracia es no tener que escribir la clase PersonaIntrospection. La gracia es trabajar menos en cosas aburridas y más en cosas “divertidas“ <img src='http://blog.aquait.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">Enter generators!</p>
<p style="margin-bottom: 0in;">Lo que vamos a hacer es que GWT genere la clase PersonaIntrospection. ¿Cómo? Usando generators. Esta es una característica bien interesante de GWT. El foco de este artículo no está en explicar generators, hay mucha literatura en Internet. Acá va un link <a href="http://code.google.com/intl/es/webtoolkit/doc/1.6/DevGuideCodingBasics.html#DevGuideDeferredBinding">http://code.google.com/intl/es/webtoolkit/doc/1.6/DevGuideCodingBasics.html#DevGuideDeferredBinding</a>. Igual no hay que ser un experto para entender lo que vamos a hacer.</p>
<p style="margin-bottom: 0in;">Básicamente vamos a escribir una clase que genere el código de XxxIntrospection para la clase Xxx según vimos en el ejemplo de Persona. Y (para no tener que realizar ningún paso previo a la compilación generando la clase con alguna utilidad externa) vamos a usar la API que tiene GWT que permite extender el compilador (com.google.gwt.core.ext). NOTA: Los que hayan utilizado APT de Java van ver unas cuantas similitudes (<a href="http://java.sun.com/javase/6/docs/technotes/guides/apt/index.html">http://java.sun.com/javase/6/docs/technotes/guides/apt/index.html</a>).</p>
<p style="margin-bottom: 0in;">Cuando el compilador de GWT encuentra con la instrucción GWT.create(class) –que devuelve una implementación de la interfaz class– invoca al generador asociado a la interfaz class (esta asociación se declara en el gwt.xml del módulo). En este generador se “escribe” el código que implementa la interfaz class. Para escribir este código tenemos la asistencia de la API com.google.gwt.core.ext.typeinfo que recuerda mucho a la API Mirror Reflection de Java.</p>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">Generate</p>
<p style="margin-bottom: 0in;">Ahora vamos a ver el generador en si. Pero primero vamos a ver como se utiliza. GWT.create() toma una interfaz y devuelve una implementación de la misma. Entonces vamos definir una interfaz de marca y la vamos a llamar Introspectable. Toda clase que queramos tener soporte de introspección va a tener que implementar esta intefaz:</p>
<pre class="brush: java">public interface Introspectable {
}</pre>
<p style="margin-bottom: 0in;">Entonces la clase Persona:</p>
<pre class="brush: java">public class Persona implements Introspectable {
    // ... atributos y métodos ...
}</pre>
<p style="margin-bottom: 0in;">Además, tenemos que tener la interfaz de idioma de la introspección:</p>
<pre class="brush: java">public interface Introspection&lt;I extends Introspectable&gt; {
    I getIntrospectable();
    void setIntrospectable(I i);
    &lt;T&gt; T getProperty(String propName);
    void setProperty(String propName, Object value);
    Collection&lt;String&gt; getPropertyNames();
}</pre>
<p style="margin-bottom: 0in;">Y para obtener una introspección y usarla:</p>
<pre class="brush: java">Persona persona = new Persona();
Introspection&lt;Persona&gt; instrospection = GWT.create(Persona.class);
instrospection.setIntrospectable(persona);

for (String prop : instrospection.getPropertyNames()) {
    System.out.println(prop + " = " + instrospection.getProperty(prop));
}

String nombre = instrospection.getProperty("nombre");
String direccion = instrospection.getProperty("direccion");
Date nacimiento = instrospection.getProperty("nacimiento");
Boolean sexo = instrospection.getProperty("sexo");</pre>
<p style="margin-bottom: 0in;">Para asociar el generador con la interfaz Introspectable, agregamos el siguiente fragmento al :</p>
<pre class="brush: xml">&lt;generate-with class="com.aquait.utils.gwt.rebind.IntrospectionGenerator"&gt;
    &lt;when-type-assignable class="com.aquait.utils.gwt.introspection.Introspectable"/&gt;
&lt;/generate-with&gt;</pre>
<p style="margin-bottom: 0in;">Así, cuando el compilador de GWT encuentra GWT.create(Persona.class), llama al generador pues la clase Persona implementa Introspectable. Luego, tenemos una implementación de la interfaz Introspection para la clase Persona.</p>
<p style="margin-bottom: 0in;">Para usarlo en un proyecto, hay que agregar esto en el &lt;modulo&gt;.gwt.xml:</p>
<pre class="brush: xml">&lt;inherits name="com.aquait.utils.gwt.Introspection"/&gt;</pre>
<p style="margin-bottom: 0in;">El módulo GWT se puede descargar de acá: <a href="http://blog.aquait.info/wp-content/uploads/2009/09/introspection4gwt.jar">introspection4gwt</a></p>
<p style="margin-bottom: 0in;">EDIT: se actualizó el archivo debido a un pequeño bug.</p>
<p style="margin-bottom: 0in;">EDIT: se volvió a actualizar debido a un bug que hacía que no se tomaran en cuenta las propiedades de las super clases.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aquait.info/2009/09/introspeccion-en-gwt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
