Categoría: javahispano

Hudson: Nuestro compañero

18 jul 2010

Os dejamos las estadísticas de uso de nuestra herramienta de integración continua preferida!
Hace más de 2 años que usamos Hudson como herramienta en todos nuestros proyectos de desarrollo, y en poco tiempo pasó a convertirse en un pilar central de nuestro entorno de desarrollo.

Tras estos dos años, estos son los datos:

Proyectos gestionados (Jobs configurados) 192
Proyectos en Activo: 52 *(usados en los últimos 20 días)
Numero total de compilaciones realizadas 6442
Despliegues automáticos al servidor de desarrollo 4127 (sobre nuestros 5 entornos)
Media de operaciones diarias: 12

La instalación es la por defecto sobre Linux, junto a un Slave que utilizamos puntualmente para las test sobre Windows.

Respecto a los plugins, aunque le hemos dado una oportunidad a practicamente todos, estos son los más utilizados:

  • SVNCopyPlugin (Plugin desarrollado internamente por Viavansi para la sincronización con el SVN del cliente tras despliegues exitosos)
  • Hudson SCP Publisher Plugin (desarrollado internamente para publicar en nuestro sistema de descargas )
  • ChuckNorris Plugin
  • SubversionTaggin Plugin
  • Disk Usage Plugin
  • Seleniumhq Plugin
  • Sonar Plugin
  • Dependency Analyzer
  • Backup Plugin
  • Deploy Plugin
  • SCP Plugin
  • Jabber Plugin

Algunos artículos relacionados:

Introducción a Hudson: http://www.xnoccio.com/362-hudson-parte-1-introduccion/
Introducción al desarrollo de Plugins: http://www.xnoccio.com/464-hudson-parte-2-crea-tus-propios-plugins/
Comparatíva: http://www.xnoccio.com/368-eligiendo-nuestro-entorno-de-integracion-continua-i/
y conclusiones http://www.xnoccio.com/372-conclusiones-finales-eligiendo-nuestro-entorno-de-integracion-continua-v/

Android y mi certificado digital

30 jun 2010

La nueva versión de Viafirma 3.0, proporciona como principal novedad el soporte para autenticación y firma digital desde dispositivos móviles como Android, iPhone o iPad.
De esta forma Viafirma se convierte en la primera plataforma de autenticación y firma digital con soporte completo para Android, iPhone o iPad.
A continuación vamos a mostraros un ejemplo de autenticación digital utilizando Viafirma desde Android.

En los próximos días iremos ofreciendo ejemplos de autenticación y firma desde los diferentes dispositivos móviles ya soportados.

¿Qué implica esto?

Pues que las entidades que opten por utilizar Viafirma podrán ofrecer servicios de autenticación y firma digital a sus usuarios móviles. Imagina por ejemplo acceder a tu banco mediante autenticación digital desde tu Android!

¿Cuándo estará disponible?

Ya está disponible para clientes corporativos y en unos días estará disponible en el Google Market de forma gratuita.

13-07-10

Disponibles ya los clientes para iPad y iPhone.

http://www.xnoccio.com/1247-firma-digital-movil-en-ipad_iphone_firma_electronica/

Plataforma de autenticación y firma digital sobre WebLogic

18 jun 2010

La nueva versión de Viafirma, coincidiendo con su instalación en dos importantes entidades bancarias,  ofrece soporte oficial para Oracle WebLogic 11. De esta forma, junto con las plataformas ya soportadas por Viafirma (Tomcat 5, Tomcat 6, Websphere, etc…), ahora se incluye:

El proceso de instalación es muy sencillo,  por lo que siguiendo los pasos del manual de instalación de Viafirma para Weblogic podremos disponer de sus servicios de autenticación (DNIe o cualquier otro certificado digital) y firma digital (XAdES, PAdES, CMS, CAdES, facturae, firma en lotes,…) desplegados sobre Weblogic .

UsernameToken en Jax-ws (1/2)

04 jun 2010

El objetivo de este artículo es mostrar como usar UsernameToken según la especificación Web Services Security UsernameToken Profile 1.0. El artículo consiera que el lector ya tiene experiencia en Jax-ws y se centra sólo en la configuración del mecanismo de seguridad para publicar y consumir servicios que requieran la identificación del solicitante con usuario y password haciendo uso de Jax-ws.

Dependencias requeridas

Aunque las dependencias necesarias están incluidas en algunos servidores de aplicaciones, si lo deseamos podemos o bien bajar la implementación de referencia directamente desde su web:

https://jax-ws-commons.dev.java.net y https://jax-ws.dev.java.net

O definir la dependencia en caso de que el proyecto sea Maven.

Definir  un nuevo manejador JAX-WS

En primer lugar indicaremos sobre la clase que implementa el WS el handlerchain.xml que define el manejador de seguridad  mediante la anotación @HandlerChain.


@HandlerChain(file = "handlerchain.xml")
@WebService(serviceName = "IcmsWSAPIService", targetNamespace = "http://www.juntadeandalucia.es/icms", name = "IcmsWSAPIClient", portName = "IcmsWSAPIPort", endpointInterface = "es.juntadeandalucia.icms.IcmsPublisherClient")
public class IcmsPublisherWSImpl implements IcmsPublisher {..}

A continuación indicaremos en el fichero handlerchain.xml el nombre de la clase que implementa en manejador de seguridad.

Implementar un manejador para WSS

Se necesitará una clase que implemente SOAPHandler que haciendo uso de XWSSProcessor se encargue de procesar los mensajes SOAP con los header WSSE. Un ejemplo de esta clase podría ser:


/**
* Web Services Security UsernameToken Profile 1.0
*
*/
public class SecurityHandler implements SOAPHandler<SOAPMessageContext> {

XWSSProcessor securityProcessor = null;

/**
* Build the Security Handler
*/
public SecurityHandler() {

try {
// Creamos el procesador SOAP para WSS
final InputStream input = this.getClass().getResourceAsStream("/user-pass-authenticate-server.xml");
final XWSSProcessorFactory factory = XWSSProcessorFactory.newInstance();
securityProcessor = factory.createProcessorForSecurityConfiguration(input, new SecurityEnvironmentHandler());
input.close();
} catch (final Exception e) {
logger.error("No se puede inicializar El Handler", e);
}

}

/**
*  Recuperamos el bloque header.
*/
public Set<QName> getHeaders() {
final QName securityHeader = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-   secext-1.0.xsd", "Security", "wsse");
final HashSet<QName> headers = new HashSet<QName>();
headers.add(securityHeader);
return headers;
}

public boolean handleFault(final SOAPMessageContext messageContext) {
return true;
}

public boolean handleMessage(final SOAPMessageContext messageContext) {
final SOAPMessage message = messageContext.getMessage();

try {
// Contexto WSS
final ProcessingContext context = securityProcessor.createProcessingContext(message);
context.setSOAPMessage(message);
SOAPMessage verifiedMsg = null;
verifiedMsg = securityProcessor.verifyInboundMessage(context);

// Obtenemos el usuario y pass indicado en la request
String username = null;
String pass = null;
final Subject subject = SubjectAccessor.getRequesterSubject(context);

final Set<Principal> principals = subject.getPrincipals();
if (!principals.isEmpty()) {
final Principal principal = principals.iterator().next();
// Obtenemos en CN: CN=userName
username = StringUtils.substringAfterLast(principal.getName(), "=");
}
final Set<Object> publicCredentials = subject.getPublicCredentials();
if (!publicCredentials.isEmpty()) {
pass = (String) publicCredentials.iterator().next();
}

// Verificamos el comportamiento user y pass
validateUser(username, pass);

messageContext.setMessage(verifiedMsg);
} catch (final XWSSecurityException e) {
logger.error("WSS validation problem. ", e);
throw SecurableSoapMessage.newSOAPFaultException("WS validation problem.", e);
}

return true;
}

/** Validación específica de la aplicación.
* @param username
* @param pass
* @throws XWSSecurityException
*/
private void validateUser(final String username, final String pass) throws XWSSecurityException {
// Verificación específica de la aplicación.
//throw new XWSSecurityException("Invalid user." + username);

}

public void close(final MessageContext messageContext) {
}

private static Logger logger = Logger.getLogger(SecurityHandler.class);

}

Esta clase será la encargada de procesar todos los mensajes, verificando que todos son válidos y contienen un usuario y pass correcto. Un ejemplo de un mensaje válido WSS sería:


<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"       S:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="XWSSGID-1255949753848350309586">
<wsse:Username>usuario</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">****</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">9w+YwOatF9l1/otioQ75d5Yr</wsse:Nonce>
<wsu:Created>2009-10-19T10:55:54.418Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</S:Header>
<S:Body>
<ns2:ping xmlns:ns2="http://www.juntadeandalucia.es/icms" xmlns:ns3="http://www.juntadeandalucia.es/icms/data">
<ns2:request>test</ns2:request>
</ns2:ping>
</S:Body>
</S:Envelope>

Próximamente cómo crear un cliente Jax-ws que consuma servicios securizados con   UsernameToken.

Creando una aplicación web basada en OSGI con Eclipse

29 abr 2010

A continuación se describen los pasos básicos a dar para crear una aplicación web  que en lugar de ser desplegada sobre la típica pila JEE, sea desplegada como un componente más dentro de un contenedor OSGi.

Jee tradicional vs OSGi

Para ello se mostrará como construir con Eclipse un bundle OSGi que haciendo uso de Jetty nos permita correr un servlet sobre Equinox.

  • Crear el proyecto base

En primer lugar, necesitaremos crear un plugin, indicando que es de tipo OSGI (implementación Equinox).

Crear un proyecto OSGi en Eclipse

  • Definición de las dependencias

Una vez que tengamos el proyecto creado, necesitaremos declarar las dependencias que necesitará nuestro módulo para poder funcionar como un servidor de aplicaciones. Las dependencias serán como mínimo:

  • javax.servlet
  • org.eclipse.equinox.http.jetty
  • org.eclipse.equinox.http.servlet
  • org.mortbay.jetty.server
  • org.eclipse.equinox.http.registry

Dependencias Eclipse OSGI Jetty

  • Construcción del servlet de ejemplo

Una vez tengamos declaradas los módulos dependientes, Eclipse se encarga de actualizar nuestro classpath y ya podremos programar nuestro primer servlet sin problemas de compilación.

/** * Osgi Example Servlet. * */
public class HolaMundoOsgiServlet extends HttpServlet{
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Petición al Servlet OSGi");
 	resp.getWriter().append("Respuesta desde un Servlet Osgi");
 }}

Como podemos ver, se trata de un servlet normal, que debería ser mapeado en el web.xml y desplegado dentro de un contenedor de servlets.

  • Activación del servlet

A diferencia del modelo tradicional (definido por la especificación JEE), la activación del servlet no requiere ningún web.xml. En su lugar, definiremos (al igual que cualquier otro servicio OSGI) un nuevo punto de extensión de nuestra aplicación. Para ello accederemos a la pestaña “Extension” y añadiremos la extensión “org.eclipse.equinox.http.registry.servlet” a nuestro módulo. Con esto le hemos indicado a OSGi que nuestro módulo hace uso del contenedor de Servlet.

Añadir extension point para definir un servicio de tipo servlet

El siguiente paso será indicar la clase que implementa el nuevo servlet y el mapeo, para ello simplemente definiremos la propiedad alias y class del nuevo servlet asociado a la extensión creada previamente.

Configurar extensiones OSGi

Con esto ya tenemos nuestra primera aplicación web OSGi.

  • Probando nuestra aplicación.

Para probar la aplicación sólo es necesario ejecutar el proyecto (Run As…>OSGi Framework) y acceder con el navegador a http://localhost:8080/exampleSi todo ha funcionado correctamente, en consola deberemos ver algo como lo siguiente:

Persistence bundle started.
Activado módulo OSGi: Ejemplo OSGI!!
Activado Servlet OSGiProviderTracker: New service detected...
ProviderTracker: Added service org.eclipse.persistence.jpa.osgi.PersistenceProviderOSGi
Petición al Servlet OSGi

Aunque aquí sólo se muestra un ejemplo muy básico, OSGI ya nos ha demostrado ser de mucha utilidad en proyectos reales muy complejos.

Por fin un estándar con el que entretejer nuestras aplicaciones.

25 oct 2009

Recientemente se ha liberado la primera versión estable de Weld, la implementación de referencia de Web Beans (Java Context and Dependenty Injection - JSR 299). Y aunque puede parecer una liberación cualquiera, en este caso estamos ante un evento realmente importante para el mundillo Java.

¿Por qué es importante esta liberación?

  • Por fin tenemos un estándar Java para la inyección, publicación, localización y búsqueda de componentes.
  • Promete una mejor orquestación entre componentes JEE, evitando los típicos problemas de interoperabilidad entre Beans Spring, componentes Seam, Wicket, JSF, EL, etc..)
  • Un remplazo estándar a las diferentes soluciones de inyección e IoC como Spring IoC, el prometedor Google Guice o el muy utilizado por nosotros Jboss Seam annotations.
  • Fin del infierno XML, definiendo un mecanismo estándar independiente de ficheros de definición XML, que junto con JSF 2.0, Servlet 3.0, JPA, Jax-ws, etc… simplifican el desarrollo JEE.

¿Consecuencias para la industria a medio plazo?

  • Es demasiado pronto para saberlo, pero…
    ¿Quizás el fin de la guerra de frameworks se inyección?…. (Google Guice vs Spring vs Jboss Seam). Consiguiendo un efecto similar al que consiguió JPA/JDO estandarizando el acceso a datos.
  • Por fin una especificación JEE con la que construir aplicaciones complejas de forma sencilla.
  • En un momento en el que muchas organizaciones están intentando estandarizar sus desarrollos, llegando incluso a restringir o imponer las tecnologías utilizadas, la preselección de implementaciones como Spring IoC o Seam carecerá de sentido. Siendo mucho más coherente la recomendación de estándares en lugar de restringir la evolución natural de la tecnología y la sana competición entre sus diferentes implementaciones.

¿Consecuencia para nosotros?

  • Ninguna…. Gracias a nuestra apuesta por Jboss Seam (desde hace ya unos años), esta especificación se encontraba ya en nuestra hoja de ruta antes incluso de que fuese un Draft, por lo que para nosotros será suficiente con una mínima adaptación al estándar.
  • La implementación es estable, la especificación muy bien pensada, y en las pruebas que hemos realizado con la beta, ha demostrado que consigue simplificar los desarrollos y hacer más comprensible el “oscuro arte de la inyección de componentes”.
  • En breve empezaremos a usarla en algún proyecto piloto (que pueda asumir el riesgo de I+D asociado), analizaremos en detalle los posibles problemas que puedan surgir, y si todo se comporta como promete a mediados de 2010 empezaremos a usar la nueva especificación en nuestros proyectos Java.

¿Defectos?

  • Llega demasiado tarde. Otros frameworks llevan, aunque de una forma mucho menos limpia,  ofreciendo algo similar desde hace ya mucho tiempo.
  • Todavía no conocemos sus defectos. Y eso es un gran problema ya que hasta que no conozcamos sus problemáticas asociadas no será seguro su uso en proyectos de envergadura.
  • Esperemos que en la huida del infierno de los ficheros de configuración XML, no nos metamos en  las tinieblas del uso de inyección e IoC para todo. Ya que una aplicación con una gran cantidad de componentes, comportamientos o atributos que dependen de la inyección hace muy complicada la comprensión de su funcionamiento.

En definitiva, todo indica que estamos antes una de las piezas clave del próximo JEE 6.

Guía de migración de proyectos Java a Maven

16 oct 2009

Objetivos

El objetivo de este artículo es servir de guía básica para la migración manual de proyectos Java no Maven a entorno Maven. Pensado y dirigido especialmente a personas con poca  experiencia previa en Maven, pero con algún conocimiento previo.

Preparación del proyecto

Como es obvio, para migrar un proyecto Java a Maven, deberemos disponer de sus fuentes y todas las librerías dependientes.

Ya que vamos a realizar modificación estructurales importantes en el proyecto, conviene asegurarnos de que los fuentes no están conectados a ningún sistema de control de versiones como Subversion. Para realizar esto, podemos o bien eliminar manualmente todos los directorios .svn de nuestro proyecto o bien desde Eclipse desconectar el proyecto.

Si lo vamos a realizar de forma manual, debemos asegurarnos de eliminar todos los directorios .svn (o .CVS si el proyecto a migrar estuviese conectado a un CVS) A modo de ejemplo, en Linux podemos ejecutar el siguiente comando desde el directorio del proyecto para eliminar todas las referencias a carpetas ‘.svn’:

 

rm -rf `find . -type d -name .svn`

Será mucho más sencillo hacerlo de forma automática desde Eclipse. Para desconectar el proyecto, teniéndolo seleccionado pulsaremos sobre el botón derecho del ratón: Team -> Disconnect.

Desconectar SVN desde Eclipse

Adaptación del proyecto

Aunque la estructura por defecto Maven puede ser modificada, es muy recomendable adaptar la organización del proyecto a migrar a la estructura por defecto más generalizada:

estructura Maven

Para hacer esta modificación de la estructura hay que tener especial cuidado en algunos aspecto o convenciones Maven:

  • Los ficheros de recursos: Maven hace una distinción entre los ficheros de clases java y los ficheros de recursos .properties y XML’s y, de hecho, salvo que le digamos lo contrario, no hará ningún tratamiento de los ficheros no java que se encuentren en el directorio src/main/java. Por este motivo, tendremos que localizar todos los ficheros de recursos (properties, XML’s) que se encuentran en el directorio java y moverlos al directorio resources (src/main/resources).
  • Eliminar la carpeta classes. Es muy común que proyectos no Maven tengan en su carpeta WEB-INF/classes los compilados del proyecto. Esta situación no sólo no es recomendable sino que puede producir problemas, por lo que los eliminaremos confiando en Maven para su generación cuando sea necesario.

Definir el pom.xml del proyecto

Una vez que la estructura del proyecto se ha adaptado a la filosofía Maven, el siguiente paso es definir el pom.xml del proyecto.

Partiremos de un fichero pom.xml básico. Este fichero de origen no tiene dependencias; durante el proceso lo adaptaremos y posteriormente iremos refinando la configuración hasta alcanzar una “mavenización” completa del proyecto.

Una vez colocado el pom.xml en el raíz de la aplicación, lo modificamos indicando el nombre del proyecto y la información básica relativa a los desarrolladores, organización y repositorio de dependencias utilizado.

Antes de continuar y añadir las dependencias, podemos hacer una comprobación previa y verificar que efectivamente nuestro IDE, en este caso Eclipse, reconoce correctamente la nueva estructura del proyecto.

Para ello nos vamos a la consola y en el directorio en el que se encuentra nuestro proyecto ejecutamos la siguiente orden:

mvn clean eclipse:eclipse

(Requiere disponer de Maven correctamente instalado en la máquina).

Si la configuración del entorno es correcta, obtendremos una salida similar a esta:

 

[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'eclipse'.
[INFO] ------------------------------------------------------------------------
[INFO] Building ejemplo
[INFO]    task-segment: [clean, eclipse:eclipse]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean]
[INFO] Deleting file set: /home/felix/workspaces/ejemplo/target (included: [**], excluded: [])
[INFO] Preparing eclipse:eclipse
[INFO] No goals needed for project - skipping
[INFO] [eclipse:eclipse]
[INFO] Adding support for WTP version 1.5.
[INFO] Using source status cache: /home/felix/workspaces/ejemplo/target/mvn-eclipse-cache.properties
[INFO] File /home/felix/workspaces/ejemplo/.project already exists.
       Additional settings will be preserved, run mvn eclipse:clean if you want old settings to be removed.
[INFO] Wrote Eclipse project for "ejemplo" to /home/felix/workspaces/ejemplo.
[INFO]
       Sources for some artifacts are not available.
       Please run the same goal with the -DdownloadSources=true parameter in order to check remote repositories for sources.
       List of artifacts without a source archive:
         o javax.servlet:servlet-api:2.4
         o javax.servlet.jsp:jsp-api:2.1
         o junit:junit:3.8.1

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Wed Sep 3 11:54:28 CET 2008
[INFO] Final Memory: 10M/80M
[INFO] ------------------------------------------------------------------------

Nos vamos a Eclipse, refrescamos el proyecto (F5 teniendo seleccionado el proyecto) y comprobamos que la nueva estructura es correcta.

Ahora que hemos comprobado que eclipse ha reconocido la nueva estructura, el siguiente paso es definir en nuestro pom.xml las dependencias. Para hacer esto eliminamos todos los .jar que se encuentran en el directorio /WEB-INF/lib y nos quedamos con una copia de ellos para posteriormente ir resolviendo las dependencias del proyecto original. Una recomendación es cortar la carpeta /WEB-INF/lib a otra ruta de nuestro disco.

Resolución de dependencias

Esta es la fase más delicada del proceso, ya que debemos asegurarnos de que todas las dependencias del proyecto quedan correctamente declaradas en el fichero pom.xml. Para realizar esta tarea es recomendadle utilizar alguna aplicación web que nos ayude a la localización de las librerías, como por ejemplo MvnRepository o MvnBrowser (recomendada), en la que podremos buscar cada uno de nuestros jar y encontrar la definición en el pom.xml que debemos utilizar.

Migración de proyectos maven con mvnBrowser

Gracias a esta web, una vez que tengamos localizada la dependencia, solo tendremos que copiar el bloque POM Dependency a nuestro fichero pom.xml.

Iremos repitiendo este proceso de forma iterativa para todos nuestras librerías .jar y añadiendo la definición de la dependencia a nuestra zona de dependencies, con ciertas salvedades y consideraciones que introducimos a continuación.

Consideraciones especiales

Hay ocasiones en las que determinar la definición de la dependencia en nuestro pom.xml puede no ser una tarea trivial. Se comentan a continuación los mecanismos de actuación recomendados según diversas casuísticas:

  • No se indica la versión de la librería en el nombre del fichero.

Por ejemplo, podemos encontrarnos una librería llamada axis-ant.jar, por lo que tendremos que averiguar previamente la versión de la librería de cara a definir la dependencia en el fichero pom.xml. Para esto suele ser muy efectivo descomprimir la librería y consultar el fichero /META-INF/MANIFEST.MF. A modo de ejemplo, en dicha librería mencionada observaríamos una linea similar a la siguiente: “Implementation-Version: 1.2.1 2243 June 14 2005″. Una vez que conozcamos la versión podremos realizar la búsqueda de la forma usual. , 1.1.1.1. Sabemos que la librería fue generada por maven, pero no conocemos su definición.

No conocemos el groupId, artifactId, etc. Podemos descomprimir el .jar y acceder al fichero pom.xml que se encuentra en /META-INF/maven para comprobar el groupId, artifactId y versión de la dependencia.

  • Dependencias especiales JEE.

Algunos jars, como por ejemplo servlet.jar, son aportados por el contenedor de aplicaciones, por lo que tendremos que definirlas marcándolas como provided. Esto le indica a Maven que estas librerías pueden ser utilizadas en tiempo de compilación, pero no serán agregadas al empaquetado final. Para declarar una dependencia de esta forma incorporaremos en nuestro pom.xml un código como este:

 

<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.4</version>
      <scope>provided</scope>
</dependency>
  • Librerías ya consideradas en las dependencias transitivas

Muchas de las dependencias dependen a su vez de otras librerías, por lo que Maven añadirá de forma transitiva nuevas librerías a nuestro proyecto. En estos casos no necesitamos definir estas nuevas dependencias transitivas en nuestro pom.xml. Como ejemplo, supongamos que un proyecto depende de estas librerías:

  • xalan-2-6.0.jar
  • xercesImpl
  • xml-apis

Al buscar la librería xalan-2-6.0.jar, observamos que la librería depende a su vez de las otras dos librerías. Por ello, para este ejemplo bastaría con declarar la dependencia a xalan-2-6.0.jar en nuestro pom.xml. Dependencias transitivas.

  • Conflictos entre librerías

En ocasiones nos podemos encontrar con que dos librerías tengan en sus dependencias a una misma tercera librería, pero de distinta versión. Ello haría que maven incluyese en nuestro Classpath 2 versiones de una misma librería, originando conflictos por duplicado de clases. En ese caso debe declararse en la dependencia de una de ellas una directiva para excluir la descarga de la librería conflictiva.

Por ejemplo, en un proyecto deseamos utilizar la librería siguiente:

 

<artifactId>jaxws-api</artifactId>
<groupId>javax.xml.ws</groupId>
<version>2.1-1</version>

Y tenemos dependencia a com.sun.xml.ws / jaxws-rt, esta librería se trae como dependencia transitiva otra versión de la librería mencionada anteriormente. Declaramos una exclusión para evitarlo:

 

<dependency>
  <groupId>com.sun.xml.ws</groupId>
  <artifactId>jaxws-rt</artifactId>
  <version>2.1.4</version>
  <exclusions>
    <exclusion>
      <artifactId>jaxws-api</artifactId>
      <groupId>javax.xml.ws</groupId>
    </exclusion>
  </exclusions>
</dependency>
  • Tenemos una librería que se encuentra en los repositorios, pero no hemos podido averiguar el número de versión.

En esta situación, si la librería no parece problemática, podríamos optar por elegir la última versión de la dependencia. En el caso de que consideremos que la versión que utiliza el proyecto puede originar problemas, lo mejor es añadir esta librería manualmente a nuestro repositorio (como si fuese una librería específica del proyecto), según se explica en el próximo punto.

  • La librería es específica del proyecto.

En estos casos tendremos que subir la dependencia a nuestro repositorio de librerías y, para evitar conflictos posteriores, se recomienda que sea subida con el mismo groupId de nuestro proyecto. Supongamos que migrando un proyecto nos topamos con librería example1.jar que no se encuentra en ningún repositorio público. En este caso la subimos a nuestro repositorio por ejemplo con la siguiente definición:

 

<dependency>
    <groupId>com.viavansi.examples</groupId>
    <artifactId>example1</artifactId>
    <version>0.0.1</version>
</dependency>

En la siguiente figura vemos cómo desplegamos una librería a Artifactory:

Artifactory

Comprobación de dependencias

Una vez que hayamos finalizado este proceso de definición de todas las dependencias en nuestro pom.xml, ejecutaremos en consola mvn dependency:tree (situados en el directorio donde se encuentre el fichero pom.xml del proyecto) para comprobar que las dependencias que se han incorporado al proyecto son las correctas. Este paso de verificación es muy importante en las migraciones de este tipo de proyectos, ya que es muy posible que alguna dependencia transitiva genere problemas. Como ejemplo, podemos observar la siguiente salida en la que comprobamos que no hay dependencias transitivas que entren en conflicto con alguna de nuestras librerías:

 

[INFO] [dependency:tree]
[INFO] com.viavansi.examples.examples1:war:0.0.1
[INFO] +- junit:junit:jar:3.8.1:test
[INFO] +- javax.servlet.jsp:jsp-api:jar:2.1:provided
[INFO] +- javax.servlet:servlet-api:jar:2.4:provided (scope not updated to compile)
[INFO] +- javax.activation:activation:jar:1.1:compile
[INFO] +- avalon-framework:avalon-framework-impl:jar:4.1.5:compile
[INFO] +- axis:axis-ant:jar:1.2.1:compile
[INFO] +- axis:axis:jar:1.2.1:compile
[INFO] +- javax.mail:mail:jar:1.3.1:compile
[INFO] +- commons-beanutils:commons-beanutils:jar:1.6:compile
[INFO] +- commons-codec:commons-codec:jar:1.3:compile
[INFO] +- commons-collections:commons-collections:jar:3.2:compile
[INFO] +- commons-dbcp:commons-dbcp:jar:1.2.2:compile
[INFO] +- commons-digester:commons-digester:jar:1.6:compile
[INFO] |  - xml-apis:xml-apis:jar:1.0.b2:compile
[INFO] +- commons-discovery:commons-discovery:jar:0.2:compile
[INFO] +- commons-httpclient:commons-httpclient:jar:3.1:compile
[INFO] +- commons-io:commons-io:jar:1.3.1:compile
[INFO] +- commons-lang:commons-lang:jar:2.2:compile
[INFO] +- commons-logging:commons-logging:jar:1.1:compile
[INFO] |  +- logkit:logkit:jar:1.0.1:compile
[INFO] |  - avalon-framework:avalon-framework:jar:4.1.3:compile
[INFO] +- commons-pool:commons-pool:jar:1.3:compile
[INFO] +- displaytag:displaytag:jar:1.1:compile
[INFO] +- displaytag:displaytag-export-poi:jar:1.1:compile
[INFO] +- dom4j:dom4j:jar:1.6.1:compile
[INFO] +- org.extremecomponents:extremecomponents:jar:1.0.1:compile
[INFO] +- com.lowagie:itext:jar:1.4.8:compile
[INFO] +- oro:oro:jar:2.0.7:compile
[INFO] +- javax.xml:jaxrpc-api:jar:1.1:compile
[INFO] +- javax.servlet:jstl:jar:1.1.2:compile
[INFO] +- log4j:log4j:jar:1.2.8:compile
[INFO] +- com.oracle:ojdbc14:jar:9.0.2.0.0:compile
[INFO] +- poi:poi:jar:2.5.1-final-20040804:compile
[INFO] +- javax.xml.soap:saaj-api:jar:1.2:compile
[INFO] +- org.springframework:spring:jar:2.0.5:compile
[INFO] +- taglibs:standard:jar:1.1.2:compile
[INFO] +- struts:struts:jar:1.2.9:compile
[INFO] |  +- commons-fileupload:commons-fileupload:jar:1.0:compile
[INFO] |  +- commons-validator:commons-validator:jar:1.1.4:compile
[INFO] |  - antlr:antlr:jar:2.7.2:compile
[INFO] +- wsdl4j:wsdl4j:jar:1.5.1:compile
[INFO] +- wss4j:wss4j:jar:1.5.0:compile
[INFO] +- xalan:xalan:jar:2.6.0:compile
[INFO] +- org.apache.xmlgraphics:xmlgraphics-commons:jar:1.2:compile
[INFO] +- xml-security:xmlsec:jar:1.2.1:compile
[INFO] +- org.directwebremoting:dwr:jar:2.0.3:compile
[INFO] +- com.viavansi:plantilla-client:jar:0.0.13:compile
[INFO] +- net.sourceforge.barbecue:barbecue:jar:1.5-beta1:compile

En caso de detectar librerías duplicadas a causa de las dependencias transitivas, deberemos proceder a definir las exclusiones necesarias en las dependencias afectadas, según se indicó anteriormente.

Redmine y Subversion (https): no actualiza las revisiones

22 sep 2009

Hola a todos,

supongo que todos conoceis la fabulosa funcionalidad que tiene Redmine respecto al acceso a un sistema de control de versiones de código fuente, como el caso que nos ocupa: Subversion. Permite consultar las diferentes revisiones, mostrando los distintos comentarios de cada revisión, permite acceder a la estructura en árbol de directorios, etc…

En la situación que os quiero comentar teníamos una instalación de Redmine totalmente funcional, con la conexión a Subversion funcionando a las mil maravillas, vía https. Sin embargo de un día para otro dentro de la pestaña “Repositorio” del proyecto dejamos de ver la estructura de carpetas y ya no se actualizan la información acerca de las sucesivas revisiones que se iban generando en el repositorio, pero sí se veían otras revisiones anteriores.

El primer paso fue mirar en el log de Redmine y se comprobó que se estaba generando un error bastante “inquietante”:

Error parsing svn output: #<REXML::ParseException: No close tag for /lists/list>
…./jruby/lib/ruby/1.8/rexml/parsers/treeparser.rb:27:in `parse’
…./jruby/lib/ruby/1.8/rexml/document.rb:204:in `build’

………………….
………………….

Tras esto, nos conectamos con un cliente subversion y comprobamos que el repositorio estaba totalmente operativo y las revisiones se estaban generando correctamente (incluso con los respectivos comentarios): ¿qué podrá estar pasando? (si quereis ir directo a la solución sólo id al final del post xD)

Como suele ser muy habitual investigamos acerca de la conexión https que se establece con Subversión, ya que en este caso Subversion se sirve vía https. Pues bien, nos dimos cuenta que el certificado del servidor (el que sirve Subversion)  estaba caducado: ¡¡ Eureka !!

Para solucionar esto simplemente actualizamos el certificado del servidor Subversion y volvimos a intentar de nuevo consultar la pestaña Repositorio de Redmine, pero no… sigue el mismo problema, no se actualizan las revisiones.

Tras poner nuestras neuronas a trabajar nos dimos cuenta que no habíamos introducido el nuevo certificado como “confiable” para Redmine… muy bien, pero ¿cómo hacer esto? Para explicar esto voy a comentar cómo Redmine se conecta con Subversion y obtiene toda esa metainformación que muestra (esto lo podemos ver en el código fuente de Subversion.rb correspondiente al adaptador de Subversion que tiene Redmine):

Redmine no hace más que ejecutar la orden “svn –xml list <url_repositorio>” y esto devuelve (o debería) un XML con toda la información, algo tan simple como eso ¿cómo puede dar problemas?

Nos disponemos a ejecutar esa misma orden de forma manual desde la máquina donde tenemos instalado Subversion y ¡sorpresa!: no nos retorna un XML correcto. A continuación, ejecutamos un simple comando de listado “svn list <url_repositorio>” y obtenemos un mensaje de aviso, preguntándonos si deseamos rechazar / aceptar de forma permanente o temporal el certificado de https://servidorSubversion . Por supuesto lo aceptamos de forma permanente (pulsando ‘P’)  y a continuación nos pidela contraseña del usuario logado en el sistema y usuario/contraseña de acceso a Subversion.

A partir de ahí todo debería funcionar, pero no: hay un pequeño detalle más. Debemos repetir el paso anterior ejecutando el comando “svn”con el mismo usuario que hace correr el servicio de Redmine. Parece que el cliente svn tiene un almacen de certificados “confiables” distinto para cada usuario que lo ejecuta.

Una vez hecho todo esto nuestro Redmine se conecta perfectamente con Subversion y obtiene toda la información actualizada.

SOLUCION.- A continuación os resumo la solución con un par de pasos que se deben seguir, espero que os resulten útiles.

  1. Ejecutar por consola el comando “svn list <url_subversion>” en la máquina en que corre Redmine y con el mismo usuario que hace correr el servicio.
  2. En el diálogo que se muestra: aceptar el certificado como confiable de manera permanente (‘P’) e introducir los uusuarios/contraseñas que se solicitan.
  3. Ejecutar por consola el comando “svn –xml list <url_subversion>” y comprobar ahora que sí nos devuelve un XML con todos los metadatos.
  4. Comprobar que Redmine nos muestra ahora los datos correctos.

Versión de Redmine utilizada: Redmine 0.8.0.stable

Personalmente creo que este tipo de “errores” se deberían reportar de forma automática por parte de Redmine (mostrando una información más intuitiva) y es de esperar que en futuras versiones tomen en cuenta todos las numerosas incidencias que podeis ver en el bugtracker del proyecto Redmine respecto a este error.

Un Saludo a todos.
Namaste y buena suerte.

Tips: Mantis en Eclipse (plugin Mylyn-Mantis)

01 jun 2009

Introducción

Mylyn-Mantis es un plugin que permite la integración en Eclipse con repositorios Mantis, de forma que se puede interactuar con un bugtracker Mantis directamente desde nuestro IDE, permitiendo:

  • Crear incidencias
  • Asignar incidencias
  • Añadir comentarios
  • Cambiar de estado incidencias
  • Resolver incidencias
  • Asociar un conjunto de código a una incidencia, a la hora de realizar un commit de código.

Utilización

Una vez que disponemos de un repositorio Mantis, podremos recuperar el conjunto de tareas de un proyecto, planificarlas, asignarlas, resolverlas, incorporar comentarios, asociar código fuente a las mismas…

Conexión a un repositorio

Gracias a Mylyn disponemos de dos nuevas vistas de interés:

  • Task Repositories: en esta vista configuramos los distintos repositorios (por ejemplo, un servidor de Mantis) que almacenan proyectos/tareas.
  • Task List: almacena tareas categorizadas de distintas formas (por ejemplo por proyectos).

Y como hemos dicho, gracias al plugin Mylyn-Mantis podemos utilizar Mantis dentro de Mylyn. Estas 2 vistas aparecen en la perspectiva “Planning”, perspectiva recomendada para trabajar con tareas.

En primer lugar deberíamos configurar el repositorio Mantis. Para ello necesitamos la vista Task Repositories. Esta vista podemos añadirla, si no la tenemos en nuestra perspectiva, a través de Window->Show View->Other, y desplegando la opción Mylyn. Dentro de esta vista, al hacer clic en el botón derecho del ratón nos aparece, entre otras, la opción de crear un nuevo repositorio de tareas (Add Task Repository):

Configuración de repositorio Mylyn

Al escoger esta opción se nos solicita qué tipo de servidor queremos configurar. En el caso de Mantis escogeremos dicha opción:

Añadir repositorio de tareas Maven con Mylyr

Y se nos piden datos sobre el servidor de Mantis:

Añadir repositorio de tareas Maven con Mylyr

Deberemos conocer la URL del servicio SOAP de Mantis (Mantis-Connect), así como nuestro usuario y contraseña. En esta ventana podemos realizar una validación de la configuración, para comprobar que sea correcta antes de grabar. Una vez hayamos hecho esta comprobación, ya disponemos de una conexión a Mantis.

Consulta a un repositorio y descarga de incidencias

Para ello creamos una query al repositorio Mantis. Dentro de la vista Task List, botón derecho del ratón, escogemos la opción “New Query”:

Añadir repositorio de tareas Maven con Mylyn

Escogeremos nuestro repositorio de tareas (Mantis) y continuamos. Le damos un título al filtro (normalmente el del proyecto con el que estemos trabajando) y en el desplegable escogemos el proyecto y un filtro. Estos filtros son queries que deben haber sido definidas previamente; es necesario disponer de al menos un filtro definido en Mantis, ya sea público o privado (un usuario, tras hacer una búsqueda avanzada, puede guardar ese filtro y recuperarlo en este momento; por ejemplo, puede crearse un filtro para recuperar sólo las incidencias no resueltas asignadas a él).

Añadir repositorio de tareas Maven con Mylyn

Al grabar se nos crea esta consulta, y el plugin comienza un proceso de sincronización con el servidor Mantis para descargarse todas las incidencias que cumplan el filtro:

listado de tareas

En cualquier momento podemos crear una nueva tarea dentro de Eclipse. Para ello, simplemente tenemos que invocar a New Task dentro de la vista Task List

Nueva tarea

Para crearla, nos pedirá primero en qué repositorio de tareas queremos grabarla (Mantis), luego pide el proyecto y se pulsa en Finish. Se llega a una ficha de la tarea donde podremos grabar sus datos. Esta ficha es idéntica a la que se observa al acceder al detalle de una tarea, donde podemos realizar prácticamente cualquier actividad sobre ella: cambiar su estado, asignación, dar comentarios, etc.

Editar tarea

Trabajando con tareas

Como se ha comentado, se recomienda el uso de la perspectiva Planning En la ficha de una tarea (parte superior derecha) disponemos de una opción para Activar / Desactivar una tarea:

Tareas en mylyn

Al activar una tarea, le indicamos a Eclipse que todo el código que incluyamos hasta el momento se corresponde con esa tarea, asociando el mismo al contexto de dicha tarea.

Si volvemos a nuestra perspectiva de trabajo (por ejemplo Java o Java EE, vista Project Explorer) es posible que dejemos de ver nuestros ficheros, advirtiendo un mensaje “Empty task context, unfocus or Alt + click”. Esto es debido a que Eclipse incorpora la posibilidad de filtrar nuestros proyectos/ficheros viendo sólo aquellos que están incluidos (relacionados) en el contexto de la tarea seleccionada:

Filtro

Simplemente pulsando sobre el icono de filtrado volveremos a ver todos los proyectos y ficheros, sin filtrar por el contexto de una tarea.

Esto por ejemplo provoca que se genere un comentario específico a la hora de hacer commit del conjunto de ficheros asociados al contexto de una tarea, muy útil para conocer qué tarea se ha resuelto con el conjunto de código entregado:

commit con mylyn

Planificando tareas

Eclipse nos permitirá planificar nuestras tareas asignadas en fechas, y nos avisará en pantalla en el momento en el que se supone que deberíamos desarrollar una tarea concreta.

Planificando tareas

Humor: Chuck Norris en el mundo Java

10 may 2009

Chuk norris domina Java

* Sólo Chuck Norris puede hacer una clase  abstracta y final.
* Chuck Norris serializa los objetos directamente en cráneos humanos.
* Chuck Norris no despliega aplicaciones web, él las mete a patadas en el servidor.
* Chuck Norris siempre utiliza sus propios patrones de diseño, y su favorito es la Patada Voladora Chuck.
* Chuck Norris puede usar para matarte cualquier clase de java.util .* , incluido el javadocs.
* Chuck Norris puede golpear tan fuerte que tu aplicación web se convierta en una aplicación swing, y es muy probable que sea una aplicación swing con una gran cantidad de iconos de cráneos humanos.
* Chuck Norris demostró el significado de Float.POSITIVE_INFINITY contando hasta él, dos veces.
* La sincronización no protege frente a Chuck Norris, si quiere el objeto, él lo toma.
* Chuck Norris no usa javac, él edita directamente los .class con un editor binario.
* El código Java de Chuck Norris nunca necesita ser optimizado. Su código es tan rápido que rompió la velocidad de la luz durante una prueba en los laboratorios de Sun matando a 37 personas.
* Cuando alguien intenta utilizar un método deprecated hecho por Chuck Norris , el método no avisa de que está deprecado. Automáticamente te pega una patada voladora en la cara en tiempo de compilación.
* El paquete java.lang originalmente contenía una ChuckNorris clase, pero fue quitado del paquete durante la revisión ya que Bill Joy recibió una patada voladora en la cara.
* Chuck Norris no tiene un error en su código, EVER!
* Chuck Norris no escribe código. Él mira a la pantalla de un ordenador hasta que obtiene el PROGRAMA que quiere.
* El código funciona más rápido cuando Chuck Norris lo mira.
* Chuck Norris modifica binarios .class ignorando el verificador de bycodes de Java.
* Chuck Norris no captura excepciones porque nadie tiene el coraje para lanzar ninguna.
* Chuck Norris puede hacer un casting a cualquier objeto sólo mirándolo.
* Si usted recibe un ChuckNorrisException lo más probable es que muera.
* Chuck Norris es el único que puede utilizar GOTO y const en Java.
* Chuck Norris puede compilar el código Java en . NET Framework, evidentemente, sólo mirándolo.
* Chuck no necesita capturar ninguna excepción de Java porque cuando va a lanzar la excepción Java tiene miedo de su patada voladora.
* Los niveles de visibilida Java son public,default, protected, private y protected By Chuck Norris “, no intente tener acceso a un campo con este último modificador!
* Chuck Norris come crudos JavaBeans y da patadas voladoras a JavaServer Faces!
* Chuck Norris puede dividir por 0!
* Recolector de basura sólo se ejecuta sobre el código de Chuck Norris para recoger los cadáveres.
* Cada línea de código de Chuck Norris se ejecuta en tiempo real. Incluso en una aplicación multi-thread.
* Cuando una CRU carga un .class de Chuck Norris duplica la velocidad.
* Chuck Norris puede ejecutar instrucciones de 64 bits en una CPU de 32 bits.
* Chuck Norris implementa “Indestructible”. Todas las demás criaturas implementan “Killable”.
* Chuck Norris sólo programa aplicaciones web en Java para conseguir ganar el .WAR!
* Chuck Norris dio una vez una patada voladora a una clase Java. El resultado es conocido como las inner class.
* Chuck Norris puede hacer herencia múltiple en Java.
* JVM no arroja excepciones a Chuck Norris, ya no. Que matara a 753 ingenieros de Sun fue suficiente.
* Chuck Norris no necesita unidad de pruebas, porque su código siempre funciona. Siempre.
* Chuck Norris extiende a Dios. ( Y Dios que era final no pudo hacer nada para evitarlo)
* Chuck Norris tiene tanta memoria de trabajo y es tan poderoso que puede ejecutar todas las aplicaciones Java en el mundo y obtener el 2% de uso de los recursos.
* Chuck Norris ya usaba en su código genéricos en la versión 1.3.
* Una clase Chuck Norris no puede ser decompilada… no se moleste en intentarlo.

Traducción libre de: http://www.ovisual.com/4/