<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.2.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>Xnoccio</title>
	<link>http://xnoccio.com</link>
	<description>Blog de Viavansi</description>
	<pubDate>Sun, 12 Oct 2008 16:16:29 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.2.2</generator>
	<language>en</language>
			<item>
		<title>Conferencia Internacional de Software Libre</title>
		<link>http://xnoccio.com/374-conferencia-internacional-de-software-libre/</link>
		<comments>http://xnoccio.com/374-conferencia-internacional-de-software-libre/#comments</comments>
		<pubDate>Sun, 12 Oct 2008 16:11:00 +0000</pubDate>
		<dc:creator>Félix García Borrego</dc:creator>
		
		<category><![CDATA[viafirma]]></category>

		<category><![CDATA[viavansi]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://xnoccio.com/374-conferencia-internacional-de-software-libre/</guid>
		<description><![CDATA[
El próximo Lunes 20 de Octubre, nos vamos a Málaga a presentar Viafirma en la Conferencia Internacional de Sofrware Libre( programa ).
]]></description>
			<content:encoded><![CDATA[<p style="text-align: center"><img src="http://www.opensourceworldconference.com/logo.jpg" width="344" height="113" /></p>
<p>El próximo Lunes 20 de Octubre, nos vamos a Málaga a presentar <a href="http://www.viafirma.org" title="Plataforma de autenticación y firma digital ( facturae, facturación electrónica, XaDES )">Viafirma</a> en la Conferencia Internacional de Sofrware Libre( <a href="http://www.opensourceworldconference.com/oswc/programme" title="Programa de la Conferencia Internacional de Software Libre, presentación de Viafirma">programa</a> ).</p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/374-conferencia-internacional-de-software-libre/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Eligiendo nuestro entorno de Integración Continua (I).</title>
		<link>http://xnoccio.com/368-eligiendo-nuestro-entorno-de-integracion-continua-i/</link>
		<comments>http://xnoccio.com/368-eligiendo-nuestro-entorno-de-integracion-continua-i/#comments</comments>
		<pubDate>Wed, 08 Oct 2008 16:09:30 +0000</pubDate>
		<dc:creator>Félix García Borrego</dc:creator>
		
		<category><![CDATA[java]]></category>

		<category><![CDATA[javahispano]]></category>

		<category><![CDATA[programación]]></category>

		<category><![CDATA[software]]></category>

		<category><![CDATA[viavansi]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://xnoccio.com/368-eligiendo-nuestro-entorno-de-integracion-continua-i/</guid>
		<description><![CDATA[Objetivos 
El objeto de este artículo es en plasmar la metodología y conclusiones obtenidas en una comparativa técnica que hemos realizado sobre algunas de las herramientas de integración  continua disponibles en el mercado. Para ello se establecen unas bases para la elección de la plataforma y se realiza una comparativa completa partiendo de una selección [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Objetivos </strong></p>
<p>El objeto de este artículo es en plasmar la metodología y conclusiones obtenidas en una comparativa técnica que hemos realizado sobre algunas de las herramientas de integración  continua disponibles en el mercado. Para ello se establecen unas bases para la elección de la plataforma y se realiza una comparativa completa partiendo de una selección de herramientas.</p>
<p>Existe un buen número de herramientas de Integración Continua en el mercado: Continuum, CruiseControl, LuntBuild, Hudson, Atlassian Bamboo, etc&#8230; Para facilitar el estudio se ha realizado una primera preselección consistente en las herramientas estrictamente Open Source más utilizadas en el mercado: Apache Continuum, LuntBuild y Hudson.</p>
<p>Antes de entrar en detalles, comentaremos cúales son los principales objetivos funcionales que se buscan a la hora de implantar un sistema de Integración Continua:</p>
<ul>
<li>Reducción del tiempo de integración. Se trata de agilizar el proceso de integración de los diversos proyectos y aplicaciones, buscando un sistema que se responsabilice de automatizar la compilación, ejecución de tests y despliegues, así como de avisar de posibles problemas a los diversos participantes en el desarrollo de un proyecto.</li>
</ul>
<ul>
<li> Reducción de errores. Uno de los objetivos más importantes que se persiguen con este tipo de sistemas es la detección de errores y conflictos en un estado temprano.</li>
</ul>
<ul>
<li> Testeo de la calidad de código y reglas de estilo. Para asegurar un mínimo de coherencia de los nuevos desarrollos con las políticas de calidad establecidas, se busca un sistema capaz de automatizar este tipo de tareas de manera sencilla.</li>
</ul>
<ul>
<li> Reducción del riesgo. Permitiendo que versiones tempranas del producto estén disponibles lo antes posible, con un número de incidencias minimizado de forma automática, y con una gestión de la configuración automática que reduce errores en despliegues.</li>
</ul>
<ul>
<li> Disponibilidad continua de la última versión del código para pruebas, agilizando los procesos de despliegue de nuevas versiones en los diferentes entornos.</li>
</ul>
<p><strong>Metodología del análisis</strong></p>
<p>Para seleccionar el sistema de Integración Continua más adecuado, hemos procedido a analizar las diversas características funcionales y técnicas de interés. Para ello se ha procedido a instalar las tres plataformas objeto del estudio (Continuum, LuntBuild y Hudson) y se ha puesto en marcha al menos un proyecto Maven sobre ellas, tratando de evaluar una serie de variables de interés.</p>
<p>A continuación se indican los criterios de selección utilizados en la comparativa:</p>
<ul>
<li> Instalación.</li>
</ul>
<p>Evaluaremos la facilidad de instalación y configuración de las herramientas, con parámetros como la documentación oficial de instalación, posibilidades de configuraciones avanzadas, dificultad de la instalación, etc.</p>
<ul>
<li>Administración, gestión de proyectos.</li>
</ul>
<p>Partiendo del hecho de que el entorno en el que se va a realizar la implantación no tiene por qué contar con personal especializado y dedicado exclusivamente a la gestión y administración de la plataforma, será recomendable que las tareas de administración asociadas al sistema elegido sean las mínimas, y que su ejecución sea lo más sencilla posible. Se analizarán parámetros como la documentación oficial destinada a esta temática o si el sistema permite una fácil generación y restauración de copias de seguridad (tanto de la definición de los proyectos y tareas configuradas como del histórico de compilaciones). También se estudiará si las tareas de administración relacionadas con la plataforma se puedan realizar mediante la interfaz Web. Así mismo, verificaremos si se permite recuperar el historial de las últimas tareas de compilación realizadas, así como poder configurar el número de días y compilaciones que se mantendrán en el historial. Con respecto a la gestión de tareas periódicas, comprobaremos si el sistema permite la definición de tareas periódicas, para facilitar la automatización de tareas repetitivas. Además, teniendo en cuenta que este tipo de herramientas están en continua evolución, se evaluará la facilidad de instalación de nuevas actualizaciones. Por último se estudiará el rendimiento de la solución. Dado que las compilaciones son tareas muy pesadas, se evaluarán los diferentes mecanismos que aporta cada sistema de Integración Continua para la gestión de hilos de compilación y la ejecución distribuida de tareas.</p>
<ul>
<li>Seguridad.</li>
</ul>
<p>Se evaluará la versatilidad y potencia en la gestión de roles, perfiles y permisos asociados a proyectos y acciones disponibles en la herramienta. Resulta interesante además poder definir perfiles de usuario específicos. Así mismo, se estudiará la posibilidad de definición de permisos especiales para proyectos concretos. Por último evaluaremos la complejidad a la hora de establecer una política avanzada de permisos, observando el nivel de personalización que permite la plataforma.</p>
<ul>
<li>Integración con sistemas externos.</li>
</ul>
<p>En la mayoría de los casos es necesario que la herramienta de Integración Continua interactúe con otros sistemas específicos, por lo que puede ser necesario el desarrollo de nuevos plugins que extiendan la funcionalidad de la plataforma. Por este motivo evaluaremos la sencillez y los mecanismos que ofrecen estos sistemas a la hora de inyectar funcionalidad personalizada.</p>
<p>Evaluaremos también el nivel de integración que tienen las diferentes herramientas de Integración Continua con sistemas de control de versiones, así como el nivel de integración con herramientas de evaluación de código (como checkstyle, PMD, etc&#8230;). Analizaremos además el nivel de integración con sistemas de gestión de incidencias, particularizando en el sistema Mantis BT. Por último evaluaremos el nivel de integración de soluciones con sistemas de test como Junit o JMeter .</p>
<ul>
<li>Tipos de Proyectos soportados.</li>
</ul>
<p>Evaluaremos los diferentes tipos de proyectos soportados, así como sus posibilidades de extensión para futuros modelos. Aunque haremos especial hincapié en el soporte completo de proyectos basados en Maven2, si bien también es relevante que el sistema permita la gestión del mayor número posible de formatos.</p>
<ul>
<li>Facilidad de uso.</li>
</ul>
<p>Ya que la plataforma de Integración Continua elegida deberá convertirse en una pieza central de nuestro entorno de software, la herramienta deberá ofrecer una interfaz sencilla, usable e intuitiva, de forma que se facilite la interacción con la herramienta por personal no especializado, sin problemas serios de aprendizaje. Haremos especial hincapié en las ayudas en línea disponibles y en la organización de la interfaz.</p>
<ul>
<li>Documentación de usuario.</li>
</ul>
<p>Evaluaremos la cantidad y calidad de la documentación de usuario disponible.</p>
<ul>
<li> Estabilidad.</li>
</ul>
<p>La herramienta elegida deberá disponer de unas excelentes características de estabilidad. El objetivo no es elegir la última tecnología relacionada con la Integración Continua, sino disponer de un entorno funcional operativo lo más robusto posible.</p>
<p>Próximamente:<br />
Apache Continuum. Eligiendo nuestro entorno de Integración Continua (II).</p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/368-eligiendo-nuestro-entorno-de-integracion-continua-i/feed/</wfw:commentRss>
		</item>
		<item>
		<title>OpenCms Content Relation Engine (CRE)</title>
		<link>http://xnoccio.com/367-cre-i/</link>
		<comments>http://xnoccio.com/367-cre-i/#comments</comments>
		<pubDate>Tue, 30 Sep 2008 11:47:26 +0000</pubDate>
		<dc:creator>Carlos González</dc:creator>
		
		<category><![CDATA[OpenCms]]></category>

		<category><![CDATA[javahispano]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://xnoccio.com/367-cre-i/</guid>
		<description><![CDATA[Una de las principales mejoras de OpenCms 7 es la incorporación del CRE (Content Relation Engine). Esta herramienta desarrollada por Michael Moossen permite establecer relaciones entre recursos del VFS (Vitual File System) de OpenCms.
Imaginemos lo siguiente:
Tenemos en el proyecto Offline un recurso A de OpenCms de tipo página html o jsp, en cuyo código hay [...]]]></description>
			<content:encoded><![CDATA[<p>Una de las principales mejoras de OpenCms 7 es la incorporación del CRE (Content Relation Engine). Esta herramienta desarrollada por <a href="http://opencms.org/en/events/opencms_days_2008/speakers/michael_moossen.html" target="_blank">Michael Moossen</a> permite establecer relaciones entre recursos del VFS (Vitual File System) de OpenCms.</p>
<p><strong>Imaginemos lo siguiente:</strong></p>
<p>Tenemos en el proyecto Offline un recurso A de OpenCms de tipo página html o jsp, en cuyo código hay un enlace a una imagen (recurso B) usando la etiqueta &lt;img&gt;.  Publicamos A.</p>
<p><strong>¿Qué ocurre en versiones anteriores de OpenCms?</strong></p>
<p>En el mejor de los casos si el recurso es de tipo página html el navegador mostraría la típica aspa roja indicando que no encuentra la imagen en el proyecto Online. En el peor de los casos, en jsp, suponiendo que la imagen fuese necesaria ya que leemos alguna propiedad (por ejemplo Description para mostrar el texto alternativo) el sistema podría dar un error 500.</p>
<p><strong>¿Qué ocurre en el nuevo OpenCms si hemos usado CRE?</strong></p>
<p>Pues que el sistema avisaría de que no hemos publicado la imagen y permitiría publicarla junto al recurso al que está asociada.</p>
<p><strong>¿Qué ha cambiado en la base de datos de OpenCms?</strong></p>
<p>Se ha añadido una nueva tabla llamada CMS_ONLINE_RESOURCE_RELATIONS para cada proyecto (sustituir ONLINE por OFFLINE) con los siguientes campos:</p>
<p>RESOURCE_SOURCE_ID: De tipo VARCHAR(36), contiene el id del recurso A.<br />
RESOURCE_SOURCE_PATH: TEXT, contiene el path en ruta absoluta del recurso A.<br />
RESOURCE_TARGET_ID: VARCHAR(36), contiene el id del recurso B.<br />
RESOURCE_TARGET_PATH: TEXT, contiene el el path en ruta absoluta al recurso B.<br />
RELATION_TYPE : INTEGER, es el tipo de relación que vamos a establecer.</p>
<p><strong>¿Dónde se configuran las relaciones?</strong></p>
<p>El el fichero opencms-workplace.xml. La configuración por defecto:</p>
<pre><code>
&lt;default-preferences&gt;
   &lt;workplace-preferences&gt;
      &lt;workplace-generaloptions&gt;
         ...
         &lt;allowbrokenrelations&gt;false&lt;/allowbrokenrelations&gt;
         &lt;publishrelatedresources&gt;true&lt;/publishrelatedresources&gt;
         ...
      &lt;/workplace-generaloptions&gt;
   &lt;/workplace-preferences&gt;
&lt;/default-preferences&gt;</code></pre>
<p><strong>¿Cómo se usan las relaciones?</strong></p>
<ol>
<li>Desde el menú flotante, opción relaciones: Podemos ver las relaciones de los recursos y asignar categorías.</li>
<li>En jsp, usando el macro %(link.strong) o %(link.weak). En vez de usar<br />
<code> </code></p>
<pre>
 &lt;img src=”&lt;cms:link&gt;/imagenes/imagen.jpg&lt;/cms:link&gt;” /&gt;</pre>
<p>usamos<br />
<code> </code></p>
<pre>
 &lt;img src=”&lt;cms:link&gt;%(link.strong:/imagenes/imagen.jpg)&lt;/cms:link&gt;” /&gt;</pre>
</li>
<li>Usando categorías:
<ul>
<li> Primero hay que definir categorías, esto se hace creando una estructura de carpetas en /system/categories/ , por ejemplo:<br />
/system/categories/categoria1/<br />
/system/categories/categoria1/subcategoria11/<br />
/system/categories/categoria1/subcategoria12/<br />
/system/categories/categoria1/subcategoria13/</li>
<li>En el .XSD usamos el widget org.opencms.widgets.CmsCategoryWidget para mostrar el listado de categorías.</li>
<li>En jsp usamos org.opencms.file.collectors.CmsCategoryResourceCollector para listar los recursos pertenecientes a dicha categoría.</li>
</ul>
</li>
<li>Desde las clases de CmsObject (crear nuevas relaciones y leer o borrar existentes) y CmsRelationFilter.</li>
</ol>
<p>Por último hay que destacar que Michael Moossen realizó una presentación muy interesante sobre CRE en los OpenCms Days. Las trasparencias que usó están disponibles en el siguiente enlace.</p>
<p><a href="http://opencms.org/export/sites/opencms/en/events/opencms_days_2008/slides/T2_MichaelMoossen.pdf" target="_blank">Trasparencias de Michael Moossen para la presentación de CRE en OpenCms Days</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/367-cre-i/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Humor: Como reconocer una tecnología desfasada</title>
		<link>http://xnoccio.com/347-humor-como-reconocer-una-tecnologia-desfasada/</link>
		<comments>http://xnoccio.com/347-humor-como-reconocer-una-tecnologia-desfasada/#comments</comments>
		<pubDate>Tue, 23 Sep 2008 18:22:03 +0000</pubDate>
		<dc:creator>Félix García Borrego</dc:creator>
		
		<category><![CDATA[Frikadas]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://xnoccio.com/347-humor-como-reconocer-una-tecnologia-desfasada/</guid>
		<description><![CDATA[En Viavansi, desde que migramos al Framework Perfecto, han ido quedando algunas tecnologías en desuso, viendo estas fotos, no hay  que ser ningún experto para saber cuales son esas tecnologías :p



]]></description>
			<content:encoded><![CDATA[<p>En Viavansi, desde que <a href="http://xnoccio.com/320-humor-el-framewok-perfecto/" title="Framework de Desarrollo de Viavansi.">migramos al Framework Perfecto</a>, han ido quedando algunas tecnologías en desuso, viendo estas fotos, no hay  que ser ningún experto para saber cuales son esas tecnologías :p<br />
<a href="http://xnoccio.com/wp-content/uploads/2008/09/09052008151.jpg" title="Humor: Como reconocer una tecnología desfasada 2"><img src="http://xnoccio.com/wp-content/uploads/2008/09/09052008151.jpg" alt="Humor: Como reconocer una tecnología desfasada 2" width="203" height="154" /></a><a href="http://xnoccio.com/wp-content/uploads/2008/09/09052008158.jpg" title="Humor: Como reconocer una tecnología desfasada struts :p"><img src="http://xnoccio.com/wp-content/uploads/2008/09/09052008158.jpg" alt="Humor: Como reconocer una tecnología desfasada struts :p" width="203" height="154" /></a><br />
<a href="http://xnoccio.com/wp-content/uploads/2008/09/09052008152.jpg" title="Humor: Como reconocer una tecnología desfasada 3"><img src="http://xnoccio.com/wp-content/uploads/2008/09/09052008152.jpg" alt="Humor: Como reconocer una tecnología desfasada 3" width="203" height="154" /></a><a href="http://xnoccio.com/wp-content/uploads/2008/09/09052008150.jpg" title="Técnología desfasada. Humor"><img src="http://xnoccio.com/wp-content/uploads/2008/09/09052008150.jpg" alt="Técnología desfasada. Humor" width="203" height="154" /></a><br />
<a href="http://xnoccio.com/wp-content/uploads/2008/09/09052008155.jpg" title="Humor: Como reconocer una tecnología desfasada 5"><img src="http://xnoccio.com/wp-content/uploads/2008/09/09052008155.jpg" alt="Humor: Como reconocer una tecnología desfasada 5" width="203" height="154" /></a><a href="http://xnoccio.com/wp-content/uploads/2008/09/09052008156.jpg" title="Humor: Como reconocer una tecnología desfasada 5"><img src="http://xnoccio.com/wp-content/uploads/2008/09/09052008156.jpg" alt="Humor: Como reconocer una tecnología desfasada 5" width="203" height="154" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/347-humor-como-reconocer-una-tecnologia-desfasada/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Hudson. Parte 1 - Introducción.</title>
		<link>http://xnoccio.com/362-hudson-parte-1-introduccion/</link>
		<comments>http://xnoccio.com/362-hudson-parte-1-introduccion/#comments</comments>
		<pubDate>Wed, 17 Sep 2008 09:45:37 +0000</pubDate>
		<dc:creator>Félix García Borrego</dc:creator>
		
		<category><![CDATA[java]]></category>

		<category><![CDATA[javahispano]]></category>

		<category><![CDATA[programación]]></category>

		<category><![CDATA[software]]></category>

		<category><![CDATA[viavansi]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://xnoccio.com/362-hudson-parte-1-introduccion/</guid>
		<description><![CDATA[¿Qué problemática resuelve?
En entornos en los que el desarrollo de software se realiza por un equipo o equipos en los que la evolución y mantenimiento del código se subdivide,  el coste de la integración entre las diferentes piezas de software tiende a aumentar, apareciendo conflictos y haciendo de la generación de distribuibles una ardua tarea.  [...]]]></description>
			<content:encoded><![CDATA[<p><strong>¿Qué problemática resuelve?</strong></p>
<p>En entornos en los que el desarrollo de software se realiza por un equipo o equipos en los que la evolución y mantenimiento del código se subdivide,  el coste de la integración entre las diferentes piezas de software tiende a aumentar, apareciendo conflictos y haciendo de la generación de distribuibles una ardua tarea.  Con idea de <strong>rebajar los costes </strong>adicionales provocados por la gestión del proceso de compilación, integración, empaquetado y generación de entregarles, aparecen herramientas  de <a href="http://es.wikipedia.org/wiki/Continuous_integration" title="Integración continua en la Wikipedia">Integración Continua</a> (CI) como Hudson.</p>
<p><strong>¿ Por qué elegir Hudson?</strong></p>
<p>Aunque es un productor reciente ha evolucionado rápidamente y actualmente es uno de los productos de referencia en el sector de las aplicaciones para Integración Continua de software, gracias a la <strong>simplicidad de su interfaz</strong> y lo sencillo que resulta el desarrollo de nuevos <strong>plugins</strong>. Prueba de este crecimiento es que actualmente es utilizado por un gran numero de proyectos entre los que se encuentra por ejemplo <a href="http://hudson.jboss.org/hudson/" title="Hudson de JBoss">JBoss.</a></p>
<p>Para hacernos una idea los principales motivos que en nuestro caso nos hicieron elegir Hudson son:</p>
<ul>
<li><strong>Fácil instalación y uso</strong>. Como buen producto cuya utilidad es la de simplificarnos la vida, la instalación y ejecución de Hudson es realmente trivial. Es suficiente con descargar el  fichero <a href="https://hudson.dev.java.net/servlets/ProjectDocumentList?folderID=2761" title="Hudson WAR">hudson.war</a><span style="font-weight: bold"></span> y ejecutarlo con &#8220;java -jar hudson.war&#8221; o bien desplegarlo en un servidor de aplicaciones.  Y esto no queda aquí, gracias a su <strong>sencilla interfaz</strong>, podemos tener nuestros primeros proyectos configurados en pocos minutos.</li>
<li><strong>Un sistema de plugins</strong> fácilmente extensible. Lo que permite la instalación y creación de nuevos plugins de forma sencilla. Esto ha permitido que exista una gran cantidad de plugins disponibles y que sea muy sencilla la creación de plugins específicos. Como ejemplo, gracias a esta simplicidad pudimos crear un plugin específico para adaptar el comportamiento de Hudson a nuestras necesidades en solo unos días.</li>
<li>Un soporte completo de <strong>Maven</strong>, lo que nos ha permitido una migración rápida de todos nuestros proyectos al nuevo sistema.</li>
<li>Soporte para compilación distribuida basada en sistemas esclavos y maestros, para mejorar los tiempos de compilación y evitar la sobrecarga.</li>
<li>Soporte para múltiples equipos y grupos de proyectos, lo que nos permite la colaboración.</li>
<li>Es un Sistema completamente <strong>Software Libre</strong>.</li>
<li>Nos permite establecer un <strong>sistema de alertas a los desarrolladores</strong> sobre el estado de sus proyectos.</li>
<li><strong>Permite la detección de actualizaciones realizadas en el SCM </strong>( en nuestro caso Subversion) para generar de forma automática los nuevos empaquetados o a intervalos regulares.</li>
<li>Y el principal motivo. Tras estar utilizándolo en el departamento de I+D durante unos meses, <strong>el software no nos dio ni un solo problema</strong>, por lo que actualmente la mayoría de nuestros proyectos están ya bajo el control de Hudson.</li>
</ul>
<p><a href="http://xnoccio.com/wp-content/uploads/2008/09/proyectos.png" title="Listado de proyectos gestionados por Hudson en Viavansi"><img src="http://xnoccio.com/wp-content/uploads/2008/09/proyectos.png" alt="Listado de proyectos gestionados por Hudson en Viavansi" height="269" width="390" /></a></p>
<p><strong>Instalación</strong></p>
<p>Como se comenta arriba, la instalación del software es realmente <strong>sencilla</strong>, y el único requisito es tener instalada una versión de Java reciente y opcionalmente un servidor de aplicaciones como por ejemplo Tomcat, si no se desea ejecutar sobre el servidor que trae embebido.</p>
<p>Para la instalación, en primer lugar necesitara descargar la última versión estable de  <a href="http://hudson.dev.java.net/" title="Sitio oficial de Hudson">http://hudson.dev.java.net</a>.</p>
<p>Si desea ejecutar Hudson en modo autónomo sera suficiente con ejecutar &#8220;java -jar hudson.war&#8221;y acceder con el navegador al puerto 8080 (http://localhost:8080) para poder utilizar Hudson.  Si lo desea, en la web oficial tambien puede encontrar los scripts para convertir hudson en un servicio.</p>
<p>Por otro lado la instalación más común de Hudson es su despliegue en un servidor de aplicaciones. Por ejemplo, para su despliegue en un Tomcat, bastara con copiar el fichero hudson.war dentro del directorio webapps.</p>
<p>Hudson utiliza un directorio especial para almacenar toda la configuración propia y de los proyectos que gestiona, por lo que no hay peligro de perdida de datos si posteriormente actualizamos a versiones más recientes del software. Por defecto el directorio es &#8220;.hudson&#8221;, localizado en el home del usuario, pero  es posible modificar este directorio estableciendo la variable de entorno HUDSON_HOME.</p>
<p><strong>Primeros pasos</strong></p>
<p>En Hudson cada proyecto de desarrollo es una tarea, por lo que para hacer que un proyecto este gestionado por hudson es suficiente con darle un nombre a la tarea y asignarle un tipo entre los disponibles (Build a maven2 project, Build a free-style software project, &#8230;)</p>
<p><a href="http://xnoccio.com/wp-content/uploads/2008/09/newjob.png" title="Paso 1. Crear Un nuero proyecto (Job) en Hudson"><img src="http://xnoccio.com/wp-content/uploads/2008/09/newjob.png" alt="Paso 1. Crear Un nuero proyecto (Job) en Hudson" height="306" width="406" /></a></p>
<p>En adelante a modo de ejemplo vamos a considerar un proyecto de tipo Maven 2. Una vez que tenemos el tipo de proyecto seleccionado, pasamos a la pantalla de configuración, en la que entre otras muchas opciones, tendremos que seleccionar el SCM en el que se encuentra proyecto(en nuestro caso Subversión), el pom.xml asociado al proyecto y el conjunto de goals que deseamos ejecutar. No entraremos en detalle a explicar cada uno de las opciones de configuración, ya que otra de las ventajas de Hudson es que ofrece ayuda en linea para todas sus opciones.</p>
<p>Una vez guardada la nueva tarea, ésta podrá ser ejecutada automáticamente si hemos configurado algún Build Triggers o lanzada de forma manual pulsando sobre Build Now, y una vez que la tarea esta en ejecución podremos ver en todo momento su estado y consola.</p>
<p><strong>Administración </strong></p>
<p>Desde el menú &#8220;Manage Hudson&#8221;, situado en la página principal, es posible acceder a todas las opciones de configuración. En particular desde la opción &#8220;Configure System&#8221; podremos acceder a todos los parametros generales como configuración del  SMTP, proxy, rutas a Maven, Ant, &#8230;<br />
Y de nuevo para cada opción de configuración dispondremos de ayuda contextual que nos hara la vida mucho más facil.</p>
<p>Como ya hemos comentado, uno de los puntos fuertes de Hudson es su sistema y manejador de plugins, al que podremos  acceder desde la opción &#8220;Manage Plugins&#8221;. Esta opción nos permitirá añadir nuevas características (como herramientas de control de estilo, nuevos SCM soportados, &#8230;) directamente desde su interfaz.</p>
<p><a href="http://xnoccio.com/wp-content/uploads/2008/09/managehudson.png" title="Consola de administración de Hudson"><img src="http://xnoccio.com/wp-content/uploads/2008/09/managehudson.png" alt="Consola de administración de Hudson" height="355" width="493" /></a></p>
<p>La lista de todos los plugins está disponible en la siguiente dirección:  <a href="http://hudson.gotdns.com/wiki/display/HUDSON/Plugins" title="Listado de plugins para Hudson">http://hudson.gotdns.com/wiki/display/HUDSON/Plugins</a></p>
<p><strong>Conclusión</strong></p>
<p>Hudson es un es un fantastico software para realizar las tareas de Integración Continua, y aunque aquí se han presentado solo las características básicas, a pesar de la simplicidad de su interfaz es un software altamente extensible y con un gran potencial.</p>
<p>Por otro lado, y aunque se enfoca principalmente hacia proyectos Java, Hudson permite gestionar proyectos de cualquier tipo, como por ejemplo proyectos C o Ruby on Rails, lo que lo hace muy recomendable enentorno heterogéneos.</p>
<p>En general, los productos de Integración Continua suelen ser complejos de manejar y gestionar, y como hemos visto, este no es el caso de Hudson, lo que resulta esencial si queremos convertir esta herramienta en una plataforma horizontal en nuestra empresa o grupo de desarrollo. Su facilidad de uso la ha demostrado durante el tiempo que llevamos utilizándolo, ya que no solo no ha requerido de personal especializado en este tipo de tareas para su gestión, sino que tampoco ha necesitado de una compleja explicación para que nuestros grupos de desarrollo empezaran a utilizarlo.</p>
<p>En resumen una herramienta para simplificarnos la vida a los desarrolladores que ofrece lo que promete.</p>
<p>Próximamente: Hudson.  Parde 2. Crea tus propios plugins</p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/362-hudson-parte-1-introduccion/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Curiosidad: La extraña implementación de NaN</title>
		<link>http://xnoccio.com/357-curiosidad-la-extrana-impelentacion-de-nan/</link>
		<comments>http://xnoccio.com/357-curiosidad-la-extrana-impelentacion-de-nan/#comments</comments>
		<pubDate>Thu, 11 Sep 2008 10:19:26 +0000</pubDate>
		<dc:creator>Félix García Borrego</dc:creator>
		
		<category><![CDATA[javahispano]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[tips]]></category>

		<category><![CDATA[programación]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://xnoccio.com/357-curiosidad-la-extrana-impelentacion-de-nan/</guid>
		<description><![CDATA[Si probáis a evaluar esta expresión: Double.NaN==Double.NaN , comprobareis con extrañeza que Java retorna false.
Sin embarco,  si realizamos la comparación con el método equals, la cosa mejora  y todo se comporta como esperábamos.
¿Por qué ocurre esto? ¿Es un Bug?
Por extraño que nos pudiera parecer no es un error en la implementación, y podemos encontrar este [...]]]></description>
			<content:encoded><![CDATA[<p>Si probáis a evaluar esta expresión: <strong>Double.NaN==Double.NaN</strong> , comprobareis con extrañeza que Java retorna false.</p>
<p>Sin embarco,  si realizamos la comparación con el método <strong>equals</strong>, la cosa mejora  y todo se comporta como esperábamos.</p>
<p><strong>¿Por qué ocurre esto? ¿Es un Bug?</strong></p>
<p>Por extraño que nos pudiera parecer no es un error en la implementación, y podemos encontrar este comportamiento en otros lenguajes orientados a objetos como C#.</p>
<p>La implementación del tipo double en Java se basa en el estandard &#8220;<a href="http://grouper.ieee.org/groups/754/" title="Estandar para el tipo Double en Java">IEEE 754 Binary Floating-Point Arithmetic standard</a>&#8220;, que define que <strong>dos números con el valor NaN nunca son iguales</strong>, por lo que el operador &#8220;<strong>==</strong>&#8221; se definió de acuerdo con esta especificación. El problema surge al conciliar este comportamiento con la especificación del método equals para Object, por lo que se decidió sobrescribir el método equals de Double para adaptarlo al comportamiento de comparación de equivalencia esperado. Y aquí tenemos el conflicto &#8220;método equals&#8221; VS  &#8220;IEEE 754&#8243;.</p>
<p>Por lo que lo recomendado es utilizar el operador cuando deseas hacer comparaciones de acuerdo con el estándar para números flotantes, y utilizar el método equals si en tu código es deseable que un NaN sea igual a un NaN.<br />
<strong>La solución.</strong></p>
<p>Si no nos queremos complicar, en la mayoría de los casos bastara con utilizar :<br />
Double.isNaN(varNum) ;</p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/357-curiosidad-la-extrana-impelentacion-de-nan/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Servidores de Correo y su Integridad</title>
		<link>http://xnoccio.com/359-servidores-de-correo-y-su-integridad/</link>
		<comments>http://xnoccio.com/359-servidores-de-correo-y-su-integridad/#comments</comments>
		<pubDate>Wed, 10 Sep 2008 23:29:38 +0000</pubDate>
		<dc:creator>Benito Galán Algora</dc:creator>
		
		<category><![CDATA[seguridad]]></category>

		<category><![CDATA[viafirma]]></category>

		<guid isPermaLink="false">http://xnoccio.com/359-servidores-de-correo-y-su-integridad/</guid>
		<description><![CDATA[No es noticia que te fastidien una aplicación que estaba corriendo bien porque otro servicio anda por ahí haciendo de las suyas y tú eres el último en enterarte.
Este caso es el que nos pasó recientemente, y lo peor de todo es que era en un entorno de producción.
El ejemplo en cuestión se trataba de [...]]]></description>
			<content:encoded><![CDATA[<p>No es noticia que te fastidien una aplicación que estaba corriendo bien porque otro servicio anda por ahí haciendo de las suyas y tú eres el último en enterarte.</p>
<p>Este caso es el que nos pasó recientemente, y lo peor de todo es que era en un entorno de producción.</p>
<p>El ejemplo en cuestión se trataba de un sistema que hacía uso de <a href="http://www.viafirma.com" title="ir a la web de Viafirma">VIAFIRMA</a> (nuestra plataforma de autenticación y firma digital). Cuando ésta enviaba los correos firmados digitalmente con el certificado instalado en producción, el &#8220;maravilloso&#8221; Exchange empezó a aplicar una regla para los correos cuyo destinatario fuese un correo externo.</p>
<p>Esta regla no era otra que interceptar el correo e inyectarle un disclaimer en el pie, del tipo &#8220;&#8230;este mensaje contiene información confidencial&#8230;.&#8221;.</p>
<p>El catastrófico resultado en los correos que recibían los usuarios:</p>
<p><code><br />
La firma no es válida<br />
El mensaje incluye una firma digital, pero la firma no es válida.<br />
La firma no coincide correctamente con el contenido del mensaje. El mensaje parece que <strong>ha sido manipulado después de que el remitente lo firmara</strong>. Usted no debería confiar en la validez de este mensaje hasta que verifique su contenido con el remitente.<br />
Firmado por: &#8220;la empresa en cuestión&#8221;<br />
</code></p>
<p>Para hacer más difícil aún la detección del problema, y sin saber aún por qué, Exchange no siempre estaba aplicando esta regla y se escapaban correos sin el disclaimer.</p>
<p>Por tanto, en sistemas de información donde apuesten por la automatización del formato de los correos salientes desde el lado servidor siempre tendrán que tener en cuenta qué REGLAS de INTEGRIDAD podrían estar rompiendo.</p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/359-servidores-de-correo-y-su-integridad/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Conexión JDBC con Oracle Cluster</title>
		<link>http://xnoccio.com/358-conexion-jdbc-con-oracle-cluster/</link>
		<comments>http://xnoccio.com/358-conexion-jdbc-con-oracle-cluster/#comments</comments>
		<pubDate>Mon, 08 Sep 2008 23:03:29 +0000</pubDate>
		<dc:creator>Benito Galán Algora</dc:creator>
		
		<category><![CDATA[oracle]]></category>

		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://xnoccio.com/358-conexion-jdbc-con-oracle-cluster/</guid>
		<description><![CDATA[Normalmente, para tareas de desarrollo hacíamos referencias a servidores Oracle que teníamos en nuestra propia red local o incluso en nuestro propio equipo (XE - express edition). Pero distinto es cuando pasamos una aplicación a producción y no tenemos a ese maravilloso DBA que te soluciona la papeleta cuando te encuentras con algo que se [...]]]></description>
			<content:encoded><![CDATA[<p>Normalmente, para tareas de desarrollo hacíamos referencias a servidores Oracle que teníamos en nuestra propia red local o incluso en nuestro propio equipo (XE - express edition). Pero distinto es cuando pasamos una aplicación a producción y no tenemos a ese maravilloso DBA que te soluciona la papeleta cuando te encuentras con algo que se sale de lo normal en tus desarrollos.</p>
<p>En este caso ese maravilloso DBA estaba buscando papas en la playa, pero afortunadamente mr. google estaba ahí para solucionarnos la papeleta. Por ello, dejo aquí estos fragmentos de código como referencia rápida en futuras conexiones a <strong>Clusters de Oracle</strong>.</p>
<p><strong>Llamada stand-alone (sin cluster ni nada raro) </strong></p>
<p><code><br />
url="jdbc:oracle:thin:@192.168.1.2:1521:DEV"<br />
</code></p>
<p><strong>Llamada a un cluster de Oracle con Balanceo de Carga</strong></p>
<p><code><br />
url="<br />
jdbc:oracle:thin:@(DESCRIPTION=<br />
(LOAD_BALANCE=on)<br />
(ADDRESS=(PROTOCOL=TCP)(HOST=myserver01)(PORT=1521))<br />
(ADDRESS=(PROTOCOL=TCP)(HOST=myserver02)(PORT=1521))<br />
(CONNECT_DATA=(SERVICE_NAME=my_orasrv)))"<br />
</code></p>
<p>donde myserver01 y myserver02 son las IP virtuales de los nodos montados. Y así con todos los nodos que tuviera el cluster. Esto lo encontramos en el foro de Sun http://forums.sun.com.</p>
<p><strong>Cluster sin Balanceo de Carga</strong></p>
<p><code></code></p>
<p>url=&#8221;jdbc:oracle:thin:@(DESCRIPTION=<br />
(ADDRESS=(PROTOCOL=TCP)(HOST=cluster_alias)(PORT=1521))<br />
(CONNECT_DATA=(SERVICE_NAME=my_orasrv)))&#8221;</p>
<p>donde invocan al cluster mediante su alias. Esta otra la encontramos en el foro de www.oraFAQ.com</p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/358-conexion-jdbc-con-oracle-cluster/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Errores al utilizar Axis2 en Mac OS X Leopard</title>
		<link>http://xnoccio.com/356-errores-al-utilizar-axis2-en-mac-os-x-leopard/</link>
		<comments>http://xnoccio.com/356-errores-al-utilizar-axis2-en-mac-os-x-leopard/#comments</comments>
		<pubDate>Mon, 08 Sep 2008 14:08:48 +0000</pubDate>
		<dc:creator>Javier Echeverría Usua</dc:creator>
		
		<category><![CDATA[java]]></category>

		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://xnoccio.com/356-errores-al-utilizar-axis2-en-mac-os-x-leopard/</guid>
		<description><![CDATA[Al volver a utilizar un proyecto Java EE que invocaba a un servicio web mediante Axis, y que funcionaba correctamente en Windows, me he encontrado con un error bastante extraño que al invocar decía:
java.util.regex.PatternSyntaxException: Dangling meta character ‘*’ near index 0 *.local
Al principio pensaba que podría deberse a que la JVM no estuviese captando la [...]]]></description>
			<content:encoded><![CDATA[<p>Al volver a utilizar un proyecto Java EE que invocaba a un servicio web mediante Axis, y que funcionaba correctamente en Windows, me he encontrado con un error bastante extraño que al invocar decía:</p>
<p>java.util.regex.PatternSyntaxException: Dangling meta character ‘*’ near index 0 *.local</p>
<p>Al principio pensaba que podría deberse a que la JVM no estuviese captando la configuración de salida por el proxy de la oficina, pero advertí que el error se daba tanto saliendo a través del proxy, como puenteándolo.</p>
<p>Pues bien, con un poco de Google, <a href="http://codebrane.com/blog/?p=355" target="_blank">me encontré la solución</a>.  Resulta que Tomcat dentro de Eclipse recupera la configuración de red de Leopard, y por defecto la variable nonProxyHosts (Omitir ajustes proxy para estos servidores y dominios) tiene el siguiente valor:</p>
<p>*.local, 169.254/16</p>
<p>Que no le gusta nada a Axis2 (se quejaba del *.local)&#8230; así que la cambiamos, eliminando esos valores. Para ello, nos vamos a Preferencias del Sistema -&gt; Red -&gt; Avanzado -&gt; Proxies.</p>
<p>Y reiniciando el Tomcat, funcionó correctamente. Viva interné.</p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/356-errores-al-utilizar-axis2-en-mac-os-x-leopard/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Arroz con Mango: Seam + Logger &#38; Finder Interceptor + Lucene&#8230;</title>
		<link>http://xnoccio.com/355-arroz-con-mango-seam-logger-finder-interceptor-lucene/</link>
		<comments>http://xnoccio.com/355-arroz-con-mango-seam-logger-finder-interceptor-lucene/#comments</comments>
		<pubDate>Fri, 05 Sep 2008 22:12:36 +0000</pubDate>
		<dc:creator>Guido Medina</dc:creator>
		
		<category><![CDATA[java]]></category>

		<category><![CDATA[javahispano]]></category>

		<category><![CDATA[usabilidad]]></category>

		<category><![CDATA[tips]]></category>

		<category><![CDATA[programación]]></category>

		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://xnoccio.com/355-arroz-con-mango-seam-logger-finder-interceptor-lucene/</guid>
		<description><![CDATA[Bueno, tuve unas necesidades en un proyecto, así que comencé por hacer un GenericDAO, luego le agregué un FinderInterceptor el cual permite que cuando hagas findByWhatever te busque un NamedQuery que esté definido en la Entidad de JPA, como tip le agregué un logger el cual loguea cada método conjunto con los parámetros pasados, aqui [...]]]></description>
			<content:encoded><![CDATA[<p>Bueno, tuve unas necesidades en un proyecto, así que comencé por hacer un GenericDAO, luego le agregué un FinderInterceptor el cual permite que cuando hagas findByWhatever te busque un NamedQuery que esté definido en la Entidad de JPA, como tip le agregué un logger el cual loguea cada método conjunto con los parámetros pasados, aqui comienzo a explicar uno por uno:</p>
<p><strong>GenericDAO; interfase que define el contrato del JPA DAO el cual implementa de forma genérica las funcionalidades del mismo; esta interfase está interceptada por un Finder del cual hablaremos más tarde; tuve que usar Lucene ya que el proyecto corre sobre MSSQL Server y el bendito no soporta translate:</strong></p>
<p><code><br />
package com.viavansi.fdu.persistencia.DAO;</code><code>import java.io.Serializable;<br />
import java.util.List;</p>
<p>import org.apache.lucene.queryParser.ParseException;</p>
<p>import com.viavansi.framework.core.persistencia.servicios.excepciones.ExcepcionPersistencia;/**<br />
 * Interface for data access objects.<br />
 *<br />
 * &lt;p&gt;<br />
 * Generic Interface DAO which provides the basic contracted operations for<br />
 * every DAO; an implementation is also provided.<br />
 *<br />
 * @param &lt;T&gt;<br />
 * The persistent class.<br />
 * @param &lt;PK&gt;<br />
 * The class of the primary key of the persistent class.<br />
 */<br />
@FinderExecutor<br />
public interface GenericDao&lt;T, PK extends Serializable&gt; { /**<br />
  * Merge.<br />
  *<br />
  * @param persistentObject<br />
  */<br />
 void update(T persistentObject) throws ExcepcionPersistencia; /**<br />
  * Make the instance persistent.<br />
  *<br />
  * @throws ExcepcionPersistencia<br />
  */<br />
 void create(T newInstance) throws ExcepcionPersistencia; /**<br />
  * Make the object transient.<br />
  *<br />
  * @param persistentObject<br />
  * @throws ExcepcionPersistencia<br />
  */<br />
 void delete(T persistentObject) throws ExcepcionPersistencia; /**<br />
  * Returns a persistent object specified by its key.<br />
  *<br />
  * @throws ExcepcionPersistencia<br />
  */<br />
 T read(PK id) throws ExcepcionPersistencia; /**<br />
  * Returns all persistent entities.<br />
  */<br />
 List&lt;T&gt; findAll() throws ExcepcionPersistencia; /**<br />
  * Resolves and executes a finder. &lt;p/&gt;<br />
  * &lt;p&gt;<br />
  * This implementation uses the short name of the type class, appending a .<br />
  * and the method name so the name of the query to look up becomes<br />
  * Pet1.findByName if the method is findByName and the type Pet1. &lt;p/&gt;<br />
  * &lt;p&gt;<br />
  * An other implementation would be useful as well that does not return a<br />
  * list but a single object.<br />
  */<br />
 List&lt;T&gt; executeFinder(String method, Object[] queryArguments)<br />
  throws ExcepcionPersistencia; List&lt;T&gt; searchByText(String expresion) throws ExcepcionPersistencia,<br />
  ParseException;</p>
<p></code><strong>Ahora definimos el DAO que contiene injectado el EntityManager:</strong></p>
<p><code><br />
package com.viavansi.fdu.persistencia.DAO;</code><code>import java.beans.PropertyDescriptor;<br />
import java.io.Serializable;<br />
import java.util.List;</p>
<p>import javax.persistence.EntityManager;<br />
import javax.persistence.Query;</p>
<p>import org.apache.commons.beanutils.BeanUtilsBean;<br />
import org.apache.commons.beanutils.PropertyUtilsBean;<br />
import org.apache.lucene.queryParser.ParseException;<br />
import org.apache.lucene.queryParser.QueryParser;<br />
import org.hibernate.search.jpa.FullTextEntityManager;<br />
import org.hibernate.search.jpa.Search;<br />
import org.jboss.seam.annotations.In;</p>
<p>import com.viavansi.framework.core.excepciones.CodigoError;<br />
import com.viavansi.framework.core.persistencia.servicios.excepciones.ExcepcionDatosNoEncontrados;<br />
import com.viavansi.framework.core.persistencia.servicios.excepciones.ExcepcionPersistencia;</p>
<p>/**<br />
 * Generic data access object.<br />
 *<br />
 * @param &lt;T&gt;<br />
 * The persistent class.<br />
 * @param &lt;PK&gt;<br />
 * The class of the primary key of the persistent class.<br />
 */<br />
public abstract class GenericJpaDaoFDU&lt;T, PK extends Serializable&gt; implements<br />
  GenericDao&lt;T, PK&gt; {</p>
<p>protected Class&lt;T&gt; type;</p>
<p>@In("fduPersistenceContext")<br />
 protected EntityManager entityManager;</p>
<p>public EntityManager getEntityManager() {<br />
  return entityManager;<br />
 }</p>
<p>public void setEntityManager(EntityManager entityManager) {<br />
  this.entityManager = entityManager;<br />
 }</p>
<p>public void create(T newInstance) throws ExcepcionPersistencia {<br />
  try {<br />
  this.entityManager.persist(newInstance);<br />
  } catch (Exception e) {<br />
  throw new ExcepcionPersistencia(CodigoError.ERROR_NO_DEFINIDO, e);<br />
  }<br />
 }</p>
<p>public void delete(T persistentObject) throws ExcepcionPersistencia {<br />
  try {<br />
  this.entityManager.remove(persistentObject);<br />
  } catch (Exception e) {<br />
  throw new ExcepcionPersistencia(CodigoError.ERROR_NO_DEFINIDO, e);<br />
  }<br />
 }</p>
<p>public T read(PK id) throws ExcepcionDatosNoEncontrados {<br />
  T t = (T) this.entityManager.find(type, id);<br />
  if (t == null) {<br />
  throw new ExcepcionDatosNoEncontrados(<br />
  CodigoError.ERROR_DATOS_NO_ENCONTRADOS,<br />
  "Datos no encontrados");<br />
  }<br />
  return t;<br />
 }</p>
<p>public void update(T transientObject) throws ExcepcionPersistencia {<br />
  try {<br />
  this.entityManager.merge(transientObject);<br />
  } catch (Exception e) {<br />
  throw new ExcepcionPersistencia(CodigoError.ERROR_NO_DEFINIDO, e);<br />
  }<br />
 }</p>
<p>@SuppressWarnings("unchecked")<br />
 public List&lt;T&gt; findAll() throws ExcepcionPersistencia {<br />
  try {<br />
  return entityManager.createQuery(<br />
  "select obj from " + this.type.getName() + " obj")<br />
  .getResultList();<br />
  } catch (Exception e) {<br />
  throw new ExcepcionPersistencia(CodigoError.ERROR_NO_DEFINIDO, e);<br />
  }<br />
 }</p>
<p>/**<br />
  * Resolves and executes a finder. &lt;p/&gt;<br />
  * &lt;p&gt;<br />
  * This implementation uses the short name of the type class, appending a .<br />
  * and the method name so the name of the query to look up becomes<br />
  * Pet1.findByName if the method is findByName and the type Pet1. &lt;p/&gt;<br />
  * &lt;p&gt;<br />
  * An other implementation would be useful as well that does not return a<br />
  * list but a single object.<br />
  *<br />
  * @throws ExcepcionPersistencia<br />
  */<br />
 @SuppressWarnings( { "unchecked" })<br />
 public List&lt;T&gt; executeFinder(String method, Object[] queryArguments)<br />
  throws ExcepcionPersistencia {<br />
  try {<br />
  String queryName = queryNameFromMethod(method);<br />
  Query query = entityManager.createNamedQuery(queryName);<br />
  for (int i = 0; i &lt; queryArguments.length; i++) {<br />
  query.setParameter(i, queryArguments[i]);<br />
  }<br />
  return query.getResultList();<br />
  } catch (Exception e) {<br />
  throw new ExcepcionPersistencia(CodigoError.ERROR_NO_DEFINIDO, e);<br />
  }<br />
 }</p>
<p>/**<br />
  * Resolves the name of the named query.<br />
  *<br />
  * @param finderMethod<br />
  * "findPerson, etc."<br />
  * @return<br />
  */<br />
 protected String queryNameFromMethod(String finderMethod) {<br />
  return type.getSimpleName() + "." + finderMethod;<br />
 }</p>
<p>/*<br />
  * (non-Javadoc)<br />
  *<br />
  * @see<br />
  * com.viavansi.fdu.persistencia.DAO.GenericDao#findWhere(java.lang.String)<br />
  */<br />
 @SuppressWarnings("unchecked")<br />
 public List&lt;T&gt; searchByText(String expression)<br />
  throws ExcepcionPersistencia, ParseException {<br />
  PropertyUtilsBean propertyUtils = BeanUtilsBean.getInstance()<br />
  .getPropertyUtils();<br />
  StringBuilder builder = new StringBuilder();<br />
  boolean firstField = true;<br />
  for (PropertyDescriptor descriptor : propertyUtils<br />
  .getPropertyDescriptors(type)) {<br />
  if (firstField) {<br />
  firstField = false;<br />
  } else {<br />
  builder.append(" OR ");<br />
  }<br />
  builder.append(descriptor.getName() + ":" + expression);<br />
  }<br />
  FullTextEntityManager fullTextEntityManager = Search<br />
  .createFullTextEntityManager(entityManager);<br />
  QueryParser parser = new QueryParser("id", new ISOLatin1Analyzer());<br />
  org.apache.lucene.search.Query luceneQuery = parser.parse(builder<br />
  .toString());<br />
  Query query = fullTextEntityManager.createFullTextQuery(luceneQuery,<br />
  type);<br />
  List result = query.getResultList();<br />
  if (result.size() == 0) {<br />
  throw new ExcepcionDatosNoEncontrados();<br />
  }<br />
  return result;<br />
 }</p>
<p>/**<br />
  *<br />
  * @param &lt;T&gt;<br />
  * @param expression<br />
  * @param entityManager<br />
  * @param type<br />
  * @return<br />
  * @throws ExcepcionPersistencia<br />
  * @throws ParseException<br />
  */<br />
 @SuppressWarnings("unchecked")<br />
 public static &lt;T&gt; List&lt;T&gt; searchByText(String expression,<br />
  EntityManager entityManager, Class&lt;T&gt; type)<br />
  throws ExcepcionPersistencia, ParseException {<br />
  PropertyUtilsBean propertyUtils = BeanUtilsBean.getInstance()<br />
  .getPropertyUtils();<br />
  StringBuilder builder = new StringBuilder();<br />
  boolean firstField = true;<br />
  for (PropertyDescriptor descriptor : propertyUtils<br />
  .getPropertyDescriptors(type)) {<br />
  if (firstField) {<br />
  firstField = false;<br />
  } else {<br />
  builder.append(" OR ");<br />
  }<br />
  builder.append(descriptor.getName() + ":" + expression);<br />
  }<br />
  FullTextEntityManager fullTextEntityManager = Search<br />
  .createFullTextEntityManager(entityManager);<br />
  QueryParser parser = new QueryParser("id", new ISOLatin1Analyzer());<br />
  org.apache.lucene.search.Query luceneQuery = parser.parse(builder<br />
  .toString());<br />
  Query query = fullTextEntityManager.createFullTextQuery(luceneQuery,<br />
  type);<br />
  return query.getResultList();<br />
 }</p>
<p>}</p>
<p></code><strong>Nuestro 1er DAO para una Entidad; como verán, se apoya en el GenericDAO, y en su implementación:</strong></p>
<p><code><br />
package com.viavansi.fdu.persistencia.DAO;</code><code>import java.util.List;</p>
<p>import org.jboss.seam.annotations.Name;</p>
<p>import com.viavansi.fdu.persistencia.VO.ProcessInfoVO;</p>
<p>/**<br />
 * @author gmedina<br />
 *<br />
 */<br />
@Name("processInfoDAO")<br />
public class ProcessInfoDAO extends GenericJpaDaoFDU&lt;ProcessInfoVO, Long&gt; {</p>
<p>public ProcessInfoDAO() {<br />
  this.type = ProcessInfoVO.class;<br />
 }</p>
<p>public List&lt;ProcessInfoVO&gt; findByProcessName(String name) {<br />
  return null;<br />
 }</p>
<p>public List&lt;ProcessInfoVO&gt; findByJbpmName(String jbpmName) {<br />
  return null;<br />
 }</p>
<p>public List&lt;ProcessInfoVO&gt; findByArea(String area) {<br />
  return null;<br />
 }</p>
<p>}</p>
<p></code><strong>Vamos a mostrar nuestro Finder interceptor el cual sigue el Interceptor pattern y está soportado por Seam; muy sencillo, si el método se llama findByWhatever el busca un named query llamado findByWhatever, en tu implementación del DAO solo debes retornar null, si retornas algo entonces el finder se anula automáticamente:</strong></p>
<p><code><br />
package com.viavansi.fdu.interceptor;</code><code>import org.jboss.seam.annotations.intercept.AroundInvoke;<br />
import org.jboss.seam.intercept.InvocationContext;</p>
<p>import com.viavansi.fdu.persistencia.DAO.GenericDao;</p>
<p>/**<br />
 * @author gmedina<br />
 *<br />
 */<br />
public class FinderInterceptor { /**<br />
  *<br />
  * @param invocation<br />
  * @return<br />
  * @throws Throwable<br />
  */<br />
 @AroundInvoke<br />
 @SuppressWarnings("unchecked")<br />
 public Object executeFinder(InvocationContext invocation) throws Throwable {<br />
  String methodName = invocation.getMethod().getName();<br />
  if (methodName.startsWith("findBy")) {<br />
  GenericDao dao = (GenericDao) invocation.getTarget();<br />
  Object result = invocation.proceed();<br />
  return result == null ? dao.executeFinder(methodName, invocation<br />
  .getParameters()) : result;<br />
  } else<br />
  return invocation.proceed();<br />
 }</p>
<p></code><strong>Nuestro persistence.xml con la configuración de Lucene que necesita:</strong></p>
<p><code><br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;persistence xmlns="<a href="http://java.sun.com/xml/ns/persistence">http://java.sun.com/xml/ns/persistence</a>&#8221;<br />
 xmlns:xsi=&#8221;<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>&#8221; version=&#8221;1.0&#8243;<br />
 xsi:schemaLocation=&#8221;<a href="http://java.sun.com/xml/ns/persistence">http://java.sun.com/xml/ns/persistence</a> <a href="http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd</a>&#8220;&gt;<br />
 &lt;!&#8211;<br />
  Conexión por defecto de la aplicación utilizando POOL de conexiones<br />
 &#8211;&gt;<br />
 &lt;persistence-unit name=&#8221;fduPersistenceUnit&#8221;<br />
  transaction-type=&#8221;RESOURCE_LOCAL&#8221;&gt;<br />
  &lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;<br />
  &lt;jta-data-source&gt;java:comp/env/jdbc/fdu&lt;/jta-data-source&gt;<br />
  &lt;class&gt;com.viavansi.fdu.persistencia.VO.UsuarioVO&lt;/class&gt;<br />
  &lt;class&gt;com.viavansi.fdu.persistencia.VO.MiembroVO&lt;/class&gt;<br />
  &lt;class&gt;com.viavansi.fdu.persistencia.VO.RolVO&lt;/class&gt;<br />
  &lt;class&gt;com.viavansi.fdu.persistencia.VO.ProcessInfoVO&lt;/class&gt;<br />
  &lt;properties&gt;<br />
  &lt;property name=&#8221;hibernate.show_sql&#8221; value=&#8221;true&#8221; /&gt;<br />
  &lt;property name=&#8221;hibernate.dialect&#8221; value=&#8221;org.hibernate.dialect.SQLServerDialect&#8221; /&gt;<br />
  &lt;property name=&#8221;hibernate.cache.provider_class&#8221; value=&#8221;org.hibernate.cache.EhCacheProvider&#8221; /&gt;<br />
  &lt;!&#8211;<br />
  Configuración para el soporte de prefijos en Hibernate. Estrategia<br />
  para generación de nombres de tablas asociadas a anotaciones Table<br />
  EJB3.0.<br />
  &#8211;&gt;<br />
  &lt;property name=&#8221;hibernate.ejb.naming_strategy&#8221;<br />
  value=&#8221;com.viavansi.framework.persistencia.jpa.NamingStrategy&#8221; /&gt;<br />
  &lt;property name=&#8221;hibernate.search.default.directory_provider&#8221;<br />
  value=&#8221;org.hibernate.search.store.FSDirectoryProvider&#8221; /&gt;<br />
  &lt;property name=&#8221;hibernate.search.default.indexBase&#8221;<br />
  value=&#8221;/Java/lucene/fdu/app&#8221; /&gt;<br />
  &lt;/properties&gt;<br />
 &lt;/persistence-unit&gt; &lt;/persistence&gt;<br />
</code></p>
<p><strong>Finalmente nuestro DAO el cual tiene anotaciones de JPA y Hibernate Search/Lucene</strong></p>
<p><code><br />
package com.viavansi.fdu.persistencia.VO;</code><code>import java.io.Serializable;<br />
import java.util.Date;</p>
<p>import javax.persistence.Column;<br />
import javax.persistence.Entity;<br />
import javax.persistence.GeneratedValue;<br />
import javax.persistence.GenerationType;<br />
import javax.persistence.Id;<br />
import javax.persistence.NamedQueries;<br />
import javax.persistence.NamedQuery;<br />
import javax.persistence.Table;<br />
import javax.persistence.Temporal;<br />
import javax.persistence.TemporalType;</p>
<p>import org.hibernate.search.annotations.Analyzer;<br />
import org.hibernate.search.annotations.DateBridge;<br />
import org.hibernate.search.annotations.DocumentId;<br />
import org.hibernate.search.annotations.Field;<br />
import org.hibernate.search.annotations.Index;<br />
import org.hibernate.search.annotations.Indexed;<br />
import org.hibernate.search.annotations.Resolution;<br />
import org.hibernate.search.annotations.Store;</p>
<p>import com.viavansi.fdu.persistencia.DAO.ISOLatin1Analyzer;</p>
<p>/**<br />
 * @author gmedina<br />
 *<br />
 */<br />
@NamedQueries( {<br />
  @NamedQuery(name = "ProcessInfoVO.findByProcessName", query = "from ProcessInfoVO processInfo where processInfo.processName = ?"),<br />
  @NamedQuery(name = "ProcessInfoVO.findByJbpmName", query = "from ProcessInfoVO processInfo where processInfo.jbpmName = ?"),<br />
  @NamedQuery(name = "ProcessInfoVO.findByArea", query = "from ProcessInfoVO processInfo where processInfo.area = ?") })<br />
@Indexed<br />
@Analyzer(impl = ISOLatin1Analyzer.class)<br />
@Entity<br />
@Table(name = "`${PREFIX_FDU}PROCESS_INFO`")<br />
public class ProcessInfoVO implements Serializable {</p>
<p>private static final long serialVersionUID = 1570433106072090149L;</p>
<p>private Long id;<br />
 private String processName;<br />
 private String jbpmName;<br />
 private Date startDate;<br />
 private Date dueDate;<br />
 private boolean active;<br />
 private String area;</p>
<p>/**<br />
  * @return the id<br />
  */<br />
 @Id<br />
 @DocumentId<br />
 @GeneratedValue(strategy = GenerationType.IDENTITY)<br />
 public Long getId() {<br />
  return id;<br />
 }</p>
<p>/**<br />
  * @param id<br />
  * the id to set<br />
  */<br />
 public void setId(Long id) {<br />
  this.id = id;<br />
 }</p>
<p>/**<br />
  * @return the processName<br />
  */<br />
 @Field(index = Index.TOKENIZED, store = Store.NO)<br />
 @Column(name = "PROCESS_NAME", unique = true, nullable = false, insertable = true, updatable = true, length = 255)<br />
 public String getProcessName() {<br />
  return processName;<br />
 }</p>
<p>/**<br />
  * @param processName<br />
  * the processName to set<br />
  */<br />
 public void setProcessName(String processName) {<br />
  this.processName = processName;<br />
 }</p>
<p>/**<br />
  * @return the jbpmName<br />
  */<br />
 @Field(index = Index.TOKENIZED, store = Store.NO)<br />
 @Column(name = "JBPM_NAME", unique = true, nullable = false, insertable = true, updatable = true, length = 255)<br />
 public String getJbpmName() {<br />
  return jbpmName;<br />
 }</p>
<p>/**<br />
  * @param jbpmName<br />
  * the jbpmName to set<br />
  */<br />
 public void setJbpmName(String jbpmName) {<br />
  this.jbpmName = jbpmName;<br />
 }</p>
<p>/**<br />
  * @return the startDate<br />
  */<br />
 @Field(index = Index.UN_TOKENIZED)<br />
 @DateBridge(resolution = Resolution.DAY)<br />
 @Temporal(TemporalType.DATE)<br />
 @Column(name = "START_DATE", unique = false, nullable = true, insertable = true, updatable = true)<br />
 public Date getStartDate() {<br />
  return startDate;<br />
 }</p>
<p>/**<br />
  * @param startDate<br />
  * the startDate to set<br />
  */<br />
 public void setStartDate(Date startDate) {<br />
  this.startDate = startDate;<br />
 }</p>
<p>/**<br />
  * @return the dueDate<br />
  */<br />
 @Field(index = Index.UN_TOKENIZED)<br />
 @DateBridge(resolution = Resolution.DAY)<br />
 @Temporal(TemporalType.DATE)<br />
 @Column(name = "DUE_DATE", unique = false, nullable = true, insertable = true, updatable = true)<br />
 public Date getDueDate() {<br />
  return dueDate;<br />
 }</p>
<p>/**<br />
  * @param dueDate<br />
  * the dueDate to set<br />
  */<br />
 public void setDueDate(Date dueDate) {<br />
  this.dueDate = dueDate;<br />
 }</p>
<p>/**<br />
  * @return the active<br />
  */<br />
 @Column(name = "ACTIVE", unique = false, nullable = false, insertable = true, updatable = true)<br />
 public boolean isActive() {<br />
  return active;<br />
 }</p>
<p>/**<br />
  * @param active<br />
  * the active to set<br />
  */<br />
 public void setActive(boolean active) {<br />
  this.active = active;<br />
 }</p>
<p>/**<br />
  * @return the area<br />
  */<br />
 @Field(index = Index.TOKENIZED, store = Store.NO)<br />
 @Column(name = "AREA", unique = false, nullable = false, insertable = true, updatable = true, length = 100)<br />
 public String getArea() {<br />
  return area;<br />
 }</p>
<p>/**<br />
  * @param area<br />
  * the area to set<br />
  */<br />
 public void setArea(String area) {<br />
  this.area = area;<br />
 }</p>
<p>/*<br />
  * (non-Javadoc)<br />
  *<br />
  * @see java.lang.Object#hashCode()<br />
  */<br />
 @Override<br />
 public int hashCode() {<br />
  final int prime = 31;<br />
  int result = 1;<br />
  result = prime * result + ((id == null) ? 0 : id.hashCode());<br />
  return result;<br />
 }</p>
<p>/*<br />
  * (non-Javadoc)<br />
  *<br />
  * @see java.lang.Object#equals(java.lang.Object)<br />
  */<br />
 @Override<br />
 public boolean equals(Object obj) {<br />
  if (this == obj) {<br />
  return true;<br />
  }<br />
  if (obj == null || !(obj instanceof ProcessInfoVO)) {<br />
  return false;<br />
  }<br />
  ProcessInfoVO other = (ProcessInfoVO) obj;<br />
  if (id == null) {<br />
  if (other.id != null) {<br />
  return false;<br />
  }<br />
  } else if (!id.equals(other.id)) {<br />
  return false;<br />
  }<br />
  return true;<br />
 }</p>
<p>}</p>
<p></code><strong>Nota: Lucene necesita construir un indice inicial, les pegaré un pedazo de código de como hacer esto:</strong></p>
<p><code><br />
@SuppressWarnings("unchecked")<br />
 public void reIndexLuceneDB() {<br />
  FullTextEntityManager fullTextEntityManager = Search<br />
  .createFullTextEntityManager(entityManager);<br />
  Class[] entityClasses = { UsuarioVO.class, RolVO.class,<br />
  ProcessInfoVO.class };<br />
  for (Class entityClass : entityClasses) {<br />
  for (Object object : entityManager.createQuery(<br />
  "select obj from " + entityClass.getName() + " obj")<br />
  .getResultList()) {<br />
  fullTextEntityManager.index(object);<br />
  }<br />
  }<br />
 }<br />
</code></p>
<p><strong>Bueno, he pegado tanto código que explicarlo todo en un solo post es difícil, asi que manden sus preguntas.</strong></p>
<p><strong>Que lo disfruten.</strong></p>
<p><strong>Guido.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/355-arroz-con-mango-seam-logger-finder-interceptor-lucene/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
