<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-8644784663970787482</atom:id><lastBuildDate>Fri, 01 Nov 2024 10:34:23 +0000</lastBuildDate><category>Patrones de Diseño</category><category>JADE</category><category>JEE</category><category>WEB</category><category>Agentes Inteligentes</category><category>FIPA</category><category>SCWCD</category><category>SPRING</category><category>ANDROID</category><category>BLAZEDS</category><category>Extension Objects</category><category>FLEX</category><category>INYECCION DE SQL</category><category>Inversion de Control</category><category>JQuery</category><category>JavaScript</category><category>Prototype</category><category>SEGURIDAD</category><category>SMA</category><category>SPRING BATCH</category><category>Tomcat</category><category>WADE</category><title>Duke Chile</title><description>Blog dedicado a las cosas entretenidas del mundo java!!</description><link>http://dukechile.blogspot.com/</link><managingEditor>noreply@blogger.com (José Luis Coronel Cortés)</managingEditor><generator>Blogger</generator><openSearch:totalResults>27</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-2244139008757665938</guid><pubDate>Sun, 24 Aug 2008 23:47:00 +0000</pubDate><atom:updated>2008-08-24T20:24:30.602-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">JavaScript</category><category domain="http://www.blogger.com/atom/ns#">JQuery</category><category domain="http://www.blogger.com/atom/ns#">WEB</category><title>JQuery</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;Cada vez que pienso en desarrollar una aplicación &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;RIA &lt;/span&gt;lo primero que se me viene a la mente  es &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Flex&lt;/span&gt;. Pero siempre existen los casos en los cuales el cliente no desea que su aplicación dependa de si sus usuarios tengan o no instalado alguna versión determinada del &quot;&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Flash Player&lt;/span&gt;&quot; en sus navegadores. Para estos casos, mi segunda opción es &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;ZK&lt;/span&gt;, pero nuevamente existe el problema de que a algunos cliente nos les gusta aventurarse en frameworks no muy conocidos (no muy conocidos por el) y prefieren más bien que sus sistema sea desarrollado utilizando algún otro framework o estándar mas conocido por la industria.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Es en estos escenarios donde recurro a mi querido (y también odiado) &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JSF&lt;/span&gt;. Hace ya bastante tiempo que no volvía a meter las manos con &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JSF&lt;/span&gt;, pero gracias a dios, hoy en día todo es mucho más fácil, si es que utilizamos “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Facelets&lt;/span&gt;” y todo el poder que nos entrega “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Spring Faces&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Hasta el momento todo está bien, pero en este último caso, me vuelvo a encontrar con el mismo problema de siempre. El cliente quiere un sistema de ensueños!!!. Que todo sea “Drag-and-Drop”, full Ajax, mucho efecto visual, etc…..&lt;br /&gt;&lt;br /&gt;Claro, si hablamos de &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JSF&lt;/span&gt;, podría utilizar &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;RichFaces&lt;/span&gt;, &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;IceFaces&lt;/span&gt;, &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;MyFaces &lt;/span&gt;o alguna otra batería de componentes. Pero que pasa en los casos en que necesito alguna funcionalidad especial que no esté implementada dentro de este conjunto de componentes?.&lt;br /&gt;&lt;br /&gt;Buscando una opción, recordé haber leído que hoy en día, muchos consideran a &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery &lt;/span&gt;como una de las mejores librerías &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Javascript &lt;/span&gt;del momento. Así que decidí ver que tanta maravilla es esta tan bullada librería, y aunque no me considero un fanático de &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Javascritp &lt;/span&gt;(muy por el contrario), la única palabra que se me ocurre para expresar el sentimiento que me produjo es GUUUUAAAAAUUUUUUU!!!!!!!.&lt;br /&gt;&lt;br /&gt;Mi objetivo es compartir algunos conceptos básicos que he podido desarrollar gracias al libro “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Learning Jquery - Better Interaction Design And Web Development With Simple Javascript Techniques&lt;/span&gt;”.&lt;br /&gt;&lt;br /&gt;Si alguien está interesado en aprender &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Javascript&lt;/span&gt;, le recomiendo el libro gratuito de Javier Eguíluz Pérez que pueden descargar desde &lt;a href=&quot;http://www.librosweb.es/&quot;&gt;aquí&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery &lt;/span&gt;es una librería &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JavaScript &lt;/span&gt;rápida y concisa, que simplifica la tediosa tarea de recorrer documentos &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;HTML &lt;/span&gt;(&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;DOM&lt;/span&gt;), manejar eventos, ejecutar animaciones y agregar interacciones con Ajax.&lt;br /&gt;&lt;br /&gt;Para utilizar &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery&lt;/span&gt;, solo necesitamos descargar la librería y en cada página que necesitemos utilizarla, simplemente definir:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;html&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;script type=&quot;text/javascript&quot; src=&quot;jquery.js&quot;&gt;&lt;/script&gt; &lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Una de las principales ventajas, además de ahorrarnos la escritura de bastante código (principalmente útil para los que no somos muy expertos en &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Javascript&lt;/span&gt;), es que nos permite manipular la página apenas se haya construido el árbol &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;DOM &lt;/span&gt;de esta,  en comparación con las funciones de Javascript, las cuales esperan a que se carguen todos los elementos de la página (incluyendo todas las imágenes).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Algunas de las principales ventajas que nos aporta esta librería son:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Nos ahorra muchas líneas de código.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Nos hace transparente el soporte de nuestra aplicación para los principales navegadores web.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Nos provee de un mecanismo para la captura de eventos.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Provee un conjunto de funciones para animar el contenido de la página en forma muy sencilla.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Integra funcionalidades para trabajar con &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;AJAX&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El primer paso será descargarnos la última versión de &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery &lt;/span&gt;desde &lt;a href=&quot;http://jquery.com/&quot;&gt;aquí&lt;/a&gt; y dejarla dentro de nuestro proyecto.&lt;br /&gt;&lt;br /&gt;Para los siguientes ejemplos he renombrado el archivo a “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;jquery.js&lt;/span&gt;” y lo he dejado guardado dentro de la carpeta “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;js&lt;/span&gt;” de mi aplicación web.&lt;br /&gt;&lt;br /&gt;Para entender mejor como nos puede ayudar &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery &lt;/span&gt;a ahorrar muchas líneas de código, nada mejor que un ejemplo comparativo “&lt;span style=&quot;font-style: italic;&quot;&gt;Sin JQuery&lt;/span&gt;” y “&lt;span style=&quot;font-style: italic;&quot;&gt;Con Jquery&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;html&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;&lt;br /&gt;&lt;html&gt;&lt;br /&gt;&lt;head&gt;&lt;br /&gt;	&lt;title&gt;JQuery - DukeChile&lt;/title&gt;&lt;br /&gt;	&lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;    &lt;script type=&quot;text/javascript&quot; src=&quot;js/ejemploBasico.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;	&lt;script type=&quot;text/javascript&quot; src=&quot;js/ejemploBasicoJQuery.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;&lt;/head&gt;&lt;br /&gt;&lt;body&gt;&lt;br /&gt;	&lt;h2&gt;Captura del evento de presionar un boton&lt;/h2&gt;&lt;br /&gt;	&lt;input type=&quot;button&quot; id=&quot;boton1&quot; value=&quot;Forma Tradicional&quot;&gt;&lt;br /&gt;&lt;br /&gt;	&lt;input type=&quot;button&quot; id=&quot;boton2&quot; value=&quot;JQuery&quot;&gt;&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;/html&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;javascript&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;addEvent(window,&#39;load&#39;,inicializarEventos,false);&lt;br /&gt;&lt;br /&gt;function inicializarEventos(){&lt;br /&gt;	var boton1 = document.getElementById(&#39;boton1&#39;);&lt;br /&gt;	addEvent(boton1, &#39;click&#39;, sePresionoElBoton, false);&lt;br /&gt;}	&lt;br /&gt;&lt;br /&gt;function addEvent(elemento,nombreevento,funcion,captura){&lt;br /&gt;	if (elemento.attachEvent){&lt;br /&gt;		elemento.attachEvent(&#39;on&#39;+nombreevento,funcion);&lt;br /&gt;		return true;&lt;br /&gt;	}&lt;br /&gt;	else if (elemento.addEventListener){&lt;br /&gt;		elemento.addEventListener(nombreevento,funcion,captura);&lt;br /&gt;		return true;&lt;br /&gt;	}&lt;br /&gt;	else&lt;br /&gt;		return false;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function sePresionoElBoton(e){&lt;br /&gt;  alert(&#39;Boton presionado forma tradicional&#39;);&lt;br /&gt;}&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;javascript&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;var x;&lt;br /&gt;x=$(document);&lt;br /&gt;x.ready(inicializarEventos);&lt;br /&gt;&lt;br /&gt;function inicializarEventos(){&lt;br /&gt;	var x;&lt;br /&gt;	x=$(&quot;#boton2&quot;);&lt;br /&gt;	x.click(sePresionoElBoton)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function sePresionoElBoton(){&lt;br /&gt;	alert(&quot;Boton presionado JQuery&quot;);&lt;br /&gt;}&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Ya a simple vista podemos ver que a diferencia de la forma tradicional, con &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery &lt;/span&gt;nos basto simplemente un par d líneas de código para lograr la misma funcionalidad. Pero, como trabaja &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery&lt;/span&gt;?.&lt;br /&gt;&lt;br /&gt;La función principal de esta librería se llama “&lt;span style=&quot;font-weight: bold;&quot;&gt;$&lt;/span&gt;”, a la cual le podemos pasar distintos valores, y la que a su vez retorna un objeto del tipo &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery &lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Si vemos el código del archivo “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;ejemploBasicoJQuery.js&lt;/span&gt;”, podremos observa que el primer método que estamos llamando es a “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;ready&lt;/span&gt;”:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;javascript&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;var x;&lt;br /&gt;x=$(document);&lt;br /&gt;x.ready(inicializarEventos);&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Este método recibe como parámetro el nombre de una función, la que se ejecutara cuando todos los elementos de la página estén cargados.&lt;br /&gt;&lt;br /&gt;Dentro de la función “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;inicializarEventos&lt;/span&gt;”, nuevamente utilizamos la función “&lt;span style=&quot;font-weight: bold;&quot;&gt;$&lt;/span&gt;” para crea un objeto de la clase &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery &lt;/span&gt;asociada a un botón de la pagina &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;HTML&lt;/span&gt;. Para lograr esto, a la función “&lt;span style=&quot;font-weight: bold;&quot;&gt;$&lt;/span&gt;” le pasamos el “&lt;span style=&quot;font-weight: bold;&quot;&gt;id&lt;/span&gt;” del botón al cual la queremos asociar precediéndolo por el caracter &quot;&lt;span style=&quot;font-weight: bold;&quot;&gt;#&lt;/span&gt;&quot;.&lt;br /&gt;&lt;br /&gt;Por último, llamamos al método click, pasándole como parámetro el nombre de la función que se ejecutará al presionar ese botón.&lt;br /&gt;&lt;br /&gt;En el caso de que queramos asociar algún elemento de una página &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;HTML &lt;/span&gt;a la función “&lt;span style=&quot;font-weight: bold;&quot;&gt;$&lt;/span&gt;”, simplemente seguimos la sintaxis:&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;$(“nombre_elemento_HTML”)&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El único problema con este tipo de función, es que estaremos referenciando a los de este tipo contenidos en nuestra página &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;HTML&lt;/span&gt;. Entonces, como podemos discriminar sobre que elemento de la pagina se efectuó alguna acción?. Simplemente llamando a la función &quot;&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;$(this)&lt;/span&gt;&quot;.&lt;br /&gt;&lt;br /&gt;Otra característica muy importante de &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery&lt;/span&gt;, es que nos permite tener acceso a los selectores &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;CSS &lt;/span&gt;de los elementos contenidos dentro del árbol &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;DOM&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Veamos un ejemplo que muestre todos los tópicos mencionados hasta el momento:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;html&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;&lt;br /&gt;&lt;html&gt;&lt;br /&gt;&lt;head&gt;&lt;br /&gt;	&lt;title&gt;JQuery - DukeChile&lt;/title&gt;&lt;br /&gt;	&lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;	&lt;script type=&quot;text/javascript&quot; src=&quot;js/ocultaFilaTabla.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;&lt;/head&gt;&lt;br /&gt;&lt;body&gt;&lt;br /&gt;	&lt;table border=&quot;1&quot; id=&quot;tabla&quot;&gt;&lt;br /&gt;		&lt;tr&gt;&lt;br /&gt;			&lt;td&gt;A-1&lt;/td&gt;&lt;td&gt;B-1&lt;/td&gt;&lt;td&gt;C-1&lt;/td&gt;&lt;br /&gt;		&lt;/tr&gt;&lt;br /&gt;		&lt;tr&gt;&lt;br /&gt;			&lt;td&gt;A-2&lt;/td&gt;&lt;td&gt;B-2&lt;/td&gt;&lt;td&gt;C-2&lt;/td&gt;&lt;br /&gt;		&lt;/tr&gt;&lt;br /&gt;		&lt;tr&gt;&lt;br /&gt;			&lt;td&gt;A-3&lt;/td&gt;&lt;td&gt;B-3&lt;/td&gt;&lt;td&gt;C-3&lt;/td&gt;&lt;br /&gt;		&lt;/tr&gt;&lt;br /&gt;	&lt;/table&gt;	&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;/html&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;javascript&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;var x;&lt;br /&gt;x=$(document);&lt;br /&gt;x.ready(inicializarEventos);&lt;br /&gt;&lt;br /&gt;function inicializarEventos(){&lt;br /&gt;	var x;&lt;br /&gt;	x=$(&quot;tr&quot;);&lt;br /&gt;	x.click(ocultarFilaTabla);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function ocultarFilaTabla(){&lt;br /&gt;	var x;&lt;br /&gt;	x=$(this);&lt;br /&gt;	x.hide();&lt;br /&gt;}&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Además de tener acceso a los selectores &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;CSS&lt;/span&gt;, también podemos tener acceso a las clases  que tengamos definidas dentro de nuestra página &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;CSSHTML &lt;/span&gt;simplemente llamando a la función:&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;$(“.nombre_clase_css”)&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Si queremos obtener el texto de un elemento, simplemente llamamos al método &quot;&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;text()&lt;/span&gt;&quot;. Por ejemplo, si tenemos el párrafo:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;html&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;p&gt;Este es un ejemplo de un párrafo&lt;/p&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Para obtener el texto llamaremos a la función &quot;&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;text()&lt;/span&gt;&quot; del elemento “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;p&lt;/span&gt;”:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;javascript&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;var x=$(&quot;p&quot;);&lt;br /&gt;x.text();&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;En cambio, si queremos modificar el texto contenido dentro del elemento, llamaremos nuevamente al método &quot;&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;text()&lt;/span&gt;&quot;, pasándole como parámetro el nuevo texto:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;javascript&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;x.text(&quot;Texto del nuevo parrafo&quot;);&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Otros métodos importantes dentro de &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery&lt;/span&gt;, son aquellos que nos permiten manipular los atributos de los elementos de nuestra página &lt;span style=&quot;font-weight: bold;&quot;&gt;HTML&lt;/span&gt;. Estos son:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;attr&lt;/span&gt;(nombre_atributo)&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;attr&lt;/span&gt;(nombre_ atributo, valor)&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;removeAttr&lt;/span&gt;(nombre_ atributo)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Por ejemplo:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;html&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;&lt;br /&gt;&lt;html&gt;&lt;br /&gt;&lt;head&gt;&lt;br /&gt;	&lt;title&gt;JQuery - DukeChile&lt;/title&gt;&lt;br /&gt;	&lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;	&lt;script type=&quot;text/javascript&quot; src=&quot;js/modificarAtributo.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;&lt;/head&gt;&lt;br /&gt;&lt;body&gt;&lt;br /&gt;	&lt;input type=&quot;button&quot; id=&quot;boton1&quot; value=&quot;Agregar borde&quot;&gt;&lt;br /&gt;	&lt;input type=&quot;button&quot; id=&quot;boton2&quot; value=&quot;Eliminar borde&quot;&gt;&lt;br /&gt;	&lt;table id=&quot;tabla&quot;&gt;&lt;br /&gt;		&lt;tr&gt;&lt;br /&gt;			&lt;td&gt;A-1&lt;/td&gt;&lt;td&gt;B-1&lt;/td&gt;&lt;td&gt;C-1&lt;/td&gt;&lt;br /&gt;		&lt;/tr&gt;&lt;br /&gt;		&lt;tr&gt;&lt;br /&gt;			&lt;td&gt;A-2&lt;/td&gt;&lt;td&gt;B-2&lt;/td&gt;&lt;td&gt;C-2&lt;/td&gt;&lt;br /&gt;		&lt;/tr&gt;&lt;br /&gt;		&lt;tr&gt;&lt;br /&gt;			&lt;td&gt;A-3&lt;/td&gt;&lt;td&gt;B-3&lt;/td&gt;&lt;td&gt;C-3&lt;/td&gt;&lt;br /&gt;		&lt;/tr&gt;&lt;br /&gt;	&lt;/table&gt;&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;/html&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;javascript&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;var x;&lt;br /&gt;x=$(document);&lt;br /&gt;x.ready(inicializarEventos);&lt;br /&gt;&lt;br /&gt;function inicializarEventos()&lt;br /&gt;{&lt;br /&gt;  var x=$(&quot;#boton1&quot;);&lt;br /&gt;  x.click(agregarBorde);&lt;br /&gt;  x=$(&quot;#boton2&quot;);&lt;br /&gt;  x.click(eliminarBorde);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function agregarBorde()&lt;br /&gt;{&lt;br /&gt;  var x=$(&quot;#tabla&quot;);&lt;br /&gt;  x.attr(&quot;border&quot;,&quot;1&quot;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function eliminarBorde()&lt;br /&gt;{&lt;br /&gt;  var x=$(&quot;#tabla&quot;);&lt;br /&gt;  x.removeAttr(&quot;border&quot;);&lt;br /&gt;}&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Eventos&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Algunos de los eventos más importantes dentro de &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery &lt;/span&gt;son:&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;mouseover/mouseout&lt;/span&gt;: Estos eventos son equivalentes a los eventos onmouseover y onmouseout de &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Javascript&lt;/span&gt;. El primero de estos se ejecuta cuando ponemos la flecha del mouse sobre un elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;HTML &lt;/span&gt;y el segundo cuando sacamos la flecha del elemento.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;hover&lt;/span&gt;: Como los eventos mouseover y mouseout son comúnmente usados, existe el evento hover que recibe dos parámetros:&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;$(elemento).hover([función de ingreso del mouse],[función de salida del mouse])&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;La primera función se ejecuta cuando ponemos la flecha del mouse sobre un elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;HTML &lt;/span&gt;y el segundo cuando sacamos la flecha del elemento.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;mousemove&lt;/span&gt;: Este evento se ejecuta cuando se mueve la flecha del mouse dentro del elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;HTML &lt;/span&gt;respectivo.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;mousedown/mouseup&lt;/span&gt;: El primer evento se ejecuta cuando presionamos alguno de los botones del mouse y el segundo cuando dejamos de presionar el botón.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;dblclick&lt;/span&gt;: Este evento se ejecuta cuando se presiona dos veces seguidas el botón izquierdo del mouse sobre un elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;HTML&lt;/span&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;focus&lt;/span&gt;: Este evento ejecuta cuando se activa el control. Podemos capturar el evento focus de un control de tipo text, textarea, button, checkbox, fileupload, password, radio, reset y submit.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;blur&lt;/span&gt;: Este evento se ejecuta cuando se pierde el foco el control. Podemos capturar el evento blur de un control de tipo text, textarea, button, checkbox,  fileupload, password, radio, reset y submit.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Efectos&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Otro concepto importante son los efectos, entre los que destacan:&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;show/hide&lt;/span&gt;: Permiten ocultar y mostrar elementos &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;HTML&lt;/span&gt;, asociándoles una pequeña animación (que se oculte o muestre lentamente).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;fadeIn/fadeOut&lt;/span&gt;: El primer efecto hace aparecer  los elementos &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;HTML &lt;/span&gt;con opacidad y el segundo lo decolora hasta hacerlo desaparecer (reduce la opacidad del elemento en forma progresiva).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;fadeTo&lt;/span&gt;: Permite modificar la opacidad de un elemento, llevando la opacidad actual hasta el valor que le pasamos como parámetro. Tambien se le puede la velocidad de la transición (en milisegundos).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;toggle&lt;/span&gt;: Permite cambiar de estado la visibilidad del elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;HTML&lt;/span&gt;; es decir si está visible pasa a oculto y si se encuentra oculto pasa a visible.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Si quieren ver todas las funcionalidades de &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery&lt;/span&gt;, les recomiendo visitar esta &lt;a href=&quot;http://www.visualjquery.com/1.1.2.html&quot;&gt;página&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Además, como toda buena librería, esta ya cuenta con un conjunto de plugins que extienden y facilitan aun más el uso de &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery&lt;/span&gt;. En esta &lt;a href=&quot;http://enhance.qd-creative.co.uk/index.php/2008/javascript/10-useful-jquery-plugins&quot;&gt;página&lt;/a&gt; encontraran un listado de los 10 plugins más populares, entre los que destaca &lt;a href=&quot;http://ui.jquery.com/&quot;&gt;JQuery UI&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Después de todo lo visto, creo que me quedare con “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;RichFaces&lt;/span&gt;” en el en mundo &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JSF&lt;/span&gt;, debido a que se integra fácilmente con &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JQuery&lt;/span&gt;.&lt;/div&gt;</description><link>http://dukechile.blogspot.com/2008/08/jquery.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-7637670003561935220</guid><pubDate>Sat, 23 Aug 2008 20:59:00 +0000</pubDate><atom:updated>2008-08-23T17:12:15.075-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">INYECCION DE SQL</category><category domain="http://www.blogger.com/atom/ns#">JEE</category><category domain="http://www.blogger.com/atom/ns#">SEGURIDAD</category><category domain="http://www.blogger.com/atom/ns#">WEB</category><title>Inyección de SQL (SQL Injection)</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;Uno de los temas a los cuales puede asistir en las “&lt;a style=&quot;font-weight: bold; font-style: italic;&quot; href=&quot;http://www.epidataconsulting.com/site/pages/jornadas&quot;&gt;Primeras Jornadas Latinoamericanas de Arquitectura de Software&lt;/a&gt;” fue “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Seguridad y Arquitectura de Software&lt;/span&gt;”, el cual fue presentado por &lt;a style=&quot;font-weight: bold; font-style: italic;&quot; href=&quot;http://www.jug.cl/display/%7Ejcherrera/Home&quot;&gt;Juan Carlos Herrera&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Dentro de los tópicos de la presentación, se menciono la &quot;&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Inyección de SQL&lt;/span&gt;&quot;, como uno de los problemas que comúnmente se presentan en la seguridad del desarrollo de software. Pero….. que es la inyección de SLQ?.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Se define la inyección de SQL, como el proceso de insertar código SQL dentro de otro código SQL, con el objetivo de alterar el funcionamiento normal de una sentencia SQL.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Este problema no se debe a que el lenguaje de programación que estemos utilizando presente este problema de seguridad, sino mas bien, gracias a nosotros, los desarrolladores, que en la mayoría de los casos, tenemos un escaso o nulo filtrado de los datos en el proceso de validación de estos dentro de nuestras aplicaciones, lo que permite a un atacante, insertar (o mejor dicho “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;inyectar&lt;/span&gt;”) código SQL dentro de las variables de nuestra aplicación, las que utilizamos para realizar consultas SQL.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Pero como sucede esto? Por qué sucede esto? Donde está el problema?&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Imaginemos que estamos desarrollando un software para una institución financiera (reconozco que no soy muy original para mis ejemplos), en donde la seguridad es vital. Como todo sistema bancario, este dispone de una base de datos donde almacena la información de sus clientes, sus cuentas, las transacciones bancarias, etc. Entonces, si  quisiéramos consultar la información de los tipos de cliente (persona o empresa), podríamos utilizar una sentencia SQL como esta:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;SELECT * FROM cliente WHERE tipoCliente=’tipoCliente’;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Donde la variable ‘&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;tipoCliente&lt;/span&gt;’ contiene el tipo de cliente que es para el banco (persona o empresa).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Con esta simple consulta podríamos obtener  todos los clientes de tipo “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;persona&lt;/span&gt;” que tenga el banco.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Imaginemos que además de consultar la información de un cliente por su tipo, queremos filtrar la información por comuna. Es decir, queremos ofrecerle al usuario la posibilidad de elegir, el tipo de cliente que quiere ver asociado a una determinada comuna.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Para esto, podríamos construir un servlet que procese esta información y cuyo resultado se despliegue en la página “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;consultaCliente.jsp&lt;/span&gt;”. Entonces, si el usuario realizaría una petición HTTP a nuestra JSP, pasándole  los valores de la consulta por GET:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;http://www.mibanco.cl/consultaCliente.jsp? tipoCliente =persona&amp;amp;comuna=macul&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El servlet que procese esta petición, tomara los parámetros enviados por el usuario y ejecutaría la siguiente consulta SQL sobre la base de datos:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;SELECT * FROM cliente WHERE tipoCliente=’persona’ AND comuna=&#39;macul&#39;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Una vez ejecutada la consulta, los resultados obtenidos serian desplegados en la página “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;consultaCliente.jsp&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Lo importante de todo esto, es que en algún punto de nuestro código, nosotros construimos la sentencia SQL en base a los valores enviados por el usuario. Es decir, si por algún motivo, al usuario se le ocurre enviarnos el valor “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;cualquiercosa&lt;/span&gt;” como comuna, nada se lo impedirá, y nuestra aplicación construirá la siguiente sentencia SQL:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;SELECT * FROM cliente WHERE tipoCliente=’persona’ AND comuna=&#39;cualquiercosa&#39;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;La pregunta es, donde está el problema en todo esto?......al parecer, no existe ningún problema, porque en el peor de los caso, esta consulta no devolverá nada, ya que la comuna “cualquiercosa” no existe. Pero…….¿qué pasaría ahora si en vez de ingresar un valor cualquiera, el usuario se le ocurriera ingresar como comuna parte de una sentencia SQL?.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Por ejemplo,  que sucedería en el caso de que el usuario enviara la siguiente consulta HTTP:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;http://www.mibanco.cl/consultaCliente.jsp? tipoCliente =persona&amp;amp;comuna= %20OR%20%22=&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Ahora nuestra aplicación construiría la siguiente consulta SQL:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;SELECT * FROM cliente WHERE tipoCliente=’persona’ AND comuna =’’ OR &#39;&#39;=’’;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Estos si es un problema!!!! Estamos permitiendo que el usuario pueda manipular la sentencia SQL. Nuestra sentencia estaría diciéndole a la base de datos que le entregue todos los clientes de tipo persona y cuya comuna sea igual a ‘ ” ‘ o la expresión ‘=’ sea verdadera.  Que en pocas palabras, le está diciendo a la base de datos que le entregue todos los clientes no importando cual sea la comuna.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Como podemos ver, el usuario está logrando alterar nuestra consulta para obtener un resultado no esperado por la aplicación. En este caso, mostrar todos los clientes de nuestro banco sin importar su comuna.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;A este proceso se le conoce como”&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Inyección de SQL&lt;/span&gt;”. Si bien este pequeño ejemplo no implica un mayor “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;peligro&lt;/span&gt;” para nuestro sistema, no podemos pasar por alto que hay una vulnerabilidad grave en nuestro sistema, que podría permitir a un atacante con un poco más de conocimiento hacer otro tipo de inyecciones más perjudiciales para nuestra aplicación.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Qué pasaría con un usuario más astuto? Imaginemos que ahora nuestro usuario tiene un alto conocimiento de SQL (algún miembro del JUG Chile), y quiere validar si nuestro sistema presenta algún problema de seguridad frente a ataques de tipo “Inyección de SQL”. Entonces, no haya nada mejor, que enviar ciertos parámetros por la URL que le permitan obtener los datos de otra tabla, como por ejemplo, la tabla “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;cuentas&lt;/span&gt;”, que contiene toda la información de las cuentas bancarias de nuestros clientes.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Entonces, esta vez nuestro usuario realiza la siguiente consulta:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;http://www.mibanco.cl/consultaCliente.jsp? tipoCliente =persona&amp;amp;comuna=%20UNION%20SELECT%20*%20FROM%20cuentas%20WHERE%20%22=&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Entonces, nuevamente nuestro servlet que procesa esta petición, tomara los parámetros enviados por el usuario y ejecutara la siguiente consulta SQL sobre la base de datos:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;SELECT * FROM clientes WHERE tipoCliente=&#39;persona&#39; AND comuna=&#39;&#39; UNION SELECT * FROM cuentas WHERE &#39;&#39;=&#39;&#39;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Ahora si estamos en serios problemas!!!!!. El usuario a logrado obtener a través de esta consulta, todos los datos de las cuentas bancarias registradas en nuestra base de datos.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Entonces, nuevamente volvemos al punto inicial. Sera que el lenguaje que estamos utilizando para programa nuestro sistema presenta este tipo de problemas de seguridad? O será acaso un problema de nuestra base de datos?; y la pregunta principal….¿Puedo yo, como desarrollador de este sistema, evitar de alguna manera este tipo de ataques?.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Si analizamos nuestra aplicación, nos encontraremos que el principal problema radica en la nula verificación de los datos enviados por el usuario antes de realizar la consulta SQL a la base de datos.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Pero qué tipo de verificación?....bueno, simplemente validar que dentro de los valores enviados por el usuario, estos no contengan código SQL que permitan la manipulación de nuestra sentencia SQL.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Si analizamos nuestro ejemplo, los valores que tendríamos que verificar, son “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;tipoCliente&lt;/span&gt;” y “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;comuna&lt;/span&gt;”. Son estos valores, los que tendríamos que validar, verificando que no contengan caracteres especiales, como por ejemplo comillas, que puedan servir al usuario para inyectar código SQL en la consulta.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;En este caso, nos bastaría con verificar que el “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;tipoCliente&lt;/span&gt;” y la “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;comuna&lt;/span&gt;”,  sólo contengan letras, sin ningún carácter especial.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Lo importante de todo esto,  es que el problema de la seguridad de nuestro sistema (debido a la inyección de SLQ), radica principalmente en la verificación de datos dentro de nuestro sistema. Por lo tanto, una solución, es filtrar siempre la entrada del usuario, de manera que atacante, nunca pueda inyectar código SQL en ningún lado dentro de nuestra aplicación.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Algunas técnicas, comúnmente recomendadas para la filtración de los valores enviados por el usuario son:&lt;br /&gt;&lt;br /&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;Limitar, siempre que se pueda, el tamaño del valor ingresado. De esta manera, limitamos la cantidad de código SQL que un atacante puede inyectar. En especial si se trata de una consulta anidada.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;No permitir, o en su defecto escapar, todos los caracteres que puedan llegar a ser usados como parte de una inyección SQL: comilla simple (’), punto y coma (;) y caracteres de comentario (/* */ y –).&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;Filtrar con expresiones regulares todo lo que ingrese el usuario. Por ejemplo, en un formulario de registro, el campo mail sólo debería aceptar letras en minúsculas, números y un arroba. Al igual que en un número de teléfono sólo deberían aceptarse números. &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;br /&gt;Otros consejos, que no se encuentran relacionados con al verificación de los valores son:&lt;br /&gt;&lt;br /&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;Realizar las consultas de la aplicación, utilizando un usuario, con la menor cantidad de privilegios posible dentro de la base de datos. De modo que si un atacante, pudiera saltarse de algún modo la verificación de los valores e inyectar código en alguna de nuestras consultas, los daños se reduzcan al no tener suficientes privilegios.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Realizar la verificación de los valores ingresados por el usuario, en todas las capas de la aplicación. Algunos desarrolladores por ejemplo, hacen una sola verificación dentro de la capa de presentación, utilizando JavaScript. Esto, puede ser fácilmente evitado, enviado los valores directamente a través del navegador.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;No mostrar los mensajes de error devueltos por la base de datos. Para un atacante podría serle muy útil esta información, en especial para hacer “&lt;a href=&quot;http://es.wikipedia.org/wiki/Blind_SQL_injection&quot;&gt;Blind Injection&lt;/a&gt;”.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;Usar Prepared Statements: Esta es una de las mejores soluciones que se pueden utilizar para evitar este tipo de ataques, ya que prácticamente son inmunes a las inyecciones SQL.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Una explicación más detalla de la inyección de SQL y artículos relacionados con el tema, la pueden encontrar &lt;a href=&quot;http://es.wikipedia.org/wiki/Inyecci%C3%B3n_SQL&quot;&gt;aquí&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Pero como todo problema en el mundo Java, siempre existe alguien con una solución. Para este tipo de ataques tenemos el framework &lt;a href=&quot;http://www.hdiv.org/&quot;&gt;HDIV&lt;/a&gt; (HTTP Data Integrity Validator).&lt;br /&gt;&lt;/div&gt;</description><link>http://dukechile.blogspot.com/2008/08/inyeccin-de-sql-sql-injection.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-6323354728460477547</guid><pubDate>Fri, 22 Aug 2008 23:31:00 +0000</pubDate><atom:updated>2008-08-22T19:37:22.785-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Patrones de Diseño</category><title>Patrones de diseño GoF (Gang of Four)</title><description>En anteriores post, hemos visto algunos de los patrones que son parte del GOF. Pero como una imagen vale más que mil palabras, aquí les dejo este &lt;a href=&quot;http://www.mcdonaldland.info/files/designpatterns/designpatternscard.pdf%29&quot;&gt;link&lt;/a&gt; en donde podrán encontrar un excelente PDF con los diagramas UML de los principales patrones.&lt;br /&gt;&lt;br /&gt;Esta no es la única opción, ya que también existe el poster de &lt;a href=&quot;http://www.amazon.com/Head-First-Design-Patterns-Poster/dp/0596102143&quot;&gt;Head Fisrt Design Patterns&lt;/a&gt;, pero que a diferencia de la opción anterior, esta utlima es pagada.&lt;br /&gt;&lt;br /&gt;Este es un poster que Cerebro no puede dejar de tener!!</description><link>http://dukechile.blogspot.com/2008/08/patrones-de-diseo-gof-gang-of-four.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-2408127954276900118</guid><pubDate>Thu, 21 Aug 2008 17:47:00 +0000</pubDate><atom:updated>2008-08-21T13:56:29.546-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">JEE</category><category domain="http://www.blogger.com/atom/ns#">SCWCD</category><category domain="http://www.blogger.com/atom/ns#">WEB</category><title>SCWCD - El descriptor de despliegue web.xml</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;El archivo &lt;span style=&quot;font-weight: bold;&quot;&gt;web.xml&lt;/span&gt; proporciona la configuración y el despliegue de información para los componentes web que conforman una aplicación.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Este archivo debe residir en el directorio WEB-INF dentro del contexto de la jerarquía de directorios que existen para una aplicación Web. Por ejemplo, si la aplicación esta empaquetada en el archivo WAR &quot;&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;dukechile.war&lt;/span&gt;&quot;, el archivo &lt;span style=&quot;font-weight: bold;&quot;&gt;web.xml&lt;/span&gt; se debe colocar en el directorio “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;dukechile/ WEB-INF&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Como todos los archivos de configuración xml, este contiene un &lt;a style=&quot;font-weight: bold;&quot; href=&quot;http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;&gt;esquema&lt;/a&gt; que describe el contenido del fichero xml y la descripción de las propiedades que va a utilizar. Dentro de este archivo definiremos la configuración de la aplicación web que estemos desarrollando.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Los elementos del &lt;span style=&quot;font-weight: bold;&quot;&gt;web.xml&lt;/span&gt; son:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;web-app&amp;gt;&lt;/span&gt;: Es el elemento raíz del fichero xml.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;icon&amp;gt;&lt;/span&gt;: Define la ruta para las imágenes asociadas a los iconos pequeño y grande que representan a la aplicación.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;display-name&amp;gt;&lt;/span&gt;: Es el nombre que representará a la aplicación dentro de las herramientas del servidor de aplicaciones, no es un nombre funcional.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;description&amp;gt;&lt;/span&gt;: Texto descriptivo de la aplicación, que al igual que las dos anteriores propiedades, sólo es representativo.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;context-param&amp;gt;&lt;/span&gt;: Permite configurar parámetros de inicialización del contexto de nuestra aplicación web.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;context-param&gt;&lt;br /&gt;    &lt;param-name&gt;nombrehost&lt;/param-name&gt;&lt;br /&gt;    &lt;param-value&gt;localhost&lt;/param-value&gt;&lt;br /&gt;    &lt;description&gt; Nombre del host en cual se esta ejecutando la aplicacion&lt;/description&gt; &lt;/context-param&gt; &lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;filter&amp;gt;&lt;/span&gt;: Permite definir un filtro en la aplicación.&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;filter&gt;&lt;br /&gt;    &lt;filter-name&gt;LogSolicitudes&lt;/filter-name&gt;&lt;br /&gt;    &lt;filter-class&gt;cl.bee.dukechile.LogSolicitudes&lt;/filter-class&gt;&lt;br /&gt;        &lt;init-param&gt;&lt;br /&gt;            &lt;param-name&gt;nombrearchivo&lt;/param-name&gt;&lt;br /&gt;            &lt;param-value&gt;registrolog&lt;/param-value&gt;&lt;br /&gt;        &lt;/init-param&gt;&lt;br /&gt;    &lt;/filter&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;filter-mapping&amp;gt;&lt;/span&gt;: Define un mapeo para aplicar las reglas de un determinado filtro a una URL.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;filter-mapping&gt;&lt;br /&gt;    &lt;filter-name&gt; LogSolicitudes &lt;/filter-name&gt;&lt;br /&gt;    &lt;url-pattern&gt;/cl/jug/dukechile/*&lt;/url-pattern&gt;&lt;br /&gt; &lt;/filter-mapping&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;listener&amp;gt;&lt;/span&gt;: Permite definir una clase oyente, la que puede escuchar eventos relacionados al clico de vida de la aplicación o modificaciones de un objeto.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;listener&gt;&lt;br /&gt;    &lt;listener-class&gt;cl.jug.dukechile.ListenerDeContexto&lt;/listener-class&gt;&lt;br /&gt;&lt;/listener&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;servlet&amp;gt;&lt;/span&gt;: Permite definir la configuración de nuestros servlets.&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;servlet&gt;&lt;br /&gt;    &lt;servlet-name&gt;DukeChile&lt;/servlet-name&gt;&lt;br /&gt;    &lt;servlet-class&gt;cl.jug.dukechile.MiServlet&lt;/servlet-class&gt;&lt;br /&gt;        &lt;init-param&gt;&lt;br /&gt;            &lt;param-name&gt;configuracion&lt;/param-name&gt;&lt;br /&gt;           &lt;param-value&gt;/WEB-INF/dukechile-config.xml&lt;/param-value&gt;&lt;br /&gt;        &lt;/init-param&gt;&lt;br /&gt;        &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;&lt;br /&gt;&lt;/servlet&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;servlet-mapping&amp;gt;&lt;/span&gt;: Permite relacionar los servlets que hemos declarado con las URL que van a escuchar.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;servlet-mapping&gt;&lt;br /&gt;    &lt;servlet-name&gt;DukeChile&lt;/servlet-name&gt;&lt;br /&gt;    &lt;url-pattern&gt;*.jsp&lt;/url-pattern&gt;&lt;br /&gt;&lt;/servlet-mapping&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;session-config&amp;gt;&lt;/span&gt;: Permite definir el timeout de la sesión en minutos.&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;session-config&gt;&lt;br /&gt;    &lt;session-timeout&gt;10&lt;/session-timeout&gt;&lt;br /&gt;&lt;/session-config&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;mime-mapping&amp;gt;&lt;/span&gt;: Permite definir una relación entre las extensiones y los tipos mime.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;mime-mapping&gt;&lt;br /&gt;    &lt;extension&gt;doc&lt;/extension&gt;&lt;br /&gt;    &lt;mime-type&gt;application/vnd.ms-word&lt;/mime-type&gt;&lt;br /&gt;&lt;/mime-mapping&gt;&lt;br /&gt;&lt;br /&gt;&lt;mime-mapping&gt;&lt;br /&gt;    &lt;extension&gt;dsp&lt;/extension&gt;&lt;br /&gt;   &lt;mime-type&gt;text/html&lt;/mime-type&gt;&lt;br /&gt;&lt;/mime-mapping&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;welcome-file-list&amp;gt;&lt;/span&gt;: Permite definir los ficheros de bienvenida de la aplicacion.&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;welcome-file-list&gt;&lt;br /&gt;    &lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt;&lt;br /&gt;    &lt;welcome-file&gt;index.html&lt;/welcome-file&gt;&lt;br /&gt;&lt;/welcome-file-list&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;tag-lib&amp;gt;&lt;/span&gt;: Permite definir las librerías de etiquetas de los ficheros JSP.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;jsp-config&gt;&lt;br /&gt;    &lt;taglib&gt;&lt;br /&gt;    &lt;taglib-uri&gt;/tags/struts-bean&lt;/taglib-uri&gt;&lt;br /&gt;    &lt;taglib-location&gt;/WEB-INF/struts-bean.tld&lt;/taglib-location&gt;&lt;br /&gt;    &lt;/taglib&gt;&lt;br /&gt;&lt;/jsp-config&gt;&lt;br /&gt; &lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;jsp-property-group&amp;lt;&lt;/span&gt;: Permite definir propiedades para un conjunto de JSP que cumplan un patrón.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;jsp-config&gt;&lt;br /&gt;    &lt;jsp-property-group&gt;&lt;br /&gt;        &lt;url-pattern&gt;*.jsp&lt;/url-pattern&gt;&lt;br /&gt;        &lt;include-prelude&gt;/cabecera.jsp&lt;/include-prelude&gt;&lt;br /&gt;        &lt;include-coda&gt;/pie.jsp&lt;/include-coda&gt;&lt;br /&gt;    &lt;/jsp-property-group&gt;&lt;br /&gt;&lt;/jsp-config&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;error-page&amp;lt;&lt;/span&gt;: Permite asociar errores HTML y excepciones lanzadas por nuestra aplicación a páginas de error personalizadas para la aplicación.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;error-page&gt;&lt;br /&gt;    &lt;error-code&gt;404&lt;/error-code&gt;&lt;br /&gt;    &lt;location&gt;/noEncontrado.jsp&lt;/location&gt;&lt;br /&gt;&lt;/error-page&gt;&lt;br /&gt;&lt;br /&gt;&lt;error-page&gt;&lt;br /&gt;    &lt;exception-type&gt;java.lang.Throwable&lt;/exception-type&gt;&lt;br /&gt;    &lt;location&gt;/error.jsp&lt;/location&gt;&lt;br /&gt;&lt;/error-page&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;resource-ref&amp;lt;&lt;/span&gt;: Permite declarar recursos externos que nuestra aplicación va a utilizar. Por ejemplo, una conexión a una base de datos.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;resource-ref&gt;&lt;br /&gt;    &lt;description&gt;Conexion BD&lt;/description&gt;&lt;br /&gt;    &lt;res-ref-name&gt;jdbc/ConexionMySQL&lt;/res-ref-name&gt;&lt;br /&gt;    &lt;res-type&gt;javax.sql.DataSource&lt;/res-type&gt;&lt;br /&gt;    &lt;res-auth&gt;Container&lt;/res-auth&gt;&lt;br /&gt;&lt;/resource-ref&gt; &lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;resource-env-ref&amp;lt;&lt;/span&gt;: Permite declarar recursos externos que nuestra aplicación va a utilizar. Este elemento es una nueva variación del elemento &lt;resource-ref&gt; añadido en Servlet 2.4 que es más simple de configurar para recursos que no necesitan información de autenticación.&lt;/resource-ref&gt;&lt;br /&gt;&lt;/div&gt;&lt;resource-ref&gt;&lt;/resource-ref&gt;&lt;/div&gt;&lt;resource-ref&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;resource-env-ref&gt;&lt;br /&gt;    &lt;resource-env-ref-name&gt;jms/StockQueue&lt;/resource-env-ref-name&gt;&lt;br /&gt;    &lt;resource-env-ref-type&gt;javax.jms.Queue&lt;/resource-env-ref-type&gt;&lt;br /&gt;&lt;/resource-env-ref&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;/resource-ref&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;resource-ref&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;security-constraint&amp;lt;&lt;/span&gt;: Permite proteger áreas de la aplicación (o la aplicación completa), asociándolas a roles que deben tener los usuarios para poder acceder. Estos usuarios y roles son los declarados en &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;tomcat-users.xml&lt;/span&gt; (para el caso de Tomcat).&lt;/resource-ref&gt;&lt;br /&gt;&lt;resource-ref&gt;&lt;/resource-ref&gt;&lt;/div&gt;&lt;resource-ref&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;security-constraint&gt;&lt;br /&gt;    &lt;web-resource-collection&gt;&lt;br /&gt;        &lt;web-resource-name&gt;Seguridad Duke Chile&lt;/web-resource-name&gt;&lt;br /&gt;        &lt;url-pattern&gt;/*&lt;/url-pattern&gt;&lt;br /&gt;    &lt;/web-resource-collection&gt;&lt;br /&gt;    &lt;auth-constraint&gt;&lt;br /&gt;        &lt;role-name&gt;duke&lt;/role-name&gt;&lt;br /&gt;    &lt;/auth-constraint&gt;&lt;br /&gt;&lt;/security-constraint&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;/resource-ref&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;resource-ref&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;login-config&amp;lt;&lt;/span&gt;: Permite configurar el tipo de login que se requerirá al entrar en un área protegida previamente declarada.&lt;/resource-ref&gt;&lt;br /&gt;&lt;resource-ref&gt;&lt;/resource-ref&gt;&lt;/div&gt;&lt;resource-ref&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;login-config&gt;&lt;br /&gt;    &lt;auth-method&gt;FORM&lt;/auth-method&gt;&lt;br /&gt;    &lt;realm-name&gt;Login por formulario&lt;/realm-name&gt;&lt;br /&gt;    &lt;form-login-config&gt;&lt;br /&gt;        &lt;form-login-page&gt;/login.jsp&lt;/form-login-page&gt;&lt;br /&gt;        &lt;form-error-page&gt;/error.jsp&lt;/form-error-page&gt;&lt;br /&gt;    &lt;/form-login-config&gt;&lt;br /&gt;&lt;/login-config&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;security-role&amp;lt;&lt;/span&gt;: Permite definir los roles de usuarios que se van a utilizar en la aplicación.&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;security-role&gt;&lt;br /&gt;    &lt;role-name&gt;duke&lt;/role-name&gt;&lt;br /&gt;&lt;/security-role&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;/resource-ref&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;resource-ref&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;env-entry&amp;lt;&lt;/span&gt;: Permite declarar una posible entrada al entorno (environment) de la aplicación.&lt;/resource-ref&gt;&lt;br /&gt;&lt;resource-ref&gt;&lt;/resource-ref&gt;&lt;/div&gt;&lt;resource-ref&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;env-entry&gt;&lt;br /&gt;    &lt;description&gt;Mensaje de bienvenida&lt;/description&gt;&lt;br /&gt;    &lt;env-entry-name&gt;bienvenida&lt;/env-entry-name&gt;&lt;br /&gt;    &lt;env-entry-type&gt;java.lang.String&lt;/env-entry-type&gt;&lt;br /&gt;    &lt;env-entry-value&gt;Bienvenido al sistema DukeChile&lt;/env-entry-value&gt;&lt;br /&gt;&lt;/env-entry&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;ejb-ref&amp;lt;&lt;/span&gt;: Permite definir una referencia a un EJB.&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;ejb-ref&gt;&lt;br /&gt;    &lt;description&gt;EJB DukeChile&lt;/description&gt;&lt;br /&gt;    &lt;ejb-ref-name&gt;ejb/DukeChileHome&lt;/ejb-ref-name&gt;&lt;br /&gt;    &lt;ejb-ref-type&gt;Entity&lt;/ejb-ref-type&gt;&lt;br /&gt;    &lt;home&gt;cl.jug.dukechile.DukeChileHome&lt;/home&gt;&lt;br /&gt;    &lt;remote&gt;cl.jug.dukechile.DukeChile&lt;/remote&gt;&lt;br /&gt;&lt;/ejb-ref&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;ejb-local-ref&amp;lt;&lt;/span&gt;: Permite definir una referencia a un EJB Local.&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;ejb-local-ref&gt;&lt;br /&gt;    &lt;ejb-ref-name&gt;ejb/DukeChile&lt;/ejb-ref-name&gt;&lt;br /&gt;    &lt;ejb-ref-type&gt;Session&lt;/ejb-ref-type&gt;&lt;br /&gt;    &lt;local-home&gt; cl.jug.dukechile.DukeChileHome&lt;/local-home&gt;&lt;br /&gt;    &lt;local&gt;cl.jug.dukechile.DukeChile&lt;/local&gt;&lt;br /&gt;    &lt;ejb-link&gt;DukeChile&lt;/ejb-link&gt;&lt;br /&gt;&lt;/ejb-local-ref&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;distributable&amp;lt;&lt;/span&gt;: Permite definir que la aplicación puede correr en un ambiente cluster.&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;web-app&gt;&lt;br /&gt;   &lt;distributable/&gt;&lt;br /&gt;&lt;/web-app&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;/resource-ref&gt;</description><link>http://dukechile.blogspot.com/2008/08/scwcd-el-descriptor-de-despliegue.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-3214927566141918220</guid><pubDate>Wed, 20 Aug 2008 17:22:00 +0000</pubDate><atom:updated>2008-08-21T12:46:01.254-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">JEE</category><category domain="http://www.blogger.com/atom/ns#">SCWCD</category><category domain="http://www.blogger.com/atom/ns#">WEB</category><title>SCWCD - Seguridad en aplicaciones Web</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;Uno de los tópicos que se debe estudiar para la certificación &lt;span style=&quot;font-weight: bold;&quot;&gt;SCWCD &lt;/span&gt;(Sun Certified Web Component Developer) son los mecanismos de seguridad en las aplicaciones Web.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Mecanismos de seguridad&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La seguridad en los servlets se reduce a cuatro conceptos principales:&lt;br /&gt;&lt;br /&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;authentication&lt;/span&gt;: El proceso de autenticación es el encargado de determinar que el interesado en acceder los recursos es realmente quien dice que es. Lo más común es hacer que el usuario o la aplicación envié un password que lo identifica.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;authorization&lt;/span&gt;: Es el proceso por el cual se restringe el acceso a ciertos recursos a un conjunto de clientes. En realidad, lo que se define es un conjunto de roles que pueden acceder a ciertos recursos y se asocia cada usuario a uno o más roles.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;data integrity&lt;/span&gt;: Es el proceso que asegura que los datos que se reciben (tanto el cliente como el servidor) no han sido corrompidos. Generalmente se usan algoritmos de encriptación para lograr esto.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;confidentiality&lt;/span&gt;: Es el proceso que intenta asegurar que solamente los clientes autorizados reciban la información. La manera de lograr esto puede ser a través del uso de claves públicas/privadas.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Tipos de autentificación definidos&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La especificación de servlet ofrece cuatro tipos de autentificación:&lt;br /&gt;&lt;br /&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;BASIC&lt;/span&gt;: Este es el método más simple, pero el más inseguro. Cuando usamos este tipo de autenticación, se abre una ventana en el browser del cliente para que este ingrese el usuario y el password. El password se envía al servidor codificado en Base64.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;FORM&lt;/span&gt;: Este método es similar a BASIC, pero utiliza un formulario provisto por el programador. Este formulario tiene que cumplir los siguientes requisitos:&lt;/li&gt;&lt;/ul&gt;&lt;ol&gt;&lt;li&gt;El atributo “action” debe ser “&lt;span style=&quot;font-weight: bold;&quot;&gt;j_security_check&lt;/span&gt;”&lt;/li&gt;&lt;li&gt;El casillero de ingreso del usuario debe llamarse “&lt;span style=&quot;font-weight: bold;&quot;&gt;j_username&lt;/span&gt;”&lt;/li&gt;&lt;li&gt;El casillero de ingreso del password debe llamarse “&lt;span style=&quot;font-weight: bold;&quot;&gt;j_password&lt;/span&gt;”&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;textarea class=&quot;html&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;form method=&quot;post&quot; action=&quot;j_security_check&quot;&gt;&lt;br /&gt;    Usuario: &lt;input type=&quot;text&quot; name=&quot;j_username&quot;&gt;&lt;br /&gt;    Password: &lt;input type=&quot;text&quot; name=&quot;j_password&quot;&gt;&lt;br /&gt;&lt;/form&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;CLIENT-CERT&lt;/span&gt;: En este método se usan certificados digitales. El browser debe tener instalado el certificado para que la comunicación se pueda establecer.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;DIGEST&lt;/span&gt;: La autenticación también es hecha utilizando usuario y password, pero el password es enviado encriptado de una forma mucho más segura (por ejemplo, utilizando HTTPS client authentication).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Autorización&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El primero paso es definir los roles que se encontraran definidos dentro de nuestro sistema. Para el caso de Tomcat, estos se definen en el archivo &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;tomcat-users.xml&lt;/span&gt;. Dentro de este archivo, cada usuario tiene asignado un usuario y password; y puede estar asociado a uno o más roles.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;tomcat-users&gt;&lt;br /&gt;     &lt;role rolename=&quot;”Admin”/&quot;&gt;&lt;br /&gt;     &lt;role rolename=&quot;”Member”/&quot;&gt;&lt;br /&gt;     &lt;role rolename=&quot;”Guest”/&quot;&gt;&lt;br /&gt;     &lt;user username=&quot;”jose”&quot; password=&quot;”duke”&quot; roles=&quot;”Admin,&quot;&gt;&lt;br /&gt;&lt;/tomcat-users&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El siguiente paso es relacionar los roles definidos en el archivo &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;tomcat-users.xml&lt;/span&gt;, con los roles a utilizar dentro del sistema. Para esto deberemos utilizar los elementos &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;security-role&amp;gt;&lt;/span&gt; y &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;role-name&amp;gt;&lt;/span&gt; dentro del archivo &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;web.xml&lt;/span&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;security-role&gt;&lt;br /&gt;     &lt;role-name&gt;Admin&lt;/role-name&gt;&lt;br /&gt;&lt;/security-role&gt;&lt;br /&gt;&lt;br /&gt;&lt;security-role&gt;&lt;br /&gt;     &lt;role-name&gt;Member&lt;/role-name&gt;&lt;br /&gt; &lt;/security-role&gt;&lt;br /&gt;&lt;br /&gt;&lt;security-role&gt;&lt;br /&gt;     &lt;role-name&gt;Guest&lt;/role-name&gt;&lt;br /&gt;&lt;/security-role&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Una vez definidos los roles, se procede a establecer “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;declarativamente&lt;/span&gt;” el acceso a un conjunto de recursos en combinación con los métodos, a los cuales tendrán accesos determinados roles. El elemento principal es el &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;security-constraint&amp;gt;&lt;/span&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;security-constraint&gt; &lt;br /&gt;&lt;br /&gt;    &lt;web-resource-collection&gt;&lt;br /&gt;        &lt;web-resource-name&gt;ActulizarDatos&lt;/web-resource-name&gt;&lt;br /&gt;        &lt;url-pattern&gt;/cl/jug/actualizar/*&lt;/url-pattern&gt;&lt;br /&gt;        &lt;url-pattern&gt;/cl/jug/listar/*&lt;/url-pattern&gt;&lt;br /&gt;        &lt;http-method&gt;GET&lt;/http-method&gt;&lt;br /&gt;        &lt;http-method&gt;POST&lt;/http-method&gt;&lt;br /&gt;    &lt;/web-resource-collection&gt;&lt;br /&gt;&lt;br /&gt;    &lt;auth-constraint&gt;&lt;br /&gt;        &lt;role-name&gt;Admin&lt;/role-name&gt; &lt;br /&gt;        &lt;role-name&gt;Member&lt;/role-name&gt; &lt;br /&gt;    &lt;/auth-constraint&gt;&lt;br /&gt;&lt;br /&gt;&lt;/security-constraint&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Donde:&lt;br /&gt;&lt;br /&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;El elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;web-resource-name&amp;gt;&lt;/span&gt; es obligatorio y utilizado principalmente por los IDEs.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;El elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;url-pattern&amp;gt;&lt;/span&gt; define el recurso al cual se limitara el acceso. Al menos se debe definir a lo menos un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;url-pattern&amp;gt;&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;El elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;http-method&amp;gt;&lt;/span&gt; describe el método HTTP que será restringido para acceder al recurso definido en los &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;url-pattern&amp;gt;&lt;/span&gt;. Si no se define ningún &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;http-method&amp;gt;&lt;/span&gt;, entonces se restringirá el acceso a todos los métodos HTTP.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;El elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;auth-constraint&amp;amp;gt&lt;/span&gt;; es opcional y permite definir cuales roles pueden llamar a los métodos HTTP restringidos por los elementos &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;http-method&amp;amp;gt&lt;/span&gt;;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Para permitir el acceso a todos los roles, se debe definir el elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;auth-constraint&amp;gt;&lt;/span&gt; de la siguiente forma:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;auth-constraint&gt;&lt;br /&gt;    &lt;role-name&gt;*&lt;/role-name&gt;&lt;br /&gt;&lt;/auth-constraint&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;O también de la forma:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;auth-constraint&gt;&lt;/auth-constraint&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;En el caso de que se quiera bloquear el acceso a todos los roles, se deberá definir el &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;auth-constraint&amp;gt;&lt;/span&gt; de la siguiente forma:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;auth-constraint/&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Es importante tener en cuenta que se puede tener más de un elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;web-resource-collection&amp;gt;&lt;/span&gt; dentro de un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;security-constraint&amp;gt;&lt;/span&gt;.  En este caso, el elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;auth-constraint&amp;gt;&lt;/span&gt; se aplica a todos los &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;web-resource-collection&amp;gt;&lt;/span&gt; definidos dentro de un &lt;span style=&quot;font-weight: bold;&quot;&gt;&amp;lt;security-constraint&amp;gt;&lt;/span&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Autentificacion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Anteriormente mencionamos que la especificación de servlet ofrece cuatro tipos de autentificación: &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;BASIC&lt;/span&gt;, &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;FORM&lt;/span&gt;, &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;CLIENT-CERT&lt;/span&gt; y &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;DIGEST&lt;/span&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Cada uno de estos tipos se puede definir en el &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;web.xml&lt;/span&gt; de siguiente forma:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;login-config&gt; &lt;br /&gt;    &lt;auth-method&gt;BASIC&lt;/auth-method&gt;&lt;br /&gt;&lt;/login-config&gt;&lt;br /&gt;&lt;br /&gt;&lt;login-config&gt; &lt;br /&gt;    &lt;auth-method&gt;FORM&lt;/auth-method&gt; &lt;br /&gt;    &lt;form-login-config&gt; &lt;br /&gt;        &lt;form-login-page&gt;/loginUsuario.html&lt;/form-login-page&gt; &lt;br /&gt;        &lt;form-error-page&gt;/loginError.html&lt;/form-error-page&gt; &lt;br /&gt;    &lt;/form-login-config&gt;&lt;br /&gt;&lt;/login-config&gt;&lt;br /&gt;&lt;br /&gt;&lt;login-config&gt; &lt;br /&gt;    &lt;auth-method&gt;CLIENT-CERT&lt;/auth-method&gt;&lt;br /&gt;&lt;/login-config&gt;&lt;br /&gt;&lt;br /&gt;&lt;login-config&gt; &lt;br /&gt;    &lt;auth-method&gt;DIGEST&lt;/auth-method&gt;&lt;br /&gt;&lt;/login-config&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Un punto importante es que de los cuatro tipos de autentificación, el tipo &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;DIGEST &lt;/span&gt;es el único que es opcional para los contenedores JEE.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Modos de transporte&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;La especificación también define tres modos para indicar la seguridad del transporte de los datos a través de la Web.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;NONE&lt;/span&gt;: Ningún tipo de cifrado, simplemente HTTP.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;CONFIDENTIAL&lt;/span&gt;: Define la confidencialidad de los datos. Es decir, que nadie pueda ver ni modificar los datos que se envían.&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;INTEGRAL&lt;/span&gt;: Define la integridad de los datos. Es decir, que  aunque alguien pueda ver lo que se envía, se garantice que los datos no se modifiquen por el camino. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;security-constraint&gt; &lt;br /&gt;&lt;br /&gt;    &lt;web-resource-collection&gt;&lt;br /&gt;        &lt;web-resource-name&gt;ActulizarDatos&lt;/web-resource-name&gt;&lt;br /&gt;        &lt;url-pattern&gt;/cl/jug/actualizar/*&lt;/url-pattern&gt;&lt;br /&gt;        &lt;url-pattern&gt;/cl/jug/listar/*&lt;/url-pattern&gt;&lt;br /&gt;        &lt;http-method&gt;GET&lt;/http-method&gt;&lt;br /&gt;        &lt;http-method&gt;POST&lt;/http-method&gt;&lt;br /&gt;    &lt;/web-resource-collection&gt;&lt;br /&gt;&lt;br /&gt;    &lt;auth-constraint&gt;&lt;br /&gt;        &lt;role-name&gt;Admin&lt;/role-name&gt; &lt;br /&gt;        &lt;role-name&gt;Member&lt;/role-name&gt; &lt;br /&gt;    &lt;/auth-constraint&gt;&lt;br /&gt;&lt;br /&gt;    &lt;user-data-constraint&gt;&lt;br /&gt;        &lt;transport-guarantee&gt;CONFIDENTIAL&lt;/transport-guarantee&gt;&lt;br /&gt;    &lt;/user-data-constraint&gt;&lt;br /&gt;&lt;br /&gt;&lt;/security-constraint&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;El metodo isUserInRole()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;La clase “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;HTTPServletRequest&lt;/span&gt;” tiene tres métodos que están asociados al manejo de la seguridad de manera “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;programática&lt;/span&gt;”, uno de estos es el método “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;isUserInRole&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;A través del método “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;isUserInRole()&lt;/span&gt;”, en vez de manejar el acceso a nivel de método HTTP, ahora podremos autorizar el acceso a una parte del código de nuestro método basados en los roles del usuario.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Antes de que se llame al método “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;isUserInRole()&lt;/span&gt;”, el usuario necesita estar autenticado. En el caso de que llame al método sobre un usuario que no ha autenticado, el contenedor retornara “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;false&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;En el caso de que este autenticado, el contenedor toma el argumento del método y compara este con los roles definidos para el usuario en el “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;request&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Si el usuario es mapeado a este rol, el contenedor retornara “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;true&lt;/span&gt;”.&lt;br /&gt;&lt;br /&gt;Por ejemplo, dentro del código en el servlet:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;if( request.isUserInRole(“DukeChile”)) { &lt;br /&gt;    // Permiso para actualizar la informacion&lt;br /&gt;} &lt;br /&gt;else { &lt;br /&gt;    // permiso solo para consultar la informacion &lt;br /&gt;}&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;servlet&gt;&lt;br /&gt;     &lt;security-role-ref&gt;&lt;br /&gt;         &lt;role-name&gt; DukeChile &lt;/role-name&gt;&lt;br /&gt;         &lt;role-link&gt;Admin&lt;/role-link&gt;&lt;br /&gt;     &lt;/security-role-ref&gt; &lt;br /&gt;      ...&lt;br /&gt; &lt;/servlet&gt; &lt;br /&gt;&lt;br /&gt;&lt;security-role&gt; &lt;br /&gt;    &lt;role-name&gt;Admin&lt;/role-name&gt; &lt;br /&gt;&lt;/security-role&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El elemento &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;security-role-ref&amp;gt;&lt;/span&gt; permite relacionar un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&amp;lt;role-name&amp;gt;&lt;/span&gt; definido “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;programáticamente&lt;/span&gt;” (en el servlet) con uno que existe en el &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;web.xml&lt;/span&gt;.&lt;br /&gt;&lt;/div&gt;</description><link>http://dukechile.blogspot.com/2008/08/scwcd-seguridad-en-aplicaciones-web_20.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-7962759339048015660</guid><pubDate>Tue, 19 Aug 2008 14:01:00 +0000</pubDate><atom:updated>2008-08-20T13:16:52.940-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">JEE</category><category domain="http://www.blogger.com/atom/ns#">WEB</category><title>JMesa</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;Muchos desarrolladores Web, alguna vez hemos utilizado &lt;a href=&quot;http://displaytag.sourceforge.net/11/&quot;&gt;DisplayTag &lt;/a&gt;para la creación de tablas con exportación y paginación automática. &lt;a href=&quot;http://displaytag.sourceforge.net/11/&quot;&gt;DisplayTag &lt;/a&gt;es un tag lib que nos permite ahorrar muchas líneas de código.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Ahora disponemos de una alternativa mucho más actualizada y potente llamada &lt;a href=&quot;http://code.google.com/p/jmesa/&quot;&gt;JMesa&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Los pasos para agregar JMesa a sus aplicaciones son muy simples.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Descargan JMesa desde &lt;a href=&quot;http://jmesa.googlecode.com/files/jmesa-2.3.3.zip&quot;&gt;aquí&lt;/a&gt; y agregan el tld que se encuentra bajo el directorio &lt;span style=&quot;font-weight: bold;&quot;&gt;/jmesa-2.3.3/dist&lt;/span&gt; del zip al directorio &lt;span style=&quot;font-weight: bold;&quot;&gt;/WEB-INF/tld&lt;/span&gt; de la aplicación.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;También deberan agregar los ficheros &lt;span style=&quot;font-weight: bold;&quot;&gt;css&lt;/span&gt;, &lt;span style=&quot;font-weight: bold;&quot;&gt;javascript&lt;/span&gt;, las &lt;span style=&quot;font-weight: bold;&quot;&gt;imágenes &lt;/span&gt;y por supuesto los &lt;span style=&quot;font-weight: bold;&quot;&gt;jar &lt;/span&gt;en sus directorios correspondientes. Como JMesa requiere de &lt;span style=&quot;font-weight: bold;&quot;&gt;JQuery&lt;/span&gt;,&lt;span style=&quot;font-weight: bold;&quot;&gt; &lt;/span&gt;también deberán agregarlo al directorio &lt;span style=&quot;font-weight: bold;&quot;&gt;js &lt;/span&gt;( JQuery lo pueden obtener desde &lt;a href=&quot;http://code.google.com/p/jqueryjs/downloads/detail?name=jquery-1.2.6.min.js&quot;&gt;aquí&lt;/a&gt;). No importa donde se coloquen los &lt;span style=&quot;font-weight: bold;&quot;&gt;css &lt;/span&gt;ni los &lt;span style=&quot;font-weight: bold;&quot;&gt;javascript &lt;/span&gt;dado que se configuraran posteriormente. Las imágenes sin embargo tienen que estar en una ruta determinada que ha de coincidir con la del valor de la clave&lt;span style=&quot;font-weight: bold;&quot;&gt; html.imagesPath&lt;/span&gt; especificada en el fichero&lt;span style=&quot;font-weight: bold;&quot;&gt; jmesa.properties&lt;/span&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Este último fichero hay que crearlo y referenciarlo en el web.xml:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;context-param&gt;&lt;br /&gt;    &lt;param-name&gt;jmesaPreferencesLocation&lt;/param-name&gt;&lt;br /&gt;    &lt;param-value&gt;WEB-INF/jmesa.properties&lt;/param-value&gt;&lt;br /&gt;&lt;/context-param&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;A continuación, deberán crear el archivo &lt;span style=&quot;font-weight: bold;&quot;&gt;jmesa.properties&lt;/span&gt; en el directorio &lt;span style=&quot;font-weight: bold;&quot;&gt;WEB-INF&lt;/span&gt; de la aplicación.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;html.table.component.theme=jmesa&lt;br /&gt;html.table.renderer.styleClass=table&lt;br /&gt;&lt;br /&gt;html.row.renderer.highlightClass=highlight&lt;br /&gt;html.row.renderer.evenClass=even&lt;br /&gt;html.row.renderer.oddClass=odd&lt;br /&gt;&lt;br /&gt;html.column.header.renderer.image.sortAsc=sortAsc.gif&lt;br /&gt;html.column.header.renderer.image.sortDesc=sortDesc.gif&lt;br /&gt;html.column.filter.renderer.image.droplistHandle=droplistHandle.gif&lt;br /&gt;&lt;br /&gt;html.tbodyClass=tbody&lt;br /&gt;html.titleClass=title&lt;br /&gt;html.filterClass=filter&lt;br /&gt;html.headerClass=header&lt;br /&gt;html.toolbarClass=toolbar&lt;br /&gt;html.statusBarClass=statusBar&lt;br /&gt;html.imagesPath=/images/table/&lt;br /&gt;html.rowcount.includePagination=false&lt;br /&gt;&lt;br /&gt;html.toolbar.maxRowsDroplist.increments=15,50,100&lt;br /&gt;&lt;br /&gt;html.toolbar.image.csv=csv.png&lt;br /&gt;html.toolbar.image.pdf=pdf.gif&lt;br /&gt;html.toolbar.image.excel=excel.gif&lt;br /&gt;html.toolbar.image.clear=clear.png&lt;br /&gt;html.toolbar.image.firstPage=firstPage.png&lt;br /&gt;html.toolbar.image.firstPageDisabled=firstPageDisabled.png&lt;br /&gt;html.toolbar.image.lastPage=lastPage.png&lt;br /&gt;html.toolbar.image.lastPageDisabled=lastPageDisabled.png&lt;br /&gt;html.toolbar.image.nextPage=nextPage.png&lt;br /&gt;html.toolbar.image.nextPageDisabled=nextPageDisabled.png&lt;br /&gt;html.toolbar.image.prevPage=prevPage.png&lt;br /&gt;html.toolbar.image.prevPageDisabled=prevPageDisabled.png&lt;br /&gt;html.toolbar.image.filter=filter.png&lt;br /&gt;html.toolbar.image.separator=separator.gif&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Con estos pasos, ya se encuentra listo y configurado. Para utilizarlo hay que definir el namespace de JMesa en nuestra página:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;%@ taglib uri=&quot;/WEB-INF/tld/jmesa.tld&quot; prefix=&quot;jmesa&quot; %&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Ahora simplemente definiremos la siguiente línea:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xhtml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;jmesa:tablefacade id=&quot;tag&quot; items=&quot;${listadoDeObjetos}&quot; var=&quot;bean&quot;&gt;&lt;br /&gt;    &lt;jmesa:htmltable&gt;&lt;br /&gt;        &lt;jmesa:htmlrow&gt;&lt;br /&gt;            &lt;jmesa:htmlcolumn property=&quot;nombre&quot; title=&quot;Nombre&quot;&gt;&lt;br /&gt;            &lt;jmesa:htmlcolumn property=&quot;apellido&quot; title=&quot;Apellido&quot;&gt;&lt;br /&gt;        &lt;/jmesa:htmlRow&gt;&lt;br /&gt;    &lt;/jmesa:htmlTable&gt;&lt;br /&gt;&lt;/jmesa:tableFacade&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Con estos simples pasos, ya podremos utilizar JMesa dentro de nuestros proyectos.</description><link>http://dukechile.blogspot.com/2008/08/jmesa.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-1336719109619859964</guid><pubDate>Sun, 17 Aug 2008 23:00:00 +0000</pubDate><atom:updated>2008-08-23T12:37:02.872-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Patrones de Diseño</category><title>El patrón “Cadena de Responsabilidad” (Chain of Responsibility) - Parte VI</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;Los últimos ataques han sido todo un éxito, cada día se logran nuevas conquistas!!!. Debido a esto, Cerebro se ha visto en la necesidad de aumentar el número de robots dentro de sus tropas. Ahora su ejército se encuentra organizado en una estructura jerárquica, para lo cual ascendió a sus mejores solados a rangos como “&lt;span style=&quot;font-weight: bold;&quot;&gt;General&lt;/span&gt;” o “&lt;span style=&quot;font-weight: bold;&quot;&gt;Coronel&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Con esta nueva estructura será mucho fácil dar órdenes a su ejército, el simplemente dará la orden a su “&lt;span style=&quot;font-weight: bold;&quot;&gt;General Mazinger Z&lt;/span&gt;” quien al leer el comunicado decidirá si debe ejecutarla el o deberá derivarla a un sub-alterno; y así sucesivamente en la jerarquía hasta llegar al “&lt;span style=&quot;font-weight: bold;&quot;&gt;Soldado El Galactico&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Genial…..como siempre este plan es simple……es magnífico……es perfecto…….pero!!!!!!!&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Cerebro se ha dado cuenta nuevamente que ha olvidado algo muy importante, su mecanismo de comunicación (implementado con el patrón “&lt;span style=&quot;font-weight: bold;&quot;&gt;Observador&lt;/span&gt;”) ya no le sirve. Ahora tiene una estructura jerárquica, y necesita que la orden pase a través de esta estructura hasta el sub-alterno al que se le desee enviar este mensaje. Por lo tanto necesita un mecanismo en el cual el receptor del mensaje pueda no solo ejecutar la orden, sino también poder comunicar esta a su sub-alterno en el caso de que no fuera dirigida a él.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Una solución sería ir replicando el patrón “&lt;span style=&quot;font-weight: bold;&quot;&gt;Observador&lt;/span&gt;” en cada uno de sus niveles jerárquicos, pero esta no es la solución más optima..&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Debido a todos estos problemas, recurre nuevamente a su gurú “&lt;span style=&quot;font-weight: bold;&quot;&gt;Martin Fowler&lt;/span&gt;” y encuentra la solución perfecta!!!!. Cerebro ha visto que el patrón “&lt;span style=&quot;font-weight: bold;&quot;&gt;Cadena de Responsabilidad&lt;/span&gt;” (&lt;span style=&quot;font-weight: bold;&quot;&gt;Chain of Responsibility&lt;/span&gt;) es ideal para solucionar su problema.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO5HPbG-3IADGOKprxZMXjxgkQapvzLL6Jgfx5EJCeWzMNqPaYSDVI60Lf4_OuRpVuorc1JKOZ5dI4Bq0SE00qdF1CUF-zlmOXTVBg0emPb1QQVce1OsdYqzV0HCW00_ivOdfc4g3bVYhj/s1600-h/cadenaderesponsabilidad.JPG&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO5HPbG-3IADGOKprxZMXjxgkQapvzLL6Jgfx5EJCeWzMNqPaYSDVI60Lf4_OuRpVuorc1JKOZ5dI4Bq0SE00qdF1CUF-zlmOXTVBg0emPb1QQVce1OsdYqzV0HCW00_ivOdfc4g3bVYhj/s400/cadenaderesponsabilidad.JPG&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5237752715081595842&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Primero necesitara definir la clase “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mensaje&lt;/span&gt;”, la cual contendrá a quien esta dirigida la orden y cuáles son las instrucciones a ejecutar.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cadena.de.responsabilidad;&lt;br /&gt;&lt;br /&gt;public class Mensaje {&lt;br /&gt;&lt;br /&gt;    private String para;&lt;br /&gt;    private String contenido;&lt;br /&gt;&lt;br /&gt;    public Mensaje(String para, String contenido) {&lt;br /&gt;        this.para = para;&lt;br /&gt;        this.contenido = contenido;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String getPara() {&lt;br /&gt;        return para;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setPara(String para) {&lt;br /&gt;        this.para = para;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String getContenido() {&lt;br /&gt;        return contenido;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setContenido(String contenido) {&lt;br /&gt;        this.contenido = contenido;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Luego, deberá definir la clase abstracta “&lt;span style=&quot;font-weight: bold;&quot;&gt;EjecutarOrdenAltoMando&lt;/span&gt;”, la cual deberán extender cada uno de los elementos de su ejército.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cadena.de.responsabilidad;&lt;br /&gt;&lt;br /&gt;abstract class EjecutarOrdenAltoMando {&lt;br /&gt;&lt;br /&gt;    protected EjecutarOrdenAltoMando subAlterno;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public void setSubAlterno(EjecutarOrdenAltoMando subAlterno){&lt;br /&gt;        this.subAlterno = subAlterno;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public abstract void ejecutarOrden(Mensaje mensaje);&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Ahora, cada sub-alterno que extienda la clase abstracta, deberá definir un mecanismo que permita discriminar si la orden enviada la debe ejecutar el, o en caso contrario, enviar la orden a su sub-alterno.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cadena.de.responsabilidad;&lt;br /&gt;&lt;br /&gt;class GeneralMazingerZ extends EjecutarOrdenAltoMando {&lt;br /&gt;&lt;br /&gt;    public void ejecutarOrden(Mensaje mensaje){&lt;br /&gt;        if (mensaje.getPara().equals(&quot;OrdenGeneral&quot;)){&lt;br /&gt;            System.out.println(mensaje.getContenido());&lt;br /&gt;        }&lt;br /&gt;        else if (subAlterno != null){&lt;br /&gt;            subAlterno.ejecutarOrden(mensaje);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cadena.de.responsabilidad;&lt;br /&gt;&lt;br /&gt;class CoronelElVengador extends EjecutarOrdenAltoMando {&lt;br /&gt;&lt;br /&gt;   public void ejecutarOrden(Mensaje mensaje){&lt;br /&gt;       if (mensaje.getPara().equals(&quot;OrdenCoronel&quot;)){&lt;br /&gt;           System.out.println(mensaje.getContenido());&lt;br /&gt;       }&lt;br /&gt;       else if (subAlterno != null){&lt;br /&gt;           subAlterno.ejecutarOrden(mensaje);&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cadena.de.responsabilidad;&lt;br /&gt;&lt;br /&gt;class SoldadoElGalatico extends EjecutarOrdenAltoMando {&lt;br /&gt;&lt;br /&gt;    public void ejecutarOrden(Mensaje mensaje){&lt;br /&gt;        if (mensaje.getPara().equals(&quot;OrdenSoldado&quot;)){&lt;br /&gt;            System.out.println(mensaje.getContenido());&lt;br /&gt;        }&lt;br /&gt;        else{&lt;br /&gt;            System.out.println(&quot;EL TIPO DE ORDEN NO EXISTE&quot;);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Finalmente, será muy fácil para Cerebro enviar un mensaje a su ejército, el simplemente dará la orden a su “&lt;span style=&quot;font-weight: bold;&quot;&gt;General&lt;/span&gt;” y listo!!&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cadena.de.responsabilidad;&lt;br /&gt;&lt;br /&gt;public class Cerebro {&lt;br /&gt;&lt;br /&gt; public static Mensaje[] generarMensajes(){&lt;br /&gt;        Mensaje mensajes [] = {&lt;br /&gt;             new Mensaje(&quot;OrdenGeneral&quot;, &quot;Ejecutar Orden General Mazinger Z&quot;),&lt;br /&gt;             new Mensaje(&quot;OrdenCoronel&quot;, &quot;Ejecutar Orden Coronel El Vengador&quot;),&lt;br /&gt;             new Mensaje(&quot;OrdenSoldado&quot;, &quot;Ejecutar Orden Soldado El Galatico&quot;),&lt;br /&gt;             new Mensaje(&quot;OrdenCoronel&quot;, &quot;Ejecutar Orden Coronel El Vengador&quot;),&lt;br /&gt;             new Mensaje(&quot;OrdenGeneral&quot;, &quot;Ejecutar Orden General Mazinger Z&quot;),&lt;br /&gt;             new Mensaje(&quot;OrdenSoldado&quot;, &quot;Ejecutar Orden Soldado El Galatico&quot;)   &lt;br /&gt;        };&lt;br /&gt;        return mensajes;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static EjecutarOrdenAltoMando configurarCadena(){&lt;br /&gt;        EjecutarOrdenAltoMando generalMazingerZ = new GeneralMazingerZ();&lt;br /&gt;     EjecutarOrdenAltoMando coronelElVengador = new CoronelElVengador();&lt;br /&gt;     EjecutarOrdenAltoMando soldadoElGalatico = new SoldadoElGalatico();&lt;br /&gt;     generalMazingerZ.setSubAlterno(coronelElVengador);&lt;br /&gt;     coronelElVengador.setSubAlterno(soldadoElGalatico);&lt;br /&gt;        return generalMazingerZ;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;     EjecutarOrdenAltoMando generalMazingerZ = configurarCadena();&lt;br /&gt;     for(Mensaje mensaje : generarMensajes()){&lt;br /&gt;         generalMazingerZ.ejecutarOrden(mensaje);&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Cerebro lo ha conseguido nuevamente, ha logrado diseñar un nuevo mecanismo de comunicación para su ejército, continuando su malvado plan………“&lt;span style=&quot;font-weight: bold;&quot;&gt;TRATAR DE CONQUISTAR AL MUNDO!!!!&lt;/span&gt;”&lt;/div&gt;</description><link>http://dukechile.blogspot.com/2008/08/el-patrn-cadena-de-responsabilidad.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO5HPbG-3IADGOKprxZMXjxgkQapvzLL6Jgfx5EJCeWzMNqPaYSDVI60Lf4_OuRpVuorc1JKOZ5dI4Bq0SE00qdF1CUF-zlmOXTVBg0emPb1QQVce1OsdYqzV0HCW00_ivOdfc4g3bVYhj/s72-c/cadenaderesponsabilidad.JPG" height="72" width="72"/><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-6027713639446041822</guid><pubDate>Sun, 20 Jul 2008 21:13:00 +0000</pubDate><atom:updated>2008-08-23T12:38:33.991-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">SPRING</category><title>Introducción a Spring Framework</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;Spring es un framework open source creado por Rod Johnson, el cual fue inicialmente descrito en su libro “&lt;span style=&quot;font-style: italic;&quot;&gt;Expert One-on-One: J2EE Design and Development&lt;/span&gt;”. El objetivo de Rod Johnson era implementar un framework que permitiese desarrollar aplicaciones empresariales de manera más fácil y rápida, utilizando POJOs (&lt;span style=&quot;font-style: italic;&quot;&gt;Plain Old Java Object&lt;/span&gt;) para lograr cosas que antes eran solamente posibles con EJBs.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Uno de los principales objetivos de Spring es no ser intrusito. Esto quiere decir, que aquellas aplicaciones configuradas para utilizar “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Beans&lt;/span&gt;” mediante Spring no necesitan depender de interfaces o clases de Spring, obteniendo su configuración a través de las propiedades de sus &quot;&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Beans&lt;/span&gt;&quot;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Este concepto puede ser aplicado a cualquier entorno, desde una aplicación J2EE hasta un applet.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Spring está compuesto por un conjunto características, las cuales están agrupadas en seis módulos principales:&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9tFxKj7K8AgIA2pL-JCXb2pTTZpHtgNd4rpxpcc8fUTWht6ShcH56Bbh9B-CX6ew7WqiNwR_Lkwcx5jOAnFqRhi5nA3-RM5LdupiKEvApxHDZQNIas5BE1VDvUtDEU5EvFCGRuU0nlMz4/s1600-h/spring-overview.png&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9tFxKj7K8AgIA2pL-JCXb2pTTZpHtgNd4rpxpcc8fUTWht6ShcH56Bbh9B-CX6ew7WqiNwR_Lkwcx5jOAnFqRhi5nA3-RM5LdupiKEvApxHDZQNIas5BE1VDvUtDEU5EvFCGRuU0nlMz4/s400/spring-overview.png&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5225207880801308674&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El paquete “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Core&lt;/span&gt;” es la parte más fundamental del framework ya que provee a este, las características de Inversión de Control (&lt;span style=&quot;font-style: italic;&quot;&gt;IoC&lt;/span&gt;) y Inyección de dependencias (&lt;span style=&quot;font-style: italic;&quot;&gt;ID&lt;/span&gt;). El concepto básico dentro del “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Core&lt;/span&gt;” es el “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;BeanFactory&lt;/span&gt;”, el cual provee una sofisticada implementación del “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Patrón Factory&lt;/span&gt;”, que remueve la necesidad generalizada de “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Singletons&lt;/span&gt;” y nos permite desacoplar la configuración y especificación de las dependencias de nuestra lógica de programación.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El paquete “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Context&lt;/span&gt;” está construido sobre una solida base provista por el paquete “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Core&lt;/span&gt;”, el cual proporciona un medio de acceso a los objetos contenidos en el framework de forma tal, que recuerda en cierta medida a la manera en cómo trabaja el registro  JNDI. Este paquete hereda algunas características del paquete “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Beans&lt;/span&gt;” y añade soporte para internacionalización (&lt;span style=&quot;font-style: italic;&quot;&gt;I18N&lt;/span&gt;), propagación de eventos, carga de recursos y la transparente creación de contextos, como por ejemplo, un “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Servlet Container&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El paquete “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;DAO&lt;/span&gt;” provee una capa de abstracción a JDBC, eliminando la tediosa codificación propia de JDBC y el parseo de los códigos de errores específicos de cada proveedor de base de datos. Así también, este paquete proporciona mecanismos de manejo de transacciones tanto programáticamente como declarativamente, cuyo manejo no está restringido a clases que implementen algún tipo de interfaz especial, sino que también está pensado para cualquiera de nuestros POJOs.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El paquete “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;ORM&lt;/span&gt;” provee una capa de integración con las APIs más populares de “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Mapeo Objeto-Relacional&lt;/span&gt;”, tales como JPA, JDO, Hibernate y iBatis. Usando este paquete nosotros pidremos utilizara cualquiera de estos ORM en combinación con todas las otras características que Spring ofrece.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El paquete “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;AOP&lt;/span&gt;” de Spring, provee una implementación para la programación “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Orientada a Aspectos&lt;/span&gt;” compatible con el “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;AOP Alliance&lt;/span&gt;” que nos permite definir, por ejemplo, interceptores a un método (&lt;span style=&quot;font-style: italic;&quot;&gt;method-interceptors&lt;/span&gt;) y puntos de corte (&lt;span style=&quot;font-style: italic;&quot;&gt;pointcuts&lt;/span&gt;) para desacoplar limpiamente algunas funcionalidades implementadas en el código que lógicamente deberían conversar por separado.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El paquete “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Web&lt;/span&gt;” de Spring provee características de integración orientadas a la Web, tales como funcionalidades para la carga de archivos, la inicialización del contenedor IoC usando “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;Servlet Listeners&lt;/span&gt;” y un contexto de aplicación orientado a la web.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El paquete “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;MVC&lt;/span&gt;” de Spring, provee una implementación del patrón MVC (&lt;span style=&quot;font-style: italic;&quot;&gt;Moldeo-Vista-Controlador&lt;/span&gt;) para las aplicaciones web. Spring MVC provee una limpia separación  entre el código del modelo de dominio y los formularios web, integrándose a todas las otras características que este framework entrega.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Ejemplo Basico&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Para poder comenzar a desarrollar en Spring lo primero que necesitamos es descargarnos la versión 2.5.5 desde &lt;a href=&quot;http://www.blogger.com/www.springframework.org&quot;&gt;www.springframework.org&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;En la sección de “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;download&lt;/span&gt;” encontraran tres tipo de archivos a descargar: Spring 2.5.5 (&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;spring-framework-2.5.5.zip&lt;/span&gt;), Spring 2.5.5 incluyendo la documentación (&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;spring-framework-2.5.5-with-docs.zip&lt;/span&gt;) y Spring 2.5.5 incluyendo todas las dependencias (&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;spring-framework-2.5.5-with-dependencies.zip&lt;/span&gt;). Para este ejemplo y los futuros ejemplos, necesitaremos la última de estas tres opciones.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Una vez descargados los archivos, procedemos a crear el proyecto. Para este caso, tenemos varias opciones: podemos utilizar Netbeans 6.x el cual ya incluye soporte para Spring, Eclipse 3.x al cual se le debe instalar Spring IDE o IntelliJ el cual también incluye soporte para Spring.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;En este caso utilizare IntelliJ para los ejemplos.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Primero creamos el proyecto seleccionado la opción “&lt;span style=&quot;font-weight: bold;&quot;&gt;File --&gt; New Project…&lt;/span&gt;”. Luego seleccionamos la opción “&lt;span style=&quot;font-weight: bold;&quot;&gt;Create Project from scratch&lt;/span&gt;” y presionamos el botón “&lt;span style=&quot;font-weight: bold;&quot;&gt;Next&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8g99E29hWZ-x4sfQXus-XO7EM-siFxndQn4NZP39Tc5qMtCeSGpR1maRDECSwNIElZj7ifIyGaTFncYCj3v8IhfvsXZJUXbfYL4wJQu838DKBPh4WJsgM3oHFVyWHP3kkd-SI6OFBEYtI/s1600-h/paso1.JPG&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8g99E29hWZ-x4sfQXus-XO7EM-siFxndQn4NZP39Tc5qMtCeSGpR1maRDECSwNIElZj7ifIyGaTFncYCj3v8IhfvsXZJUXbfYL4wJQu838DKBPh4WJsgM3oHFVyWHP3kkd-SI6OFBEYtI/s400/paso1.JPG&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5225208708831202114&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;A continuación, ingresamos el nombre del proyecto, que para nuestro caso será “&lt;span style=&quot;font-weight: bold;&quot;&gt;SpringBasico&lt;/span&gt;” y presionamos el botón “&lt;span style=&quot;font-weight: bold;&quot;&gt;Next&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz9wKcl91oyftq3wMxiPnFYP2p_srb_UhiV74gVh3FHWBa495ywEEbiSQHsOo3cXT6hHcN0FexcdX4XZqnd6RlQkQhnPKSgwCn0Zr_3kemLWAqo952LrZ6znNcAqBCbQlR8Lcw8jD8yNrC/s1600-h/paso2.JPG&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz9wKcl91oyftq3wMxiPnFYP2p_srb_UhiV74gVh3FHWBa495ywEEbiSQHsOo3cXT6hHcN0FexcdX4XZqnd6RlQkQhnPKSgwCn0Zr_3kemLWAqo952LrZ6znNcAqBCbQlR8Lcw8jD8yNrC/s400/paso2.JPG&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5225209027585445570&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Luego, seleccionamos la opción “&lt;span style=&quot;font-weight: bold;&quot;&gt;Create source Directory&lt;/span&gt;” y presionamos el botón “&lt;span style=&quot;font-weight: bold;&quot;&gt;Next&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Por último, seleccionamos que la tecnología deseada para utilizar en el proyecto es “&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring&lt;/span&gt;” y presionamos el botón “&lt;span style=&quot;font-weight: bold;&quot;&gt;Finish&lt;/span&gt;”. Con lo que se nos construirá la estructura básica de nuestro proyecto.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq1inBV3-_xs7uNek3q57rXwicER7mX5EkdP5vLlvLtHYVYlXid8A9Og-kDCuFUm7IhLw7X1PE8TXusFYndOtPbe-kTE3RgJBXvTgselJJ-RplMAGmYOuyQY4zAEClau96JN6H71GRFwpR/s1600-h/paso3.JPG&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq1inBV3-_xs7uNek3q57rXwicER7mX5EkdP5vLlvLtHYVYlXid8A9Og-kDCuFUm7IhLw7X1PE8TXusFYndOtPbe-kTE3RgJBXvTgselJJ-RplMAGmYOuyQY4zAEClau96JN6H71GRFwpR/s400/paso3.JPG&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5225209298711522018&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El único problema, es que la última versión de IntelliJ IDEA solamente tiene soporte hasta la versión 2.0.7 de Spring, razón por la cual necesitaremos cambiar la librería “&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring.jar&lt;/span&gt;” por la versión que nosotros descargamos.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Para esto, nos posicionamos sobre el proyecto, presionamos el botón derecho del mouse y seleccionamos la opción “&lt;span style=&quot;font-weight: bold;&quot;&gt;Module Settings&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSVQxOmZ0DSdXOM0Qf_EhgzEEsgfH8eUCVe0jSmNseYd0_pmMCWsOLwnHjvt14WdrSx8mYj5yAneAtguSf6eRKYhOA07LylXV4skoOZoeCKKGmByNeDqKpXjM9TmrZV7xd_8u8qR8hTPhP/s1600-h/paso4.JPG&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSVQxOmZ0DSdXOM0Qf_EhgzEEsgfH8eUCVe0jSmNseYd0_pmMCWsOLwnHjvt14WdrSx8mYj5yAneAtguSf6eRKYhOA07LylXV4skoOZoeCKKGmByNeDqKpXjM9TmrZV7xd_8u8qR8hTPhP/s400/paso4.JPG&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5225209556078433986&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Luego, en las opciones de “&lt;span style=&quot;font-weight: bold;&quot;&gt;Project Settings&lt;/span&gt;” seleccionamos “&lt;span style=&quot;font-weight: bold;&quot;&gt;Libraries&lt;/span&gt;”. Es aquí donde cambiaremos el nombre de nuestro paquete de librerías y modificaremos el “&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring.jar&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El primer paso será cambiar el nombre del paquete “&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring-2.0.7&lt;/span&gt;” por “&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring-2.5.5&lt;/span&gt;”. Luego, seleccionamos la ruta del archivo “&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring.jar&lt;/span&gt;” y presionamos el botón “&lt;span style=&quot;font-weight: bold;&quot;&gt;Detach&lt;/span&gt;”. Por último, presionamos el botón “&lt;span style=&quot;font-weight: bold;&quot;&gt;Attach Classes…&lt;/span&gt;”, seleccionamos el archivo “&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring.jar&lt;/span&gt;” que se encuentra en la carpeta “&lt;span style=&quot;font-weight: bold;&quot;&gt;dist&lt;/span&gt;” de la versión que descargamos anteriormente y presionamos el botón “&lt;span style=&quot;font-weight: bold;&quot;&gt;Ok&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Para finalizar, presionamos el botón “&lt;span style=&quot;font-weight: bold;&quot;&gt;Apply&lt;/span&gt;” para que confirme y actualice todos los cambios, y presionamos el botón “&lt;span style=&quot;font-weight: bold;&quot;&gt;OK&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El último cambio lo deberemos realizar sobre el archivo “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;spring-config.xml&lt;/span&gt;”. Como IntelliJ solamente tiene soporta para Spring 2.0.7, la definición XSD de este archivo es para la versión 2 de Spring. Por esta razón, deberemos cambiar esta por la versión 2.5.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot; xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; p=&quot;http://www.springframework.org/schema/p&quot; context=&quot;http://www.springframework.org/schema/context&quot; schemalocation=&quot;http://www.springframework.org/schema/beans                            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd                            http://www.springframework.org/schema/context                            http://www.springframework.org/schema/context/spring-context-2.5.xsd&quot;&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Para nuestro primer ejemplo, desarrollaremos una idea simple que nos permita ver algunos de los beneficios básicos de Spring.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Imaginemos que necesitamos construir un robot, al cual le ensamblaremos un par de piernas, un par de brazos y una cabeza. Una primera propuesta a nuestro problema sería la siguiente:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso1;&lt;br /&gt;&lt;br /&gt;public class BrazoImpl {&lt;br /&gt;&lt;br /&gt;    private String tipo;&lt;br /&gt;&lt;br /&gt;    public void setTipo(String tipo){&lt;br /&gt;        this.tipo = tipo;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void mover(){&lt;br /&gt;       System.out.println(&quot;Moviendo el brazo : &quot; + tipo);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso1;&lt;br /&gt;&lt;br /&gt;public class PiernaImpl {&lt;br /&gt;&lt;br /&gt;    private String tipo;&lt;br /&gt;&lt;br /&gt;    public void setTipo(String tipo){&lt;br /&gt;        this.tipo = tipo;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void arrodillarse(){&lt;br /&gt;       System.out.println(&quot;Arrodillando la pierna : &quot; + tipo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void saltar(){&lt;br /&gt;       System.out.println(&quot;Saltando con la pierna : &quot; + tipo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void correr(){&lt;br /&gt;       System.out.println(&quot;Corriendo con la pierna : &quot; + tipo);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso1;&lt;br /&gt;&lt;br /&gt;public class CabezaImpl {&lt;br /&gt;&lt;br /&gt;    public void mover(){&lt;br /&gt;        System.out.println(&quot;Moviendo la cabeza&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void pensar(){&lt;br /&gt;        System.out.println(&quot;Pensando.....&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso1;&lt;br /&gt;&lt;br /&gt;public class RobotImpl {&lt;br /&gt;&lt;br /&gt;    private CabezaImpl cabezaImpl;&lt;br /&gt;    private BrazoImpl brazoDImpl;&lt;br /&gt;    private BrazoImpl brazoIImpl;&lt;br /&gt;    private PiernaImpl piernaDImpl;&lt;br /&gt;    private PiernaImpl piernaIImpl;&lt;br /&gt;&lt;br /&gt;    public RobotImpl(){&lt;br /&gt;        cabezaImpl = new CabezaImpl();&lt;br /&gt;        brazoDImpl = new BrazoImpl();&lt;br /&gt;        brazoDImpl.setTipo(&quot;derecho&quot;);&lt;br /&gt;        brazoIImpl = new BrazoImpl();&lt;br /&gt;        brazoIImpl.setTipo(&quot;izquierdo&quot;);&lt;br /&gt;        piernaDImpl = new PiernaImpl();&lt;br /&gt;        piernaDImpl.setTipo(&quot;derecha&quot;);&lt;br /&gt;        piernaIImpl = new PiernaImpl();&lt;br /&gt;        piernaIImpl.setTipo(&quot;izquierda&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void moverRobot(){&lt;br /&gt;        cabezaImpl.mover();&lt;br /&gt;        brazoDImpl.mover();&lt;br /&gt;        brazoIImpl.mover();&lt;br /&gt;        piernaDImpl.correr();&lt;br /&gt;        piernaIImpl.correr();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso1;&lt;br /&gt;&lt;br /&gt;public class Test {&lt;br /&gt;&lt;br /&gt;    public static void main(String args[]){&lt;br /&gt;        RobotImpl robotImpl = new RobotImpl();&lt;br /&gt;        robotImpl.moverRobot();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El problema con esta implementación es que el código esta “&lt;span style=&quot;font-weight: bold;&quot;&gt;Altamente Acoplado&lt;/span&gt;”. Que sucedería si decidimos cambiar la implementación de un brazo? No solamente tendríamos que modificar la clase “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;BrazoImpl&lt;/span&gt;”, sino también la clase “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;RobotImpl&lt;/span&gt;”. Es aquí donde la inversión de control “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;IoC&lt;/span&gt;” y la inyección de dependencias “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;ID&lt;/span&gt;” nos ayudan (más información de IoC y ID  la pueden encontrar &lt;a href=&quot;http://dukechile.blogspot.com/2008/06/inversion-de-control-ioc.html&quot;&gt;aquí&lt;/a&gt;).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El primer cambio que tendremos que realizar al código, es que cada pieza del robot deberá implementar una interfaz, con lo cual estaremos definiendo un contrato para cada una de estas piezas, y en el caso de que necesitemos diseñar un nuevo brazo o una nueva pierna, simplemente deberemos implementar la interfaz asociada al tipo de pieza.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso2;&lt;br /&gt;&lt;br /&gt;public interface Brazo {&lt;br /&gt;&lt;br /&gt;    void mover();&lt;br /&gt;    &lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso2;&lt;br /&gt;&lt;br /&gt;public class BrazoImpl implements Brazo{&lt;br /&gt;&lt;br /&gt;    private String tipo;&lt;br /&gt;&lt;br /&gt;    public void setTipo(String tipo){&lt;br /&gt;        this.tipo = tipo;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void mover(){&lt;br /&gt;       System.out.println(&quot;Moviendo el brazo : &quot; + tipo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso2;&lt;br /&gt;&lt;br /&gt;public interface Pierna {&lt;br /&gt;&lt;br /&gt;    void arrodillarse();&lt;br /&gt;    void saltar();&lt;br /&gt;    void correr();&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso2;&lt;br /&gt;&lt;br /&gt;public class PiernaImpl implements Pierna{&lt;br /&gt;&lt;br /&gt;    private String tipo;&lt;br /&gt;&lt;br /&gt;    public void setTipo(String tipo){&lt;br /&gt;        this.tipo = tipo;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void arrodillarse(){&lt;br /&gt;       System.out.println(&quot;Arrodillando la pierna : &quot; + tipo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void saltar(){&lt;br /&gt;       System.out.println(&quot;Saltando con la pierna : &quot; + tipo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void correr(){&lt;br /&gt;       System.out.println(&quot;Corriendo con la pierna : &quot; + tipo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso2;&lt;br /&gt;&lt;br /&gt;public interface Cabeza {&lt;br /&gt;&lt;br /&gt;    void mover();&lt;br /&gt;    void pensar();&lt;br /&gt;    &lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso2;&lt;br /&gt;&lt;br /&gt;public class CabezaImpl implements Cabeza{&lt;br /&gt;&lt;br /&gt;    public void mover(){&lt;br /&gt;        System.out.println(&quot;Moviendo la cabeza&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void pensar(){&lt;br /&gt;        System.out.println(&quot;Pensando.....&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso2;&lt;br /&gt;&lt;br /&gt;public interface Robot {&lt;br /&gt;&lt;br /&gt;    void moverRobot();&lt;br /&gt;    &lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso2;&lt;br /&gt;&lt;br /&gt;public class RobotImpl implements Robot{&lt;br /&gt;&lt;br /&gt;    private Cabeza cabeza;&lt;br /&gt;    private Brazo  brazoD;&lt;br /&gt;    private Brazo  brazoI;&lt;br /&gt;    private Pierna piernaD;&lt;br /&gt;    private Pierna piernaI;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public void moverRobot(){&lt;br /&gt;        cabeza.mover();&lt;br /&gt;        brazoD.mover();&lt;br /&gt;        brazoI.mover();&lt;br /&gt;        piernaD.correr();&lt;br /&gt;        piernaI.correr();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;    public void setCabeza(Cabeza cabeza) {&lt;br /&gt;        this.cabeza = cabeza;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setBrazoD(Brazo brazoD) {&lt;br /&gt;        this.brazoD = brazoD;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setBrazoI(Brazo brazoI) {&lt;br /&gt;        this.brazoI = brazoI;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setPiernaD(Pierna piernaD) {&lt;br /&gt;        this.piernaD = piernaD;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setPiernaI(Pierna piernaI) {&lt;br /&gt;        this.piernaI = piernaI;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Pero quien se encargara de ensamblar el robot? Aquí es donde Spring entra en acción. En el archivo “&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;spring-config.xml&lt;/span&gt;” definiremos cada una de estas piezas como “&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Beans&lt;/span&gt;” de Spring.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot; xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; p=&quot;http://www.springframework.org/schema/p&quot; context=&quot;http://www.springframework.org/schema/context&quot; schemalocation=&quot;http://www.springframework.org/schema/beans                            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd                            http://www.springframework.org/schema/context                            http://www.springframework.org/schema/context/spring-context-2.5.xsd&quot;&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;brazoD&quot; class=&quot;cl.jug.spring.basico.paso2.BrazoImpl&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;tipo&quot; value=&quot;derecho&quot;&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;brazoI&quot; class=&quot;cl.jug.spring.basico.paso2.BrazoImpl&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;tipo&quot; value=&quot;izquierdo&quot;&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;piernaD&quot; class=&quot;cl.jug.spring.basico.paso2.PiernaImpl&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;tipo&quot; value=&quot;derecha&quot;&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;piernaI&quot; class=&quot;cl.jug.spring.basico.paso2.PiernaImpl&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;tipo&quot; value=&quot;izquierda&quot;&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;cabeza&quot; class=&quot;cl.jug.spring.basico.paso2.CabezaImpl&quot;&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;robot&quot; class=&quot;cl.jug.spring.basico.paso2.RobotImpl&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;brazoD&quot; ref=&quot;brazoD&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;brazoI&quot; ref=&quot;brazoI&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;piernaD&quot; ref=&quot;piernaD&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;piernaI&quot; ref=&quot;piernaI&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;cabeza&quot; ref=&quot;cabeza&quot;&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;&lt;/beans&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Como podemos observar, para definir un bean en Spring se utiliza el tag “&lt;span style=&quot;font-weight: bold;&quot;&gt;bean&lt;/span&gt;”, al cual se le asigna un “&lt;span style=&quot;font-weight: bold;&quot;&gt;id&lt;/span&gt;” único y la clase que define al bean.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Utilizando el tag “&lt;span style=&quot;font-weight: bold;&quot;&gt;property&lt;/span&gt;” se puede inyectar un valor al bean. El atributo “&lt;span style=&quot;font-weight: bold;&quot;&gt;name&lt;/span&gt;” es el nombre del atributo de la clase que tiene definido un método set en el bean, y el atributo “&lt;span style=&quot;font-weight: bold;&quot;&gt;value&lt;/span&gt;”, es el valor que se le inyectara a este bean a través del método set.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Ahora, nuestra clase Test es mucho más simple:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso2;&lt;br /&gt;&lt;br /&gt;import org.springframework.beans.factory.BeanFactory;&lt;br /&gt;import org.springframework.beans.factory.xml.XmlBeanFactory;&lt;br /&gt;import org.springframework.core.io.ClassPathResource;&lt;br /&gt;&lt;br /&gt;public class Test {&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) throws Exception {&lt;br /&gt;        BeanFactory factory = new XmlBeanFactory(new ClassPathResource(&quot;spring-config.xml&quot;));&lt;br /&gt;        Robot robot = (Robot) factory.getBean(&quot;robot&quot;);&lt;br /&gt;        robot.moverRobot();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Hasta aquí todo bien, pero.....……que sucedería si tuviéramos que definir 60 beans que representen a algunos objetos del dominio de nuestra aplicación, los que a su vez dependen de 15 objetos de servicios o cualquier otra cosa. Lo único que conseguiríamos sería un gran archivo XML con muchas definiciones de beans.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Una solución sería dividir este XML, en XMLs más pequeños, pero igual seguiríamos con el problema de que en la medida que se necesiten nuevos bean se seguirán definiendo nuevos archivos XML.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Con la versión de Spring 2.5 tenemos una mejor opción, el uso de anotaciones!!. En esta versión, Spring provee un conjunto de anotaciones que resuelven la dependencia de los objetos sin tener que utilizar XML.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Veamos un ejemplo de esto:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso3;&lt;br /&gt;&lt;br /&gt;public interface Brazo {&lt;br /&gt;&lt;br /&gt;    void mover();&lt;br /&gt;&lt;br /&gt;    void setTipo(String tipo);&lt;br /&gt;    &lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso3;&lt;br /&gt;&lt;br /&gt;import org.springframework.stereotype.Component;&lt;br /&gt;import org.springframework.context.annotation.Scope;&lt;br /&gt;&lt;br /&gt;@Scope(&quot;prototype&quot;)&lt;br /&gt;@Component(&quot;brazo&quot;)&lt;br /&gt;public class BrazoImpl implements Brazo{&lt;br /&gt;&lt;br /&gt;    private String tipo;&lt;br /&gt;&lt;br /&gt;    public void setTipo(String tipo){&lt;br /&gt;        this.tipo = tipo;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void mover(){&lt;br /&gt;       System.out.println(&quot;Moviendo el brazo : &quot; + tipo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso3;&lt;br /&gt;&lt;br /&gt;public interface Pierna {&lt;br /&gt;&lt;br /&gt;    void arrodillarse();&lt;br /&gt;    void saltar();&lt;br /&gt;    void correr();&lt;br /&gt;&lt;br /&gt;    void setTipo(String tipo);&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso3;&lt;br /&gt;&lt;br /&gt;import org.springframework.stereotype.Component;&lt;br /&gt;import org.springframework.context.annotation.Scope;&lt;br /&gt;&lt;br /&gt;@Scope(&quot;prototype&quot;)&lt;br /&gt;@Component(&quot;pierna&quot;)&lt;br /&gt;public class PiernaImpl implements Pierna{&lt;br /&gt;&lt;br /&gt;    private String tipo;&lt;br /&gt;&lt;br /&gt;    public void setTipo(String tipo){&lt;br /&gt;        this.tipo = tipo;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void arrodillarse(){&lt;br /&gt;       System.out.println(&quot;Arrodillando la pierna : &quot; + tipo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void saltar(){&lt;br /&gt;       System.out.println(&quot;Saltando con la pierna : &quot; + tipo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void correr(){&lt;br /&gt;       System.out.println(&quot;Corriendo con la pierna : &quot; + tipo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso3;&lt;br /&gt;&lt;br /&gt;public interface Cabeza {&lt;br /&gt;&lt;br /&gt;    void mover();&lt;br /&gt;    void pensar();     &lt;br /&gt;    &lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso3;&lt;br /&gt;&lt;br /&gt;import org.springframework.stereotype.Component;&lt;br /&gt;import org.springframework.context.annotation.Scope;&lt;br /&gt;&lt;br /&gt;@Scope(&quot;prototype&quot;)&lt;br /&gt;@Component(&quot;cabeza&quot;)&lt;br /&gt;public class CabezaImpl implements Cabeza{&lt;br /&gt;&lt;br /&gt;    public void mover(){&lt;br /&gt;        System.out.println(&quot;Moviendo la cabeza&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void pensar(){&lt;br /&gt;        System.out.println(&quot;Pensando.....&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso3;&lt;br /&gt;&lt;br /&gt;public interface Robot {&lt;br /&gt;&lt;br /&gt;    void moverRobot();&lt;br /&gt;    &lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso3;&lt;br /&gt;&lt;br /&gt;import org.springframework.beans.factory.annotation.Autowired;&lt;br /&gt;import org.springframework.beans.factory.annotation.Qualifier;&lt;br /&gt;import org.springframework.stereotype.Component;&lt;br /&gt;&lt;br /&gt;import javax.annotation.PostConstruct;&lt;br /&gt;&lt;br /&gt;@Component(&quot;robot&quot;)&lt;br /&gt;public class RobotImpl implements Robot{&lt;br /&gt;&lt;br /&gt;    @Autowired(required=true)&lt;br /&gt;    @Qualifier(&quot;cabeza&quot;)&lt;br /&gt;    private Cabeza cabeza;&lt;br /&gt;&lt;br /&gt;    @Autowired(required=true)&lt;br /&gt;    @Qualifier(&quot;brazo&quot;)&lt;br /&gt;    private Brazo  brazoD;&lt;br /&gt;&lt;br /&gt;    @Autowired(required=true)&lt;br /&gt;    @Qualifier(&quot;brazo&quot;)&lt;br /&gt;    private Brazo brazoI;&lt;br /&gt;&lt;br /&gt;    @Autowired(required=true)&lt;br /&gt;    @Qualifier(&quot;pierna&quot;)&lt;br /&gt;    private Pierna piernaD;&lt;br /&gt;&lt;br /&gt;    @Autowired(required=true)&lt;br /&gt;    @Qualifier(&quot;pierna&quot;)&lt;br /&gt;    private Pierna piernaI;&lt;br /&gt;&lt;br /&gt;    @PostConstruct&lt;br /&gt;    public void inicializarTipos(){&lt;br /&gt;        brazoD.setTipo(&quot;derecho&quot;);&lt;br /&gt;        brazoI.setTipo(&quot;izquierdo&quot;);&lt;br /&gt;        piernaD.setTipo(&quot;derecha&quot;);&lt;br /&gt;        piernaI.setTipo(&quot;izquierda&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;    public void moverRobot(){&lt;br /&gt;        cabeza.mover();&lt;br /&gt;        brazoD.mover();&lt;br /&gt;        brazoI.mover();&lt;br /&gt;        piernaD.correr();&lt;br /&gt;        piernaI.correr();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;    public void setCabeza(Cabeza cabeza) {&lt;br /&gt;        this.cabeza = cabeza;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setBrazoD(Brazo brazoD) {&lt;br /&gt;        this.brazoD = brazoD;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setBrazoI(Brazo brazoI) {&lt;br /&gt;        this.brazoI = brazoI;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setPiernaD(Pierna piernaD) {&lt;br /&gt;        this.piernaD = piernaD;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setPiernaI(Pierna piernaI) {&lt;br /&gt;        this.piernaI = piernaI;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;La anotación &quot;&lt;span style=&quot;font-weight: bold;&quot;&gt;@ Autowired&lt;/span&gt;&quot; le informa a Spring, que deberá inyectar automáticamente la dependencia, basado en el tipo definido como Autowired (para nuestro caso, las piezas del robot).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Spring también nos permite definir que objeto será inyectado basándose no solamente en su tipo, sino también utilizando el nombre del bean, a través de la anotación &quot;&lt;span style=&quot;font-weight: bold;&quot;&gt;@ Qualifier&lt;/span&gt;&quot;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Pero como le definimos un nombre a los beans? Utilizando la anotación &quot;&lt;span style=&quot;font-weight: bold;&quot;&gt;@Component&lt;/span&gt;&quot;. Con esta anotación, registramos un nuevo bean que se encuentra disponible para ser inyectado por el contenedor de Spring.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Con estas anotaciones, ya no es necesario definir los &quot;&lt;span style=&quot;font-weight: bold;&quot;&gt;Beans&lt;/span&gt;&quot; en un XML.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Ahora, solamente nos queda decirle a Spring, que los bean se encuentran definidos utilizando anotaciones, para lo cual nuestro XML de configuración se reduce a esto:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot; xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; p=&quot;http://www.springframework.org/schema/p&quot; context=&quot;http://www.springframework.org/schema/context&quot; schemalocation=&quot;http://www.springframework.org/schema/beans                            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd                            http://www.springframework.org/schema/context                            http://www.springframework.org/schema/context/spring-context-2.5.xsd&quot;&gt;&lt;br /&gt;&lt;br /&gt;    &lt;context:annotation-config/&gt;&lt;br /&gt;&lt;br /&gt;    &lt;context:component-scan package=&quot;cl.jug.spring.basico.paso3&quot;&gt;   &lt;br /&gt;&lt;br /&gt;&lt;/beans&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Para nuestro test utilizaremos JUnit integrado a Spring:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package cl.jug.spring.basico.paso3;&lt;br /&gt;&lt;br /&gt;import org.springframework.test.AbstractDependencyInjectionSpringContextTests;&lt;br /&gt;import org.springframework.beans.factory.annotation.Autowired;&lt;br /&gt;&lt;br /&gt;public class TestRobot extends AbstractDependencyInjectionSpringContextTests {&lt;br /&gt;&lt;br /&gt;    @Autowired    &lt;br /&gt;    private Robot robot;&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    protected String[] getConfigLocations() {&lt;br /&gt;        return new String[] { &quot;spring-config2.xml&quot; };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void testEjecutarRobot() {&lt;br /&gt;        robot.moverRobot();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setRobot(Robot robot) {&lt;br /&gt;        this.robot = robot;&lt;br /&gt;    }&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Con este simple ejemplo ya podemos ver algunos de los conceptos básicos de Spring.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;En el próximo post veremos las diversas opciones de configuración de los Beans utilizando XML y algunos conceptos básicos del “&lt;span style=&quot;font-weight: bold;&quot;&gt;Core&lt;/span&gt;” como el &quot;&lt;span style=&quot;font-weight: bold;&quot;&gt;BeanFactory&lt;/span&gt;&quot;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Si alguien quiere mas información sobre el paquete “&lt;span style=&quot;font-weight: bold;&quot;&gt;JDBC&lt;/span&gt;”, José Miguel Selman está desarrollando una excelente serie de artículos introductorios que pueden encontrar &lt;a href=&quot;http://www.joseselman.com/2008/07/introduccion-a-acceso-a-bases-de-datos-con-java-jdbc-desafios/&quot;&gt;aquí&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;</description><link>http://dukechile.blogspot.com/2008/07/introduccin-spring-framework.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9tFxKj7K8AgIA2pL-JCXb2pTTZpHtgNd4rpxpcc8fUTWht6ShcH56Bbh9B-CX6ew7WqiNwR_Lkwcx5jOAnFqRhi5nA3-RM5LdupiKEvApxHDZQNIas5BE1VDvUtDEU5EvFCGRuU0nlMz4/s72-c/spring-overview.png" height="72" width="72"/><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-3428788653498033127</guid><pubDate>Tue, 08 Jul 2008 17:18:00 +0000</pubDate><atom:updated>2008-08-23T12:34:24.193-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Patrones de Diseño</category><title>El patrón &quot;Memento&quot; - Parte V</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;Cerebro se siente preparado para llevar a cabo su malvado plan. Tiene los conocimientos teóricos, tiene los conocimientos prácticos, pero hay tantos detalles que pulir antes de lanzarse a la conquista del mundo!.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;En los ejemplos anteriores, hemos visto como Cerebro ha implementado el “&lt;span style=&quot;font-weight: bold;&quot;&gt;Patron Prototype&lt;/span&gt;” (para crear su ejército de robots clones), el “&lt;span style=&quot;font-weight: bold;&quot;&gt;Patron Extension Objects&lt;/span&gt;” (para asignarles sus roles), el “&lt;span style=&quot;font-weight: bold;&quot;&gt;Patron Command&lt;/span&gt;” (para asignarles las ordenes), y el ”&lt;span style=&quot;font-weight: bold;&quot;&gt;Patron Observer&lt;/span&gt;” (para implementar el sistema de comunicaciones). Parece que Cerebro ha estado bastante ocupado implementando patrones, pero ha sido suficiente?. NO!!.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Si recuerdan el “&lt;span style=&quot;font-weight: bold;&quot;&gt;Patron Observer&lt;/span&gt;”, dejamos a los robots “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” y “&lt;span style=&quot;font-weight: bold;&quot;&gt;El Vengador&lt;/span&gt;” en el instante previo al ataque final. Están esperando a recibir la orden de ataque. Cada robot esta alerta, escuchando la radio, esperando escuchar la señal secreta, para abandonar su posición y lanzarse a cumplir las órdenes recibidas.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Cerebro está a punto de presionar el botón de &quot;Atacar&quot;, cuando de repente se da cuenta de que algo no está bien. Qué pasa si me veo obligado a dar la orden de retirada a mis tropas?. No es que mi plan vaya a fallar (después de todo soy un genio del mal), pero ya se sabe, no se puede confiar en los subordinados, y que pasa si tengo que cancelar el ataque cuando mis huestes ya han comenzado a avanzar?.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Ciertamente, Cerebro es un genio. Se ha dado cuenta de un sutil error en su plan. Qué pasaría si tiene que dar la orden de cancelar el ataque cuando sus tropas ya han abandonado su posición inicial?. Bueno, ha implementado un mecanismo de comunicaciones, así que puede mandar la señal secreta de retirada, no?. Pero hay un problema; los robots “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” y “&lt;span style=&quot;font-weight: bold;&quot;&gt;El Vengador&lt;/span&gt;” no implementan un buen sistema del manejo de la memoria (sabía que no tenía que instalarles Windows!!!!).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;La cuestión es complicada. Un robot “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” y “&lt;span style=&quot;font-weight: bold;&quot;&gt;El Vengador&lt;/span&gt;” no tienen buen manejo de la memoria. Solo pueden recordar una cosa a la vez. Por tanto, pueden recordar que tienen que atacar, que tienen que moverse hacia algún lugar, pero en cuanto se meten esa información en la memoria no son capaces de recordar nada más.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Dicho de otra forma, Cerebro les puede decir que vuelvan a su posición original, pero eso no va a servir de nada, porque no se acuerdan de cuál era su posición original.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Peeeeeero, Cerebro recuerda vagamente, como entre una nebulosa, haber leído algo del “&lt;span style=&quot;font-weight: bold;&quot;&gt;Patron Memento&lt;/span&gt;” de su gurú “&lt;span style=&quot;font-weight: bold;&quot;&gt;Martin Fowler&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7iugmY5wdjZnsE1MW-yObtvTZH0GWVJDW4gJmpam009Ifp4JaIedCrzWwWEdX1v7w0FFAxn55IB8wUY_Kh0kC5SEeU1od6Y6wJ6d0pR_drYaok6k6BIG-r7umyBIHHpe5WmdbN9FwOZLQ/s1600-h/memento.JPG&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7iugmY5wdjZnsE1MW-yObtvTZH0GWVJDW4gJmpam009Ifp4JaIedCrzWwWEdX1v7w0FFAxn55IB8wUY_Kh0kC5SEeU1od6Y6wJ6d0pR_drYaok6k6BIG-r7umyBIHHpe5WmdbN9FwOZLQ/s400/memento.JPG&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5237752203969082658&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Qué pasaría si cada robot “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” y “&lt;span style=&quot;font-weight: bold;&quot;&gt;El Vengador&lt;/span&gt;” fuera capaz de escribir en un cuaderno su posición inicial, y entregara ese cuaderno a su Sargento?. Y si el Sargento guardara esos cuadernos, y se los entregara a sus propietarios en el caso de que necesitasen volver a las posiciones iníciales?. Problema resuelto!. Es perfecto!. Las ovejas y las vacas solo tendrán que recordar una posición (la posición hacia la que se supone que tiene que ir, sin importar si están atacando o están en retirada), mientras una entidad externa les guardara la información que necesitaran para retirarse.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Pero cómo puede un robot “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” o “&lt;span style=&quot;font-weight: bold;&quot;&gt;El Vengador&lt;/span&gt;” guardar su información relevante en un cuaderno?. Fácil, cada robot será responsable de crear una instancia de la clase en la que se va a guardar su información interna, y la entregara a su sargento.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package memento.paso1;&lt;br /&gt;&lt;br /&gt;public class MazingerZMemento {&lt;br /&gt;&lt;br /&gt;    private int numeroSerie;&lt;br /&gt;    private String ubicacion;&lt;br /&gt;&lt;br /&gt;    public MazingerZMemento(int numeroSerie, String ubicacion) {&lt;br /&gt;        this.numeroSerie = numeroSerie;&lt;br /&gt;        this.ubicacion = ubicacion;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String getUbicacion() {&lt;br /&gt;        return ubicacion;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setUbicacion(String ubicacion) {&lt;br /&gt;        this.ubicacion = ubicacion;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Un momento!. Cerebro se ha dado cuenta de que hay un punto débil en su plan. Si el Sargento guarda los cuadernos con las posiciones iníciales de los robots, hay riesgos de seguridad. Qué pasa si los enemigos roban esa información?. O incluso peor!!. Y si los enemigos no roban esa información, pero la sustituyen por información falsa?. Pero……un momento!. Si la información contenida en los cuadernos estuviera encriptado, o solo fuera accesible por los robots, el problema estaría resuelto, nadie podría cambiarla!.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Por tanto, para evitar posibles cambios en esa información, Cerebro va a tomar dos medidas drásticas. Por un lado, todos los valores guardados en la clase &lt;span style=&quot;font-weight: bold;&quot;&gt;MazingerZMemento&lt;/span&gt; solo se podrán asignar a través del constructor. De ese modo, Cerebro se asegura que solo se podrán asignar al crear la clase, y nunca después.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Pero desgraciadamente, no es suficiente (es tan difícil conseguir un buen plan…uffff). Cerebro quiere evitar que la información guardada en el “&lt;span style=&quot;font-weight: bold;&quot;&gt;Memento&lt;/span&gt;” sea modificada. De hecho, quiere que solo sea el robot “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” o “&lt;span style=&quot;font-weight: bold;&quot;&gt;El Vengador&lt;/span&gt;”, el que pueda crear su memento correspondiente, y asignar sus valores. De esa forma, puede asegurarse de que nadie modifique esa información.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Hacer eso en Java es bastante fácil. Basta con colocar la clase &lt;span style=&quot;font-weight: bold;&quot;&gt;MazingerZMemento&lt;/span&gt; en el mismo package que la clase &lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;/span&gt;&quot;&lt;span style=&quot;font-weight: bold;&quot;&gt;MazingerZ&lt;/span&gt;&quot;, y hacer tanto su constructor como sus variables de clase protected. De esa forma, solo pueden crear instancias de esa clase otras clases que estén en su mismo paquete.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Por tanto la clase “&lt;span style=&quot;font-weight: bold;&quot;&gt;MazingerZ&lt;/span&gt;” es:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package memento.paso2;&lt;br /&gt;&lt;br /&gt;public class MazingerZMemento {&lt;br /&gt;&lt;br /&gt;    protected int numeroSerie;&lt;br /&gt;    protected String ubicacion;&lt;br /&gt;&lt;br /&gt;    protected MazingerZMemento(int numeroSerie, String ubicacion) {&lt;br /&gt;        this.numeroSerie = numeroSerie;&lt;br /&gt;        this.ubicacion = ubicacion;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package memento.paso2;&lt;br /&gt;&lt;br /&gt;public class MazingerZ {&lt;br /&gt;&lt;br /&gt;    private int numeroSerie;&lt;br /&gt;    private String ubicacion;&lt;br /&gt;&lt;br /&gt;    public MazingerZ(int numeroSerie, String ubicacion) {&lt;br /&gt;        this.numeroSerie = numeroSerie;&lt;br /&gt;        this.ubicacion = ubicacion;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public MazingerZMemento getMemento() {&lt;br /&gt;        return new MazingerZMemento(numeroSerie, ubicacion);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setMemento(MazingerZMemento memento) {&lt;br /&gt;        numeroSerie = memento.numeroSerie;&lt;br /&gt;        ubicacion = memento.ubicacion;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String getUbicacion() {&lt;br /&gt;        return ubicacion;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setUbicacion(String ubicacion) {&lt;br /&gt;        this.ubicacion = ubicacion;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String toString() {&lt;br /&gt;        return &quot;MazingerZ : numeroSerie &quot; + numeroSerie + &quot; ubicacion &quot; + ubicacion;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package memento.paso2;&lt;br /&gt;&lt;br /&gt;public class Sargento {&lt;br /&gt;&lt;br /&gt;    public void atacar() {&lt;br /&gt;        MazingerZ mazingerZ = new MazingerZ(1, &quot;5.2345&quot;);&lt;br /&gt;        MazingerZMemento estadoInicial = mazingerZ.getMemento();&lt;br /&gt;        System.out.println(&quot;posicion inicial&quot;);&lt;br /&gt;        System.out.println(mazingerZ);&lt;br /&gt;        System.out.println(&quot;cambiar esta posicion&quot;);&lt;br /&gt;        mazingerZ.setUbicacion(&quot;2.9961&quot;);&lt;br /&gt;        System.out.println(&quot;nueva posicion&quot;);&lt;br /&gt;        System.out.println(mazingerZ);&lt;br /&gt;        System.out.println(&quot;volver a la ubicacion inicial!&quot;);&lt;br /&gt;        mazingerZ.setMemento(estadoInicial);&lt;br /&gt;        System.out.println(mazingerZ);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        Sargento sargento = new Sargento();&lt;br /&gt;        sargento.atacar();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Cerebro lo ha conseguido de nuevo!!. Ha sido capaz de encapsular el estado interno de un objeto en otro objeto distinto, y encapsularlo tan bien que ese segundo objeto solo puede ser utilizado por el objeto que lo creo.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Ya está todo listo para conquistar al mundo!!!!!!!!&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://dukechile.blogspot.com/2008/08/el-patrn-cadena-de-responsabilidad.html&quot;&gt;Parte 6&lt;/a&gt;</description><link>http://dukechile.blogspot.com/2008/07/el-patrn-memento.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7iugmY5wdjZnsE1MW-yObtvTZH0GWVJDW4gJmpam009Ifp4JaIedCrzWwWEdX1v7w0FFAxn55IB8wUY_Kh0kC5SEeU1od6Y6wJ6d0pR_drYaok6k6BIG-r7umyBIHHpe5WmdbN9FwOZLQ/s72-c/memento.JPG" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-4711323034399889169</guid><pubDate>Sat, 05 Jul 2008 18:55:00 +0000</pubDate><atom:updated>2008-08-23T12:32:32.228-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Patrones de Diseño</category><title>El patrón &quot;Observer&quot; (Observador) - Parte IV</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;Esta desencadenado!!!!! El primer ataque ha sido lanzado. Cerebro ha dado las órdenes a sus tropas para dominar el mundo.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;En los ejemplos anteriores hemos visto como Cerebro ha conseguido clonar cualquier robot utilizando un “&lt;span style=&quot;font-weight: bold;&quot;&gt;Patron Prototype&lt;/span&gt;”, ha conseguido darles un rol dinámicamente con el “&lt;span style=&quot;font-weight: bold;&quot;&gt;Patron Extension Objects&lt;/span&gt;”, y ha repartido las ordenes con un “&lt;span style=&quot;font-weight: bold;&quot;&gt;Patron command&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Pero como ya sabemos, Cerebro está loco, pero no es tonto. Sabe, que algo puede salir mal, que un pequeño detalle puede destruir sus planes de dominar el mundo. Pero también sabe que una retirada a tiempo es una victoria.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Por lo tanto, ha equipado a sus tropas de una radio de comunicaciones. Pero, porque ha hecho esto?. Sencillo, en el fragor de la batalla, las comunicaciones directas se hacen complicadas. Es difícil hacer llegar las ordenes, y muchas veces no se tiene claro a quien le estamos dando esas órdenes ( será a “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” o “&lt;span style=&quot;font-weight: bold;&quot;&gt;El Vengador&lt;/span&gt;”? ). Conquistar el mundo no es fácil, de hecho muchos lo han intentado pero no lo han conseguido.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Cerebro ha estudiado con detenimiento todos los intentos anteriores para no reproducir los mismos errores que otros han cometido. Qué pasaría si para dar nuevas órdenes, necesitase que el sargento “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” tuviese que recorrer la trinchera indicando uno por uno a todos los robots que se retirasen?. Desde que le diese la orden al primer robot, hasta que se la diese al último, pasaría un tiempo precioso. Además, y si ocurre algo por el camino?. Las posibilidades de que las órdenes no lleguen a todos los integrantes de la tropa son amplias.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Sabiendo esto,  Cerebro recurre nuevamente a su gurú “&lt;span style=&quot;font-weight: bold;&quot;&gt;Marin Fowler&lt;/span&gt;” y decide hacer un cambio fácil y rápido el comportamiento de sus tropas, utilizando el “&lt;span style=&quot;font-weight: bold;&quot;&gt;Patron Observer&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKKBYznOwpQP1H16izJdQ5j07bXHw_DAz_VNO_Cl-PXJhE5igWLbxYEyIUphIy-zV7eFkhzRliFJgs7F54aXm5Q7NINH0ZA-adbv_5ho_7yxIyilEgZxxwojx4-aDEAIu6igM3l7AdPihm/s1600-h/observador.JPG&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKKBYznOwpQP1H16izJdQ5j07bXHw_DAz_VNO_Cl-PXJhE5igWLbxYEyIUphIy-zV7eFkhzRliFJgs7F54aXm5Q7NINH0ZA-adbv_5ho_7yxIyilEgZxxwojx4-aDEAIu6igM3l7AdPihm/s400/observador.JPG&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5237751700795542722&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Como Cerebro no es tonto, ha encontrado una malvada forma de enviar las órdenes a sus tropas. Los robots “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” y “&lt;span style=&quot;font-weight: bold;&quot;&gt;El Vengador&lt;/span&gt;”, estarán equipados con una radio que sintoniza “La señal del mal”. Sus tropas estarán atentas a la radio, y cuando esta emita una canción de “Metallica” les indicara que acción deben tomar.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;El código sería algo así:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package observer.paso1;&lt;br /&gt;&lt;br /&gt;public class Mensaje {&lt;br /&gt;&lt;br /&gt;    private String mensaje = &quot;&quot;;&lt;br /&gt;&lt;br /&gt;    public String getMensaje() {&lt;br /&gt;        return mensaje;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setMensaje(String mensaje) {&lt;br /&gt;        this.mensaje = mensaje;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package observer.paso1;&lt;br /&gt;&lt;br /&gt;public interface Observador {&lt;br /&gt;&lt;br /&gt;    public void actualizar(Mensaje informacion);&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package observer.paso1;&lt;br /&gt;&lt;br /&gt;public interface Sujeto {&lt;br /&gt;&lt;br /&gt;    public void addObservador(Observador obs);&lt;br /&gt;&lt;br /&gt;    public void removerObservador(Observador obs);&lt;br /&gt;&lt;br /&gt;    public void notificarObservador();&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package observer.paso1;&lt;br /&gt;&lt;br /&gt;public class MazingerZ implements Observador {&lt;br /&gt;&lt;br /&gt;    public MazingerZ() {&lt;br /&gt;        System.out.println(&quot;Construyendo robot Mazinger Z&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void mostrar(String arg) {&lt;br /&gt;        System.out.println(&quot;Mazinger Z : &quot; + arg);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void actualizar(Mensaje mensaje) {&lt;br /&gt;        mostrar(&quot;Actualizado&quot;);&lt;br /&gt;        String kk = mensaje.getMensaje();&lt;br /&gt;        mostrar(&quot;Mensaje de texto : &quot; + kk);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package observer.paso1;&lt;br /&gt;&lt;br /&gt;public class ElVengador implements Observador {&lt;br /&gt;&lt;br /&gt; public ElVengador() {&lt;br /&gt;  System.out.println(&quot;Construyendo robot El Vengador&quot;);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private void mostrar(String arg) {&lt;br /&gt;  System.out.println(&quot;El Vengador : &quot; + arg);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void actualizar(Mensaje mensaje) {&lt;br /&gt;  mostrar(&quot;Actualizado&quot;);&lt;br /&gt;  String kk = mensaje.getMensaje();&lt;br /&gt;  mostrar(&quot;Mensaje de texto : &quot; + kk);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package observer.paso1;&lt;br /&gt;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;&lt;br /&gt;public class Cerebro implements Sujeto {&lt;br /&gt;&lt;br /&gt;    private ArrayList misObservadores;&lt;br /&gt;    private Mensaje mensaje;&lt;br /&gt;&lt;br /&gt;    public Cerebro(){&lt;br /&gt;        mostrar(&quot;Creando a Cerebro&quot;);&lt;br /&gt;        misObservadores = new ArrayList();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void mostrar(String arg){&lt;br /&gt;        System.out.println(&quot;Cerebro : &quot;+arg);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void addObservador(Observador observador){&lt;br /&gt;        mostrar(&quot;Anadido un nuevo Observador&quot;);&lt;br /&gt;        misObservadores.add(observador);&lt;br /&gt;        mostrar(&quot;Ya tengo : &quot; + misObservadores.size() + &quot; observadores &quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void removerObservador(Observador observador){&lt;br /&gt;        mostrar(&quot;Eliminando un observador&quot;);&lt;br /&gt;        misObservadores.remove(observador);&lt;br /&gt;        mostrar(&quot;ahora me quedan : &quot; + misObservadores.size() + &quot; observadores &quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void notificarObservador(){&lt;br /&gt;        mostrar(&quot;notificar observador&quot;);&lt;br /&gt;        mensaje = new Mensaje();&lt;br /&gt;        mensaje.setMensaje(&quot;En la nave&quot;);&lt;br /&gt;        for( int i = 0; i &amp;lt; misObservadores.size(); i++ ){&lt;br /&gt;            Observador observador = (Observador) misObservadores.get(i);&lt;br /&gt;            observador.actualizar(mensaje);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package observer.paso1;&lt;br /&gt;&lt;br /&gt;public class Test {&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        Cerebro cerebro = new Cerebro();&lt;br /&gt;        MazingerZ mazingerZ1 = new MazingerZ();&lt;br /&gt;        ElVengador elVengador1 = new ElVengador();&lt;br /&gt;        MazingerZ mazingerZ2 = new MazingerZ();&lt;br /&gt;        ElVengador elVengador2 = new ElVengador();&lt;br /&gt;        MazingerZ mazingerZ3 = new MazingerZ();&lt;br /&gt;        ElVengador elVengador3 = new ElVengador();&lt;br /&gt;        cerebro.addObservador(mazingerZ1);&lt;br /&gt;        cerebro.addObservador(mazingerZ2);&lt;br /&gt;        cerebro.addObservador(mazingerZ3);&lt;br /&gt;        cerebro.addObservador(elVengador1);&lt;br /&gt;        cerebro.addObservador(elVengador2);&lt;br /&gt;        cerebro.addObservador(elVengador3);&lt;br /&gt;        cerebro.removerObservador(mazingerZ1);&lt;br /&gt;        cerebro.notificarObservador();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;De este modo, Cerebro se puede comunicar rápidamente con todas sus tropas. Es brillante, es genial, es maravilloso, es.........perfecto?. Bueno, la verdad es que está muy bien, pero imaginemos por un momento, una situación en la que un robot consigue infiltrarse en el alto mando enemigo, y descubre que el enemigo está a punto de ser derrotado, y justo en ese momento de éxtasis, la radio emite “The Call of Ktulu&quot; (la canción que indica a las tropas que hay que retirarse).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;NOOOOOOOOO (bueno, esto está traducido, claramente, un robot diría algo así como BEP-BEP-BEP). Nuestro robot espía, tiene una información valiosísima, pero que no puede comunicar a su alto mando, porque la forma de transmisión es únicamente de tipo “&lt;span style=&quot;font-weight: bold;&quot;&gt;Push&lt;/span&gt;” (desde Cerebro a sus tropas), por lo que no hay retorno.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Qué situación, el robot necesita transmitir que el ataque debe continuar pero......jajajajajajajaja, Cerebro ha pensado en ello, y ha decidido implementar un “&lt;span style=&quot;font-weight: bold;&quot;&gt;Patron observer&lt;/span&gt;” que permita la transmisión tipo “&lt;span style=&quot;font-weight: bold;&quot;&gt;Push&lt;/span&gt;” (del sujeto emisor a todos los sujetos receptores) y tipo “&lt;span style=&quot;font-weight: bold;&quot;&gt;Pull&lt;/span&gt;” (uno de los objetos receptores, puede solicitar una información al objeto emisor para que este la envié a todos los demás). Así, nuestro robot espía, estará equipado con un número de teléfono al que podrá llamar y solicitar que emitan &quot;Master of Puppets&quot;, y cuando esta canción sea emitida por la radio, los robots “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” y “&lt;span style=&quot;font-weight: bold;&quot;&gt;El Vengador&lt;/span&gt;” que la escuchen, sabrán que ha llegado el momento de la ofensiva final!!!. Para ello, Cerebro deberá modificar ligeramente su código.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El primer paso será que nuestro sujeto, implementara un nuevo método que hemos añadido a la interfaz Sujeto( solicitarInformacion ), que permitirá recibir las llamadas telefónicas del robot espía. Veremos también que el constructor de los robots “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” y “&lt;span style=&quot;font-weight: bold;&quot;&gt;El Vengador&lt;/span&gt;” también ha cambiado un poco. Ahora estos robots, almacenaran una referencia al constructor. También modificaremos el código de nuestro robot “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” (suponemos que este será el robot espía en el momento en que decide que pese a lo que emite la radio, hay que atacar y pide que se emita “Master of Puppets” que es otra señal de ataque ).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;El código final sería algo así:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package observer.paso2;&lt;br /&gt;&lt;br /&gt;import observer.paso1.Mensaje;&lt;br /&gt;import observer.paso1.Observador;&lt;br /&gt;&lt;br /&gt;public interface Sujeto {&lt;br /&gt;&lt;br /&gt;    public void addObservador(Observador obs);&lt;br /&gt;&lt;br /&gt;    public void removerObservador(Observador obs);&lt;br /&gt;&lt;br /&gt;    public void notificarObservador(Mensaje mensaje);&lt;br /&gt;&lt;br /&gt;    public void solicitarInformacion(String arg);&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package observer.paso2;&lt;br /&gt;&lt;br /&gt;import observer.paso1.Mensaje;&lt;br /&gt;import observer.paso1.Observador;&lt;br /&gt;&lt;br /&gt;public class MazingerZ implements Observador {&lt;br /&gt;&lt;br /&gt;    private Sujeto cerebro;&lt;br /&gt;&lt;br /&gt;    public MazingerZ(Sujeto sujeto) {&lt;br /&gt;        mostrar(&quot;creando a Mazinger Z&quot;);&lt;br /&gt;        this.cerebro = sujeto;&lt;br /&gt;        this.cerebro.addObservador(this);&lt;br /&gt;        this.cerebro.solicitarInformacion(&quot;Master of Puppets&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void mostrar(String arg) {&lt;br /&gt;        System.out.println(&quot;Mazinger Z : &quot; + arg);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void actualizar(Mensaje mensaje) {&lt;br /&gt;        mostrar(&quot;Actualizandome : &quot; + mensaje.getMensaje());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package observer.paso2;&lt;br /&gt;&lt;br /&gt;import observer.paso1.Mensaje;&lt;br /&gt;import observer.paso1.Observador;&lt;br /&gt;&lt;br /&gt;public class ElVengador implements Observador {&lt;br /&gt;&lt;br /&gt;    public ElVengador(){&lt;br /&gt;        mostrar(&quot;creando a El Vengador&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void mostrar(String arg) {&lt;br /&gt;        System.out.println(&quot;El Vengador : &quot; + arg);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void actualizar(Mensaje mensaje) {&lt;br /&gt;        mostrar(&quot;Actualizandome : &quot; + mensaje.getMensaje());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package observer.paso2;&lt;br /&gt;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;&lt;br /&gt;import observer.paso1.Mensaje;&lt;br /&gt;import observer.paso1.Observador;&lt;br /&gt;&lt;br /&gt;public class Cerebro implements Sujeto{&lt;br /&gt;&lt;br /&gt;    private ArrayList misObservadores;&lt;br /&gt;&lt;br /&gt;    public Cerebro(){&lt;br /&gt;        mostrar(&quot;Creando un nuevo Cerebro&quot;);&lt;br /&gt;        misObservadores = new ArrayList();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void mostrar(String arg){&lt;br /&gt;        System.out.println(&quot;Cerebro : &quot;+arg);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void addObservador(Observador obs){&lt;br /&gt;        mostrar(&quot;Anadido un nuevo observador&quot;);&lt;br /&gt;        misObservadores.add(obs);&lt;br /&gt;        mostrar(&quot;Ya tengo : &quot; + misObservadores.size() + &quot; observadores &quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void removerObservador(Observador obs){&lt;br /&gt;        mostrar(&quot;Eliminando observador&quot;);&lt;br /&gt;        misObservadores.remove(misObservadores.indexOf(obs));&lt;br /&gt;        mostrar(&quot;ahora me quedan : &quot; + misObservadores.size() + &quot; observadores &quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void notificarObservador(Mensaje msg ){&lt;br /&gt;        mostrar(&quot;notificar observadores&quot;);&lt;br /&gt;        for( int i = 0; i &amp;lt; misObservadores.size(); i++ ){&lt;br /&gt;            Observador obs = (Observador) misObservadores.get(i);&lt;br /&gt;            obs.actualizar(msg);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void solicitarInformacion(String arg){&lt;br /&gt;        mostrar(&quot;recibiendo una peticion&quot;);&lt;br /&gt;        Mensaje mensaje = new Mensaje();&lt;br /&gt;        mensaje.setMensaje(arg);&lt;br /&gt;        this.notificarObservador(mensaje);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package observer.paso2;&lt;br /&gt;&lt;br /&gt;public class Test {&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        Cerebro dispar = new Cerebro();&lt;br /&gt;        MazingerZ mazingerZ = new MazingerZ(dispar);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Evidentemente, Cerebro que ha estudiado la API de JAVA y sabe que existe la clase &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;java.util.Observable&lt;/span&gt; y la interface &lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;java.util.Observer.&lt;/span&gt; La primera no la ha utilizado, pues eso implicaría que Cerebro extienda o herede de “&lt;span style=&quot;font-weight: bold;&quot;&gt;Observable&lt;/span&gt;”. Esto podría ser posible, pero en realidad Cerebro extiende de una larga extirpe de profesores diabólicos empeñados en conquistar el mundo, y ni quiere ni puede extender de Observable. ( c&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;lass Cerebro extends ExtirpeDeProfesoresDiabolicos, Observable&lt;/span&gt; --&gt; esto no es posible ). Por eso ha decidido construirse su propia interface “&lt;span style=&quot;font-weight: bold;&quot;&gt;Sujeto&lt;/span&gt;”.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Con respecto a la interface &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;java.util.Observer&lt;/span&gt;, si la podría haber utilizado para que sus robots “&lt;span style=&quot;font-weight: bold;&quot;&gt;Mazinger Z&lt;/span&gt;” y “&lt;span style=&quot;font-weight: bold;&quot;&gt;El Vengador&lt;/span&gt;” la implementasen en lugar de implementar “&lt;span style=&quot;font-weight: bold;&quot;&gt;Observador&lt;/span&gt;”, pero ya saben, los genios del mal les gusta hacer las cosas a su manera.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Esta historia continuara……&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://dukechile.blogspot.com/2008/07/el-patrn-memento.html&quot;&gt;PARTE 5&lt;/a&gt;</description><link>http://dukechile.blogspot.com/2008/07/el-patrn-observer-observador.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKKBYznOwpQP1H16izJdQ5j07bXHw_DAz_VNO_Cl-PXJhE5igWLbxYEyIUphIy-zV7eFkhzRliFJgs7F54aXm5Q7NINH0ZA-adbv_5ho_7yxIyilEgZxxwojx4-aDEAIu6igM3l7AdPihm/s72-c/observador.JPG" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-3417252366133458648</guid><pubDate>Thu, 03 Jul 2008 23:40:00 +0000</pubDate><atom:updated>2008-08-23T12:29:46.594-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Patrones de Diseño</category><title>El patrón &quot;Command&quot; - Parte III</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;Todo está preparado. Cerebro ya cuenta con un gran número de copias de los robots “Mazinger Z” y “El Vengador”. Además, ha asignado los roles a cada uno de estos. Es el momento perfecto para que Cerebro lance su ataque final. Ha llegado el momento de conquistar el mundo!!!!&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Pero como dará Cerebro la orden de atacar a sus tropas?.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Cerebro está loco, pero no es idiota. Quiere conquistar el mundo, para lo cual ha ideado un plan malvado perfecto!!!. Pero sabe que tener un buen plan (aunque sea malvado) no es una garantía para el éxito. Necesita un plan de emergencia.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Cerebro quiere que algunos de sus robots soldados participen en el primer (y por tanto, glorioso) ataque. Pero también quiere reservar unos cuantos robots soldados y dejarlos descansando, mientras sus colegas son masacrados en el campo de batalla, para que puedan ser utilizados como refuerzos.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Pero, como podrá hacerlo?. Cerebro es un genio muuuuuy ocupado, por lo tanto el ataque debe poder ser lanzado sin mucha intervención de su parte. Algo tan simple como apretar el botón de &quot;Dominar el Mundo&quot; sería perfecto. Es rápido, es fácil, y Cerebro puede delegar la tarea incluso a Pinky.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Eso sería perfecto, pero para conseguirlo tiene que encontrar la forma de poderle decir a cada robot que es lo que se supone que debe hacer cuando el &quot;glorioso momento del ataque&quot; llegue.&lt;br /&gt;&lt;/div&gt;Pero cómo ?. El unico conocimiento que tiene Cerebro de los robots soldados es su interfaz, porque sabe que cada robot soldado implementa la interfaz &lt;span style=&quot;font-weight: bold;&quot;&gt;AccionSoldado&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Resumiendo, lo que en realidad necesita es que algunos robots ejecuten uno de los métodos de &lt;span style=&quot;font-weight: bold;&quot;&gt;AccionSoldado&lt;/span&gt;, y otros robots ejecuten uno distinto cuando reciban la orden de atacar.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package command.paso1;&lt;br /&gt;&lt;br /&gt;public interface AccionSoldado {&lt;br /&gt;&lt;br /&gt;    public void destruir();&lt;br /&gt;&lt;br /&gt;    public void mover();&lt;br /&gt;&lt;br /&gt;    public void esperarPorMasOrdenes();&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package command.paso1;&lt;br /&gt;&lt;br /&gt;import extensionobject.paso1.AccionesBasicas;&lt;br /&gt;import extensionobject.paso1.Rol;&lt;br /&gt;&lt;br /&gt;public class RolSoldado extends Rol implements AccionSoldado{&lt;br /&gt;&lt;br /&gt;    private AccionesBasicas sujeto;&lt;br /&gt;&lt;br /&gt;    public RolSoldado(AccionesBasicas sujeto){&lt;br /&gt;        this.sujeto = sujeto;&lt;br /&gt;        System.out.println(&quot;RolSoldado creado&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void destruir(){&lt;br /&gt;        System.out.println(&quot;Interfaz soldado destruir&quot;);&lt;br /&gt;        sujeto.moverBrazos();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void mover(){&lt;br /&gt;        System.out.println(&quot;Interfaz soldado mover&quot;);&lt;br /&gt;        sujeto.moverBrazos();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void esperarPorMasOrdenes(){&lt;br /&gt;        System.out.println(&quot;Estoy esperando por mas ordenes!!!!&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Tanto la interfaz &lt;span style=&quot;font-weight: bold;&quot;&gt;AccionSoldado &lt;/span&gt;como la clase &lt;span style=&quot;font-weight: bold;&quot;&gt;RolSoldado &lt;/span&gt;no han cambiado.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Cerebro ha logrado crear diez mil robots soldados, y diez mil robots fabricantes, utilizando dos arrays para almacenar una referencia a todos ellos.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Por tanto, al apretar el botón de &quot;Al ataqueeeeeeeeeeeeeee&quot; podría hacer algo así…..&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;public void atacar( CommandActions aLasArmas [ ] ) {&lt;br /&gt;    int contRobots = aLasArmas.length;&lt;br /&gt;&lt;br /&gt;    for( int idx=0; idx &amp;lt; contRobots; idx++ ) {&lt;br /&gt;        aLasArmas [ idx ].ejecutar( );&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Cerebro está loco, pero no es un tonto. No le gusta la solución que ha encontrado. Por que?. Bueno, no es exactamente lo que quería. Cerebro simplemente quiere poder decir &quot;Al ataqueeeeeeeee&quot;, y comenzar a reírse histéricamente mientras los robots se lanzan ciegamente a cumplir sus órdenes.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Cerebro sospecha que todo podría ser mucho más fácil si pudiera darle a cada uno de los robots un sobre conteniendo sus órdenes. Cuando el &quot;Momento de gloria&quot; llegue, simplemente le tendría que decirle a cada robot que habrá el sobre y obedezca las ordenes contenidas en el. Pero él no quiere saber de qué forma tienen que cumplir esas órdenes los robots, de hecho, ni siquiera quiere saber si le está mandando algo a un robot “Mazinger Z” o “El Vengador”, o a lo que sea.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Pero justo en ese momento, comienza a reírse con más fuerza que nunca. Porque ha recordado el patrón &lt;span style=&quot;font-weight: bold;&quot;&gt;Command&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyqoyqmtujlEhR4WV5wgckC3HsXbroNdR1ttloetl_kS21b-cr1UsKKdZlmkPDqsWa9XfE8TT00OndRHdHUj98-v9l1Gt1BjYmeNkFI27NPGcG0-gefv42GNQPxURsq3pOLntDSTW8lxED/s1600-h/command.JPG&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyqoyqmtujlEhR4WV5wgckC3HsXbroNdR1ttloetl_kS21b-cr1UsKKdZlmkPDqsWa9XfE8TT00OndRHdHUj98-v9l1Gt1BjYmeNkFI27NPGcG0-gefv42GNQPxURsq3pOLntDSTW8lxED/s400/command.JPG&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5237750999852246178&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Cerebro quiere dar cuatro órdenes diferentes. Dos para ser obedecidas por los robots soldado (&quot;ataca&quot;, y &quot;espera hasta recibir nuevas órdenes&quot;), y las otras dos dirigidas a los robots fabricantes ( &quot;comienza a construir la fortaleza&quot;, y &quot;diseña armas&quot; ).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Para esto, va a encapsular la orden y el receptor de dicha orden, en un paquete ( el sobre ). Cómo?....&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;En primer lugar, escribirá la siguiente interfaz:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;public interface CommandActions {&lt;br /&gt;    &lt;br /&gt;    public void ejecutar( );&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Y los distintos comandos serán…..&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package command.paso3;&lt;br /&gt;&lt;br /&gt;public interface CommandActions {&lt;br /&gt;&lt;br /&gt;    public void ejecutar();&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package command.paso3;&lt;br /&gt;&lt;br /&gt;import command.paso1.AccionSoldado;&lt;br /&gt;&lt;br /&gt;public class SoldadoAtacar implements CommandActions {&lt;br /&gt;&lt;br /&gt;    private AccionSoldado recivir;&lt;br /&gt;&lt;br /&gt;    public SoldadoAtacar(AccionSoldado soldado){&lt;br /&gt;        recivir = soldado;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void ejecutar(){&lt;br /&gt;        recivir.destruir();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package command.paso3;&lt;br /&gt;&lt;br /&gt;import command.paso1.AccionSoldado;&lt;br /&gt;&lt;br /&gt;public class SoldadoEsperar implements CommandActions {&lt;br /&gt;&lt;br /&gt;    private AccionSoldado recivir;&lt;br /&gt;&lt;br /&gt;    public SoldadoEsperar(AccionSoldado soldado) {&lt;br /&gt;        recivir = soldado;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void ejecutar() {&lt;br /&gt;        recivir.esperarPorMasOrdenes();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package command.paso3;&lt;br /&gt;&lt;br /&gt;import extensionobject.paso1.AccionFabricante;&lt;br /&gt;&lt;br /&gt;public class FabricanteConstruir implements CommandActions {&lt;br /&gt;&lt;br /&gt;    private AccionFabricante recivir;&lt;br /&gt;&lt;br /&gt;    public FabricanteConstruir(AccionFabricante fabricante) {&lt;br /&gt;        recivir = fabricante;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void ejecutar() {&lt;br /&gt;        recivir.construir();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package command.paso3;&lt;br /&gt;&lt;br /&gt;import extensionobject.paso1.AccionFabricante;&lt;br /&gt;&lt;br /&gt;public class FabricanteDisenar implements CommandActions {&lt;br /&gt;&lt;br /&gt;    private AccionFabricante recivir;&lt;br /&gt;&lt;br /&gt;    public FabricanteDisenar(AccionFabricante fabricante) {&lt;br /&gt;        recivir = fabricante;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void ejecutar() {&lt;br /&gt;        recivir.disenar();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Por tanto, cuando Cerebro presione el botón de &quot;al ataqueeeeeeeeee&quot;, tendrá que hacer un método algo así:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;public void atacar( CommandActions aLasArmas [ ] ) {&lt;br /&gt;    int contRobots = aLasArmas.length;&lt;br /&gt;    for( int idx=0; idx &amp;lt; contRobots; idx++ ) {&lt;br /&gt;        aLasArmas [ idx ].ejecutar( );&lt;br /&gt;    }&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Este método recibe como parámetro un array conteniendo todos los comandos. Ese array se podría construir con un código similar a este…..&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package command.paso4;&lt;br /&gt;&lt;br /&gt;import command.paso1.AccionSoldado;&lt;br /&gt;import command.paso1.RolSoldado;&lt;br /&gt;import extensionobject.paso1.AccionFabricante;&lt;br /&gt;import extensionobject.paso1.RolFabricante;&lt;br /&gt;import command.paso3.SoldadoAtacar;&lt;br /&gt;import command.paso3.SoldadoEsperar;&lt;br /&gt;import command.paso3.CommandActions;&lt;br /&gt;import command.paso3.FabricanteConstruir;&lt;br /&gt;import command.paso3.FabricanteDisenar;&lt;br /&gt;import extensionobject.paso2.MazingerZ;&lt;br /&gt;&lt;br /&gt;public class Disparar {&lt;br /&gt;&lt;br /&gt;    public Disparar() {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void atacar(CommandActions aLasArmas[]) {&lt;br /&gt;        int contRobots = aLasArmas.length;&lt;br /&gt;        for (int idx = 0; idx &amp;lt; contRobots; idx++) {&lt;br /&gt;            aLasArmas[idx].ejecutar();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        MazingerZ mazingerZ = null;&lt;br /&gt;        CommandActions aLasArmas[] = new CommandActions[20];&lt;br /&gt;        AccionSoldado accionSoldado = null;&lt;br /&gt;        AccionFabricante accionFabricante = null;&lt;br /&gt;        SoldadoAtacar soldadoAtacar = null;&lt;br /&gt;        SoldadoEsperar soldadoEsperar = null;&lt;br /&gt;        FabricanteConstruir fabricanteConstruir = null;&lt;br /&gt;        FabricanteDisenar fabricanteDisenar = null;&lt;br /&gt;        for (int i = 0; i &amp;lt; 5; i++) {&lt;br /&gt;            mazingerZ = new MazingerZ();&lt;br /&gt;            mazingerZ.addExtension(&quot;RolSoldado&quot;, new RolSoldado(mazingerZ));&lt;br /&gt;            accionSoldado = (AccionSoldado) mazingerZ.getExtension(&quot;RolSoldado&quot;);&lt;br /&gt;            soldadoAtacar = new SoldadoAtacar(accionSoldado);&lt;br /&gt;            aLasArmas[i] = soldadoAtacar;&lt;br /&gt;        }&lt;br /&gt;        for (int i = 5; i &amp;lt; 10; i++) {&lt;br /&gt;            mazingerZ = new MazingerZ();&lt;br /&gt;            mazingerZ.addExtension(&quot;RolSoldado&quot;, new RolSoldado(mazingerZ));&lt;br /&gt;            accionSoldado = (AccionSoldado) mazingerZ.getExtension(&quot;RolSoldado&quot;);&lt;br /&gt;            soldadoEsperar = new SoldadoEsperar(accionSoldado);&lt;br /&gt;            aLasArmas[i] = soldadoEsperar;&lt;br /&gt;        }&lt;br /&gt;        for (int i = 10; i &amp;lt; 15; i++) {&lt;br /&gt;            mazingerZ = new MazingerZ();&lt;br /&gt;            mazingerZ.addExtension(&quot;RolCampesino&quot;, new RolFabricante(mazingerZ));&lt;br /&gt;            accionFabricante = (AccionFabricante) mazingerZ.getExtension(&quot;RolCampesino&quot;);&lt;br /&gt;            fabricanteConstruir = new FabricanteConstruir(accionFabricante);&lt;br /&gt;            aLasArmas[i] = fabricanteConstruir;&lt;br /&gt;        }&lt;br /&gt;        for (int i = 15; i &amp;lt; 20; i++) {&lt;br /&gt;            mazingerZ = new MazingerZ();&lt;br /&gt;            mazingerZ.addExtension(&quot;RolCampesino&quot;, new RolFabricante(mazingerZ));&lt;br /&gt;            accionFabricante = (AccionFabricante) mazingerZ.getExtension(&quot;RolCampesino&quot;);&lt;br /&gt;            fabricanteDisenar = new FabricanteDisenar(accionFabricante);&lt;br /&gt;            aLasArmas[i] = fabricanteDisenar;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        //A LA TAQUE!!!!&lt;br /&gt;        System.out.println(&quot;*******************************************&quot;);&lt;br /&gt;        Disparar cerebro = new Disparar();&lt;br /&gt;        cerebro.atacar(aLasArmas);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El código es horrible, pero sirve para ilustrar como Cerebro ha creado una colección de objetos, cada uno de los cuales encapsula un comando y el receptor de dicho comando.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Ahora, Cerebro no necesita saber nada acerca de esos comandos, ni del receptor de los mismos. Simplemente tiene que decir &quot;ejecutar el  comando!!&quot;, y el comando hará el resto.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;De hecho, Cerebro ha conseguido desacoplar tres procesos diferentes: la creación de los objetos (implementando el patrón &lt;span style=&quot;font-weight: bold;&quot;&gt;Prototype &lt;/span&gt;), la asignación de roles a esos objetos ( con el patrón &lt;span style=&quot;font-weight: bold;&quot;&gt;Extension Objects&lt;/span&gt; ), y la forma en que esos roles pasan a la acción ( el patron &lt;span style=&quot;font-weight: bold;&quot;&gt;Command &lt;/span&gt;).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Con esto, ha dado un paso más en su malvado plan de CONQUISTAR AL MUNDO!!!!!&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://dukechile.blogspot.com/2008/07/el-patrn-observer-observador.html&quot;&gt;PARTE 4&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;</description><link>http://dukechile.blogspot.com/2008/07/el-patrn-command.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyqoyqmtujlEhR4WV5wgckC3HsXbroNdR1ttloetl_kS21b-cr1UsKKdZlmkPDqsWa9XfE8TT00OndRHdHUj98-v9l1Gt1BjYmeNkFI27NPGcG0-gefv42GNQPxURsq3pOLntDSTW8lxED/s72-c/command.JPG" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-6591475410042423593</guid><pubDate>Tue, 24 Jun 2008 01:30:00 +0000</pubDate><atom:updated>2008-08-23T12:37:36.204-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">JEE</category><category domain="http://www.blogger.com/atom/ns#">Tomcat</category><title>Tutorial de Tomcat en Cluster</title><description>&lt;div align=&quot;justify&quot;&gt;Lo primero que necesitaremos será descargar el servidor Web Apache para poder hacer el balanceo de carga (Load Balancing) y la compartición de carga (Load Sharing).&lt;br /&gt;&lt;br /&gt;Para esto, descargaremos el archivo &lt;strong&gt;apache_2.2.9-win32-x86-no_ssl-r2.msi&lt;/strong&gt; desde &lt;a href=&quot;http://archive.apache.org/dist/httpd/binaries/win32/&quot;&gt;aquí&lt;/a&gt;. Una vez descargado, procedemos a la instalación.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;p align=&quot;justify&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGkAP3uBL3GMdsJ4zzALqrJ-veJgr3FjatEkjLPIImKTqDycBe3IZktwtJNJ-W_LPbICfwWbfLMj89flcGmSZOuxtpTXE-w65xBDHwpyat112Nu_9Lg2NEUXf10H3VbxcFDvOYBTcWzX6v/s1600-h/tom1.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215500027212781938&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGkAP3uBL3GMdsJ4zzALqrJ-veJgr3FjatEkjLPIImKTqDycBe3IZktwtJNJ-W_LPbICfwWbfLMj89flcGmSZOuxtpTXE-w65xBDHwpyat112Nu_9Lg2NEUXf10H3VbxcFDvOYBTcWzX6v/s400/tom1.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYQ8EaQWy9_8MQhUEds7Z0ALk7RjfFU8oULk5dfCfzoTLxf7mdlezWe0a8h8l-VuhlQit_3PfTm177vUq2ZNf9c5n9rudmK49k4GzzUbMc7FABzIqsb16QSZU0Qjhh_kVy7HrD3LxuPt7X/s1600-h/tom2.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215500027527573810&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYQ8EaQWy9_8MQhUEds7Z0ALk7RjfFU8oULk5dfCfzoTLxf7mdlezWe0a8h8l-VuhlQit_3PfTm177vUq2ZNf9c5n9rudmK49k4GzzUbMc7FABzIqsb16QSZU0Qjhh_kVy7HrD3LxuPt7X/s400/tom2.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNdwAODDXnRWSCzQoOdiCzT4aAhUfrc_fU8wP3vpwb19bOYY-q6a-UlnnckLXe2poPaF4-3r8TE7EuFqiFO7_5WMrotgpBH-9ekjQ4-2TkjPnWgF431hpO-pb6A7mvLYnSiFyMv_rzFge5/s1600-h/tom3.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215500027121262738&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNdwAODDXnRWSCzQoOdiCzT4aAhUfrc_fU8wP3vpwb19bOYY-q6a-UlnnckLXe2poPaF4-3r8TE7EuFqiFO7_5WMrotgpBH-9ekjQ4-2TkjPnWgF431hpO-pb6A7mvLYnSiFyMv_rzFge5/s400/tom3.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4fiTorNfc3WiBYr8cbHNJFcOq5unqv-GcSI5RIjnweA4sUrGmRcNNO7YGFMeRfOGIXLuNcD6RA4jgVCu2paYJWTepOSZTN3xUd629OoqWqcayCxvw3m9OFZq1ybkuAe1nzZvgDPzW_BEI/s1600-h/tom4.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215500032080340658&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4fiTorNfc3WiBYr8cbHNJFcOq5unqv-GcSI5RIjnweA4sUrGmRcNNO7YGFMeRfOGIXLuNcD6RA4jgVCu2paYJWTepOSZTN3xUd629OoqWqcayCxvw3m9OFZq1ybkuAe1nzZvgDPzW_BEI/s400/tom4.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5wE756BwB_JIe_j1Czpm0GPRbvmSgpMjjnhuPAwoPzfu1ypt19ggtxi5qBTbV17R-66KTiTY0bwgcuoArv3UVrS5hCGPJKE3w8ffdfnuIRR4f304B0oxBDodRCVZ6yLYy4QmPP7e88v8X/s1600-h/tom5.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215500032498103266&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5wE756BwB_JIe_j1Czpm0GPRbvmSgpMjjnhuPAwoPzfu1ypt19ggtxi5qBTbV17R-66KTiTY0bwgcuoArv3UVrS5hCGPJKE3w8ffdfnuIRR4f304B0oxBDodRCVZ6yLYy4QmPP7e88v8X/s400/tom5.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHMlPRM_RX3ASflNKSEQ2bB378nUvy1fGSRRoo6fnW35RZYtq7WkI_OZKONP3vhIRskvl82yKlNd9_gZu02TJ_gDr5S_UzGYo-sdIneKyWKwXCy9AYN7V-38AJ33EJ9Q7mv2Z-OP8_uHo4/s1600-h/tom6.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215500587932600514&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHMlPRM_RX3ASflNKSEQ2bB378nUvy1fGSRRoo6fnW35RZYtq7WkI_OZKONP3vhIRskvl82yKlNd9_gZu02TJ_gDr5S_UzGYo-sdIneKyWKwXCy9AYN7V-38AJ33EJ9Q7mv2Z-OP8_uHo4/s400/tom6.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQaRCM2wRqIkIFlmDvZ-CAfzRZAe_N_e0vYnnn17FMqHPsbfsJhTj45zBiSqULecyiCFoEh6TCoABFtRx15uN_EHiFTnufVSHh_KMrcEqnACaf9a91cBlOd1Us9iewoxWh0CqsqTd9mdDc/s1600-h/tom7.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215500584227904402&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQaRCM2wRqIkIFlmDvZ-CAfzRZAe_N_e0vYnnn17FMqHPsbfsJhTj45zBiSqULecyiCFoEh6TCoABFtRx15uN_EHiFTnufVSHh_KMrcEqnACaf9a91cBlOd1Us9iewoxWh0CqsqTd9mdDc/s400/tom7.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;Ya instalado el servidor Web Apache, deberemos proceder a instalar Tomcat y definir el tipo de cluster a implementar.&lt;br /&gt;&lt;br /&gt;Existen dos tipos de cluster que podemos construir en Tomcat: cluster vertical (en una sola maquina) o cluster horizontal (en muchas maquinas).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Cluster vertical&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;El primer paso será la instalación de Tomcat, para lo que deberemos bajar el archivo &lt;strong&gt;apache-tomcat-6.0.9.exe&lt;/strong&gt; desde &lt;a href=&quot;http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.9/bin/&quot;&gt;aquí&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Una vez descargado el archivo, procederemos instalar Tomcat. Para este ejemplo, vamos a simular que el cluster está compuesto por tres nodos, por lo tanto, necesitaremos instalar tres instancias de Tomcat las cuales llamaremos: &lt;strong&gt;TomcatNodo1&lt;/strong&gt;, &lt;strong&gt;TomcatNodo2&lt;/strong&gt; y &lt;strong&gt;TomcatNodo3&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;El paso que realizaremos a continuación deberemos repetirlo para cada nodo.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcjbHUcx12drnETkEAA2Yw9EYCwrV-QCRbCL4kS8i5zZjIV8UiUhvIUsfOajmkiBkFICckuEQEp7G8FE3J0ryEVTmEKPdLJnR92quWg8SSzKpGmFTKjXTPal5f7znbidqY_82oBN9xyUNd/s1600-h/tom8.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215500901999757058&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcjbHUcx12drnETkEAA2Yw9EYCwrV-QCRbCL4kS8i5zZjIV8UiUhvIUsfOajmkiBkFICckuEQEp7G8FE3J0ryEVTmEKPdLJnR92quWg8SSzKpGmFTKjXTPal5f7znbidqY_82oBN9xyUNd/s400/tom8.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcxnCXSE_s5H92osAmhkL9oBE-Zcan9Ktjwc-xKcHRFD3SZyiLNYimCDos5RmW96hE1v-2pP-qOSPE4HBVcp9ZNf3jlF4_REVNDZnVB0GiVSfrFZ1PaxyJ2mc65hFvi1EUBd1WBa9NoI2N/s1600-h/tom9.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215500899273431922&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcxnCXSE_s5H92osAmhkL9oBE-Zcan9Ktjwc-xKcHRFD3SZyiLNYimCDos5RmW96hE1v-2pP-qOSPE4HBVcp9ZNf3jlF4_REVNDZnVB0GiVSfrFZ1PaxyJ2mc65hFvi1EUBd1WBa9NoI2N/s400/tom9.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5LhfFe8j9_S2GTo3WefYjDrhw4rIV2vQvbHh25tt0pxhepNIFNDOCKn-MWAUA4-yanjJsDLbMITrZ7YsE_nJCKq_WeztEyJNaNAtDEdw5xyR_WkbOiYlA-FrG80DdmRFgZ_HcfurjI_La/s1600-h/tom10.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215500898846186594&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5LhfFe8j9_S2GTo3WefYjDrhw4rIV2vQvbHh25tt0pxhepNIFNDOCKn-MWAUA4-yanjJsDLbMITrZ7YsE_nJCKq_WeztEyJNaNAtDEdw5xyR_WkbOiYlA-FrG80DdmRFgZ_HcfurjI_La/s400/tom10.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9vYOcG9Bi4PijUuHVcRT6t8FBnh4r-F7Hskamcb2SH3RIFofAeGM5suanO9GPcRvgko6EXwjgBV9TcXBs77U1WpDS4VcSMspCqwZQZ3udE7A7drgmDoPjadOt7wDWFkzS0eDiiZWvgsTH/s1600-h/tom11.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215500904809340002&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9vYOcG9Bi4PijUuHVcRT6t8FBnh4r-F7Hskamcb2SH3RIFofAeGM5suanO9GPcRvgko6EXwjgBV9TcXBs77U1WpDS4VcSMspCqwZQZ3udE7A7drgmDoPjadOt7wDWFkzS0eDiiZWvgsTH/s400/tom11.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtQWHyoW8j_iSBXrdgJb_KxFSXkvqWZAxhvs7NFcbZv8BautVRNf1ZM3_c64uLFnd7eMJSG0rnO-EO_fc8tw06QcXaoX_FsKG3Bj7QTKUFBdeLw5PaPOGaRQO2Ry_3qJae35Tu0HtlmAi-/s1600-h/tom12.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215500904432604434&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtQWHyoW8j_iSBXrdgJb_KxFSXkvqWZAxhvs7NFcbZv8BautVRNf1ZM3_c64uLFnd7eMJSG0rnO-EO_fc8tw06QcXaoX_FsKG3Bj7QTKUFBdeLw5PaPOGaRQO2Ry_3qJae35Tu0HtlmAi-/s400/tom12.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmNqjTRlqypeBOXqcMsBESFaLfn_8fXOge8oEzbaeZfOPRXa0D65WeDw44P9PbRdGaL54DbNPRqY6XgjJSTfH_h3OmrksUk_0yOiRBUeQ8SVWP7zgBIReQNRvI0JW8YQCQjEMYDd2jO_A0/s1600-h/tom13.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215501237638009506&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmNqjTRlqypeBOXqcMsBESFaLfn_8fXOge8oEzbaeZfOPRXa0D65WeDw44P9PbRdGaL54DbNPRqY6XgjJSTfH_h3OmrksUk_0yOiRBUeQ8SVWP7zgBIReQNRvI0JW8YQCQjEMYDd2jO_A0/s400/tom13.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;Una vez instalado los tres nodos, deberemos realizar una pequeña modificación al archivo &lt;strong&gt;server.xml&lt;/strong&gt; de cada uno de los nodos. Este archivo se encuentra en la carpeta &quot;&lt;strong&gt;conf&lt;/strong&gt;&quot; de cada uno de los nodos.&lt;br /&gt;&lt;br /&gt;Para cada uno de los &lt;strong&gt;server.xml&lt;/strong&gt; deberemos realizar los siguientes cambios:&lt;br /&gt;&lt;br /&gt;Cambiar los puertos&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;server port=&quot;XXXX&quot; shutdown=&quot;SHUTDOWN&quot;&gt;&lt;br /&gt;&lt;br /&gt;    &lt;connector port=&quot;XXXX&quot; protocol=&quot;HTTP/1.1&quot; connectiontimeout=&quot;20000&quot; redirectport=&quot;8443&quot;&gt;&lt;br /&gt;&lt;br /&gt;    &lt;connector port=&quot;XXXX&quot; protocol=&quot;AJP/1.3&quot; redirectport=&quot;8443&quot;&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Agregamos el “&lt;strong&gt;jvmRoute&lt;/strong&gt;” para cada caso.&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;engine name=&quot;Catalina&quot; defaulthost=&quot;localhost&quot; jvmroute=&quot;tomcatNodoX&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Descomentamos el tag “&lt;strong&gt;cluster&lt;/strong&gt;”&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;cluster classname=&quot;org.apache.catalina.ha.tcp.SimpleTcpCluster&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Nodo1&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;!-- Note:  A &quot;Server&quot; is not itself a &quot;Container&quot;, so you may not      define subcomponents such as &quot;Valves&quot; at this level.      Documentation at /docs/config/server.html  --&gt;&lt;br /&gt;&lt;br /&gt;&lt;server port=&quot;8015&quot; shutdown=&quot;SHUTDOWN&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!--APR library loader. Documentation at /docs/apr.html --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;listener classname=&quot;org.apache.catalina.core.AprLifecycleListener&quot; sslengine=&quot;on&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;listener classname=&quot;org.apache.catalina.core.JasperListener&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;listener classname=&quot;org.apache.catalina.mbeans.ServerLifecycleListener&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;listener classname=&quot;org.apache.catalina.mbeans.GlobalResourcesLifecycleListener&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- Global JNDI resources        Documentation at /docs/jndi-resources-howto.html   --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;globalnamingresources&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- Editable user database that can also be used by          UserDatabaseRealm to authenticate users     --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;resource name=&quot;UserDatabase&quot; auth=&quot;Container&quot; type=&quot;org.apache.catalina.UserDatabase&quot; description=&quot;User database that can be updated and saved&quot; factory=&quot;org.apache.catalina.users.MemoryUserDatabaseFactory&quot; pathname=&quot;conf/tomcat-users.xml&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/globalnamingresources&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- A &quot;Service&quot; is a collection of one or more &quot;Connectors&quot; that share        a single &quot;Container&quot; Note:  A &quot;Service&quot; is not itself a &quot;Container&quot;,         so you may not define subcomponents such as &quot;Valves&quot; at this level.        Documentation at /docs/config/service.html    --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;service name=&quot;Catalina&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- A &quot;Connector&quot; represents an endpoint by which requests are received          and responses are returned. Documentation at :          Java HTTP Connector: /docs/config/http.html (blocking &amp;amp; non-blocking)          Java AJP  Connector: /docs/config/ajp.html          APR (HTTP/AJP) Connector: /docs/apr.html          Define a non-SSL HTTP/1.1 Connector on port 8080     --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;connector port=&quot;8081&quot; protocol=&quot;HTTP/1.1&quot; maxthreads=&quot;150&quot; connectiontimeout=&quot;20000&quot; redirectport=&quot;8443&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- Define a SSL HTTP/1.1 Connector on port 8443          This connector uses the JSSE configuration, when using APR, the           connector should be using the OpenSSL style configuration          described in the APR documentation --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!--     &lt;connector port=&quot;8443&quot; protocol=&quot;HTTP/1.1&quot; sslenabled=&quot;true&quot; maxthreads=&quot;150&quot; scheme=&quot;https&quot; secure=&quot;true&quot; clientauth=&quot;false&quot; sslprotocol=&quot;TLS&quot;&gt;&lt;br /&gt;&lt;br /&gt;    --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- Define an AJP 1.3 Connector on port 8009 --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;connector port=&quot;8109&quot; protocol=&quot;AJP/1.3&quot; redirectport=&quot;8443&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- An Engine represents the entry point (within Catalina) that processes          every request.  The Engine implementation for Tomcat stand alone          analyzes the HTTP headers included with the request, and passes them          on to the appropriate Host (virtual host).          Documentation at /docs/config/engine.html --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- You should set jvmRoute to support load-balancing via AJP ie : --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;engine name=&quot;Standalone&quot; defaulthost=&quot;localhost&quot; jvmroute=&quot;tomcatNodo1&quot;&gt;         &lt;br /&gt;&lt;br /&gt;     &lt;br /&gt;&lt;br /&gt;    &lt;engine name=&quot;Catalina&quot; defaulthost=&quot;localhost&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!--For clustering, please take a look at documentation at:           /docs/cluster-howto.html  (simple how to)           /docs/config/cluster.html (reference documentation) --&gt;&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt;&lt;br /&gt;      &lt;cluster classname=&quot;org.apache.catalina.ha.tcp.SimpleTcpCluster&quot;&gt;&lt;br /&gt;&lt;br /&gt;            &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!-- The request dumper valve dumps useful debugging information about            the request and response data received and sent by Tomcat.            Documentation at: /docs/config/valve.html --&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!--       &lt;valve classname=&quot;org.apache.catalina.valves.RequestDumperValve&quot;&gt;&lt;br /&gt;&lt;br /&gt;      --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!-- This Realm uses the UserDatabase configured in the global JNDI            resources under the key &quot;UserDatabase&quot;.  Any edits            that are performed against this UserDatabase are immediately            available for use by the Realm.  --&gt;&lt;br /&gt;&lt;br /&gt;      &lt;realm classname=&quot;org.apache.catalina.realm.UserDatabaseRealm&quot; resourcename=&quot;UserDatabase&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!-- Define the default virtual host            Note: XML Schema validation will not work with Xerces 2.2.        --&gt;&lt;br /&gt;&lt;br /&gt;      &lt;host name=&quot;localhost&quot; appbase=&quot;webapps&quot; unpackwars=&quot;true&quot; autodeploy=&quot;true&quot; xmlvalidation=&quot;false&quot; xmlnamespaceaware=&quot;false&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;!-- SingleSignOn valve, share authentication between web applications              Documentation at: /docs/config/valve.html --&gt;&lt;br /&gt;&lt;br /&gt;        &lt;!--         &lt;valve classname=&quot;org.apache.catalina.authenticator.SingleSignOn&quot;&gt;&lt;br /&gt;&lt;br /&gt;        --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;!-- Access log processes all example.              Documentation at: /docs/config/valve.html --&gt;&lt;br /&gt;&lt;br /&gt;        &lt;!--         &lt;valve classname=&quot;org.apache.catalina.valves.AccessLogValve&quot; directory=&quot;logs&quot; prefix=&quot;localhost_access_log.&quot; suffix=&quot;.txt&quot; pattern=&quot;common&quot; resolvehosts=&quot;false&quot;&gt;&lt;br /&gt;&lt;br /&gt;        --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;/host&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/engine&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/service&gt;&lt;br /&gt;&lt;br /&gt;&lt;/server&gt;&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Nodo2&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;!-- Note:  A &quot;Server&quot; is not itself a &quot;Container&quot;, so you may not      define subcomponents such as &quot;Valves&quot; at this level.      Documentation at /docs/config/server.html  --&gt;&lt;br /&gt;&lt;br /&gt;&lt;server port=&quot;8205&quot; shutdown=&quot;SHUTDOWN&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!--APR library loader. Documentation at /docs/apr.html --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;listener classname=&quot;org.apache.catalina.core.AprLifecycleListener&quot; sslengine=&quot;on&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;listener classname=&quot;org.apache.catalina.core.JasperListener&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;listener classname=&quot;org.apache.catalina.mbeans.ServerLifecycleListener&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;listener classname=&quot;org.apache.catalina.mbeans.GlobalResourcesLifecycleListener&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- Global JNDI resources        Documentation at /docs/jndi-resources-howto.html   --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;globalnamingresources&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- Editable user database that can also be used by          UserDatabaseRealm to authenticate users     --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;resource name=&quot;UserDatabase&quot; auth=&quot;Container&quot; type=&quot;org.apache.catalina.UserDatabase&quot; description=&quot;User database that can be updated and saved&quot; factory=&quot;org.apache.catalina.users.MemoryUserDatabaseFactory&quot; pathname=&quot;conf/tomcat-users.xml&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/globalnamingresources&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- A &quot;Service&quot; is a collection of one or more &quot;Connectors&quot; that share        a single &quot;Container&quot; Note:  A &quot;Service&quot; is not itself a &quot;Container&quot;,         so you may not define subcomponents such as &quot;Valves&quot; at this level.        Documentation at /docs/config/service.html    --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;service name=&quot;Catalina&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- A &quot;Connector&quot; represents an endpoint by which requests are received          and responses are returned. Documentation at :          Java HTTP Connector: /docs/config/http.html (blocking &amp;amp; non-blocking)          Java AJP  Connector: /docs/config/ajp.html          APR (HTTP/AJP) Connector: /docs/apr.html          Define a non-SSL HTTP/1.1 Connector on port 8080     --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;connector port=&quot;8082&quot; protocol=&quot;HTTP/1.1&quot; maxthreads=&quot;150&quot; connectiontimeout=&quot;20000&quot; redirectport=&quot;8443&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- Define a SSL HTTP/1.1 Connector on port 8443          This connector uses the JSSE configuration, when using APR, the           connector should be using the OpenSSL style configuration          described in the APR documentation --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!--     &lt;connector port=&quot;8443&quot; protocol=&quot;HTTP/1.1&quot; sslenabled=&quot;true&quot; maxthreads=&quot;150&quot; scheme=&quot;https&quot; secure=&quot;true&quot; clientauth=&quot;false&quot; sslprotocol=&quot;TLS&quot;&gt;&lt;br /&gt;&lt;br /&gt;    --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- Define an AJP 1.3 Connector on port 8009 --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;connector port=&quot;8209&quot; protocol=&quot;AJP/1.3&quot; redirectport=&quot;8443&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- An Engine represents the entry point (within Catalina) that processes          every request.  The Engine implementation for Tomcat stand alone          analyzes the HTTP headers included with the request, and passes them          on to the appropriate Host (virtual host).          Documentation at /docs/config/engine.html --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- You should set jvmRoute to support load-balancing via AJP ie : --&gt; &lt;br /&gt;&lt;br /&gt;    &lt;engine name=&quot;Standalone&quot; defaulthost=&quot;localhost&quot; jvmroute=&quot;tomcatNodo2&quot;&gt;         &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;    &lt;engine name=&quot;Catalina&quot; defaulthost=&quot;localhost&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!--For clustering, please take a look at documentation at:           /docs/cluster-howto.html  (simple how to)           /docs/config/cluster.html (reference documentation) --&gt;&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt;&lt;br /&gt;      &lt;cluster classname=&quot;org.apache.catalina.ha.tcp.SimpleTcpCluster&quot;&gt;&lt;br /&gt;&lt;br /&gt;           &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!-- The request dumper valve dumps useful debugging information about            the request and response data received and sent by Tomcat.            Documentation at: /docs/config/valve.html --&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!--       &lt;valve classname=&quot;org.apache.catalina.valves.RequestDumperValve&quot;&gt;&lt;br /&gt;&lt;br /&gt;      --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!-- This Realm uses the UserDatabase configured in the global JNDI            resources under the key &quot;UserDatabase&quot;.  Any edits            that are performed against this UserDatabase are immediately            available for use by the Realm.  --&gt;&lt;br /&gt;&lt;br /&gt;      &lt;realm classname=&quot;org.apache.catalina.realm.UserDatabaseRealm&quot; resourcename=&quot;UserDatabase&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!-- Define the default virtual host            Note: XML Schema validation will not work with Xerces 2.2.        --&gt;&lt;br /&gt;&lt;br /&gt;      &lt;host name=&quot;localhost&quot; appbase=&quot;webapps&quot; unpackwars=&quot;true&quot; autodeploy=&quot;true&quot; xmlvalidation=&quot;false&quot; xmlnamespaceaware=&quot;false&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;!-- SingleSignOn valve, share authentication between web applications              Documentation at: /docs/config/valve.html --&gt;&lt;br /&gt;&lt;br /&gt;        &lt;!--         &lt;valve classname=&quot;org.apache.catalina.authenticator.SingleSignOn&quot;&gt;&lt;br /&gt;&lt;br /&gt;        --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;!-- Access log processes all example.              Documentation at: /docs/config/valve.html --&gt;&lt;br /&gt;&lt;br /&gt;        &lt;!--         &lt;valve classname=&quot;org.apache.catalina.valves.AccessLogValve&quot; directory=&quot;logs&quot; prefix=&quot;localhost_access_log.&quot; suffix=&quot;.txt&quot; pattern=&quot;common&quot; resolvehosts=&quot;false&quot;&gt;&lt;br /&gt;&lt;br /&gt;        --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;/host&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/engine&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/service&gt;&lt;br /&gt;&lt;br /&gt;&lt;/server&gt;&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Nodo3&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;!-- Note:  A &quot;Server&quot; is not itself a &quot;Container&quot;, so you may not      define subcomponents such as &quot;Valves&quot; at this level.      Documentation at /docs/config/server.html  --&gt;&lt;br /&gt;&lt;br /&gt;&lt;server port=&quot;8305&quot; shutdown=&quot;SHUTDOWN&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!--APR library loader. Documentation at /docs/apr.html --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;listener classname=&quot;org.apache.catalina.core.AprLifecycleListener&quot; sslengine=&quot;on&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;listener classname=&quot;org.apache.catalina.core.JasperListener&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;listener classname=&quot;org.apache.catalina.mbeans.ServerLifecycleListener&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;listener classname=&quot;org.apache.catalina.mbeans.GlobalResourcesLifecycleListener&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- Global JNDI resources        Documentation at /docs/jndi-resources-howto.html   --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;globalnamingresources&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- Editable user database that can also be used by          UserDatabaseRealm to authenticate users     --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;resource name=&quot;UserDatabase&quot; auth=&quot;Container&quot; type=&quot;org.apache.catalina.UserDatabase&quot; description=&quot;User database that can be updated and saved&quot; factory=&quot;org.apache.catalina.users.MemoryUserDatabaseFactory&quot; pathname=&quot;conf/tomcat-users.xml&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/globalnamingresources&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- A &quot;Service&quot; is a collection of one or more &quot;Connectors&quot; that share        a single &quot;Container&quot; Note:  A &quot;Service&quot; is not itself a &quot;Container&quot;,         so you may not define subcomponents such as &quot;Valves&quot; at this level.        Documentation at /docs/config/service.html    --&gt;&lt;br /&gt;&lt;br /&gt;  &lt;service name=&quot;Catalina&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- A &quot;Connector&quot; represents an endpoint by which requests are received          and responses are returned. Documentation at :          Java HTTP Connector: /docs/config/http.html (blocking &amp;amp; non-blocking)          Java AJP  Connector: /docs/config/ajp.html          APR (HTTP/AJP) Connector: /docs/apr.html          Define a non-SSL HTTP/1.1 Connector on port 8080     --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;connector port=&quot;8083&quot; protocol=&quot;HTTP/1.1&quot; maxthreads=&quot;150&quot; connectiontimeout=&quot;20000&quot; redirectport=&quot;8443&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- Define a SSL HTTP/1.1 Connector on port 8443          This connector uses the JSSE configuration, when using APR, the           connector should be using the OpenSSL style configuration          described in the APR documentation --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!--     &lt;connector port=&quot;8443&quot; protocol=&quot;HTTP/1.1&quot; sslenabled=&quot;true&quot; maxthreads=&quot;150&quot; scheme=&quot;https&quot; secure=&quot;true&quot; clientauth=&quot;false&quot; sslprotocol=&quot;TLS&quot;&gt;&lt;br /&gt;&lt;br /&gt;    --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- Define an AJP 1.3 Connector on port 8009 --&gt;&lt;br /&gt;&lt;br /&gt;    &lt;connector port=&quot;8309&quot; protocol=&quot;AJP/1.3&quot; redirectport=&quot;8443&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- An Engine represents the entry point (within Catalina) that processes          every request.  The Engine implementation for Tomcat stand alone          analyzes the HTTP headers included with the request, and passes them          on to the appropriate Host (virtual host).          Documentation at /docs/config/engine.html --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- You should set jvmRoute to support load-balancing via AJP ie : --&gt; &lt;br /&gt;&lt;br /&gt;    &lt;engine name=&quot;Standalone&quot; defaulthost=&quot;localhost&quot; jvmroute=&quot;tomcatNodo3&quot;&gt;         &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;    &lt;engine name=&quot;Catalina&quot; defaulthost=&quot;localhost&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!--For clustering, please take a look at documentation at:           /docs/cluster-howto.html  (simple how to)           /docs/config/cluster.html (reference documentation) --&gt;&lt;br /&gt;&lt;br /&gt;     &lt;br /&gt;&lt;br /&gt;      &lt;cluster classname=&quot;org.apache.catalina.ha.tcp.SimpleTcpCluster&quot;&gt;&lt;br /&gt;&lt;br /&gt;             &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!-- The request dumper valve dumps useful debugging information about            the request and response data received and sent by Tomcat.            Documentation at: /docs/config/valve.html --&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!--       &lt;valve classname=&quot;org.apache.catalina.valves.RequestDumperValve&quot;&gt;&lt;br /&gt;&lt;br /&gt;      --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!-- This Realm uses the UserDatabase configured in the global JNDI            resources under the key &quot;UserDatabase&quot;.  Any edits            that are performed against this UserDatabase are immediately            available for use by the Realm.  --&gt;&lt;br /&gt;&lt;br /&gt;      &lt;realm classname=&quot;org.apache.catalina.realm.UserDatabaseRealm&quot; resourcename=&quot;UserDatabase&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;!-- Define the default virtual host            Note: XML Schema validation will not work with Xerces 2.2.        --&gt;&lt;br /&gt;&lt;br /&gt;      &lt;host name=&quot;localhost&quot; appbase=&quot;webapps&quot; unpackwars=&quot;true&quot; autodeploy=&quot;true&quot; xmlvalidation=&quot;false&quot; xmlnamespaceaware=&quot;false&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;!-- SingleSignOn valve, share authentication between web applications              Documentation at: /docs/config/valve.html --&gt;&lt;br /&gt;&lt;br /&gt;        &lt;!--         &lt;valve classname=&quot;org.apache.catalina.authenticator.SingleSignOn&quot;&gt;&lt;br /&gt;&lt;br /&gt;        --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;!-- Access log processes all example.              Documentation at: /docs/config/valve.html --&gt;&lt;br /&gt;&lt;br /&gt;        &lt;!--         &lt;valve classname=&quot;org.apache.catalina.valves.AccessLogValve&quot; directory=&quot;logs&quot; prefix=&quot;localhost_access_log.&quot; suffix=&quot;.txt&quot; pattern=&quot;common&quot; resolvehosts=&quot;false&quot;&gt;&lt;br /&gt;&lt;br /&gt;        --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;/host&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/engine&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/service&gt;&lt;br /&gt;&lt;br /&gt;&lt;/server&gt;&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Con estos cambios ya tenemos configurado nuestro cluster vertical.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Cluster Horizontal&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;La configuración de un cluster horizontal es un poco más fácil ya que no es necesario realizar cambios a los puertos.&lt;br /&gt;&lt;br /&gt;Para cada uno de los archivos &lt;strong&gt;server.xml&lt;/strong&gt; se debe realizar los siguientes cambios:&lt;br /&gt;&lt;br /&gt;Agregamos el “&lt;strong&gt;jvmRoute&lt;/strong&gt;” para cada caso (igual que para el cluster vertical)&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;engine name=&quot;Catalina&quot; defaulthost=&quot;localhost&quot; jvmroute=&quot;tomcatNodoX&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Descomentamos el tag “&lt;strong&gt;cluster&lt;/strong&gt;” (igual que para el cluster vertical)&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;cluster classname=&quot;org.apache.catalina.ha.tcp.SimpleTcpCluster&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Configuración del cluster con Apache&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;Una vez configurado el tipo de cluster (Horizontal o Vertical), vamos a construir una pequeña aplicación de ejemplo.&lt;br /&gt;&lt;br /&gt;El primer paso será definir en el &lt;strong&gt;web.xml&lt;/strong&gt; de la aplicación el tag &lt;strong&gt;&amp;lt;distributable /&amp;gt;&lt;/strong&gt; para activar el intercambio de la sesión a través de la instancia del cluster.&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot;?&gt;&lt;br /&gt;&lt;br /&gt;&lt;web-app xmlns=&quot;http://java.sun.com/xml/ns/javaee&quot; xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; schemalocation=&quot;http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot; version=&quot;2.5&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;distributable&gt;  &lt;br /&gt;&lt;br /&gt;&lt;/web-app&gt;&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Ahora necesitaremos integrar el servidor web Apache con Tomcat instalando el modulo mod_jk. Para esto, deberemos descargar el archivo &lt;strong&gt;mod_jk-1.2.26-httpd-2.2.4.so&lt;/strong&gt; desde &lt;a href=&quot;http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/win32/jk-1.2.26/&quot;&gt;aquí&lt;/a&gt; y dejarlo en la carpeta “&lt;strong&gt;modules&lt;/strong&gt;” de Apache.&lt;br /&gt;&lt;br /&gt;Ya instalado el mod_jk, deberemos editar el archivo &lt;strong&gt;httpd.conf&lt;/strong&gt; que está en la carpeta “&lt;strong&gt;conf&lt;/strong&gt;” con las siguientes líneas:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;LoadModule jk_module modules/mod_jk-1.2.26-httpd-2.2.4.so&lt;br /&gt;&lt;br /&gt;JkWorkersFile &quot;C:\Archivos de programa\Apache Software Foundation\Apache2.2\conf\workers.properties&quot;&lt;br /&gt;&lt;br /&gt;JkLogFile &quot;logs/mod_jk.log&quot;&lt;br /&gt;&lt;br /&gt;JkLogLevel error&lt;br /&gt;&lt;br /&gt;JkMount /cluster loadbalancer&lt;br /&gt;&lt;br /&gt;JkMount /cluster/* loadbalancer&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Ahora deberemos crear el archivo &lt;strong&gt;workers.properties&lt;/strong&gt; dentro de la carpeta “&lt;strong&gt;conf&lt;/strong&gt;” del Apache. En este archivo definiremos las propiedades para cada una de las instancias de Tomcat a ejecutar.&lt;br /&gt;&lt;br /&gt;En el caso de que nuestro cluster sea &lt;strong&gt;vertical&lt;/strong&gt;, el archivo de propiedades deberá contener lo siguiente:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;workers.tomcat_home=/tomcatNodo1&lt;br /&gt;&lt;br /&gt;workers.java_home=$JAVA_HOME&lt;br /&gt;&lt;br /&gt;ps=/&lt;br /&gt;&lt;br /&gt;worker.list=tomcatNodo1,tomcatNodo2,tomcatNodo3,loadbalancer&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo1.port=8109&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo1.host=localhost&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo1.type=ajp13&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo1.lbfactor=1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo2.port=8209&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo2.host=localhost&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo2.type=ajp13&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo2.lbfactor=1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo3.port=8309&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo3.host=localhost&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo3.type=ajp13&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo3.lbfactor=1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;worker.loadbalancer.type=lb&lt;br /&gt;&lt;br /&gt;worker.loadbalancer.balanced_workers=tomcatNodo1,tomcatNodo2,tomcatNodo3&lt;br /&gt;&lt;br /&gt;worker.loadbalancer.sticky_session=1&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Para el caso de que el cluster sea &lt;strong&gt;horizontal&lt;/strong&gt; deberemos definir el host para cada uno de los nodos del cluster:&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;workers.tomcat_home=/tomcatNodo1&lt;br /&gt;&lt;br /&gt;workers.java_home=$JAVA_HOME&lt;br /&gt;&lt;br /&gt;ps=/&lt;br /&gt;&lt;br /&gt;worker.list=tomcatNodo1,tomcatNodo2,tomcatNodo3,loadbalancer&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo1.port=8009&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo1.host=192.168.1.1&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo1.type=ajp13&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo1.lbfactor=1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo2.port=8009&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo2.host=192.168.1.2&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo2.type=ajp13&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo2.lbfactor=1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo3.port=8009&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo3.host=192.168.1.3&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo3.type=ajp13&lt;br /&gt;&lt;br /&gt;worker.tomcatNodo3.lbfactor=1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;worker.loadbalancer.type=lb&lt;br /&gt;&lt;br /&gt;worker.loadbalancer.balanced_workers=tomcatNodo1,tomcatNodo2,tomcatNodo3&lt;br /&gt;&lt;br /&gt;worker.loadbalancer.sticky_session=1&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Uno de los atributos más importantes es “&lt;strong&gt;Ibfactor&lt;/strong&gt;”, el cual define el factor para el balanceo de carga, restringiendo el numero de “&lt;strong&gt;request&lt;/strong&gt;” a enviar a una instancia particular de Tomcat.&lt;br /&gt;&lt;br /&gt;Por último, crearemos unas páginas JSP para cada uno de los nodos, con los cuales validaremos que el cluster este funcionado correctamente.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;TomcatNodo1&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;textarea class=&quot;html&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;%   session.setAttribute(&quot;dukechile&quot;,&quot;dukechile&quot;); %&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;title&amp;gt;DukeChile - Culster&amp;lt;/title&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;table width=&quot;100%&quot; border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;tr bgcolor=&quot;#CCCCCC&quot;&gt;&lt;br /&gt;&lt;br /&gt;    &lt;td width=&quot;13%&quot;&gt;Tomcat Nodo 1&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;    &lt;td width=&quot;87%&quot;&gt; &lt;/td&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;td&gt;Session ID :&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;    &lt;td&gt;&lt;%=session.getId()%&gt;&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;TomcatNodo2&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;textarea class=&quot;html&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;%   session.setAttribute(&quot;dukechile&quot;,&quot;dukechile&quot;); %&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;title&amp;gt;DukeChile - Culster&amp;lt;/title&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;table width=&quot;100%&quot; border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;tr bgcolor=&quot;#CCCCCC&quot;&gt;&lt;br /&gt;&lt;br /&gt;    &lt;td width=&quot;13%&quot;&gt;Tomcat Nodo 2&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;    &lt;td width=&quot;87%&quot;&gt; &lt;/td&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;td&gt;Session ID :&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;    &lt;td&gt;&lt;%=session.getId()%&gt;&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;TomcatNodo3&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;textarea class=&quot;html&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;%   session.setAttribute(&quot;dukechile&quot;,&quot;dukechile&quot;); %&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;title&amp;gt;DukeChile - Culster&amp;lt;/title&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;table width=&quot;100%&quot; border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;tr bgcolor=&quot;#CCCCCC&quot;&gt;&lt;br /&gt;&lt;br /&gt;    &lt;td width=&quot;13%&quot;&gt;Tomcat Nodo 3&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;    &lt;td width=&quot;87%&quot;&gt; &lt;/td&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;td&gt;Session ID :&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;    &lt;td&gt;&lt;%=session.getId()%&gt;&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Por último, se debe reiniciar el Apache y luego iniciar cada una de las instancias del Tomcat.&lt;br /&gt;&lt;br /&gt;Una vez los nodos estén iniciados, ejecutaremos la página &lt;strong&gt;cluster.jsp&lt;/strong&gt; y validaremos el ID de la sesión asignada además del nombre del nodo que atendió la petición.&lt;br /&gt;&lt;br /&gt;Recargamos nuevamente la pagina, y validamos que el ID de la sesión siga siendo la misma, con esto, validamos que el cluster este funcionado correctamente.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzAL1jwJSrQRH1PtgVAe6QD1zo2KEDEMao-lrsK1297l2Ca5CY4CSJDYETP1dwES6vPBeuUiCoIn624PbGZmWlNS2YOlF4puBygzkrWuXZkdQHBErcMJ7qkI0BmplN3gF7_Qg7co0_khOS/s1600-h/tom14.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215501718751561314&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzAL1jwJSrQRH1PtgVAe6QD1zo2KEDEMao-lrsK1297l2Ca5CY4CSJDYETP1dwES6vPBeuUiCoIn624PbGZmWlNS2YOlF4puBygzkrWuXZkdQHBErcMJ7qkI0BmplN3gF7_Qg7co0_khOS/s400/tom14.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_Qdlq0GYb_hMInb17hX4tbyadqOZD4cg6hV_EL3ew1KoAdSSgHsGDsq3NPpdqGtoWK-ec94g6Vb-iKBDdKcVkdCPElE7UCVaU_V1vKM1xdOFg0LQZQgh2iu6vS4tnIujbJ3TzSanbT4Dg/s1600-h/tom15.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215501724315301250&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_Qdlq0GYb_hMInb17hX4tbyadqOZD4cg6hV_EL3ew1KoAdSSgHsGDsq3NPpdqGtoWK-ec94g6Vb-iKBDdKcVkdCPElE7UCVaU_V1vKM1xdOFg0LQZQgh2iu6vS4tnIujbJ3TzSanbT4Dg/s400/tom15.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbyqZ8w19Yoqj1ZaFoX4nr8MNOhjirG7QSYyg3jyQeQ6xZ31xm4uhYZNyb9rvC4GniY-krRVW0CchmzDecivUPE7yu9EaqfVz-l54vDG2Zu05dlJWOgUJyWXw7iV0Cw5owZ2oLWcZyhPyX/s1600-h/tom16.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5215501726641067650&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbyqZ8w19Yoqj1ZaFoX4nr8MNOhjirG7QSYyg3jyQeQ6xZ31xm4uhYZNyb9rvC4GniY-krRVW0CchmzDecivUPE7yu9EaqfVz-l54vDG2Zu05dlJWOgUJyWXw7iV0Cw5owZ2oLWcZyhPyX/s400/tom16.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;Si necesitan ajustar mejor la configuración del cluster, les recomiendo el libro “&lt;a href=&quot;http://www.wrox.com/WileyCDA/WroxTitle/productCd-0471753610.html&quot;&gt;PROFESIONAL APACHE TOMCAT 6&lt;/a&gt;”.</description><link>http://dukechile.blogspot.com/2008/06/tutorial-de-tomcat-en-cluster.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGkAP3uBL3GMdsJ4zzALqrJ-veJgr3FjatEkjLPIImKTqDycBe3IZktwtJNJ-W_LPbICfwWbfLMj89flcGmSZOuxtpTXE-w65xBDHwpyat112Nu_9Lg2NEUXf10H3VbxcFDvOYBTcWzX6v/s72-c/tom1.JPG" height="72" width="72"/><thr:total>6</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-2875557359595481126</guid><pubDate>Sun, 22 Jun 2008 00:14:00 +0000</pubDate><atom:updated>2008-08-18T12:17:08.711-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Extension Objects</category><category domain="http://www.blogger.com/atom/ns#">Patrones de Diseño</category><title>El patrón “Extension Objects” - Parte II</title><description>&lt;div align=&quot;justify&quot;&gt;En el episodio anterior, Cerebro logro programar una máquina capaz de crear muchas copias de robots, logrando construir un gran ejército para CONQUISTAR AL MUNDO!!!.&lt;br /&gt;&lt;br /&gt;Pero de repente, se dio cuenta que va a necesitar muchos robots del tipo “Mazinger Z” y también del tipo “El Vengador”, pero no todos los robots deberían tener el mismo rol. Por qué?. Bueno, dominar el mundo no es fácil. Hace falta organización. Hace falta un malvado plan!.&lt;br /&gt;&lt;br /&gt;Entonces Cerebro ideo un plan. Quiere entrenar a algunos de sus robots como soldados para crear maquinas de matar sin misericordia!!!!.&lt;br /&gt;&lt;br /&gt;Pero también quiere que otros robots trabajen en las fábricas haciendo armas, y también necesita que otro grupo de robots trabaje en la construcción de una fortaleza…….ufff.&lt;br /&gt;&lt;br /&gt;Por lo tanto, se puede decir que necesita poder asignar distintos roles a los robots que ha construido.&lt;br /&gt;&lt;br /&gt;Entonces, Cerebro comienza a pensar…….muy bien, ya tengo una clase que representa un robot “Mazinger Z”, pero ahora necesito tener un “Mazinger Z” que se comporte como un soldado, otro que se comporte como un fabricante, otro como constructor y lo mismo para “El Vengador”. Eso suena a &quot;extender la funcionalidad de una clase&quot;, o no?....Brillante!!.&lt;br /&gt;&lt;br /&gt;Escribiré una clase “MazingerZSoldado” que extienda a “MazingerZ”, y otra clase, “MazingerZFabricante”, que también extienda a “MazingerZ”.&lt;br /&gt;&lt;br /&gt;Pero antes de ponerse a escribir código, Cerebro se da cuenta que probablemente esa no sea la mejor solución, porque cada vez que quiera asignar un nuevo rol a una robot, tendrá que escribir una nueva subclase (por ejemplo, una “MazingerZIngeniero”, o una “MazingerZConstructor”).&lt;br /&gt;&lt;br /&gt;Además, el no sabe a priori cuantos roles va a necesitar asignar a un robot. Todo depende de lo que necesite en el futuro. Necesita dar soporte a la adición de interfaces desconocidas a la clase “MazingerZ”.&lt;br /&gt;&lt;br /&gt;También se da cuenta que su primera forma de atacar el problema tiene otro punto débil, y es que no podrá re-asignar un rol. Si crea un “MazingerZSoldado”, tendrá esta para siempre, aunque la necesite para construir nuevos robots.&lt;br /&gt;&lt;br /&gt;Pero también se da cuenta de otro punto débil, este es mucho más sutil. Una clase “MazingerZSoldado” y una “MazingerZ” son exactamente lo mismo. La única diferencia es que una de ellas tiene un comportamiento particular, pero en esencia, son lo mismo. Por tanto, no es muy apropiado representarlas utilizando clases distintas.&lt;br /&gt;&lt;br /&gt;Cerebro está loco, pero no es tonto. Por tanto, decide que ha encontrado demasiados puntos débiles para su idea inicial, y que por tanto, es el momento de acudir al patrón “Extension Objects”.&lt;br /&gt;&lt;br /&gt;Este patrón intenta anticipar la extensión de la interfaz de un objeto en el futuro (eso quiere decir: se pueden añadir interfaces a una clase en tiempo de ejecución). Así que empieza a leer, y a reírse. Y cuanto más lee, mas se ríe.&lt;br /&gt;&lt;br /&gt;La idea es muy sencilla. Una clase (MazingerZ) será capaz de cambiar la interfaz que implementa en tiempo de ejecución, seleccionando esa interfaz de entre una colección de objetos ( los Extension Objects ). Cada uno de esos objetos encapsularan uno de los roles (MazingerZSoldado, MazingerZFabricante,... ).&lt;br /&gt;&lt;br /&gt;Pero como será capaz la clase “MazingerZ“ de seleccionar la interfaz a implementar? Y de igual manera la clase “ElVengador”?. Bien, ambas clases implementaran la siguiente interfaz.&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;public interface Sujeto{&lt;br /&gt;&lt;br /&gt;    public Rol getExtension( String nombreExt );&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;La clase “MazingerZ” implementa una interfaz para encapsular las acciones que implementa por ser un robot (mover la cabeza, mover las piernas, los brazos).&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package extensionobject.paso1;&lt;br /&gt;&lt;br /&gt;public interface Sujeto {&lt;br /&gt;&lt;br /&gt;    public Rol getExtension( String nombreExt );&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package extensionobject.paso1;&lt;br /&gt;&lt;br /&gt;public interface AccionesBasicas {&lt;br /&gt;&lt;br /&gt;    void moverBrazos( );&lt;br /&gt;    void moverPiernas( );&lt;br /&gt;    void moverCabeza( );&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package extensionobject.paso1;&lt;br /&gt;&lt;br /&gt;public interface AccionFabricante {&lt;br /&gt;&lt;br /&gt;    void construir();&lt;br /&gt;    void disenar();&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package extensionobject.paso1;&lt;br /&gt;&lt;br /&gt;public interface AccionSoldado {&lt;br /&gt;&lt;br /&gt;    void atacar();&lt;br /&gt;    void defender();&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package extensionobject.paso1;&lt;br /&gt;&lt;br /&gt;public abstract class Rol {&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package extensionobject.paso1;&lt;br /&gt;&lt;br /&gt;public class RolFabricante extends Rol implements AccionFabricante{&lt;br /&gt;&lt;br /&gt;    private AccionesBasicas sujeto;&lt;br /&gt;    &lt;br /&gt;    public RolFabricante(AccionesBasicas sujeto){&lt;br /&gt;        this.sujeto = sujeto;&lt;br /&gt;        System.out.println(&quot;RolFabricante creado&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void construir(){&lt;br /&gt;        System.out.println(&quot;Interfaz construir ejecutada&quot;);&lt;br /&gt;        sujeto.moverBrazos();&lt;br /&gt;        sujeto.moverPiernas();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void disenar(){&lt;br /&gt;        System.out.println(&quot;Interfaz disenar ejecutada&quot;);&lt;br /&gt;        sujeto.moverCabeza();&lt;br /&gt;        sujeto.moverBrazos();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package extensionobject.paso1;&lt;br /&gt;&lt;br /&gt;public class RolSoldado extends Rol implements AccionSoldado{&lt;br /&gt;&lt;br /&gt;    private AccionesBasicas sujeto;&lt;br /&gt;    &lt;br /&gt;    public RolSoldado(AccionesBasicas sujeto){&lt;br /&gt;        this.sujeto = sujeto;&lt;br /&gt;        System.out.println(&quot;RolSoldado creado&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void atacar() {&lt;br /&gt;        System.out.println(&quot;Interfaz atacar ejecutada&quot;);&lt;br /&gt;        sujeto.moverBrazos();&lt;br /&gt;        sujeto.moverPiernas();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void defender() {&lt;br /&gt;        System.out.println(&quot;Interfaz defender ejecutada&quot;);&lt;br /&gt;        sujeto.moverBrazos();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package extensionobject.paso1;&lt;br /&gt;&lt;br /&gt;public class MazingerZ implements Sujeto, AccionesBasicas{&lt;br /&gt;&lt;br /&gt;    private RolSoldado rolSoldado;&lt;br /&gt;    private RolFabricante rolFabricante;&lt;br /&gt;&lt;br /&gt;    public MazingerZ() {&lt;br /&gt;        System.out.println(&quot;Creada la plantilla de Mazinger Z&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Rol getExtension(String nombreExt) {&lt;br /&gt;        Rol retornarValor = null;&lt;br /&gt;        if( nombreExt.equals(&quot;RolSoldado&quot;) ){&lt;br /&gt;            if( rolSoldado == null ){&lt;br /&gt;                retornarValor = new RolSoldado(this);&lt;br /&gt;            }&lt;br /&gt;            else{&lt;br /&gt;                retornarValor = rolSoldado;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        else if( nombreExt.equals(&quot;RolFabricante&quot;) ){&lt;br /&gt;            if( rolFabricante == null ){&lt;br /&gt;                retornarValor = new RolFabricante(this);&lt;br /&gt;            }&lt;br /&gt;            else{&lt;br /&gt;                retornarValor = rolFabricante;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        return retornarValor;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void moverBrazos() {&lt;br /&gt;        System.out.println(&quot;Mazinger Z mueve los brazos&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void moverPiernas() {&lt;br /&gt;        System.out.println(&quot;Mazinger Z mueve las piernas&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void moverCabeza() {&lt;br /&gt;        System.out.println(&quot;Mazinger Z mueve la cabeza&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package extensionobject.paso1;&lt;br /&gt;&lt;br /&gt;public class ManejarRobots {&lt;br /&gt;&lt;br /&gt;    public static void main(String args[]){&lt;br /&gt;        MazingerZ robot = new MazingerZ();&lt;br /&gt;        AccionSoldado robotSoldado = (AccionSoldado) &lt;br /&gt;                         robot.getExtension(&quot;RolSoldado&quot;);&lt;br /&gt;        robotSoldado.atacar();&lt;br /&gt;        AccionFabricante robotFabricante = &lt;br /&gt;    (AccionFabricante) robot.getExtension(&quot;RolFabricante&quot;);&lt;br /&gt;        robotFabricante.disenar();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Fíjense como la clase “MazingerZ” implementa el método “getExtension”, que elige la clase que debe devolver de entre una colección de roles (que son variables de la clase). Y los roles ?.&lt;br /&gt;&lt;br /&gt;Para ese caso está la clase abstracta Rol (no he implementado nada en el, pero cualquier funcionalidad común a los roles debería implementarse aquí).&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;public abstract class Rol {&lt;br /&gt;&lt;br /&gt;} &lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Pero Cerebro no es tonto, y sabe que en algún momento necesitara cambiar los roles de sus Robots. En algún momento puede llegar a necesitar que los robots que tienen el rol fabricante deban pasar a tener el rol soldado. Sería posible construir un “MazingerZ” con distintos tipos de roles, y que estos puedan ser modificados en cualquier momento?.&lt;br /&gt;&lt;br /&gt;Entonces Cerebro luego de estudiar mejor el patrón “Extension Objects” decide refactorizar su código.&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package extensionobject.paso2;&lt;br /&gt;&lt;br /&gt;import extensionobject.paso1.Rol;&lt;br /&gt;&lt;br /&gt;public interface Sujeto {&lt;br /&gt;&lt;br /&gt;    Rol getExtension(String nombreExt);&lt;br /&gt;    void addExtension(String nombreExt, Rol extension);&lt;br /&gt;    void removerExtension(String nombreExt);&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package extensionobject.paso2;&lt;br /&gt;&lt;br /&gt;import extensionobject.paso1.AccionesBasicas;&lt;br /&gt;import extensionobject.paso1.Rol;&lt;br /&gt;&lt;br /&gt;import java.util.HashMap;&lt;br /&gt;&lt;br /&gt;public class MazingerZ implements Sujeto, AccionesBasicas {&lt;br /&gt;&lt;br /&gt;    private HashMap rolesCol;&lt;br /&gt;&lt;br /&gt;    public MazingerZ(){&lt;br /&gt;        System.out.println(&quot;Creada la plantilla de Mazinger Z&quot;);&lt;br /&gt;        rolesCol = new HashMap();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Rol getExtension(String nombreExt) {&lt;br /&gt;        return (Rol) rolesCol.get(nombreExt);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void addExtension(String nombreExt, Rol extension) {&lt;br /&gt;        rolesCol.put(nombreExt, extension);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void removerExtension(String nombreExt) {&lt;br /&gt;        rolesCol.remove(nombreExt);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public void moverBrazos() {&lt;br /&gt;        System.out.println(&quot;Mazinger Z mueve los brazos&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void moverPiernas() {&lt;br /&gt;        System.out.println(&quot;Mazinger Z mueve las piernas&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void moverCabeza() {&lt;br /&gt;        System.out.println(&quot;Mazinger Z mueve la cabeza&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package extensionobject.paso2;&lt;br /&gt;&lt;br /&gt;import extensionobject.paso1.AccionSoldado;&lt;br /&gt;import extensionobject.paso1.RolSoldado;&lt;br /&gt;import extensionobject.paso1.RolFabricante;&lt;br /&gt;import extensionobject.paso1.AccionFabricante;&lt;br /&gt;&lt;br /&gt;public class ManejarRobots {&lt;br /&gt;&lt;br /&gt;    public static void main(String args[]){&lt;br /&gt;        MazingerZ robot = new MazingerZ();&lt;br /&gt;        robot.addExtension(&quot;RolSoldado&quot;, &lt;br /&gt;                     new RolSoldado(robot));&lt;br /&gt;        AccionSoldado robotSoldado = (AccionSoldado)&lt;br /&gt;                    robot.getExtension(&quot;RolSoldado&quot;);&lt;br /&gt;        robotSoldado.atacar();&lt;br /&gt;        robot.removerExtension(&quot;RolSoldado&quot;);&lt;br /&gt;        robot.addExtension(&quot;RolFabricante&quot;, &lt;br /&gt;                    new RolFabricante(robot) );&lt;br /&gt;        AccionFabricante robotFabricante = &lt;br /&gt;                ( AccionFabricante ) robot.getExtension&lt;br /&gt;                (&quot;RolFabricante&quot;);&lt;br /&gt;        robotFabricante.construir();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Ahora, los robots construidos por su máquina podrán cambiar su rol en tiempo de ejecución primero pueden ser soldados, luego fabricantes, mas tarde lo que a Cerebro le dé la gana).&lt;br /&gt;&lt;br /&gt;Cerebro ha conseguido mantener la abstracción “MazingerZ” limpia de operaciones específicas para un robot. Eso también lo podría haber conseguido gracias a la herencia, definiendo las operaciones para los robots en las subclases, pero eso habría generado una jerarquía difícil de manejar.&lt;br /&gt;&lt;br /&gt;Cerebro a dado un paso más en su plan de CONQUISTAR AL MUNDO!!!!!.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://dukechile.blogspot.com/2008/07/el-patrn-command.html&quot;&gt;PARTE 3&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;</description><link>http://dukechile.blogspot.com/2008/06/el-patrn-extension-objects.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-6343834684794068045</guid><pubDate>Sun, 15 Jun 2008 17:03:00 +0000</pubDate><atom:updated>2008-08-23T12:26:00.629-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Patrones de Diseño</category><category domain="http://www.blogger.com/atom/ns#">Prototype</category><title>El patron prototype (prototipo) - Parte I</title><description>&lt;div align=&quot;justify&quot;&gt;De la literatura relacionada con patrones de diseño, hay dos libros que recuerdo haber leído con mucho agrado (esos libros que cuesta dejar de leerlos). Uno de ellos es el “Head First Design Patterns”, el cual realmente me rompió los esquemas de los libros que hasta el momento había leído por la forma en que presenta cada uno de los patrones. El otro libro es el “Design Patterns for Dummies”, que para este caso su título lo dice todo.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;Hace un tiempo atrás, necesitaba hacer una clase de patrones de diseño en una universidad, y fue del primer libro, de donde saque muchas ideas para enseñar algunos patrones básicos.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;El primer patrón que veremos será el “Prototype”, pero siguiendo la filosofía del “Head First Design Patterns” en la simpleza de enseñar patrones.&lt;br /&gt;&lt;br /&gt;Para lograr esto, el protagonista principal de estos post sera…..&lt;br /&gt;&lt;/div&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5212155798546422834&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy1iHeTb69hBYSxfU_u7M8i8f_jL0xfxiOFyQIYwzOhghRwauQB0204Zln6ugDVFwDpxxh4JUlq1RPeP57iX3fscuIs92zbU4Pxkzvg-tU6woUT-tjiSp-W-1Onp2PSUS__6e5Fl9o2UE4/s400/cerebro.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Como todos sabemos, Cerebros es un ratón cuyo único deseo es llevar a cabo su malvado plan para…..DOMINAR AL MUNDO!!!!.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Una mañana, ideo un plan malévolo pero perfecto!!!. Recordando su niñez cuando veía el “Show de los Robots” o “Pipiripao” (uff……que viejo), decidió construir un ejercicito de robots y así dominar el mundo!!!!. Para lograr su objetivo, debía construir una máquina capaz de construir cualquier tipo de robot y que fuera programada en Java.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Así que comenzó a programar su máquina para construir su primer robot: &lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso1;&lt;br /&gt;&lt;br /&gt;public class MazingerZ {&lt;br /&gt;&lt;br /&gt;    public MazingerZ(){&lt;br /&gt;        System.out.println(&quot;Construyendo robot Mazinger Z&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt; &lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso1;&lt;br /&gt;&lt;br /&gt;public class MaquinaGeneradora {&lt;br /&gt;&lt;br /&gt;    public MazingerZ construirMazingerZ() {&lt;br /&gt;        return new MazingerZ();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public MazingerZ[] cosntruirMuchosMZ(int numeroRobots){&lt;br /&gt;        MazingerZ[] mazingerZ = new MazingerZ[numeroRobots];&lt;br /&gt;        for (int k = 0; k &amp;lt; numeroRobots; k++) {&lt;br /&gt;            mazingerZ[k] = new MazingerZ();&lt;br /&gt;        }&lt;br /&gt;        return mazingerZ;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt; &lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso1;&lt;br /&gt;&lt;br /&gt;public class ConquistarAlMundo{&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args){&lt;br /&gt;        MaquinaGeneradora mg = new MaquinaGeneradora();&lt;br /&gt;        mg.construirMazingerZ();&lt;br /&gt;        mg.cosntruirMuchosMZ(20);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Tras construir un ejército de robots, Cerebro de dio cuenta que construir un ejército de robots tipo “El Vengador” unidos a los “Mazinger Z” le ayudaría a dominar el mundo más rápido.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Pero aquí se le presento el primer problema. Su máquina no fue programada para construir “El Vengador”, sino solamente para construir “Mazinger Z”.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Así que Cerebro, como buen programador, decide refactorizar su código para añadir a su máquina la funcionalidad necesaria para construir “El Vengador”. &lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso2;&lt;br /&gt;&lt;br /&gt;public class ElVengador {&lt;br /&gt;&lt;br /&gt;    public ElVengador(){&lt;br /&gt;        System.out.println(&quot;Construyendo robot El Vengador&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt; &lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso2;&lt;br /&gt;&lt;br /&gt;import prototipo.paso1.MazingerZ;&lt;br /&gt;&lt;br /&gt;public class MaquinaGeneradora {&lt;br /&gt;&lt;br /&gt;    public MazingerZ construirMazingerZ() {&lt;br /&gt;        return new MazingerZ();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public ElVengador construirElVengador() {&lt;br /&gt;        return new ElVengador();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public MazingerZ[] cosntruirMuchosMZ(int numeroRobots) {&lt;br /&gt;        MazingerZ[] mazingerZ = new MazingerZ[numeroRobots];&lt;br /&gt;        for (int k = 0; k &amp;lt; numeroRobots; k++) {&lt;br /&gt;            mazingerZ[k] = new MazingerZ();&lt;br /&gt;        }&lt;br /&gt;        return mazingerZ;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public ElVengador[] cosntruirMuchosEV(int numeroRobots) {&lt;br /&gt;        ElVengador[] elVengador = new ElVengador[numeroRobots];&lt;br /&gt;        for (int k = 0; k &amp;lt; numeroRobots; k++) {&lt;br /&gt;            elVengador[k] = new ElVengador();&lt;br /&gt;        }&lt;br /&gt;        return elVengador;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt; &lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso2;&lt;br /&gt;&lt;br /&gt;public class ConquistarAlMundo{&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args){&lt;br /&gt;        MaquinaGeneradora mg = new MaquinaGeneradora();&lt;br /&gt;        mg.construirMazingerZ();&lt;br /&gt;        mg.cosntruirMuchosMZ(20);&lt;br /&gt;        mg.construirElVengador();&lt;br /&gt;        mg.cosntruirMuchosEV(18);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Cerebro está loco, pero no es tonto. Por tanto, enseguida se da cuenta de que puede encontrarse con problemas si decide construir otro tipo de robots como “El Gran Dragón del Espacio” o “Afrodita A”.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Tras pensar cuidadosamente sobre su problema, decide hacer una nueva refactorización a su código. &lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso3;&lt;br /&gt;&lt;br /&gt;import prototipo.paso1.MazingerZ;&lt;br /&gt;import prototipo.paso2.ElVengador;&lt;br /&gt;&lt;br /&gt;public class MaquinaGeneradora {&lt;br /&gt;&lt;br /&gt;    public Object construirRobot(String tipo){&lt;br /&gt;  if( tipo.equals(&quot;MazingerZ&quot;) ){&lt;br /&gt;   return new MazingerZ();&lt;br /&gt;  }&lt;br /&gt;  else if( tipo.equals(&quot;ElVengador&quot;) ){&lt;br /&gt;   return new ElVengador();&lt;br /&gt;  }&lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public Object[] construirMuchosRobots(String tipo, int numero){&lt;br /&gt;  Object robots[] = new Object[numero];&lt;br /&gt;  if( tipo.equals(&quot;MazingerZ&quot;) ){&lt;br /&gt;   for( int k=0; k&amp;lt; numero; k++ ){&lt;br /&gt;    robots[ k ] = new MazingerZ();&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  else if( tipo.equals(&quot;ElVengador&quot;) ){&lt;br /&gt;   for( int k=0; k&amp;lt; numero; k++ ){&lt;br /&gt;    robots[ k ] = new ElVengador();&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  return robots;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso3;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class ConquistarAlMundo {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;&lt;br /&gt;        MaquinaGeneradora mg = new MaquinaGeneradora();&lt;br /&gt;&lt;br /&gt;        mg.construirRobot(&quot;MazingerZ&quot;);&lt;br /&gt;&lt;br /&gt;        mg.construirMuchosRobots(&quot;MazingerZ&quot;, 12);&lt;br /&gt;&lt;br /&gt;        mg.construirRobot(&quot;ElVengador&quot;);&lt;br /&gt;&lt;br /&gt;        mg.construirMuchosRobots(&quot;ElVengador&quot;, 8);&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Tras varios minutos de las típicas risas histéricas de Pinky, Cerebro comienza a darse cuenta que la forma en que ha programado su máquina tiene bastantes puntos débiles.&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;En primer lugar, el método “construirRobot” devuelve un Object, no un “Mazinger Z” o un “El Vengador”. Por qué?....porque ese método no sabe lo que va a crear a priori. Cerebro se da cuenta que esta no es la mejor solución.&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;También se da cuenta que si en algún momento quisiera construir algún otro tipo de robot, debería programar nuevamente su máquina, lo cual la transforma, en una maquina difícil de mantener.&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Pero entonces, una idea empieza a abrirse paso en su malvado cerebro. Aun no sabe exactamente cómo hacerlo, pero que pasaría si pudiera darle algo a la maquina (un robot del tipo Mazinger Z, El Vengador, Afrodita A, etc…) y pedirle a la misma que le entrege 800 copias del mismo?....brillante!!!. Así, no tendría que preocuparse de cómo funciona la maquina, simplemente esta devolvería tantas copias como necesite del original.&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Entonces cerebro recuerda haber estudiado el patrón “Prototype”. Para lograr esto, la maquina no puede saber que tiene que construir ni cómo debe construirlo (la creación de la copia), y tampoco puede ser una responsabilidad de cada uno de los robots (o cosas a copiar). La maquina, simplemente debe recibir un robot y le dirá a este que produzca tantas copias de el mismo como se necesiten y luego las devolverá.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghdvbNh4qcS_ExZVLYlxkCr13iMNbTY4OGuQK3jRHbbgkdS3CjjKax3qCTgdOSuxclcQ19JINauZ01pFAfV5LUXA3LUrMqABkcDrwBk3UVqPfF651HttSwcWeE4lmeUnAlX5RzVDk0MLL_/s1600-h/prototipo.JPG&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghdvbNh4qcS_ExZVLYlxkCr13iMNbTY4OGuQK3jRHbbgkdS3CjjKax3qCTgdOSuxclcQ19JINauZ01pFAfV5LUXA3LUrMqABkcDrwBk3UVqPfF651HttSwcWeE4lmeUnAlX5RzVDk0MLL_/s400/prototipo.JPG&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5237749966304267218&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;De hecho, Cerebro se ha dado cuenta de que la forma en la que deben crearse las nuevas copias de los robots no ha de ser la misma para todos, sino que en algunos casos le va a interesar utilizar el mecanismo de clonado de Java, y en otros tener un control más fino del mismo.&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Así que, la primera tarea de Cerebro será crear una interfaz (que extiende Cloneable, implementando de este modo el método clone()), que será el que implemente cada uno de los robots.&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;public interface ClonarRobot extends Cloneable {&lt;br /&gt;&lt;br /&gt;    public ClonarRobot duplicar( );&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;También sería posible que todos los robots extendieran de una clase base, y que por lo tanto el tipo que devuelve el método duplicar() fuera esa clase base. Pero de la manera anteriormente comentada el diseño es mucho más flexible.&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;El método duplicar() será el encargado de crear y devolver una nueva copia de cada robot que lo implemente. &lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso4;&lt;br /&gt;&lt;br /&gt;public interface ClonarRobot extends Cloneable {&lt;br /&gt;&lt;br /&gt;    ClonarRobot duplicar( );&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt; &lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso4;&lt;br /&gt;&lt;br /&gt;public class ElVengador implements ClonarRobot{&lt;br /&gt;&lt;br /&gt;    public ElVengador() {&lt;br /&gt;        System.out.println(&quot;Creada la plantilla de El Vengador&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public ClonarRobot duplicar() {&lt;br /&gt;        System.out.println(&quot;El Vengador se va a clonar a si mismo&quot;);&lt;br /&gt;        ElVengador elVengador = null;&lt;br /&gt;        try {&lt;br /&gt;            elVengador = (ElVengador) super.clone();&lt;br /&gt;        }&lt;br /&gt;        catch (Exception e) {&lt;br /&gt;            System.out.println(&quot;error al clonar El Vengador&quot;);&lt;br /&gt;        }&lt;br /&gt;        return elVengador;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String toString() {&lt;br /&gt;        return &quot;El Vengador - Ya estoy listo para la batalla!!!&quot;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt; &lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso4;&lt;br /&gt;&lt;br /&gt;public class MazingerZ implements ClonarRobot{&lt;br /&gt;&lt;br /&gt;    public MazingerZ() {&lt;br /&gt;        System.out.println(&quot;Creada la plantilla de Mazinger Z&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public ClonarRobot duplicar() {&lt;br /&gt;        System.out.println(&quot;Mazinger Z se va a clonar a si mismo&quot;);&lt;br /&gt;        MazingerZ mazingerZ = null;&lt;br /&gt;        try {&lt;br /&gt;            mazingerZ = (MazingerZ) super.clone();&lt;br /&gt;        }&lt;br /&gt;        catch (Exception e) {&lt;br /&gt;            System.out.println(&quot;error al clonar Mazinger Z&quot;);&lt;br /&gt;        }&lt;br /&gt;        return mazingerZ;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String toString() {&lt;br /&gt;        return &quot;Mazinger Z - Ya estoy listo para la batalla!!!&quot;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt; &lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso4;&lt;br /&gt;&lt;br /&gt;public class MaquinaGeneradora {&lt;br /&gt;&lt;br /&gt;    public Cloneable crearCopia(ClonarRobot plantilla) {&lt;br /&gt;  return plantilla.duplicar();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public Cloneable[] crearMuchasCopias(int numeroCopias, ClonarRobot plantilla) {&lt;br /&gt;  Cloneable[] copias = new Cloneable[numeroCopias];&lt;br /&gt;  for (int i = 0; i &amp;lt; numeroCopias; i++) {&lt;br /&gt;   copias[i] = plantilla.duplicar();&lt;br /&gt;  }&lt;br /&gt;  return copias;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package prototipo.paso4;&lt;br /&gt;&lt;br /&gt;public class ConquistarAlMundo {&lt;br /&gt;&lt;br /&gt;    public static void mostrar(String texto){&lt;br /&gt;        System.out.println(&quot;&quot;);&lt;br /&gt;        System.out.println(texto);&lt;br /&gt;        System.out.println(&quot;&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        MaquinaGeneradora mg = new MaquinaGeneradora();&lt;br /&gt;        mostrar(&quot;Creando plantilla de Mazinger Z y El Vengador&quot;);&lt;br /&gt;        MazingerZ plantillaMazingerZ = new MazingerZ();&lt;br /&gt;        ElVengador plantillaElVengador = new ElVengador();&lt;br /&gt;        MazingerZ mazingerZClonado = (MazingerZ) mg.crearCopia(plantillaMazingerZ);&lt;br /&gt;        mostrar(&quot;Primera Mazinger Z clonado&quot;);&lt;br /&gt;        System.out.println(mazingerZClonado);&lt;br /&gt;        ElVengador elVengadorClonado = (ElVengador) mg.crearCopia(plantillaElVengador);&lt;br /&gt;        mostrar(&quot;Primer El Vengador clonado&quot;);&lt;br /&gt;        System.out.println(elVengadorClonado);&lt;br /&gt;        mostrar(&quot;Creando 10 nuevos Mazinger Z&quot;);&lt;br /&gt;        Cloneable nuevosMazingerZ[] = mg.crearMuchasCopias(10, plantillaMazingerZ);&lt;br /&gt;        mostrar(&quot;Creando 10 nuevos El Vengador&quot;);&lt;br /&gt;        Cloneable nuevosElVengador[] = mg.crearMuchasCopias(10, plantillaElVengador);&lt;br /&gt;        mostrar(&quot;Inicializando los Mazinger Z&quot;);&lt;br /&gt;        for(int i=0; i&lt;&gt;            System.out.println(nuevosMazingerZ[i]);&lt;br /&gt;        }&lt;br /&gt;        mostrar(&quot;Inicializando los El Vengador&quot;);&lt;br /&gt;        for(int i=0; i&lt;&gt;            System.out.println(nuevosElVengador[i]);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Ahora, Cerebro puede seguir construyendo su ejército para conquistar el mundo el mundo con los clones creados por su máquina, sabiendo que puede crear copias de todo lo que le dé la gana, porque le ha dado a su máquina el “don” de crear objetos sin saber de qué tipo deben ser.&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Pero Cerebro es un hombre de ciencia, y en su afán por alcanzar el conocimiento absoluto, sigue leyendo la documentación sobre el patrón prototype, y entonces se da cuenta de que también ha separado el código que crea los objetos del código que maneja los detalles de la creación de nuevos objetos. &lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Esta historia continuara……&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;&lt;a href=&quot;http://dukechile.blogspot.com/2008/06/el-patrn-extension-objects.html&quot;&gt;Parte 2&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;</description><link>http://dukechile.blogspot.com/2008/06/el-patron-prototype-prototipo.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy1iHeTb69hBYSxfU_u7M8i8f_jL0xfxiOFyQIYwzOhghRwauQB0204Zln6ugDVFwDpxxh4JUlq1RPeP57iX3fscuIs92zbU4Pxkzvg-tU6woUT-tjiSp-W-1Onp2PSUS__6e5Fl9o2UE4/s72-c/cerebro.JPG" height="72" width="72"/><thr:total>9</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-7438388247099551096</guid><pubDate>Thu, 12 Jun 2008 18:01:00 +0000</pubDate><atom:updated>2008-07-04T09:34:22.381-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Inversion de Control</category><category domain="http://www.blogger.com/atom/ns#">Patrones de Diseño</category><title>Inversion de Control (IoC)</title><description>&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Hace un tiempo atrás convencí a un amigo de que aprendiera Spring, contándole de todas las ventajas que podría lograr utilizando este framework. El comenzó a estudiarlo y como a todos nos ha pasado, le sorprendió la facilidad con la que puede desarrollar aplicaciones.&lt;/span&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Hasta ahí todo iba muy bien, pero cuando le pregunte que le pareció la “inversión de control” y la “inyección de dependencia”, me dijo que lo único que entendía era que Spring utilizaba estos patrones…...pero de que se trataba……ni idea!!!!&lt;/span&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Así que mi querido amigo XXX (no te voy a echar al agua)…...este post es para ti.&lt;/span&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Imaginemos que tenemos una clase “Componente” que necesita usar la clase “Servicio”. Una solución para esto podría ser :&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso1;&lt;br /&gt;&lt;br /&gt;public class Servicio {&lt;br /&gt;&lt;br /&gt;    public String ejecutarServicio(){&lt;br /&gt;        return &quot;Simulacion de llamada a un servicio&quot;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso1;&lt;br /&gt;&lt;br /&gt;public class Componente {&lt;br /&gt;&lt;br /&gt;    private Servicio servicio;&lt;br /&gt;&lt;br /&gt;    public Componente(){&lt;br /&gt;        servicio = new Servicio();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void ejecutarServicio(){&lt;br /&gt;        String mensaje = servicio.ejecutarServicio();&lt;br /&gt;        System.out.println(mensaje);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso1;&lt;br /&gt;&lt;br /&gt;public class ClaseTest {&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        Componente componente = new Componente();&lt;br /&gt;        componente.ejecutarServicio();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;El problema de esto es que estamos acoplando las clases. Qué pasaría si por algún requerimiento, el desarrollador modifica el código, solicitando ahora algún parámetro en el constructor de la clase “Servicio”?. Esto nos llevaría no solo a modificar el código de la clase “Servicio”, sino también el de la clase “Componente”.&lt;/span&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;O pero aun, tu jefe te dice que no le gusta como esta implementada la clase “Servicio”, así que él, en un acto de iluminación divina, desarrollo la clase “Servicio2” la cual (supuestamente) es mejor a la anterior. Por lo tanto, nuevamente tendremos que modificar nuestra clase “Componente”:&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;&lt;codigo&gt;&lt;/codigo&gt;&lt;/span&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso2;&lt;br /&gt;&lt;br /&gt;public class Servicio2 {&lt;br /&gt;&lt;br /&gt;    public String ejecutarServicio(){&lt;br /&gt;        return &quot;Simulacion de llamada a un servicio optimizada&quot;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso2;&lt;br /&gt;&lt;br /&gt;public class Componente {&lt;br /&gt;&lt;br /&gt;    //private Servicio servicio;&lt;br /&gt;    private Servicio2 servicio2;&lt;br /&gt;&lt;br /&gt;    public Componente(){&lt;br /&gt;        //servicio = new Servicio();&lt;br /&gt;        servicio2 = new Servicio2();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void ejecutarServicio(){&lt;br /&gt;        //String mensaje = servicio.ejecutarServicio();&lt;br /&gt;        String mensaje = servicio2.ejecutarServicio();&lt;br /&gt;        System.out.println(mensaje);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso2;&lt;br /&gt;&lt;br /&gt;public class ClaseTest {&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        Componente componente = new Componente();&lt;br /&gt;        componente.ejecutarServicio();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;…..y mejor ni pensemos si alguien se pone original (nunca faltan!!!!) y comience a modificar el constructor de la clase “Servicio2”.&lt;/span&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Pero como nada es tan terrible, una solución para estos casos es la “Inversión de control”.&lt;/span&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;El primer cambio que tendremos que hacer a nuestro código, es olvidarnos de usar “new XXX()”, para lo cual definiremos un método “setXXX” que nos pase una referencia de una instancia de la clase “Servicio2” :&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;&lt;codigo&gt;&lt;/codigo&gt;&lt;/span&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso3;&lt;br /&gt;&lt;br /&gt;public class Componente {&lt;br /&gt;&lt;br /&gt;    private Servicio2 servicio2;&lt;br /&gt;&lt;br /&gt;    public Componente(){&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setServicio2(Servicio2 servicio2){&lt;br /&gt;        this.servicio2 = servicio2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void ejecutarServicio(){&lt;br /&gt;        String mensaje = servicio2.ejecutarServicio();&lt;br /&gt;        System.out.println(mensaje);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso3;&lt;br /&gt;&lt;br /&gt;public class Servicio2 {&lt;br /&gt;&lt;br /&gt;    public String ejecutarServicio(){&lt;br /&gt;        return &quot;Simulacion de llamada a un servicio optimizada&quot;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso3;&lt;br /&gt;&lt;br /&gt;public class ClaseTest {&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        Componente componente = new Componente();&lt;br /&gt;        componente.setServicio2(new Servicio2());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Hasta aquí todo va bien, pero que pasaría si nuestro jefe, en un acto de arrepentimiento te dice “evaluando la situación, pienso que debemos volver a usar la clase “Servicio” hasta que nuevo aviso (por no decir, hasta que arregle los errores en mi código)”, y nosotros que ya pensábamos que teníamos casi todo controlado, nuevamente tendremos que volver a cambiar el código de la clase “Componente”, modificando el atributo y el método “setXXX”.&lt;/span&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Pero como buenos programadores, sabemos que no va a faltar el jefe original que se le ocurra volver a cambiar el servicio, así que, para evitar problemas a futuro, definiremos una interfaz para el servicio. De ahora en adelante, cualquier clase servicio que se le pase a la clase “Componente”, deberá implementar esta interfaz (ufff….ya no deberemos tocar el código de la clase “Componente”).&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;&lt;codigo&gt;&lt;/codigo&gt;&lt;/span&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso4;&lt;br /&gt;&lt;br /&gt;public class Componente {&lt;br /&gt;&lt;br /&gt;    private ServicioI servicio;&lt;br /&gt;&lt;br /&gt;    public Componente(){&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setServicio(ServicioI servicio){&lt;br /&gt;        this.servicio = servicio;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void ejecutarServicio(){&lt;br /&gt;        String mensaje = servicio.ejecutarServicio();&lt;br /&gt;        System.out.println(mensaje);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso4;&lt;br /&gt;&lt;br /&gt;public interface ServicioI {&lt;br /&gt;&lt;br /&gt;    String ejecutarServicio();&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso4;&lt;br /&gt;&lt;br /&gt;public class Servicio implements ServicioI{&lt;br /&gt;&lt;br /&gt;    public String ejecutarServicio(){&lt;br /&gt;        return &quot;Simulacion de llamada a un servicio&quot;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso4;&lt;br /&gt;&lt;br /&gt;public class Servicio2 implements ServicioI{&lt;br /&gt;&lt;br /&gt;    public String ejecutarServicio(){&lt;br /&gt;        return &quot;Simulacion de llamada a un servicio optimizada&quot;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;package dukechile.jug.ioc.paso4;&lt;br /&gt;&lt;br /&gt;public class ClaseTest {&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        Componente componente = new Componente();&lt;br /&gt;        componente.setServicio(new Servicio());&lt;br /&gt;        componente.ejecutarServicio();&lt;br /&gt;        componente.setServicio(new Servicio2());&lt;br /&gt;        componente.ejecutarServicio();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Como vemos, cambiar el tipo de servicio en la clase “Componente” ya no tiene impacto en nuestro código!!!! (Obviamente..…hasta que no falte el original que cambie la interfaz!!!).&lt;/span&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Hasta aquí toda esta correcto, pero nos falta un pequeño elemento, el “Ensamblador”, cuya tarea principal es obtener la información de cómo cada uno de los elementos debe ser inyectado en otros elementos.&lt;/span&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Para estos casos, es donde frameworks como PicoContainer o Spring utilizan el patrón “Inversión de Control”, los cuales se encargan de realizar la inyección de los elementos. El como lo hacen, puede ser a través de código o en un archivo de configuración.&lt;/span&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:Verdana;&quot;&gt;Para el caso de la “Inyección de dependencias” existen tres mecanismos:&lt;/span&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Inyección de Interfaz (IoC tipo 1)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Inyección de Setter (IoC tipo 2)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Inyección de Constructor (IoC 3)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Que diferencias existen entre los distintos tipos de inyección, va mas allá de este post, pero el señor Martin Fowler lo explica muy bien en este &lt;/span&gt;&lt;a href=&quot;http://martinfowler.com/articles/injection.html&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;articulo&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;La inversión de control no es la única forma de solucionar este problema, también existe el patrón “Service Locator”, pero eso es tema para otro post.&lt;/span&gt;&lt;/p&gt;</description><link>http://dukechile.blogspot.com/2008/06/inversion-de-control-ioc.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><thr:total>7</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-3526645066107591758</guid><pubDate>Fri, 06 Jun 2008 03:32:00 +0000</pubDate><atom:updated>2008-07-04T09:33:31.901-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">BLAZEDS</category><category domain="http://www.blogger.com/atom/ns#">FLEX</category><title>Tutorial de BlazeDS – Parte 1</title><description>&lt;div align=&quot;justify&quot;&gt;Hace poco vimos en una pequeña introducción a BlazeDS en el JUG DAY, pero como el tiempo es corto, es muy difícil poder explicar todas las ventajas que este “Data Services” nos ofrece. Por esta razón, comenzare a explicar en una serie de post cuales son las partes que componen BlazeDS a través de pequeños ejemplos.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;BlazeDS está construido como una aplicación web, cuyo corazón es una infraestructura de mensajería que permite integrar un “Back-End” desarrollado en Java con un “Front-End” en Flex. Esta infraestructura de mensajería nos permite el intercambio de datos a través de dos tipos de servicios: Mensajería y RPC (Remote Procedure Call).&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Servicios RPC&lt;/strong&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;Los servicios RPC están diseñados para aplicaciones en la cuales el modelo “Llamada / Respuesta” es una buena opción para acceder a datos externos. Este servicio permite hacer llamadas asincrónicas a un servicio remoto que procesara esta solicitud y retornara el resultado a la aplicación Flex.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;Un componente RPC que reside en el cliente, puede ser creado con MXML o ActionScript. Este es el encargado de hacer la llamada remota al servicio y almacenar los datos de respuesta del servicio en un objeto ActionScript, desde el cual la aplicación pueda obtener los datos fácilmente. La implementación de un servicio RPC puede ser un HTTP URL, el cual usara http POST o GET; un servicio web SOAP compatible o un objeto Java en una aplicación web Java. Los componentes RPC que residen en el cliente pueden ser del tipo: HTTPService, WebService y RemoteObject.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;El siguiente diagrama provee una visión de cómo los componentes RPC interactúan con servicios RPC.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208608357227293074&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ5ndvckb7DALNX5p31ssgAoF3Tq0PnPAOzRjnycLKTDpbzvhmOQsEtNeeGtIVNq41v9y9QEpf1htrfYA-hdk4-1dVX_Cl0uWDE8FVdNLov5sHF8_ZiBal2FGhvkQ6UwyWYOZsYqUAajJl/s400/rpc1.JPG&quot; border=&quot;0&quot; /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;Mensajeria&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;La capacidad de mensajería en BlazeDS está construida sobre la misma infraestructura de mensajería de los servicios RPC. Utilizando un componente de mensajería se puede desarrollar aplicaciones colaborativas y en tiempo real. Estos componentes proveen una API a las aplicaciones cliente para enviar texto y objetos dentro de un mensaje, permitiendo configurar el destino de este en un archivo de configuración que reside en el servidor de aplicaciones.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;Es posible crear un componente de mensajería a través de MXML o ActionScript, el cual define el destino de los mensajes a enviar al servidor, envía los mensajes a estos destinos y recibe mensajes de otros clientes de mensajería. Los componentes que envían mensajes son llamados “Producidores”, y los que reciben mensajes son llamados “Consumidores”. Los mensajes enviados son transportados a través de “Canales”, los cuales utilizan un protocolo de transporte especifico, como por ejemplo el Action Message Format (AMF).&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;Los clientes de mensajería pueden ser una aplicación Flex u otro tipo de aplicaciones, como por ejemplo una aplicación JMS. JMS es una API en Java que permite desarrollar aplicación para crear, enviar, recibir y leer mensajes. Las aplicaciones JMS pueden publicar y suscribirse al mismo destino de mensajería que las aplicaciones Flex. Sin embargo, se puede crear una variedad de aplicaciones de mensajería solo utilizando el servicio de mensajería de BlazeDS.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Instalación&lt;/strong&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;BlazeDS puede ser descargado desde &lt;a href=&quot;http://opensource.adobe.com/wiki/display/blazeds/BlazeDS&quot;&gt;http://opensource.adobe.com/wiki/display/blazeds/BlazeDS&lt;/a&gt;, existiendo la opción de descargar el código fuente del proyecto, la opción binaria (la cual contiene un archivo WAR) y la opción “Turnkey”, la cual es una versión lista para utilizar, ya que incluye un Tomcat 6.0.14, un archivo WAR y el SDK de Flex 3.0. Para efectos de los ejemplos a desarrollar a lo largo de los post, necesitaremos descarga la versión “Turnkey”.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;Una vez descargado el archivo, descomprímanlo en la carpeta “C:\blazeds_turnkey”, el cual contendrá la siguiente estructura:&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208608362065642290&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNe5bnbCphiF4V3bNpv3kuqAtCRNw8QpCbM2dWhdqVd4yAUEPvMvwfJndQfzyaia2riX7CcIsiBPtvrBigu1Edv3EihTDGYaIgzooZV8WvfpJ2YZPQSfydnTbNoX2ysX8404DiMY_rMHDb/s400/rpc2.JPG&quot; border=&quot;0&quot; /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;Para validar que todo funciona correctamente, ejecuten el archivo “startup.bat” que se encuentra en la carpeta “C:\blazeds_turnkey\tomcat\bin” (es necesario tener correctamente configurada la variable de entorno JAVA_HOME).&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;Una vez que Tomcat se encuentre listo, podrán acceder a la página de administración de BlazeDS en &lt;a href=&quot;http://localhost:8400/ds-console/index.html.&quot;&gt;http://localhost:8400/ds-console/index.html.&lt;/a&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Creación de un proyecto&lt;/strong&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;Tenemos dos opciones de crear un proyecto Flex integrado a BlazeDS. La primera opción es dejar ambos códigos fuentes integrados en un solo proyecto, o en caso contrario, construir dos proyectos por separado.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Proyecto integrado&lt;/strong&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;El primer paso será crear un proyecto Flex que llamaremos “DukeFlex”, seleccionaremos que el tipo de servidor de aplicaciones es “J2EE”, y por último la opción de creación de un proyecto Java/Flex usando WPT.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208608367907056354&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZsPyPXnibubdH_4HdUa3jK1GwulssYZ7LnvWO8qNs-u_KC8vFfoT2s-FU08KJgrQq0Y7ugjxTTJXXPxnQCm89FToDpbVzvHc5_NSSmj8fCtjWFCUGpJlYotdfflzdTEqz7HgkgJJ8C7ea/s400/rpc3.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Seguidamente deberemos definir el servidor de aplicaciones (para este ejemplo utilizare Tomcat 6.x), indicarle donde se encuentra el archivo WAR de BlazeDS, en la opción “Output Folder” borrar el texto “bin-debug” y presionar el botón “Finish”.&lt;/p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208608372481499234&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvwP5StXpYcYupXUp5b9NyB3KwhuM6DWImwwK-vvt5AZssToqhNFlljDYXRAuMjsl0ofyGvlog5QjgzX57EdC1Wv-zzVOfE-eaLskd_yeExv_NFUIoaP9TnoSX3z97TpvwQuxbUoLroIQe/s400/rpc4.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;Ahora crearemos una clase Java que retorne el mensaje “Duke Chile - JUG”, para lo cual deberán cambiar la perspectiva de “Flex” a “Java”.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208608375932567106&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjagxUTYa441v267RinTRp_u8lc6-pEkZ5dlxeDOTfLMKlC41QFUiqAy7T9gw6yf4JjjhAKic4315nqTK7fr_315_gLxblvgyg9j6kzgOqWgSoVeKqzMO0TUjLUfE6YEbFdgritRdfLjRtI/s400/rpc5.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208609669405534674&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrzqhiWE9aI6y9yNIPlyLnfps13Buwm4s5kQQnmUPK2aiiTFzF5jTGRkYc0D8LBo1xvY1Tjom5W-mqp_qMwk56V5w6PVsYSaA4ZNSvf7iGkH1a-UD_gvBAboTVX7a46rLxFtpV3vvSjzFG/s400/rpc6.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208609671551533266&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKml1C_2S0dxQmL2VGtTZ9H0t6hUAkA2OAfh6Sa-yZGw26-aSiXLxfva7XdEhi8ImNkbA-goJJedEV8aaSzrFq62bFXgm4kiR4TW_LsBTWog_i5-6B_ap20Ko95E0Q5lIkcl_eTbw3Qd5a/s400/rpc7.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Una vez creada la clase Java, necesitaremos registrarla como destino en el archivo remoting-config.xml.&lt;/p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208609676899818690&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipTFnf81ktdtuZCJHbI8afJ7LpBqFRd4T6t0vu4uipJk3hxQhyQF7Xuj3I420Fp42VZizCjyWGGaZ5HguPwItZuesMRg0RNRhf745gMRK9akcjwvu5C59IWpownR2aJKiSaQh_W405RnSB/s400/rpc8.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Una vez que tenemos configurado el servicio, el siguiente paso será crear una pequeña página en Flex que llame al método “mensaje”, obtenga el texto del servicio y lo muestre en una ventana de mensajes.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Para esto, volveremos a la perspectiva “Flex” y abriremos el archivo DukeFlex.mxml que está en la carpeta “flex_src” del proyecto.&lt;/p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208609680134644930&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ5nka-ZUbc2b0A3wzJ7wrdkJ7yjumcxMsKLwR3Ux8iCvixgdiDfhLGWzQTIHOiwHkYMOeM_9co2a1gs6IM_7L-QQRAV9Z8AxHPNGiYq8fHGRte1olng6FsKCZdnb52be0NeZ-UlenCTGu/s400/rpc9.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;br /&gt;Dentro de este archivo deberemos crear un objeto “RemoteObject” y definirle el “destination” con “servicioDukeChile”. También deberemos construir un objeto “Button” que llame al servicio y que muestre el mensaje en una ventana de “Alerta”.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208609684059553202&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSgg6JDH3Xhf_gk1i1RhCdoLyK6vLbVT-VV86IeVtAJi5NwDq-u8Pxye1EbpeR8FOcExwR2-BXnFcBHhYRLPoqRcsOweS2lYGORDKRwNZ26uGMLa2UY2gJwyyND0hoSDcrGpgTbU28xs9V/s400/rpc10.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Por último, deberemos realizar un cambio en el “Context Root” del proyecto, cambiando la definición de “WebContent” por “DukeFlex” que es el nombre del proyecto. Para esto deberán presionar el botón derecho del mouse sobre la carpeta del proyecto y seleccionar la opción “Properties”. Dentro de la ventana de propiedades seleccionar la opción “Flex Server” y realizar el cambio.&lt;/p&gt;&lt;br /&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208611215550764178&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8d8yTBPhCsHyK9nD4crfiV_lktBGNVPt_pAi-u5PqVN4aU-70Y0odlFiRCYW47VYUm1zGJr2lJDhVdN3KVS8mMV_e-asXyYfnMDslYkZV6Q4fQWc_qxq2i0-gyNELjc26hmFiySXzn5Y8/s400/rpc11.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;br /&gt;Por último, botón derecho sobre el archivo “DukeFlex.mxml” y seleccionar la opción “Run as --&gt; Flex Application”, con lo cual se iniciara Tomcat y mostrara la página Flex con el botón de prueba.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208611231906006306&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3c6shRiA0yooWAFiv4NF5cYKrou8piN_LUO4M3dKbE1NG23VIoA1JERWOgKzEivJrNGDngEXCES0vrnEPO0R4f9OSlMWwELKyRl0N1P_xH7xLoCKMwEUvl6YdDPOpfJpKAdlz2cTwz-ib/s400/rpc12.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;br /&gt;Al presionar el botón “Llamar servicio”, se llamará al método “mensaje”.&lt;br /&gt;&lt;br /&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208611245719049890&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimiHqtEN4kMv218947hQRLaZK70s4btJjQ_DEuNjJOVJq5ZKhEYIbONxaHOsiL2K2SxxGRpsI8Gu6W7KHDXVJdI04-Aa2lKTLM7k-LzjnskcBwNrWEjA99VdDE3M225OW4khdX7_Q57fuk/s400/rpc13.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;&lt;strong&gt;Proyectos separados&lt;/strong&gt;&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Lo primero que tendremos que hacer es crear la carpeta “dukechile” en “C:\blazeds_turnkey\tomcat\webapps” y dentro de esta copiar el contenido que está en la carpeta “C:\blazeds_turnkey\blazeds”. Con esto tendremos la estructura básica de un proyecto web para BlazeDS.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;El siguiente paso será crear un proyecto “Java” al cual llamaremos “DukeFlexServidor”, seleccionaremos la opción “Create project from existing source”, en la opción “Directory” le indicamos la ruta completa hasta la carpeta “WEB-INF” del proyecto “dukechile” y presionamos el botón “Next”.&lt;/p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208611255963922882&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhassug9JN_EKjVnhTZXIG8WRdl0Th0JMzBjApzfFEODnWQTQPOSAgWH-Ly_W5bjzqzYRtzfWqQZmeidoRD0IV587F22V0xsK2ycg2VWtlJV1u7GrMrCCdEZw-bcNIcMA7Eihn7VKKiTDpy/s400/rpc14.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;En la siguiente opción, deberemos definir la carpeta “src” como nuestro “source foulder”, definiremos la carpeta “classes” como el lugar donde quedaran las clases compiladas y presionamos el botón “Finish”.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;El siguiente paso será crear la clase “ServicioDukeChile” igual a la detallada en “Proyecto Integrado”.&lt;/p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208612490441950034&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPFhX36Zm_Xi8lA6FzbeGjIgHmXZeJrqcfiwuhDGQ1_h83zpZ42Am0Gcg7Kd3afpJ0nXwSldvxZa81NyrJf_tfj29rSXzbdmTeThcg0nGL0sFwFHeRyZv5C6Ug0tfb_W9COaOWDm15T5BD/s400/rpc16.JPG&quot; border=&quot;0&quot; /&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208611271983320130&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQrwKGLa5gJg-PUlxx29oHhtV3NCLazVMuNqemDvsB_5F-SgBBxvIYAMNL2Xah-GmfuM9AUbjbai9Qv1a0l2lJojnRqxeFX_d5j_yFVQwNq5Imdf0HG33tOXQD07gDSCdMkwep8dVwv-T2/s400/rpc15.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208612495578339314&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghj1wyAOheMzsZJW3J3METGdmG2MbBxi5tlns5DgWPcHAiIFq49ttDgijbGcF3i6MJdiPhhDYXXGH4zJSwCCOvy0LUJoAn7EOxQUMCcVVYvs6Xy7t1t8aM7NaW67kJw7_I0lNmrnaIyazX/s400/rpc17.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Una vez creada la clase Java, necesitaremos registrarla como destino en el archivo remoting-config.xml.&lt;/p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208613495238407538&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrPwDcVtXJ1_yIKlrKgFRwjlllAEOnNjIarJ_3iVQgpG02DyBKSj6QniZH1FiikG7CLaJETsIndBsaldUpA2JjuUuR2LexYIxAS_tIwn2ltBQYzngmMz8g9Ri-egrL6cfuczwZ7yRVOxoH/s400/rpc18.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;br /&gt;Con esto ya tendremos listo la parte del lado del servidor. Ahora construiremos la aplicación cliente para cual deberemos crear un proyecto Flex que llamaremos “DukeFlexCliente”, pero que a diferencia de la versión “Proyecto integrado”, en este caso solo seleccionaremos que el servidor de aplicación a utilizar es “J2EE”. Una vez definido esto, presionamos el botón “Next”.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208613498394453730&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpxJpwzdTbpHDggd7xp-DPBJHTQh744PYa9LljVqsET3UKY5GtYkQy0wt-zrZnccfieuFtTzBshmzLGncnj6ixcXOqT1TKj_GYLKZxyi_lK_hTi0Vszu0eUF37c5W0YjzzSwSmXo_ck-MG/s400/rpc19.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;En esta opción deberemos definir que el “Root folder” es la carpeta “dukechile” definida anteriormente dentro del “blazeds_turnkey”. Además deberemos modificar el “Root URL” y el “ContextRoot” como se muestra en la imagen.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Una vez que los datos son modificados, será necesario validar la nueva configuración, para lo cual presionaremos el botón “Validate Configuration”.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Por último, presionamos el botón “Finish” para crear el proyecto Flex.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208613496879864578&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9AivlRFQX-L92kmMJaB32Hq-BTRhC65JuKPQGDzWNiZLnC772GMQgo4C80JCEiFxNwQ3bGuPAWmskZBC-xxGcC0g6g2bpJOb8UjJpBn5BNvFCAKQzzXeDY8Lap5e2XVsbtFCl7IJijhHc/s400/rpc20.JPG&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;En el archivo “DukeFlexCliente” construiremos el mismo ejemplo que realizamos en la opción “Proyecto integrado”.&lt;/p&gt;&lt;p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208613502011858066&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAodwxgKt76dEwlY7Cs9Gvr2LT8Paq97fQcBjk_O3YEplzS5cIiAwJC0hYS7sps5BTXW8X0dyMKK_B_wFKgoH4u_ceH2fR5EDaqq5z6F1POXuAbVtrLeO32VPTDbTc9TjdRMZ6n_RUcAjz/s400/rpc21.JPG&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;&lt;p&gt;Para probar la aplicación deberemos iniciar Tomcat, para lo cual ejecutaremos el archivo “C:\blazeds_turnkey\tomcat\bin\startup.bat”.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208613501660706482&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvh1kVGGwzrjrbJJR2JF8aMXKeLMKrgl653Srk2EbIKXZN9NJtv27Gl_L_fmkhBybDHsPcnrH8ajoW_69vJIb9W6G_rgnL8G6ilq49FKCSJLUY3Yr0TIfqC5r1jjalcMpZjc5eYVYDU6wo/s400/rpc22.JPG&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;&lt;p&gt;Por último, botón derecho sobre el archivo “DukeFlexCliente.mxml” y seleccionar la opción “Run as --&gt; Flex Application”, con lo cual se mostrara la página Flex con el botón de prueba.&lt;/p&gt;&lt;p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208614920873844050&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOVEiMUk33t0jyh8pXM4OztM64R1bXU-CBUIj2G5Mwd5ohyphenhyphenCvg0M2rCNIdv_M2R24S1_Rz3o-OUE6MDo7wBYqmnuosinZNG0Pqv4IBw7G22H91kGTe3xVsvc0UO3sSl7vfB3q6hC8aUpcS/s400/rpc13.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;Al presionar el botón “Llamar servicio”, se llamará al método “mensaje”.&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5208615347626735362&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ4-55VW7JhcVN6DjJpgDOvFLhWvw7KWfpDjGBXDhuVISvcO0k3yi9IBkM8jSnY4wtB4Wk7cHP8PNd0vTuL2HjQHwKJjg0E1IteCKe7t_3Q9Ek5g_Oh1KBNFl0HGT8Nu3hOC_qrRgQtbO0/s400/rpc13.JPG&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Con estos pasos ya podemos comenzar a crear nuestros primeros proyectos utilizando BlazeDS. Además, como vimos anteriormente, tenemos la posibilidad de integrar todo en un mismo proyecto, o tener por separado el proyecto Flex del Java.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;En el siguiente post comenzaremos a analizar los servicios RPC, cuales son los canales definidos para este tipo de servicios, su configuración en BalzeDS y un pequeño ejemplo que involucre estos tópicos.&lt;/p&gt;</description><link>http://dukechile.blogspot.com/2008/06/tutorial-de-blazeds-parte-1.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ5ndvckb7DALNX5p31ssgAoF3Tq0PnPAOzRjnycLKTDpbzvhmOQsEtNeeGtIVNq41v9y9QEpf1htrfYA-hdk4-1dVX_Cl0uWDE8FVdNLov5sHF8_ZiBal2FGhvkQ6UwyWYOZsYqUAajJl/s72-c/rpc1.JPG" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-7065059308334056235</guid><pubDate>Sat, 24 May 2008 23:50:00 +0000</pubDate><atom:updated>2008-07-04T09:32:39.105-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">SPRING</category><category domain="http://www.blogger.com/atom/ns#">SPRING BATCH</category><title>Primeros pasos con Spring Batch</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;Hace un tiempo atrás José Miguel Selman publico en su &lt;a href=&quot;http://www.jug.cl/blogs/jselman/entry/batch_para_java_spring_batch&quot;&gt;blog&lt;/a&gt; el lanzamiento oficial de la versión 1.0 de Spring Batch y desde aquella vez que he querido poder programar un simple ejemplo para meter mis manos en esta nueva funcionalidad que nos ofrece la gente de “&lt;span style=&quot;font-weight: bold;&quot;&gt;SpringSource&lt;/span&gt;”, pero por motivos de tiempo (trabajo, clases, JUG,&lt;span style=&quot;font-size:0;&quot;&gt; &lt;/span&gt;proyectos de investigación,…..etc) nunca he podido darme un tiempo, hasta hoy que me decidí a como de lugar programar mis primeras líneas en” &lt;span style=&quot;font-weight: bold;&quot;&gt;Spring Batch&lt;/span&gt;” (mas bien no jugar PS3 :-( …....pero bueno….Lost Planet puede esperar). &lt;/div&gt;&lt;p class=&quot;MsoNormal&quot; style=&quot;text-align: justify;&quot;&gt;En “&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring Batch&lt;/span&gt;” un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt; es un proceso que se encuentra compuesto por uno o más &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Step&lt;/span&gt;. Para construir un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt; utilizaremos una &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JobInstance&lt;/span&gt;, la cual nos permitirá definir un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt;, asociándole un conjunto de propiedades llamadas &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JobParameters&lt;/span&gt;.&lt;span style=&quot;font-size:0;&quot;&gt; &lt;/span&gt;Cada ejecución de una &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JobInstance&lt;/span&gt; será una &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JobExcecution&lt;/span&gt;.&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot; style=&quot;text-align: justify;&quot;&gt;Por ejemplo, supongamos que necesitamos cada cierto periodo de tiempo leer un información de un repositorio de datos (una base de datos, un chache, etc…), generar un archivo XML que represente a esa información e insertar este una cola de mensajería JMS. Este conjunto de tareas sería un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt; el cual estaría compuesto de tres &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Step&lt;/span&gt;. Si además, parametrizamos este &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt; para que se ejecute cada cierto periodo de tiempo (una hora por ejemplo), cada periodo de tiempo seria una &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JobInstance&lt;/span&gt; &lt;span style=&quot;font-size:0;&quot;&gt;&lt;/span&gt;y cada vez que se ejecute esta instancia (depende de la hora), sería una &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JobExecution&lt;/span&gt;. Este modelo propuesto por “&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring Batch&lt;/span&gt;” permite a los desarrolladores una gran flexibilidad respecto a cómo nuestros &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job &lt;/span&gt;serán lanzados y ejecutados.&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot; style=&quot;text-align: justify;&quot;&gt;El responsable de ejecutar cada uno de los &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt; &lt;span style=&quot;font-size:0;&quot;&gt;&lt;/span&gt;definidos, además del grupo de parámetros asociados a este será el &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JobLauncher&lt;/span&gt;. Por último, en muchos casos, necesitaremos algún lugar donde poder almacenar información en tiempo de ejecución relacionada con el proceso batch, para lo cual se utiliza un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;JobRepository&lt;/span&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot; style=&quot;text-align: justify;&quot;&gt;Para cada &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job &lt;/span&gt;es recomendable utilizar un archivo XML&lt;span style=&quot;font-size:0;&quot;&gt; &lt;/span&gt;de contexto diferente (ya veo un modulo de procesos batch definido con Impala….full!!!). Sin embargo, necesitaremos un conjunto de beans que serán utilizados por cada uno de estos &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt;. Estos objetos los agruparemos en el&lt;span style=&quot;font-size:0;&quot;&gt; &lt;/span&gt;applicationContext.xml, los cuales serán importados desde cada una de las definiciones de los &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt;.&lt;/p&gt;&lt;p class=&quot;MsoListParagraphCxSpFirst&quot; style=&quot;text-indent: -18pt;&quot;&gt;Es Los objetos comunes son:&lt;/p&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JobLauncher&lt;/span&gt;: El cual será el responsable de iniciar un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job &lt;/span&gt;cargando cada uno de sus parámetros asociados. La implementación más básica se encuentra proveida por la clase &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;SimpleJobLauncher&lt;/span&gt;, la cual se soporta en un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;TaskExecutor &lt;/span&gt;para iniciar cada uno de los &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt;. Si no se especifica el tipo de &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;TaskExecutor &lt;/span&gt;se configurara un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;SyncTaskExecutor &lt;/span&gt;por defecto. &lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JobRepository&lt;/span&gt;: Para el manejo del repositorio utilizaremos un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;SimpleJobRepository&lt;/span&gt;, la cual requerirá un conjunto de DAOs para almacenar la información.&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JobInstanceDAO, JobExecutionDAO y StepExecutionDAO&lt;/span&gt;: Estos DAO serán usados&lt;span style=&quot;font-size:0;&quot;&gt; &lt;/span&gt;por el&lt;span style=&quot;font-size:0;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;SimpleJobRepository &lt;/span&gt;para almacenar información relacionada con la ejecución de los &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt;. Para esto, “&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring Batch&lt;/span&gt;” provee dos tipos de implementación: basados en Map (se almacenan los datos en memoria) y en JDBC.&lt;/li&gt;&lt;/ul&gt;&lt;p class=&quot;MsoNormal&quot;&gt;En el archivo &lt;span style=&quot;font-weight: bold;&quot;&gt;applicactionContext.xml&lt;/span&gt; quedaria asi:&lt;/p&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot; xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; schemalocation=&quot;http://www.springframework.org/schema/beans         http://www.springframework.org/schema/beans/spring-beans-2.5.xsd&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- DEFINICION DEL REPOSITORIO PARA LOS JOB --&gt;&lt;br /&gt;  &lt;bean id=&quot;jobRepository&quot; class=&quot;org.springframework.batch.core.repository.support.SimpleJobRepository&quot;&gt;&lt;br /&gt;    &lt;constructor-arg&gt;&lt;br /&gt;      &lt;bean class=&quot;org.springframework.batch.core.repository.dao.MapJobInstanceDao&quot;&gt;&lt;br /&gt;    &lt;/constructor-arg&gt;&lt;br /&gt;    &lt;constructor-arg&gt;&lt;br /&gt;      &lt;bean class=&quot;org.springframework.batch.core.repository.dao.MapJobExecutionDao&quot;&gt;&lt;br /&gt;    &lt;/constructor-arg&gt;&lt;br /&gt;    &lt;constructor-arg&gt;&lt;br /&gt;      &lt;bean class=&quot;org.springframework.batch.core.repository.dao.MapStepExecutionDao&quot;&gt;&lt;br /&gt;    &lt;/constructor-arg&gt;&lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- DEFINICION DEL LANZADOR DE LOS JOB AL CUAL SE LE INJECTA EL REPOSITORIO --&gt;&lt;br /&gt;  &lt;bean id=&quot;jobLauncher&quot; class=&quot;org.springframework.batch.core.launch.support.SimpleJobLauncher&quot;&gt;&lt;br /&gt;    &lt;property name=&quot;jobRepository&quot; ref=&quot;jobRepository&quot;&gt;&lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;&lt;/beans&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Para programar nuestro ejemplo, la clase deberá implementar la interfaz &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Tasklet&lt;/span&gt;.&lt;span style=&quot;font-size:0;&quot;&gt; &lt;/span&gt;Dentro de esta clase programaremos la lógica que deberá ejecutar un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt;, que en nuestro caso será un mensaje por consola.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;textarea class=&quot;java&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;package cl.jug;&lt;br /&gt;&lt;br /&gt;import org.springframework.batch.core.step.tasklet.Tasklet;&lt;br /&gt;import org.springframework.batch.repeat.ExitStatus;&lt;br /&gt;&lt;br /&gt;public class EjemploTasklet implements Tasklet {&lt;br /&gt;&lt;br /&gt;  private String mensaje;&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public ExitStatus execute() throws Exception {&lt;br /&gt;    System.out.print(mensaje);&lt;br /&gt;    return ExitStatus.FINISHED;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void setMensaje(String mensaje) {&lt;br /&gt;    this.mensaje = mensaje;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;p class=&quot;MsoNormal&quot; style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;color:black;&quot;&gt;Fíjense que el método “&lt;span style=&quot;font-weight: bold;&quot;&gt;execute&lt;/span&gt;” retorna un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;ExitStatus &lt;/span&gt;para indicar el estado de ejecución del &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Tasklet&lt;/span&gt;.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;/div&gt;&lt;p class=&quot;MsoNormal&quot; style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;line-height: 115%;&quot;&gt;Ahora solo nos queda definir nuestro primer &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job &lt;/span&gt;en un archivo de contexto que llamaremos EjemploBasicoJob.xml. Dentro de este, utilizaremos la implementación de un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;SimpleJob &lt;/span&gt;la cual ejecutara todos los &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Step &lt;/span&gt;secuencialmente. Para poder definir un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Tasklet &lt;/span&gt;dentro de un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt;, deberemos utilizar un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;TaskletStep&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;br /&gt;&lt;textarea class=&quot;xml&quot; name=&quot;code&quot; rows=&quot;10&quot; cols=&quot;60&quot;&gt;&lt;br /&gt;&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot; xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; schemalocation=&quot;http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;import resource=&quot;applicationContext.xml&quot;&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- DEFINICION DE CADA UNO DEL LOS PASOS A EJECUTAR --&gt;&lt;br /&gt;  &lt;bean id=&quot;paso1&quot; class=&quot;cl.jug.EjemploTasklet&quot;&gt;&lt;br /&gt;    &lt;property name=&quot;mensaje&quot; value=&quot;Ejemplo de Spring Batch - &quot;&gt;&lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;  &lt;bean id=&quot;paso2&quot; class=&quot;cl.jug.EjemploTasklet&quot;&gt;&lt;br /&gt;    &lt;property name=&quot;mensaje&quot; value=&quot;http://www.jug.cl - &quot;&gt;&lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;  &lt;bean id=&quot;paso3&quot; class=&quot;cl.jug.EjemploTasklet&quot;&gt;&lt;br /&gt;    &lt;property name=&quot;mensaje&quot; value=&quot;jcoronel@jug.cl&quot;&gt;&lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- DEFINICION DEL EJECUTOR DE LOS PASOS DE MANERA SECUENCIAL --&gt;&lt;br /&gt;  &lt;bean id=&quot;taskletStep&quot; abstract=&quot;true&quot; class=&quot;org.springframework.batch.core.step.tasklet.TaskletStep&quot;&gt;&lt;br /&gt;    &lt;property name=&quot;jobRepository&quot; ref=&quot;jobRepository&quot;&gt;&lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;  &lt;!-- DEFINICION DEL JOB EL CUAL ESTA COMPUESTO DE TRES PASOS SECUENCIALES --&gt;&lt;br /&gt;  &lt;bean id=&quot;ejemploJob&quot; class=&quot;org.springframework.batch.core.job.SimpleJob&quot;&gt;&lt;br /&gt;    &lt;property name=&quot;name&quot; value=&quot;ejemploJob&quot;&gt;&lt;br /&gt;    &lt;property name=&quot;jobRepository&quot; ref=&quot;jobRepository&quot;&gt;&lt;br /&gt;    &lt;property name=&quot;steps&quot;&gt;&lt;br /&gt;      &lt;list&gt;&lt;br /&gt;        &lt;bean parent=&quot;taskletStep&quot;&gt;&lt;br /&gt;          &lt;property name=&quot;tasklet&quot; ref=&quot;paso1&quot;&gt;&lt;br /&gt;        &lt;/bean&gt;&lt;br /&gt;        &lt;bean parent=&quot;taskletStep&quot;&gt;&lt;br /&gt;          &lt;property name=&quot;tasklet&quot; ref=&quot;paso2&quot;&gt;&lt;br /&gt;        &lt;/bean&gt;&lt;br /&gt;        &lt;bean parent=&quot;taskletStep&quot;&gt;&lt;br /&gt;          &lt;property name=&quot;tasklet&quot; ref=&quot;paso3&quot;&gt;&lt;br /&gt;        &lt;/bean&gt;&lt;br /&gt;      &lt;/list&gt;&lt;br /&gt;    &lt;/property&gt;&lt;br /&gt;  &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;&lt;/beans&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;span style=&quot;line-height: 115%;&quot;&gt;&lt;span style=&quot;line-height: 115%;font-family:arial;&quot; &gt;&lt;/span&gt;&lt;span style=&quot;color:black;&quot;&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot; style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;color:black;&quot;&gt;“&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring Batch&lt;/span&gt;” provee muchas formas de ejecutar un &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt;. La más simple es utilizando la clase &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;CommandLineJobRunner&lt;/span&gt;, al cual se puede ejecutar desde línea de comandos y recibe como parámetros iniciales el nombe del archivo de contexto XML donde está definido el &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job &lt;/span&gt;y el nombre del bean del &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt;. En mi caso lo estoy ejecutando desde Eclipse, así que solo necesitao crear una nueva “&lt;span style=&quot;font-weight: bold;&quot;&gt;Java Application&lt;/span&gt;” y en el “&lt;span style=&quot;font-weight: bold;&quot;&gt;Main class&lt;/span&gt;” definir la clase &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;CommandLineJobRunner&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAvAm8Ea2uaxh5dxgWu73AmlZYP6mbDunZd2fjO19GsQQNlaxjOv-mS28vDMjptrCBTK7IL3OtKnFcPTdCg5RAEquE7hiil_dNHCRFIc_B49RDfOFUa8DrHmbV0Yn14OvqfPrAv1XoEdVx/s1600-h/sb1.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5204109851186268146&quot; style=&quot;margin: 0px auto 10px; display: block; cursor: pointer; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAvAm8Ea2uaxh5dxgWu73AmlZYP6mbDunZd2fjO19GsQQNlaxjOv-mS28vDMjptrCBTK7IL3OtKnFcPTdCg5RAEquE7hiil_dNHCRFIc_B49RDfOFUa8DrHmbV0Yn14OvqfPrAv1XoEdVx/s400/sb1.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;color:black;&quot;&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;color:black;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;color:black;&quot;&gt;Por último, se le debe pasar por parámetro el nombre del archivo XML de contexto donde se encuentra definido el &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job &lt;/span&gt;y el nombre del bean del &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;Job&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;color:black;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4pSPBzBSdK2_iiDqCL6l2-03JFnoZog2jNKoPovdDow2V_ky-rauiGrDsPWqd8gm6T24jJktP1VH93JCRdutTh4U6vVf7_OSWXjeA4g5wUmQ9EU-P4QnOXlbjnK0CLwdhQSJgVImZEOB_/s1600-h/sb2.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5204109859776202754&quot; style=&quot;margin: 0px auto 10px; display: block; cursor: pointer; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4pSPBzBSdK2_iiDqCL6l2-03JFnoZog2jNKoPovdDow2V_ky-rauiGrDsPWqd8gm6T24jJktP1VH93JCRdutTh4U6vVf7_OSWXjeA4g5wUmQ9EU-P4QnOXlbjnK0CLwdhQSJgVImZEOB_/s400/sb2.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;color:black;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;color:black;&quot;&gt;El codigo fuente desde este ejemplo lo pueden descargar desde aqui&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;color:black;&quot;&gt;&lt;br /&gt;&lt;embed src=&quot;http://www.driveway.com/driveway/driveway_widget.swf?user=&quot; type=&quot;application/x-shockwave-flash&quot; wmode=&quot;transparent&quot; allowscriptaccess=&quot;always&quot; width=&quot;480&quot; height=&quot;370&quot;&gt;&lt;/embed&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;color:black;&quot;&gt;&lt;br /&gt;Más información respecto a ejemplo más complejos lo pueden consultar en &lt;a href=&quot;http://static.springframework.org/spring-batch/spring-batch-docs/reference/html/execution.html&quot;&gt;http://static.springframework.org/spring-batch/spring-batch-docs/reference/html/execution.html&lt;/a&gt;.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;color:black;&quot;&gt;Nos vemos en el JUG DAY!!!!&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;</description><link>http://dukechile.blogspot.com/2008/05/primeros-pasos-con-spring-batch.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAvAm8Ea2uaxh5dxgWu73AmlZYP6mbDunZd2fjO19GsQQNlaxjOv-mS28vDMjptrCBTK7IL3OtKnFcPTdCg5RAEquE7hiil_dNHCRFIc_B49RDfOFUa8DrHmbV0Yn14OvqfPrAv1XoEdVx/s72-c/sb1.JPG" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-208286867873741650</guid><pubDate>Tue, 01 Apr 2008 18:46:00 +0000</pubDate><atom:updated>2008-08-10T23:09:29.604-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Agentes Inteligentes</category><category domain="http://www.blogger.com/atom/ns#">JADE</category><title>Mensajeria en JADE</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;JADE se encuentra basado en las especificaciones FIPA en cuanto al formato de los mensajes, los cuales están divididos en diferentes slots que contiene la información (lenguaje, protocolo, contenido. . . ), y sobre estos se definen funciones de creación (set) y consulta (get).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Los métodos básicos de los que se dispone para el manejo de los mensajes entre agentes son:&lt;br /&gt;&lt;br /&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;strong&gt;send(ACLMessage):&lt;/strong&gt; Se usa para enviar un mensaje una vez ingresados todos los parametros de este. El mensaje es enviado desde el agente que invoca el método a todos los destinatarios que contienen el campo :receiver.&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;&lt;/strong&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;strong&gt;ACLMessage receive( ):&lt;/strong&gt; Recibe un mensaje de la cola de mensajes del agente. Se puede especificar que tipo de mensaje se quiere recibir mediante una plantilla de mensaje (MessageTemplate).&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;&lt;/strong&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;strong&gt;ACLMessage blockingReceive( ):&lt;/strong&gt; Bloquea el agente mientras no se reciba un mensaje. Al igual que en el método anterior, se puede especificar el tipo de mensaje a recibir, con lo que se desecharía el resto, y el agente permanecería bloqueado hasta recibir el mensaje deseado.&lt;/li&gt;&lt;/ul&gt;La siguiente figura muestra la secuencia de envió de un mensaje en JADE:&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5ynqIQBA_On_VJrx-S7JdJM2QETkzOtjHNtC3Mfr3_vhvu88Rbzx5qRZh1CN4MetWSE0fWJRiA2ZPvXqP6hUjBL_isQYZG1SBl_xK8zRaYa-IcCroYEJ2w339f-S8_vZaUZh_7rxaNio4/s1600-h/mensaje1.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5184350567333385042&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5ynqIQBA_On_VJrx-S7JdJM2QETkzOtjHNtC3Mfr3_vhvu88Rbzx5qRZh1CN4MetWSE0fWJRiA2ZPvXqP6hUjBL_isQYZG1SBl_xK8zRaYa-IcCroYEJ2w339f-S8_vZaUZh_7rxaNio4/s400/mensaje1.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;Como se aprecia en la figura anterior el agente A1 prepara el mensaje configurando como receptor de este al agente A2 y lo envía a través del canal de distribución de mensajes de JADE, el cual guarda el mensaje en la cola de recepción del agente A2. Una vez guardado el mensaje en la cola de recepción, el agente A2 puede proceder en cualquier momento a retirar este.&lt;/p&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;El lenguaje que se utiliza comúnmente para escribir los mensajes es el FIPA-SL (Semantic Lenguaje), el cual contiene un ámbito mas general ya que permite: formar expresiones lógicas, intercambiar información entre agentes y expresar acciones a realizar.&lt;/p&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;strong&gt;Agent Communication Language (ACL)&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;strong&gt;&lt;/strong&gt;En una sociedad multiagente, los agentes deben cooperar para realizar sus tareas y alcanzar sus objetivos. Los mecanismos de comunicación tradicionales permiten que dos agentes se transfieran información, pero eso es insuficiente cuando el objetivo es conseguir un comportamiento social. Es decir, son necesarios otros mecanismos que permitan dotar a los mensajes intercambiados de un contenido semantico.&lt;/p&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;Para definir el modelo de comunicación, FIPA parte de la idea que los agentes poseen capacidad de razonamiento. Esta capacidad viene dada por una serie de actitudes mentales que se definen como:&lt;/p&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;strong&gt;Creencias:&lt;/strong&gt; Conjunto de proposiciones que el agente acepta como verdaderas. Lo que el agente conoce del mundo.&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;strong&gt;Objetivos:&lt;/strong&gt; Conjunto de propiedades que el agente quiere que sean verdaderas aunque actualmente no están entre sus creencias.&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;strong&gt;Intenciones:&lt;/strong&gt; Conjunto de acciones planificadas por el agente que le permiten llegar a un estado deseado.&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Mediante sus acciones, un agente puede contribuir a cambiar el estado de su entorno y así satisfacer sus objetivos. Un agente influye en el conocimiento y acciones de otros agentes mediante un acto de comunicación (speech act), que se realiza mediante el envió de un mensaje desde el origen al destino. Ambos extremos de la comunicación deben entender el mensaje, y este debe ser algo mas que un intercambio de datos: debe tener asociado un contenido semantico accesible por ambas partes.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;La solución adoptada por FIPA se basa en la utilización de mensajes ACL que tienen que ser comprendidos por cualquier agente del sistema. El uso de mensajes ACL permite el envió de información junto a su contenido semantico.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;El lenguaje ACL (Agent Communication Language) desarrollado por FIPA es una evolución del lenguaje KQML (Knowledge Query Manipulation Language). La definición semántica formal de los mensajes ACL ha sido uno de los esfuerzos mayores dentro del estándar FIPA, y otorga a este lenguaje de una gran aceptación como estándar dentro del mundo de los agentes.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Desde este punto de vista, hay que entender un agente como una entidad que entiende el lenguaje ACL y es capaz de intercambiar conocimiento con otros agentes mediante el uso del mismo. Ya no se habla de que la interfaz de un agente (objeto) ofrezca una serie de servicios que se puedan invocar o instanciar, sino que un agente va a proporcionar ciertos servicios que se le pueden solicitar mediante un mensaje ACL que incluya dicha solicitud. Se pasa de un modelo de objetos a un modelo de agentes inteligentes basados en actos de comunicación.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;strong&gt;Niveles de un mensaje ACL&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;strong&gt;&lt;/strong&gt;&lt;strong&gt;Contenido:&lt;/strong&gt; Contenido real del mensaje en el lenguaje de representación propio.&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;strong&gt;Mensaje:&lt;/strong&gt; El nivel de mensaje conforma la esencia del mensaje. Determina el tipo de interacciones que se pueden tener con un agente que habla ACL. La función principal del nivel de mensaje es identificar el protocolo a ser utilizado para enviar el mensaje y proporciona al emisor una preformativa para que añada el contenido.&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;strong&gt;Comunicación:&lt;/strong&gt; Relativo a los parámetros de comunicación a más bajo nivel: identidad del emisor y receptor, y un identificador único asociado con la comunicación.&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;La siguiente figura muestra los niveles de comunicación en un mensaje ACL:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlKYShE-GkUAojyc6cCVFnSTwozfRefsa-ii3NFI3nAkeT_4bnsMhKKKNoSV7BkdjgJ_TVuzoakgsKITd34Xsncf1mJHx3idh6O2obnEnm7tPabdnYkZuf7mJaabLj3JqNIt3WjrypvCWO/s1600-h/mensaje2.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5184350571628352354&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlKYShE-GkUAojyc6cCVFnSTwozfRefsa-ii3NFI3nAkeT_4bnsMhKKKNoSV7BkdjgJ_TVuzoakgsKITd34Xsncf1mJHx3idh6O2obnEnm7tPabdnYkZuf7mJaabLj3JqNIt3WjrypvCWO/s400/mensaje2.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;strong&gt;Estructura de un mensaje ACL&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;Un mensaje ACL esta formado por:&lt;/p&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Identificador del tipo de comunicación&lt;/span&gt;: Define el significado principal del mensaje. Es decir, lo que el agente origen pretende con dicho mensaje. Por ejemplo: ”inform”(un agente transmite información a otro), ”request”(un agente solicita a otro que realice una accion), ”agree”(un agente acepta la petición realizada), ”query”(un agente solicita información a otro).&lt;/li&gt;&lt;/ul&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Secuencia de parámetros del mensaje&lt;/span&gt;: Es un conjunto de parejas clave-valor que permiten asociar a cada acto de comunicación concreto toda la información necesaria.&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;Ejemplo de mensaje ACL:&lt;/p&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;(inform&lt;br /&gt;      :sender agente1&lt;br /&gt;      :receiver: agente2&lt;br /&gt;      :content&lt;br /&gt;             (velocidad agenteA 40)&lt;br /&gt;      :in-reply-to round-4&lt;br /&gt;      :reply-with bid04&lt;br /&gt;      :language sl&lt;br /&gt;      :ontology ontologia-agente&lt;br /&gt;)&lt;/p&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Este mensaje enviado del agente1 al agente2 informa que la velocidad del agente A es de 40, utiliza el lenguaje SL y la ontología ontologia-agente para describir esta información.&lt;br /&gt;&lt;/div&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;La siguiente figura muestra la estructura de los mensajes que se intercambian entre agentes:&lt;/p&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLeUS_-EzrHT4iv0AUnpypf6uvbj6h-Ko3l6UfjSjWigvJXRnZEsOBOmMFiCyYRS2CXa3vf8vQpURTOHpWYYD-wUeNvMP3C99cpm4YIxeTb8GCWU8vl-Eu-46FffOIqmk0gK0fsvuxVaCt/s1600-h/mensaje3.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5184350571628352370&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLeUS_-EzrHT4iv0AUnpypf6uvbj6h-Ko3l6UfjSjWigvJXRnZEsOBOmMFiCyYRS2CXa3vf8vQpURTOHpWYYD-wUeNvMP3C99cpm4YIxeTb8GCWU8vl-Eu-46FffOIqmk0gK0fsvuxVaCt/s400/mensaje3.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;strong&gt;Parámetros del mensaje&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;Los parámetros básicos del lenguaje ACL definidos por la especificación FIPA, son los siguientes: &lt;/p&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPgwZwpH65XVJMee1H0z7tkbSQzJJycGDAiqAqjuEI55oRmFVGp9an8eArOb7k2PZw9xpUyUi3nWrIkx89ETTP25PbnQ4MzKHJCBjHSNGM0elRTPB3b_iD0rU9u-kauxX9m5KLpxkAYjIL/s1600-h/mensaje4.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5184350575923319682&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPgwZwpH65XVJMee1H0z7tkbSQzJJycGDAiqAqjuEI55oRmFVGp9an8eArOb7k2PZw9xpUyUi3nWrIkx89ETTP25PbnQ4MzKHJCBjHSNGM0elRTPB3b_iD0rU9u-kauxX9m5KLpxkAYjIL/s400/mensaje4.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt; &lt;/p&gt;</description><link>http://dukechile.blogspot.com/2008/04/mensajeria-en-jade.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5ynqIQBA_On_VJrx-S7JdJM2QETkzOtjHNtC3Mfr3_vhvu88Rbzx5qRZh1CN4MetWSE0fWJRiA2ZPvXqP6hUjBL_isQYZG1SBl_xK8zRaYa-IcCroYEJ2w339f-S8_vZaUZh_7rxaNio4/s72-c/mensaje1.JPG" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-951675107219306917</guid><pubDate>Sat, 29 Mar 2008 18:31:00 +0000</pubDate><atom:updated>2008-08-23T12:38:06.039-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Agentes Inteligentes</category><category domain="http://www.blogger.com/atom/ns#">JADE</category><title>Manejo de comportamientos en JADE</title><description>&lt;div align=&quot;justify&quot;&gt;Las tareas o servicios que un agente hace se especifican a través de comportamientos. Un comportamiento (behaviour) hace referencia a una funcionalidad que incorpora el agente. Para que un agente pueda crear uno o más comportamientos debe heredar la clase jade.core.behaviours.Behaviour. Una vez que se ha implementado, el agente puede ejecutar ese comportamiento cada vez que sea invocado dentro del método setup del agente, el cual los anexa al agente a través del metodo addBehaviour perteneciente a la clase Agent.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;Se puede pensar que los comportamientos son como los hilos de ejecución en Java (threads), ya que al igual que estos, en un agente pueden ejecutarse a la vez tantos comportamientos como sea necesario. Sin embargo, a diferencia de los hilos, el decidir que comportamiento se ejecuta en cada momento es tarea del desarrollador del agente. Esto es así para que cada agente sea equivalente únicamente a un único hilo, con el consiguiente ahorro de ciclos de CPU y memoria que esto implica.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;La creación de los comportamientos se realiza extendiendo la clase jade.core. Behaviours, para lo cual la clase Agent tiene dos métodos para poder agregar o eliminar comportamientos:&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;addBehaviour&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;removeBehaviour&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Estos comportamientos pueden ser anexados dentro del método setup (lo habitual), desde cualquier comportamiento, o desde otros agentes. Algunos métodos con los que cuentan los comportamientos son:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;action:&lt;/strong&gt; Método que implementa la tarea a realizar.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;done:&lt;/strong&gt; Método booleano que comprueba si la tarea ha acabado, eliminándola si retorna true.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;block:&lt;/strong&gt; Método que bloquea la ejecución del comportamiento. El bloqueo se hace efectivo cuando el método action retorna, el cual puede ser configurado con un determinado tiempo.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;restar:&lt;/strong&gt; Se reinicia explícitamente un comportamiento bloqueado.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;reset:&lt;/strong&gt; Retorna el comportamiento a su estado inicial.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;onStart:&lt;/strong&gt; Acciones antes de iniciar el comportamiento.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;onEnd:&lt;/strong&gt; Acciones antes de finalizar el comportamiento.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;JADE no guarda el estado de los comportamientos, razón por la cual es responsabilidad del desarrollador guardar el último estado de este.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Los comportamientos pueden ser agrupados en tres grandes grupos:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Comportamientos one-shot:&lt;/strong&gt; Son aquellos que se ejecutan de manera casi instantánea, y solamente una vez.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Comportamientos cíclicos:&lt;/strong&gt; Son aquellos que nunca son sacados del conjunto de comportamientos del agente y cuyo método action siempre ejecuta el mismo código. Por lo tanto, nunca finalizan.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Comportamientos genéricos:&lt;/strong&gt; Un poco más complejos ya que el código que se ejecuta en ellos depende del estatus del agente, y eventualmente analizan su ejecución.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Otro tipo de comportamientos en JADE son los compuestos, que permiten combinar comportamientos previamente definidos de manera conveniente para aplicarles un orden de ejecución determinado; estos son:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;Secuenciales a través de SequentialBehaviour.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;En paralelo a través de ParallelBehaviour.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;Guiados mediante un autómata finito deterministico a través de FSMBehaviour.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Existen comportamientos a los cuales se les puede definir su ejecución a través de un tiempo de espera; estos son WakerBehaviour y TickerBehaviour, los cuales tienen en común que su ejecución es diferida. Se invocan y aguardan hasta que se ha cumplido un determinado tiempo. El primero de estos solamente se ejecuta una vez y el segundo es un comportamiento cíclico.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Los objetos behaviour describen pequeñas tareas que debe realizar el agente ejecutándose según un planificador que se encuentra implementado en la clase Agent. El planificador va ejecutando según una política round-robin (o por turnos rotatorios) de los objetos behaviour que se encuentran en una cola FIFO.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Los objetos behaviour tienen dos métodos que se deben reescribir, action() y done(). El método action() es en donde se deben desarrollar las tareas que debe realizar el agente, mientras que el método done() es llamado cuando el action() finaliza. El planificador va ejecutando uno a uno los métodos action() de la cola y cuando el método action() de un objeto finaliza se llama al método done(), el cual debe retornar un valor booleano. Si retorna true, el objeto es sacado fuera del planificador ya que se da por concluida su tarea, mientras que si retorna false se vuelve a planificar.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Si en algún momento de la ejecución del método action() se requiere esperar por la llegada de un mensaje, existe el método block() para mandar a una cola de bloqueados cuando el método action() finaliza (no cuando se llama a block()). Cuando se produce la llegada de un mensaje, todos los objetos en la cola de bloqueados se planifican y deben comprobar si el mensaje llegado es para ellos o no. En caso de que un objeto no sea el destinatario del mensaje este debe volver a bloquearse.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Es importante que los métodos action() sean cortos, de esta forma se permite un cierto grado de paralelismo. Si se necesita realizar una tarea que va a requerir un largo periodo de tiempo, entonces el desarrollador deberá dividir la tarea en subtareas y cada una de ellas implementarla mediante un objeto behaviour. Con el fin de ayudar en esta labor, JADE proporciona una jerarquía de clases behaviour, que permite incluso simular maquinas de estados finitos.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;SimpleBehaviour:&lt;/strong&gt; Representa un comportamiento atómico.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;OneShotBehaviour:&lt;/strong&gt; Representa un comportamiento que se debe ejecutar solo una vez, por eso su método done() retorna true, si no es redefinido.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;CyclicBehaviour:&lt;/strong&gt; Representa un comportamiento que debe ejecutarse una serie de veces. El método done, si no es redefinido, devuelve false.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;SenderBehaviour:&lt;/strong&gt; Encapsula la acción de envió de un mensaje ACL. Este mensaje debe ser especificado en el constructor.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;ReceiverBehaviour:&lt;/strong&gt; Encapsula la acción de recepción de un mensaje ACL. Termina cuando se recibe el mensaje o cuando pasa una cierta cantidad de tiempo especificada en el constructor.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;WakerBehaviour:&lt;/strong&gt; Implementa un comportamiento OneShot que se ejecuta justo después de que haya pasado un tiempo especificado.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;CompositeBehaviour:&lt;/strong&gt; Esta clase se compone de diferentes sub-behaviours que se pueden ejecutar siguiendo diferentes políticas de planificación, las cuales vienen determinadas por la subclase elegida, las que pueden ser: SequentialBehaviour, ParallelBehaviour y FSMBehavior.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;SequentialBehaviour:&lt;/strong&gt; Esta clase deriva de CompositeBehaviour y ejecuta sub-behaviours de forma secuencial, y termina cuando todos los métodos action() han terminado.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOxjNYDoLL0QXSKxj08xJStY74yWlEHFf7s-r63WszO7f0OXF6smyT_LTmdPjKff9-ARxvd905ZmCldi8fQvaSHIOGuq3qJ9hvFkT71eQFc3CcQdA2t9Jukt6pCLjcRez-G08pKtg74ilC/s1600-h/comp1.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5183233416274924322&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOxjNYDoLL0QXSKxj08xJStY74yWlEHFf7s-r63WszO7f0OXF6smyT_LTmdPjKff9-ARxvd905ZmCldi8fQvaSHIOGuq3qJ9hvFkT71eQFc3CcQdA2t9Jukt6pCLjcRez-G08pKtg74ilC/s400/comp1.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;ParallelBehaviour:&lt;/strong&gt; Esta clase deriva de CompositeBehaviour y ejecuta los sub-behaviours de manera concurrente. En el constructor de la clase se puede especificar cuando se desea que acabe la ejecución: cuando todos los sub-behaviours lo han hecho, cuando uno termine, o cuando un numero especificado lo logre.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnSQZx5scQwB6jAh702Zg3u4iOKPZi9K9ewcEsFw5yUJipWq0ZvjV_uC49SOKsy66yH2PFmX4D89atrdfLSQDzl_hWxnAlMOF_V_LsogE2m1-Sg18ozbPPiQJ3Zujk5w36sULVLyaScGpn/s1600-h/comp2.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5183233420569891634&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnSQZx5scQwB6jAh702Zg3u4iOKPZi9K9ewcEsFw5yUJipWq0ZvjV_uC49SOKsy66yH2PFmX4D89atrdfLSQDzl_hWxnAlMOF_V_LsogE2m1-Sg18ozbPPiQJ3Zujk5w36sULVLyaScGpn/s400/comp2.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;FSMBehaviour:&lt;/strong&gt; Esta clase permite definir una maquina de estados finita mediante sub-behaviours. Cada sub- comportamiento representa un estado de la maquina, y las transiciones se van produciendo según la salida de dichos estados. La finalización se alcanza cuando se termine de ejecutar algún sub-behaviour que se haya registrado como estado final.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSOHKMdRzzLtB2xJQfYIxejINtdTkKUV6QiyecyTt5RaTbnn7QZ9e7hkw8iWnFmItZX-NaCUE559kkdrzbr-qiokEl4Rp9PKxUQMRuDAO92y1iPhLLxRgSRZYec80GH95IZTRW351kl4Fz/s1600-h/comp3.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5183233420569891650&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSOHKMdRzzLtB2xJQfYIxejINtdTkKUV6QiyecyTt5RaTbnn7QZ9e7hkw8iWnFmItZX-NaCUE559kkdrzbr-qiokEl4Rp9PKxUQMRuDAO92y1iPhLLxRgSRZYec80GH95IZTRW351kl4Fz/s400/comp3.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Adjunto dos codigos de ejemplo para que vean lo facil que es agregar comportamientos a un agente.&lt;/p&gt;&lt;p&gt;En el proximo post veremos mensajeria y ACL.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;embed src=&quot;http://www.driveway.com/driveway/driveway_widget_account.swf?user=u6i8m4c6z0&quot; wmode=&quot;transparent&quot; allowscriptaccess=&quot;always&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;480&quot; height=&quot;370&quot;&gt;&lt;/embed&gt;</description><link>http://dukechile.blogspot.com/2008/03/comportamientos.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOxjNYDoLL0QXSKxj08xJStY74yWlEHFf7s-r63WszO7f0OXF6smyT_LTmdPjKff9-ARxvd905ZmCldi8fQvaSHIOGuq3qJ9hvFkT71eQFc3CcQdA2t9Jukt6pCLjcRez-G08pKtg74ilC/s72-c/comp1.JPG" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-9051879529263462091</guid><pubDate>Fri, 14 Mar 2008 17:40:00 +0000</pubDate><atom:updated>2008-07-04T09:32:10.963-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Agentes Inteligentes</category><category domain="http://www.blogger.com/atom/ns#">FIPA</category><category domain="http://www.blogger.com/atom/ns#">JADE</category><title>Conceptos básicos de programación de un agente en JADE</title><description>&lt;div align=&quot;justify&quot;&gt;Hasta el momento hemos visto parte de la especificación FIPA y algunas de las funcionalidades básicas de JADE….pero falta lo mas importante, la programación de un agente, para luego continuar con un SMA!!!&lt;br /&gt;&lt;br /&gt;Para crear un agente en JADE se debe extender la clase jade.core.Agent. Esta contiene dos métodos muy importantes que tienen que ser implementados necesariamente. Estos son &lt;em&gt;setup()&lt;/em&gt; y &lt;em&gt;takedown()&lt;/em&gt;, los cuales permiten inicializar y finalizar el agente respectivamente.&lt;br /&gt;&lt;br /&gt;La siguiente figura muestra la estructura de un agente:&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5177655667783563410&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN4CS0Kfe6eZEkTp357iUx8CHJ4ZKIJiWEBVG31X00j_KBbCVR1so776EL5fJeghJ5vGMKpjE0WDfySWEcbGXfjwg_TFSrhuNsyhADyEFt00Zr69lNWN328rQphRFDSCJZ_8PP-E928tRQ/s400/agente1.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;&lt;br /&gt;Cada agente del sistema multiagente será una instancia de una clase java que sea subclase de la clase Agent. Esta clase se compondrá básicamente de un método &lt;em&gt;setup&lt;/em&gt;, que se ejecutara al iniciarse el agente y que contendrá código de inicialización, incluyendo instrucciones que especificaran la ontología a utilizar y los comportamientos asociados al agente. Además del método &lt;em&gt;setup&lt;/em&gt;, se dispondrá de una clase interna a la clase del agente por cada uno de los comportamientos asociados al agente.&lt;br /&gt;&lt;br /&gt;Estos comportamientos básicamente se utilizan para el envió y recepción de mensajes, aunque también se podrían realizar otras tareas&lt;br /&gt;&lt;br /&gt;A continuación se muestra el código del agente &lt;em&gt;EstructuraBasica&lt;/em&gt;, correspondiente a un agente simple al que no se ha asociado ningún comportamiento ni ninguna ontología, y que se tomara como base para implementar los futuros ejemplos de agentes:&lt;br /&gt;&lt;br /&gt;package ejemplo1;&lt;br /&gt;&lt;br /&gt;import jade.core.Agent;&lt;br /&gt;import jade.domain.FIPAAgentManagement.ServiceDescription;&lt;br /&gt;import jade.domain.FIPAAgentManagement.DFAgentDescription;&lt;br /&gt;import jade.domain.DFService;&lt;br /&gt;import jade.domain.FIPAException;&lt;br /&gt;&lt;br /&gt;public class EstructuraBasica extends Agent {&lt;br /&gt;&lt;br /&gt;protected void setup() {&lt;br /&gt;/* Registrarse con el agente DF */&lt;br /&gt;DFAgentDescription dfd = new DFAgentDescription();&lt;br /&gt;ServiceDescription sd = new ServiceDescription();&lt;br /&gt;sd.setType(&quot;EstructuraBasica&quot;);&lt;br /&gt;sd.setName(getName());&lt;br /&gt;dfd.setName(getAID());&lt;br /&gt;dfd.addServices(sd);&lt;br /&gt;try {&lt;br /&gt;DFService.register(this,dfd);&lt;br /&gt;}&lt;br /&gt;catch (FIPAException e) {&lt;br /&gt;System.err.println(&quot;Problemas : &quot; +e.getMessage());&lt;br /&gt;doDelete();&lt;br /&gt;}&lt;br /&gt;} &lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;}&lt;br /&gt;&lt;br /&gt;En este ejemplo se observa como el agente &lt;em&gt;EstructuraBasica&lt;/em&gt; es una subclase de &lt;em&gt;Agent&lt;/em&gt; y por lo tanto se pueden crear agentes de la clase &lt;em&gt;EstructuraBasica&lt;/em&gt; utilizando &quot;&lt;em&gt;java jade.Boot&lt;/em&gt;&quot;. Todos los agentes heredan la clase &lt;em&gt;jade.core.Agent&lt;/em&gt;, para lo cual cada uno de estos al momento de ser creado tiene un identificador único el cual es un objeto de la clase &lt;em&gt;jade.core.AID&lt;/em&gt;. El AID que se genera es del tipo: &lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;strong&gt;nombre_agente@host:puerto/JADE&lt;/strong&gt;&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Al momento de crearse el agente se realizan varias tareas automáticamente; algunas de estas son:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Se llama al constructor del agente&lt;/li&gt;&lt;li&gt;Se crea un identificador del agente (AID)&lt;/li&gt;&lt;li&gt;Se registra el agente en el AMS&lt;/li&gt;&lt;li&gt;Se ejecuta el método setup&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;En el método setup se pueden realizar las siguientes operaciones:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Modificar el registro del AMS&lt;/li&gt;&lt;li&gt;Registra el agente en el DF&lt;/li&gt;&lt;li&gt;Agregar los comportamientos (Behaviours) que ejecutara el agente&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Otros métodos con los que cuenta la clase Agent son:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;doDelete:&lt;/strong&gt; Finaliza la ejecución del agente.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;TakeDown:&lt;/strong&gt; Se ejecuta antes de que el agente finalice. Un uso común es el de desregistrar al agente del DF.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;La siguiente figura muestra el ciclo de ejecución de un agente: &lt;/p&gt;&lt;br /&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5177655822402386082&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWnrgtcj6G8mc2ctnz6lhofE9GY0792c7bYFwBunuVGK2rEI4ZsFNZ1yiaShBGh_SsSErn2TlaX8p6eDSbfSubS7H4zh2Isr3o5ivfPBJ-1UfVjrjrgX_vxPOvbTizCEZeL3ed4yyiyo3s/s400/agente2.JPG&quot; border=&quot;0&quot; /&gt;El acceso a los métodos del DF se realiza importando la clase &lt;em&gt;jade.domain.DFService&lt;/em&gt; con la cual se construyen dos tipos de objetos:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;DFAgentDescription:&lt;/strong&gt; Permite guardar el nombre del agente y el o los tipos de servicios que este desea registrar.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ServiceDescription:&lt;/strong&gt; Permite guardar el nombre y tipo de servicio que el agente desea registrar.&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Hay que recordar que el AMS es un agente de gestión que controla el estado y el acceso a la plataforma. También proporciona un servicio de ”páginas blancas” que permite la localización de agentes a partir de sus nombres, y que el DF proporciona un servicio de “páginas amarillas” al resto de los agentes. Los agentes usan el DF para registrar sus servicios o para obtener los servicios de los demás agentes.&lt;br /&gt;&lt;br /&gt;Estos serán unos puntos muy importantes al momento de desarrollar un SMA.&lt;br /&gt;&lt;br /&gt;Con esto hasta el momento hemos visto la estructura básica de un agente, los métodos mas importantes que componen las estructura de un agente y una pequeña descripción de estos.&lt;br /&gt;&lt;br /&gt;Para que sea mas claro les adjunto un video en el cual se detalla la ejecución de cuatro agentes básicos de ejemplo, estos son:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;BuscarAMS:&lt;/strong&gt; Permite obtener una lista de todos los agentes que se encuentren registrados en el AMS.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;RegistrarDF:&lt;/strong&gt; Permite registrar un servicio en el directorio facilitador.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;BuscarDF:&lt;/strong&gt; Permite obtener un listado de todos los servicios registrados en el directorio facilitador.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;EjemploCompletoDF:&lt;/strong&gt; Permite registrar un servicio en el directorio facilitador y obtener un listado de los agentes registrados en el DF que presten un servicio determinado.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;En el próximo post veremos los distintos tipos de comportamientos (Behaviours) y comenzaremos a programar nuestros primeros SMA.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;embed src=&quot;http://www.driveway.com/driveway/driveway_widget_account.swf?user=y6v0t4w2o2&quot; allowscriptaccess=&quot;always&quot; wmode=&quot;transparent&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;480&quot; height=&quot;370&quot;&gt;&lt;/embed&gt;</description><link>http://dukechile.blogspot.com/2008/03/conceptos-bsicos-de-programacin-de-un.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN4CS0Kfe6eZEkTp357iUx8CHJ4ZKIJiWEBVG31X00j_KBbCVR1so776EL5fJeghJ5vGMKpjE0WDfySWEcbGXfjwg_TFSrhuNsyhADyEFt00Zr69lNWN328rQphRFDSCJZ_8PP-E928tRQ/s72-c/agente1.JPG" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-5669106629392362439</guid><pubDate>Sat, 08 Mar 2008 02:32:00 +0000</pubDate><atom:updated>2008-07-04T09:31:36.330-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">JADE</category><title>Herramientas de JADE</title><description>&lt;div align=&quot;justify&quot;&gt;Hasta el momento hemos visto parte del estándar FIPA, ahora veremos como este se encuentra implementado en JADE.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt; &lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;JADE dispone de un conjunto de herramientas para ayudar en la administración y monitorización de los procesos de depuración del sistema.&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt; &lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;Para poder iniciar una sesión y crear los agentes, se debe escribir el siguiente comando en alguna consola de sistema:&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;br /&gt;&lt;div align=&quot;center&quot;&gt;&lt;strong&gt;java jade.Boot -platform [opciones] [lista de agentes]&lt;/strong&gt;&lt;/div&gt;&lt;br /&gt;&lt;div align=&quot;center&quot;&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;En el campo de opciones se puede especificar por ejemplo si se quiere ejecutar el entorno grafico, para lo cual se debe escribir el parámetro “-gui”. Respecto a la lista de agentes, esta debe ser una cadena de texto, donde cada uno de ellos se debe encontrar separado por un espacio en blanco y seguir el siguiente formato:&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;br /&gt;&lt;div align=&quot;center&quot;&gt;&lt;strong&gt;[Nombre_Agente]:ClasseJava&lt;/strong&gt;&lt;/div&gt;&lt;div align=&quot;center&quot;&gt;&lt;/div&gt;&lt;br /&gt;&lt;div align=&quot;justify&quot;&gt;La siguiente figura muestra la ejecución de la pantalla principal de JADE: &lt;/div&gt;&lt;br /&gt;&lt;p align=&quot;center&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS9ViGYuAlUodVbght2lmdfhsgfDhcD4R6_Oks8wLn_AIH62MmkbWE6F4JUforDXIw5ncHjShQN7LQ3yND1aebkpCrqyN9o6cobt-oW-6mRFPVKruaHF0Ej5_1PYxHVgPXlyrtpSZSlOpM/s1600-h/jade1.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5175193762464725010&quot; style=&quot;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS9ViGYuAlUodVbght2lmdfhsgfDhcD4R6_Oks8wLn_AIH62MmkbWE6F4JUforDXIw5ncHjShQN7LQ3yND1aebkpCrqyN9o6cobt-oW-6mRFPVKruaHF0Ej5_1PYxHVgPXlyrtpSZSlOpM/s400/jade1.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Cuando se ejecuta el entorno grafico, aunque no se inicie ningún agente propio, se crearan tres agentes automaticamente:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;El agente RMA:&lt;/strong&gt; El cual se encuentra encargado de controlar la interfaz.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;El agente DF:&lt;/strong&gt; En donde se suscribirán los servicios de los agentes.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;El agente AMS:&lt;/strong&gt; En donde se guardaran las direcciones de los agentes.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;En la parte superior de la interfaz se encuentra la barra de menu, la cual contiene las siguientes opciones:&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;File:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Close RMA Agent:&lt;/strong&gt; Cierra la interfaz anteriormente mostrada, aunque la plataforma de agentes continuara funcionando, así como todos aquellos agentes que estuvieran activos.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Exit this container:&lt;/strong&gt; Destruye el container donde el agente RMA se aloja, matando a este agente y todos aquellos que le acompañaran dentro del container. Si dicho container es el MainContainer será toda la plataforma la que se desactivara. &lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Shutdown Agent Platform:&lt;/strong&gt; Cierra totalmente la plataforma, eliminando todos los agentes y containers.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Actions:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Start New Agent:&lt;/strong&gt; Esta acción crea un agente. Al usuario se le preguntara por el nombre del agente y la clase a la cual se instanciara (los agentes son instancias de alguna clase). Si hubiera algún container seleccionado, este será en el que dicho agente se alojara. También se puede indicar el nombre del container en el que se desea ejecutar el agente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Kill:&lt;/strong&gt; Mata a todos los agentes y elimina todos los containers seleccionados. Si el MainContainer estuviera seleccionado, la plataforma entera seria cerrada.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Suspend:&lt;/strong&gt; Suspende los agentes seleccionados.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Resume:&lt;/strong&gt; Este comando vuelve a poner en estado de activo los agentes seleccionados que estuvieran suspendidos.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Send Message:&lt;/strong&gt; Este comando permite enviar un mensaje ACL a un agente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;Migrate Agent: Esta acción permite migrar un agente. Cuando se selecciona, un dialogo es mostrado en donde el usuario debe especificar el container de la plataforma donde el agente seleccionado debe migrar. No todos los agentes pueden ser migrados debido a una falta de serializacion en su implementación.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Clone Agent:&lt;/strong&gt; Esta opción permite clonar un agente. Cuando es seleccionado, un cuadro de dialogo es mostrado donde el usuario debe introducir el nombre del nuevo agente y el container donde será alojado.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Tools:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Start Sniffer:&lt;/strong&gt; Crea un agente de tipo Sniffer. El agente Sniffer es una de las herramientas que proporciona la JADE para la depuración durante el proceso de desarrollo del sistema multiagente. Básicamente permite comprobar como se produce la interacción e intercambio de mensajes entre los agentes que se seleccionen.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Para iniciar el agente Sniffer primero se debe seleccionar el contenedor donde se alojara, y tras ello seleccionar dentro del menú Tools la opción Start Sniffer o pulsar el botón correcto de la barra de botones.&lt;br /&gt;&lt;br /&gt;Tras hacer esto se creara un nuevo agente en el contenedor seleccionado. Se le asignara automaticamente un nombre sniffer0 como se muestra en la siguiente imagen de ejemplo:&lt;/p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5175197877043394594&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsoL5xeyaQb8H2wWIAM58f0ratT0XAsoWB_N7-AfIwt5ekpA7MnhyphenhyphenA-driQ09s4Irpe5XhgZkG3mOqMVprj6pbYlEpRiWP9ZmC-R-BIIDXXvovo1FDxllkOYSHO83fagMpuklvPpy7N8L4/s400/jade2.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;Asociado al agente Sniffer se dispone de una interfaz grafica en la que se irán viendo los mensajes enviados y recibidos por los distintos agentes que se hayan decidido inspeccionar.&lt;br /&gt;&lt;br /&gt;La siguiente figura muestra la interfaz del agente Sniffer:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5175198177691105330&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC74v_Sp5lVf7fuskUirJG2e1WXZN_cBJ_a_TLo6ZvucmSk0WhSVktNOtGwMp_Dwax3ojHPkJ_Nt0i8_fQ_bHIMHc7I-7JgdqGfclFiDM36Hmi8YqwKWTeGlUYECqRkdJQm_fiC-jzn_pR/s400/jade3.JPG&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;En la parte superior se dispone de una barra de menús, con una barra de botones debajo correspondiendo cada uno de estos botones con las distintas opciones del primero de los menús. En la parte inferior se dispone de dos paneles. En el de la izquierda se muestra el árbol de plataformas, contenedores y agentes. En la parte derecha se puede ver el intercambio de mensajes entre los agentes seleccionados. Las opciones del menú Actions más importantes, que van a permitir realizar la depuración de la plataforma multiagente que se este desarrollando, son las siguientes:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Do sniff this agent(s):&lt;/strong&gt; Añade el o los agentes seleccionados al panel de la derecha donde se visualiza el intercambio de mensajes.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Do not sniff this agent(s):&lt;/strong&gt; Elimina el agente o los agentes seleccionados del panel de la derecha donde se visualiza el intercambio de mensajes.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Show only agent(s):&lt;/strong&gt; Añade el agente o agentes seleccionados al panel donde se visualiza el intercambio de mensajes, pero solo mostrara el agente, no los mensajes que lleguen hasta el o provengan de el.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Clear Canvas:&lt;/strong&gt; Borra todos los mensajes que estuvieran dibujados hasta el momento en el panel. Se continúa con el proceso de depuración.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Una vez elegidos los agentes para los que se desea observar su intercambio de mensajes, la ventana tendrá un aspecto similar al siguiente:&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5175198435389143106&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDr707KC5V2bS8hkiBqbW475FfAskgHSnTMxPEfVT9b2tljNG3Nhw9AvIlQucK0DwgRJAIDEMxatZ5hjWJc-yjMlF7m4w2MfB7Lm3WYpMNgXg_5RxFbTutAuhzEJWVEKdCLhUXw47I8fS2/s400/jade4.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;Los mensajes enviados y recibidos aparecen en orden cronológico comenzando desde la parte superior. Si queremos analizar los distintos campos de un mensaje no tenemos mas que hacer dobleclick sobre el mensaje que deseemos.&lt;/p&gt;&lt;p&gt;Otra opcion es el DummyAgent:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Start DummyAgent:&lt;/strong&gt; Crea un agente de tipo DummyAgent. El agente DummyAgent es otra de las herramientas proporcionadas por JADE para la depuración del sistema multiagente. Se trata de un agente enviador de mensajes que tiene asociado una interfaz grafica que permite indicar los distintos campos del mensaje a enviar, así como visualizar los mensajes enviados y recibidos. Lo primero que se debe hacer para crear un agente de este tipo es seleccionar el contenedor donde se alojara. Después seleccionar la opción Start DummyAgent del menú Tools, o el botón correspondiente de la barra de botones.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Al nuevo DummyAgent se le asignara automaticamente un nombre y se desplegara un cuadro de dialogo con el que se puede acceder a todas las funcionalidades de este, como se muestra en la siguiente figura:&lt;br /&gt;&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5175199217073191010&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheZdKP4g_-NW2PrYN9gebJ2TYtMM-oh9ZtwUo0WCYettlIXq6hSg7NILQRScLzDFu6o1ZhA5HlK8gn3eKHKTU_A4MRMLxPnXmn1tR3gSpRYF0p24498fR3-G8Rr8mTYlOzPlQGYK9ZdHph/s400/jade5.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;Básicamente se trata de un agente que permite enviar mensajes y visualizar la cola de mensajes enviados y recibidos, ası como los detalles de cada uno de estos mensajes. En la parte superior se dispone de la barra de menús, con una barra de iconos que representan las distintas acciones disponibles. Bajo esta se encuentra una serie de botones cuya funcionalidad coincide con la de las distintas opciones de los menús superiores. La parte principal de la ventana esta dividida en dos. En la izquierda se dispone de una serie de campos donde se puede introducir el valor de los campos del mensaje a enviar. En la parte derecha se muestra la cola de mensajes enviados y recibidos. Haciendo doble-click sobre alguno de estos mensajes se puede ver el valor de cada uno de sus campos. Con respecto a los menús, a continuación se muestra la función de cada una de sus opciones:&lt;br /&gt;&lt;br /&gt;Menu General:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Exit:&lt;/strong&gt; Cierra el dialogo del agente DummyAgent, eliminándolo de la plataforma.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Menu Current message:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Reset:&lt;/strong&gt; Vacía todos los campos del mensaje a enviar.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Send:&lt;/strong&gt; Envia el mensaje con los valores de los campos especificados en la parte izquierda del dialogo. Al hacerlo, se mostrara el mensaje, enviado en la cola de mensajes, en la parte derecha de la ventana, así como las contestaciones, en el caso de que las hubiera.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Open:&lt;/strong&gt; Abre un mensaje almacenado en disco.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Save:&lt;/strong&gt; Guarda el mensaje en disco.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Menu Queued message:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Open queue:&lt;/strong&gt; Abre una cola de mensajes almacenados en el disco.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Save queue:&lt;/strong&gt; Guarda la cola de mensajes en disco.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Set as current:&lt;/strong&gt; Toma los valores de los campos del mensaje seleccionado en la cola de mensajes y rellena los campos de la parte izquierda de la ventana correspondientes al mensaje a enviar con dichos valores.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Reply:&lt;/strong&gt; Permite crear un mensaje de respuesta.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;View:&lt;/strong&gt; Muestra un cuadro de dialogo donde se puede examinar los valores de los campos del mensaje seleccionado de la cola de mensajes.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Delete:&lt;/strong&gt; Elimina el mensaje seleccionado de la cola de mensajes.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Show the DF GUI:&lt;/strong&gt; Activa la interfaz del agente DF, desde la cual se puede observar los agentes que se han registrado y que servicios ofrecen.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;La siguiente figura muestra la interfaz del DF:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5175199552080640114&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh__XYOY2_QICEUQ7fWRfqMVWE81gku6i6sZKFWz9MOM5q8uR-znAvPNmEtDI02Agjx7TIlvjiyurNE6agQLvX5ywPLgYnAjcVxCeY4joP7EJu49WWznIY9vEUxR9p7UAPZHm3VuOT8MlOn/s400/jade6.JPG&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;&lt;p&gt;Otra opicion es el InstrospectorAgent:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Start IntrospectorAgent:&lt;/strong&gt; Inicia un agente de tipo IntrospectorAgent, mostrando su interfaz asociada. Este agente permite monitorizar y controlar el ciclo de vida de un agente y muestra las colas de entrada y salida de mensaje.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;La siguiente figura muestra la interfaz del IntrospectorAgent:&lt;/p&gt;&lt;br /&gt;&lt;p align=&quot;justify&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5175200028822009986&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8RVl1q1rT0dxoJRYug4xVT7BLPPL6Gfyd2YjoCEwzZtl6qg0Jil-jomvXJFaPSltPxd8iVD6QkVnvhyphenhyphenyqJiD9jYnr6SqOsaug8e9HzkYergPOP2mPN_vLhBmK2slY4exsYmh2uROcYgfM/s400/jade7.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;Tambien se encuntr la opcion para ver las peltaformas remotas:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Remote Platforms:&lt;/strong&gt; Este menú permite controlar plataformas remotas que cumplan con las especificaciones FIPA. Estas plataformas no tienen por que ser JADE.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Hasta ahora ya hemos visto de manera rápida parte de la especificación FIPA y como JADE implementa esta y las opciones de las que dispone el framework para administrar los agentes.&lt;br /&gt;&lt;br /&gt;En el próximo post comenzaremos con la programación en JADE, veremos la estructura de un agente, como registrarse en el DF, la comunicación con ACL…...y muchas cosas mas que se encuentran en el desarrollo de agentes inteligentes y SMA.&lt;/p&gt;</description><link>http://dukechile.blogspot.com/2008/03/herramientas-de-jade.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS9ViGYuAlUodVbght2lmdfhsgfDhcD4R6_Oks8wLn_AIH62MmkbWE6F4JUforDXIw5ncHjShQN7LQ3yND1aebkpCrqyN9o6cobt-oW-6mRFPVKruaHF0Ej5_1PYxHVgPXlyrtpSZSlOpM/s72-c/jade1.JPG" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-8216035380760748345</guid><pubDate>Mon, 03 Mar 2008 22:46:00 +0000</pubDate><atom:updated>2008-07-04T09:31:06.010-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ANDROID</category><category domain="http://www.blogger.com/atom/ns#">JADE</category><title>Ya se encuentra disponible la version 1.0 de JADE-ANDROID</title><description>&lt;div align=&quot;justify&quot;&gt;Android es una plataforma para desarrollar aplicaciones para dispositivos móviles que incluyan el sistema operativo realizado por el Open Handset Alliance en Noviembre del 2007(mas información en &lt;a href=&quot;http://code.google.com/android/&quot; target=&quot;_blank&quot;&gt;http://code.google.com/android/&lt;/a&gt; y &lt;a href=&quot;http://www.openhandsetalliance.com/&quot; target=&quot;_blank&quot;&gt;http://www.openhandsetalliance.com/&lt;/a&gt; ). &lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;&lt;br /&gt;El lenguaje de programación en Android es Java, el cual incluye la nueva maquina virtual Dalvik, la cual permite acceder a todas las funcionalidades propias del dispositivo móvil.&lt;br /&gt;&lt;br /&gt;La posibilidad de combinar la expresividad de FIPA soportada por los agentes en JADE junto con el poder de la plataforma Android, permitirá el desarrollo de innovadoras aplicaciones basadas en modelos sociales y peer-to-peer.&lt;br /&gt;&lt;br /&gt;JADE-Android es distribuido como un add-on de JADE y se encuentra disponible para descarga bajo licencia LGPL en la sitio web de JADE. Este add-on también incluye una aplicación de ejemplo llamada Dummy Agent la cual corre sobre Android SDK m5-rc14&lt;br /&gt;&lt;br /&gt;Información mas detallada acerca de como usar JADE-Android puede ser encontrada en la guía del usuario incluida en el archivo de distribución del add-on.&lt;br /&gt;&lt;br /&gt;Este será un gran año para la comunidad Jade, ya que junto con este add-on, también tenemos la nueva versión del add-on WSIG (Web Service Integration Getawey) pronto tendremos la nueva versión de JADE y WADE.&lt;/div&gt;</description><link>http://dukechile.blogspot.com/2008/03/ya-se-encuentra-disponible-la-version.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-809200015327240015</guid><pubDate>Sun, 24 Feb 2008 22:32:00 +0000</pubDate><atom:updated>2008-07-04T09:30:13.571-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">FIPA</category><title>FIPA parte 2</title><description>&lt;div align=&quot;justify&quot;&gt;Continuando con la especificación FIPA, terminare de detallar alguno de los puntos mas importantes para luego ver como esta se encuentra implementada en JADE.&lt;br /&gt;&lt;br /&gt;El Directorio Facilitador (DF) proporciona un servicio de paginas amarillas al resto de los agentes. Cualquier plataforma de agentes FIPA tiene que tener al menos un DF. Los agentes usan el DF para registrar sus servicios o para obtener los servicios de los demás agentes.&lt;br /&gt;&lt;br /&gt;Los DF’s pueden registrarse entre ellos. De la misma forma, los componentes AMS y ACC también pueden registrarse con un DF. Todos los DF’s tienen un nombre por defecto que empieza por ”df ”.&lt;br /&gt;&lt;br /&gt;Las acciones de gestión que soporta son:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;lu&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;register:&lt;/strong&gt; Petición de registro de los servicios de un agente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;search:&lt;/strong&gt; Petición de búsqueda de agentes que proporcionen determinados servicios.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;deregister:&lt;/strong&gt; Petición de borrado de los servicios registrados de un agente. &lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;modify:&lt;/strong&gt; Petición de modificación de los servicios registrados de un agente &lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Solo un Agent Management System (AMS) puede existir en una plataforma de agentes FIPA. Este es responsable de gestionar las operaciones de su plataforma tales como la creación de agentes, borrado de agentes, decidir si un agente puede registrarse en la plataforma y supervisar la migración de los agentes a/desde la plataforma.&lt;br /&gt;&lt;br /&gt;El AMS es la autoridad en toda la plataforma. Puede solicitar a un agente que finalice su ejecución (quit) e incluso obligarle a finalizar.&lt;br /&gt;&lt;br /&gt;El AMS gestiona una lista con todos los agentes que se encuentran en la plataforma. En la lista se encuentran las identificaciones GUID de los agentes asociadas a sus direcciones en la plataforma. Para que un agente resida en la plataforma tiene que registrarse con el AMS.&lt;br /&gt;&lt;br /&gt;Todos los AMS tienen un nombre por defecto que empieza con “ams”. Las acciones de gestión que tiene que soportar cualquier AMS son:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;register-agent:&lt;/strong&gt; Petición de registro de un agente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;deregister-agent:&lt;/strong&gt; Petición de borrar del registro a un agente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;modify-agent:&lt;/strong&gt; Petición de modificación del registro de un agente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;query-platform-profile:&lt;/strong&gt; Petición del perfil de la plataforma.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;authenticate:&lt;/strong&gt; Petición de autentificar la identidad de un agente creado en la plataforma.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;search-agent:&lt;/strong&gt; Petición de búsqueda de la dirección de un agente.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Existe una acción de gestión para movilidad que también tiene que soportar cualquier AMS:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;move:&lt;/strong&gt; Petición de transferencia/migración de un agente.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Además de las acciones de gestión intercambiadas entre el AMS y los agentes en la plataforma, el AMS puede proporcionar a la plataforma la realización de las siguientes operaciones:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;suspend agent:&lt;/strong&gt; Suspender o parar la ejecución de una agente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;terminate agent:&lt;/strong&gt; Finalizar la ejecución de un agente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;create agent:&lt;/strong&gt; Crear un agente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;resume agent execution:&lt;/strong&gt; Continuar con la ejecución de un agente suspendido.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;invoke agent:&lt;/strong&gt; Empezar la ejecución de un agente recién creado.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;execute agent:&lt;/strong&gt; Ejecutar un agente después de moverse.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;resource management:&lt;/strong&gt; Gestionar los recursos.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Existe una acción de gestión que tienen que soportar los agentes utilizados por el AMS:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;quit:&lt;/strong&gt; Petición de terminación de un agente, la cual finaliza la ejecución del agente que recibe la solicitud.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;El ACC proporciona el encaminamiento de mensajes entre agentes de diferentes plataformas FIPA. Todos los agentes FIPA tienen acceso al menos a un ACC. Únicamente mensajes dirigidos a agentes pueden ser enviados a un ACC.&lt;br /&gt;&lt;br /&gt;El encaminamiento de mensajes entre diferentes plataformas requiere un protocolo de interoperabilidad por defecto (especificándose el protocolo de transporte, codificación y direccionamiento). Este protocolo es IIOP.&lt;br /&gt;&lt;br /&gt;La acción de gestión que soporta es:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;forward:&lt;/strong&gt; Petición de envió de un mensaje desde un agente a otro.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Esta acción no debe de interpretarse como el mecanismo por defecto para enviar mensajes entre los agentes de la misma plataforma. Estos podrán comunicarse empleando el método interno (IPMT) que se haya implementado en la plataforma.&lt;br /&gt;&lt;br /&gt;Dentro del Agent Plataform (AP) el ciclo de vida de los agentes FIPA esta caracterizado por:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;Definir los posibles estados y transiciones de un agente independientemente del tipo de implementación de la plataforma.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;Cada agente es físicamente gestionado en una plataforma. Si el agente es estacionario, su ciclo de vida siempre será en la misma plataforma.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;Cada agente descrito con el modelo de ciclo de vida es asumido como una instancia con nombre propio y único que se ejecuta de forma independientemente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;Cada agente solo puede encontrase en un estado en una única plataforma al mismo tiempo.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;El ciclo de vida de los agentes se representa mediante estados y transiciones, los cuales se muestran en la siguiente figura: &lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihDxmjmv2DWM44Mudk4yoFnhGdrEptIZtf-b4EZ5aHRZp-HsUfGjSnLEMfEpwXPmbpJfelhJZVQf7aprm9olDIU4UOlTaIUUx528W_uFvJ2H3t5KV1bj4m5Pl3fjWX8UpK9tjqGDEWK_jM/s1600-h/fipa2.JPG&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5170678588245556770&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihDxmjmv2DWM44Mudk4yoFnhGdrEptIZtf-b4EZ5aHRZp-HsUfGjSnLEMfEpwXPmbpJfelhJZVQf7aprm9olDIU4UOlTaIUUx528W_uFvJ2H3t5KV1bj4m5Pl3fjWX8UpK9tjqGDEWK_jM/s400/fipa2.JPG&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Únicamente los agentes móviles pueden entrar en el estado “transit”. Esto asegura que los agentes estacionarios ejecuten todas sus instrucciones en el nodo donde fueron invocados.&lt;br /&gt;&lt;br /&gt;Las acciones para pasar los agentes de un estado a otro son:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Create:&lt;/strong&gt; Creación de un nuevo agente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Invoke:&lt;/strong&gt; Invocación o activación de un nuevo agente una vez inicializado.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Destroy:&lt;/strong&gt; Se fuerza la terminación de un agente. Esta acción solo puede ser iniciada por el AMS y no puede ser ignorada.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Quit:&lt;/strong&gt; Se solicita la terminación de un agente. El agente puede ignorar la acción.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Suspend:&lt;/strong&gt; Pone a un agente en el estado de suspendido. Esta acción puede ser iniciada por el propio agente o por el AMS.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Resume:&lt;/strong&gt; Saca a un agente del estado suspendido. Esta acción solo puede ser iniciada por el AMS.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Wait:&lt;/strong&gt; Pone a un agente en el estado de espera. Esta acción solo puede ser iniciada por el propio agente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Wake up:&lt;/strong&gt; Saca a un agente del estado de espera. Esta acción solo puede ser iniciada por el AMS.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Las siguientes acciones solo son usadas por los agentes móviles:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Move:&lt;/strong&gt; Pone a un agente en el estado de transición. Esta acción solo puede ser iniciada por el propio agente.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Execute:&lt;/strong&gt; Saca al agente del estado&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;La plataforma en la cual se creo un agente se denomina la Home Agent Platform (HAP) de dicho agente. La responsabilidad del HAP es garantizar la identidad del agente en sus relaciones con otros agentes y plataformas. El estándar FIPA requiere que cada agente tenga un HAP que responda por el ante el resto de la comunidad de agentes. Por tal motivo:&lt;br /&gt;&lt;br /&gt;Es necesario que a partir del análisis del GUID de un agente pueda obtenerse la dirección IIOP-URL del HAP.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Es necesario que el HAP pueda autentificar la identidad del agente en la plataforma. Para ello, el AMS del HAP soporta la acción “authenticate”.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;El AMS del HAP de un agente es responsable de guardar la dirección de dicho agente. Por otro lado, el agente tiene la responsabilidad de asegurar que la dirección guardada por el AMS sea valida. Un agente siempre debe registrarse en su HAP. El nombre de un agente (GUID) es el mismo durante toda su existencia.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Un agente puede registrarse en una plataforma si se cumple alguna de las siguientes condiciones:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;El agente se creo en la plataforma.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;El agente migro a la plataforma. Ambas plataformas, HAP y destino, tienen que soportar movilidad de agentes.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;El agente se registra dinámicamente en una plataforma diferente a su HAP como agente local. Ambas plataformas tienen que soportar registro dinámico.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Al registrarse un agente se facilita al AMS la siguiente información:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;El identificador global y único del agente (GUID).&lt;/li&gt;&lt;li&gt;La dirección local del agente.&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;El agente se registra en el AMS mediante la acción “register-agent”.&lt;br /&gt;&lt;br /&gt;Un agente tiene dos opciones cuando desea contactarse (enviar un mensaje) con otro agente de una plataforma diferente:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Puede solicitar que el ACC de su plataforma envié el mensaje al ACC y agente de la otra plataforma.&lt;/li&gt;&lt;li&gt;Puede contactarse directamente con el ACC de la otra plataforma y enviarle el mensaje.&lt;/li&gt;&lt;/ul&gt;&lt;p align=&quot;justify&quot;&gt;Es necesario el GUID del agente destino para poder contactar con el. El mensaje se enviara al HAP del agente destino y a partir de aquí se hará llegar a dicho agente. Alternativamente, si se desea enviar el mensaje directamente al agente o a una plataforma (distinta del HAP) donde el agente se registro dinámicamente, entonces se deberá indicar además del GUID la dirección destino.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Aun quedan puntos pendientes por ver de la especificación, pero ya que con lo visto hasta ahora podemos comenzar a ver los primeros códigos de ejemplo en JADE….pero eso será para el próximo post.&lt;/p&gt;&lt;/lu&gt;</description><link>http://dukechile.blogspot.com/2008/02/fipa-parte-2.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihDxmjmv2DWM44Mudk4yoFnhGdrEptIZtf-b4EZ5aHRZp-HsUfGjSnLEMfEpwXPmbpJfelhJZVQf7aprm9olDIU4UOlTaIUUx528W_uFvJ2H3t5KV1bj4m5Pl3fjWX8UpK9tjqGDEWK_jM/s72-c/fipa2.JPG" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-632297375842400031</guid><pubDate>Sun, 24 Feb 2008 00:00:00 +0000</pubDate><atom:updated>2008-07-04T09:29:44.013-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">FIPA</category><title>Introduccion a FIPA - parte 1</title><description>El creciente desarrollo de grupos de investigación en torno a los sistemas multiagente fomento la aparición de nuevas formas para el desarrollo de esta tecnología, lo cual conllevo a que cada uno de estos grupos presentara soluciones diferentes e independientes.&lt;br /&gt;&lt;br /&gt;Algunos problemas que se presentaron fue la carencia de una definición estándar de sistema multiagente e incompatibilidad, lo que conllevo a una incapacidad para satisfacer los fuertes requisitos de las empresas e industrias actuales.&lt;br /&gt;&lt;br /&gt;Esto promovió la creación de diversos organismos, los cuales se preocuparıan de desarrollar una definición estándar para la construcción de sistemas multiagente. Algunos de estos organismos son:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;OMG (Object Management Group) quienes desarrollaron MASIF (Mobile Agent System Interoperability Facilities). &lt;/div&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;KSE (Knowledge Sharing Effort) quienes desarrollaron KQML (Knowledge Querying and Manipulation Language) y KIF (Knowledge Interchange Format). &lt;/div&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;Agent Society, cuya labor principal es el intercambio y recopilación de información sobre agentes. &lt;/div&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;FIPA (Foundation for Intelligent Physical Agents) cuya labor principal es el desarrollo de especificaciones de una arquitectura para sistemas multiagente, infraestructura y aplicaciones.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;De estos, FIPA es el que más relevancia a tomado fuerza estos últimos años.&lt;br /&gt;&lt;br /&gt;En su versión inicial (FIPA 97) tres documentos integraban esta parte del estándar:&lt;br /&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;Agent Management&lt;br /&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;Agent Communication Language &lt;/div&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;Agent/Software Integration&lt;br /&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div align=&quot;justify&quot;&gt;Posteriormente se han ido actualizando e incluyendo nuevos documentos hasta alcanzar la versión de FIPA-2000 con la que actualmente se trabaja.&lt;br /&gt;&lt;br /&gt;El “Agent Management” proporciona la normativa del entorno donde los agentes FIPA se crean y operan. Establece el modelo lógico de referencia para la gestión de agentes (creación, registro, localización, comunicación, migración y terminación de los agentes). El modelo presenta un conjunto de capacidades lógicas y no implica ninguna configuración física, sino que deja los detalles de implementación a elección del equipo de desarrollo. &lt;/div&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Agente:&lt;/strong&gt; Es el componente básico y principal del modelo. Combina una o más capacidades de servicio dentro de un entorno de ejecución integrado y unificado que proporciona servicios de comunicación, acceso a software externo y acceso a los usuarios.&lt;br /&gt;&lt;br /&gt;Un agente tiene que tener uno o más dueños. Además debe disponer de una identidad propia proporcionada por un identificador global y único GUID (Globally Unique Identifier) denominado nombre del agente. Una gente puede registrarse con un número de direcciones en las cuales puede ser contactado. &lt;/div&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Agent Platform (AP):&lt;/strong&gt; Proporciona la infraestructura fısica y lógica necesaria en la cual los agentes pueden ejecutarse. Una plataforma de agentes esta constituida por el hardware (puede haber varios computadores), el sistema operativo, software de comunicaciones y software de agentes. &lt;/div&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Directory Facilitator (DF):&lt;/strong&gt; Componente que siempre tiene que aparecer en cualquier plataforma de agentes FIPA. Es un agente que proporciona un servicio de ”paginas amarillas” a los demás agentes. Un agente puede utilizar el DF para registrar sus servicios o para encontrar los servicios ofrecidos por otros agentes. &lt;/div&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Agent Management System (AMS):&lt;/strong&gt; Componente que siempre tiene que aparecer en cualquier plataforma de agentes FIPA, uno por plataforma. Es un agente de gestión que controla el estado y el acceso a la plataforma. También proporciona un servicio de ”paginas blancas” que permite la localización de agentes a partir de sus nombres. &lt;/div&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Agent Communication Channel (ACC):&lt;/strong&gt; Todos los agentes tienen acceso al menos a un ACC. El ACC es el canal de comunicación por defecto entre agentes de diferentes plataformas. Tiene que soportar el protocolo de comunicación para interoperabilidad IIOP (Internet Inter-ORB Protocol ). &lt;/div&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;div align=&quot;justify&quot;&gt;&lt;strong&gt;Internal Platform Message Transport (IPMT):&lt;/strong&gt; Método de intercambio de mensajes dentro de la misma plataforma el cual depende de la implementación.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div align=&quot;justify&quot;&gt;El modelo de referencia para la gestión de agentes esta formado por los siguientes componentes lógicos, los cuales se muestran en la siguiente figura: &lt;/div&gt;&lt;br /&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5170336318006771218&quot; style=&quot;margin: 0px auto 10px; display: block; text-align: center;&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3B9UAYyIzNa6m9qAvdeqm8ZyPEEuB0PjSXmHJvjgTaCgQzgZypB3E7weAKedFWMvvonPlbio7ud2wthobhqbhTHy5CNZtcq5iNKaGb-awLp6cL0_14uL99F_yLdtu9SU4rzphM-1P5U4F/s400/fipa1.JPG&quot; border=&quot;0&quot; /&gt;&lt;br /&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;En el próximo post continuare detallando el estándar FIPA, pera luego comenzar con la parte entretenida..….la programación de agentes y sistemas multiagentes!!!!&lt;br /&gt;&lt;br /&gt;&lt;div align=&quot;justify&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;</description><link>http://dukechile.blogspot.com/2008/02/introduccion-fipa-parte-1.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3B9UAYyIzNa6m9qAvdeqm8ZyPEEuB0PjSXmHJvjgTaCgQzgZypB3E7weAKedFWMvvonPlbio7ud2wthobhqbhTHy5CNZtcq5iNKaGb-awLp6cL0_14uL99F_yLdtu9SU4rzphM-1P5U4F/s72-c/fipa1.JPG" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8644784663970787482.post-253685834737138484</guid><pubDate>Fri, 22 Feb 2008 00:37:00 +0000</pubDate><atom:updated>2008-07-04T09:29:15.800-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">JADE</category><category domain="http://www.blogger.com/atom/ns#">WADE</category><title>JADE WADE (Workflow and Agent Development Environment)</title><description>&lt;div align=&quot;justify&quot;&gt;En el AAMAS 2008 (Autonomous Agents and Multuagent Systems) se presentara un tutorial de WADE, el cual es la principal evolución de JADE y añade a este la habilidad de definir sistemas lógicos dentro de un workflow. WADE no es precisamente un add-on, pero si es un complemento para la plataforma (esta construido sobre JADE) proveyendo administración avanzada, mecanismos de tolerancia a fallos y habilitando a un grupo de agentes, ejecutar cooperativamente complejas tareas definidas en el workflow. WADE será liberado como Open Source en Abril de este año junto con la versión 3.6 de JADE.&lt;br /&gt;&lt;br /&gt;Más información en http://gaips.inesc-id.pt/aamas2008/tutorials.html&lt;/div&gt;</description><link>http://dukechile.blogspot.com/2008/02/jade-wade-workflow-and-agent.html</link><author>noreply@blogger.com (José Luis Coronel Cortés)</author><thr:total>0</thr:total></item></channel></rss>