Archive for the ‘Tecnología’ Category

Configuración de log4j en Glassfish para desarrollo

Viernes, noviembre 20th, 2009

Bueno, después de un tiempo sin escribir nada nuevo y no por no encontrarme con problemas curiosos, sino por falta de tiempo, aquí estoy con un nuevo artículo. Esta vez el problema fue configurar el log4j para un nuevo proyecto. Realmente es un problema con el que ya me encontré hace tiempo y que solucioné en su momento pero que había quedado olvidado en mi subconsciente.

Configurar log4j para una aplicación web es una tarea bastante sencilla y que no presenta demasiados contratiempos si no hay errores de sintaxis. Aquí he de hacer un apunte para decir que suelo configurar el log4j con un fichero log4j.properties y no con un log4j.xml. No hay una poderosa razón detrás, sólo viejos hábitos.

Pero sigamos con la explicación. Si la aplicación web que hemos realizado la desplegamos sobre Glassfish, bien dejándola en la carpeta autodeploy o bien desde la interfaz web de configuración de Glassfish, el log4j nos funcionará sin problemas y podremos ver en el fichero server.log los mensajes que hayamos configurado para mostrar desde log4j (si hemos puesto que el appender sea ConsoleAppender). Pero si estamos desarrollando la aplicación web desde Eclipse y tenemos configurado el servidor Glassfish dentro del Eclipse es posible que nos encontremos con el mismo problema con el que yo me encontré: el log4j no escribe en el server.log.

Después de muchos quebraderos de cabeza comprobando que la configuración del log4j es correcta e incluso eliminando el 95% de la configuración para dejar sólamente un logger y un appender, no había forma de ver las entradas que supuestamente estaba escribiendo en el log. Aunque esto no es del todo cierto, ya que sí que podía ver los mensajes que tenían un level igual o superior a WARN. Este dato es curioso ya que en mi log4j.properties había configurado el logger para TRACE. Todo hacía indicar que se estaba cargando una configuración que no era la que yo indicaba en el fichero con el que estaba tratando. Entonces tocó revisar que Glassfish no tenía más aplicaciones desplegadas, que no tenía más proyectos abiertos en Eclipse (hay que ver las cosas que hacemos cuando algo nos falla y nos frustramos) y que no había ninguna otra posible configuración cargándose ni desde un fichero .properties, .xml o desde Java.

Fue entonces cuando me puse a googlear y di con un mail de la lista de correo de Struts2 en el que uno de los participantes daba un enlace a una página de la wiki de Glassfish, donde se explica cómo resolver este problema. Como la página está en inglés y no encontré ninguna otra web donde se comentara este problema pues voy a poner aquí los pasos para corregir este problema en castellano.

  1. Crear una carpeta llamada logging dentro de la carpeta lib del dominio para el que queramos configurar el domain.
  2. Dejar el .jar del log4j dentro la carpeta recién creada logging.
  3. Dejar también el fichero de configuración de log4j.
  4. Arrancar el servidor y acceder a la interfaz web de configuración de Glassfish. Lo normal es que accedamos a ella con http://localhost:4848/.
  5. Vamos a la sección Application Server, luego hacemos click en la pestaña JVM Settings (o Configuración JVM si lo tenemos en castellano) y después en Path Settings (o Configuración de ruta).
  6. En el textarea correspondiente a System Classpath (Ruta de clase del sistema) debemos escribir la ruta completa hasta el fichero .jar incluyendo el nombre del propio fichero .jar y también la ruta completa de la carpeta logging que hemos creado.
  7. Una vez hecho esto le damos a Guardar y reiniciamos el domain.

En mi caso (esta vez) sólo tuve que modificar el fichero log4j.properties que se encontraba en la carpeta logging para añadir la configuración del nuevo proyecto. Esto es lo que hay que hacer cada vez que queramos desarrollar una nueva aplicación.

La información ha sido obtenida de aquí.

Struts2 FileUploadInterceptor & Content-Type

Jueves, agosto 13th, 2009

Tras desarrollar una aplicación para un cliente en Struts2 un día recibimos una incidencia sobre un comportamiento extraño que tenía lugar al subir un fichero. Resulta que el formulario se enviaba sin problemas y se devolvía la correspondiente página indicando que se había modificado correctamente la información. Pero el fichero enviado no se había subido al servidor.

Después de que mi compañero David Canós reprodujera la incidencia en su ordenador me puse a averiguar si había algo en el formulario o en el Action que lo recibe que pudiera ocasionar el error. Activé el log y al probarlo en mi ordenador descubrí que a mi me funcionaba de la forma esperada. No obstante el log predijo que el error se debía a que el servidor no detectaba un Content-Type en el fichero enviado. Cogí el mismo fichero que había probado mi compañero (después de que me lo enviara por mail y también me lo pasara con un pendrive) y me seguía funcionando bien. Entonces pensé que se habría seteado el mime durante la copia de un SO a otro (aunque gastemos el mismo SO) y se lo reenvié para que probara una vez más. Volvió a fallarle. Probó también con otros ficheros y con otros le daba el mismo problema.

Llegados a este punto me puse a pensar y recordé que mi compañero usaba Chrome normalmente y en la empresa donde ocurrió el problema usan Safari (pues principalmente trabajan con Mac) así que no podía ser por un problema del navegador. Pero yo lo había probado con Firefox y con IE7 así que le dije a mi compañero que probara una vez más pero desde Firefox. Cuál fue mi sorpresa cuando el fichero (el mismo de todas las veces) se envió correctamente. Sabiendo el origen y el motivo sólo quedaba arreglar el error. Y ahora es cuando viene lo más divertido: modifiqué la configuración del servidor para que contemplara las extensiones extrañas (app.log.001 por ejemplo) y les asignara por defecto ‘text/plain’ como Mime-Type, pero el problema seguía ocurriendo. Por tanto la solución residía en Struts2 y más concretamente en el FileUploadInterceptor.

Me descargué el código fuente del core de Struts2 para poder acceder al código fuente del FileUploadInterceptor. Después de comprender el proceso del interceptor y de poner un par de System.out para comprobar el momento en el que estaba fallando el código hice la siguiente modificación:

Código antiguo:

...
// Bind allowed Files
Enumeration fileParameterNames = multiWrapper.getFileParameterNames();

while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
    // get the value of this input tag
    String inputName = (String) fileParameterNames.nextElement();

    // get the content type
    String[] contentType = multiWrapper.getContentTypes(inputName);

    if (isNonEmpty(contentType)) {
        // get the name of the file from the input tag
        String[] fileName = multiWrapper.getFileNames(inputName);

        if (isNonEmpty(fileName)) {
            // Get a File object for the uploaded File
...

Código generado:

...
// bind allowed Files
Enumeration fileParameterNames = multiWrapper.getFileParameterNames();

while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
    // get the value of this input tag
    String inputName = (String) fileParameterNames.nextElement();

    // get the content type
    String[] contentType = multiWrapper.getContentTypes(inputName);

    if((contentType.length < 1) || (contentType[0] == null)){
        contentType = new String[]{"text/plain"};
    }

    if (isNonEmpty(contentType)) {
        // get the name of the file from the input tag
        String[] fileName = multiWrapper.getFileNames(inputName);

        if (isNonEmpty(fileName)) {
            // get a File object for the uploaded File
...

De esta forma consigo que si el fichero no trae ningún Content-Type le asigno por defecto el ‘text/plain’ para que no me falle. Por supuesto también me toco modificar la configuración del fichero struts.xml para poder usar mi FileUploadInterceptor modificado en vez del que trae Struts2 en la pila de interceptores ParamsPrepareParamsStack.

La moraleja es que parece que ni Safari ni Chrome le setean el Content-Type de la petición HTTP o uno por defecto al fichero que se envía en un formulario aunque este no tenga Content-Type.

Contenido estático en Glassfish v2: alternatedocroot

Miércoles, junio 17th, 2009

Después de mucho tiempo tratando con la configuración de Glassfish y tras varios quebraderos de cabeza me he decidido a escribir este artículo para tratar de aclarar un poco el tema de servir contenido estático con Glassfish.

La propiedad alternatedocroot de Glassfish se asemeja en parte a la directiva Alias del servidor web Apache. Esta propiedad nos va a permitir acceder a carpetas que están fuera del contenedor del servidor. Una de las ventajas que nos puede proporcionar este hecho es que podemos tener las imágenes del proyecto fuera del mismo, disminuyendo así, por poner un ejemplo, el peso del fichero .war a desplegar.

Lo primero que hay que saber es que no hay que tocar la configuración de Glassfish para conseguir nuestro objetivo de servir contenido estático, sino que debemos modificar el fichero sun-web.xml de nuestro proyecto java. Para ello tenemos que añadir la siguiente propiedad dentro del elemento sun-web-app:

<sun-web-app ...>
....
<property name="alternatedocroot_1" value="from=/{ruta virtual}/*
        dir={ruta física}" />
....
</sun-web-app ...>

Explicamos a continuación cada uno de los elementos. En el name tenemos que indicar la propiedad de la configuración de Glassfish que queremos definir para este proyecto. Si quisiéramos definir más de un elemento de este tipo simplemente habría que iterar el número del nombre del alternatedocroot.
El campo value se compone de dos partes:

1. Elemento from: indica a partir de qué dirección URL se ha de servir el contenido estático.
2. Elemento dir: indica la ruta física donde tengamos almacenado el contenido estático.

Con un ejemplo se ve claro:

<property name="alternatedocroot_1" value="from=/img/* dir=/srv/web/img/"/>

Esta propiedad está indicando al servidor Glassfish que las consultas realizadas sobre la dirección http://localhost/img/ serán resueltas buscando la información en la carpeta /srv/web/img/. En caso de tener el servidor sobre Windows la propiedad se escribiría de la siguiente forma:

<property name="alternatedocroot_1" value="from=/img/* dir=c:\server\img\"/>

Es importante tener en cuenta que el nombre de la última carpeta de la ruta física ha de coincidir con el nombre de la ruta virtual. En el caso en que pusiéramos dos carpetas en el elemento from, dichas carpetas deberían ser las últimas de la ruta física.

Para terminar voy a poner un enlace del que he sacado gran parte de esta información, aparte de los foros de Java de Sun y el “ensayo-error”. El enlace es del blog de Jan Luehe, uno de los desarrolladores de Glassfish:

http://blogs.sun.com/jluehe/

Instalación de Subversion en Windows

Miércoles, junio 10th, 2009

En este artículo se va a explicar cómo instalar y configurar un servidor de Subversion y cómo
acceder a dicho servidor de versiones usando dos herramientas distintas: TortoiseSVN y el plugin
de Subversion para eclipse Subclipse.
Cuando traté de montar el servidor de Subversion estuve preguntando a amigos que trabajan en el
mundo de la programación y además trabajan con Subversion y obtuve la misma respuesta: “no
tengo ni idea”. Así que me puse a buscar por Internet y como no encontré ninguna página donde me
informara sobre como instalar el servidor de Subversion y el plugin para eclipse pues me he
decidido a hacerlo yo, y de paso pongo también la forma de configurar el TortoiseSVN por si no se
quiere trabajar con eclipse. Aquí van los distintos pasos a seguir:

1. Instalación de Subversion
2. Configuración de Subversion
3. Primeros pasos con Subversion
4. Creación de un servicio de Windows para Subversion
5. Instalación y configuración de TortoiseSVN
6. Instalación y configuración de Subclipse

1. Instalación de Subversion
Descargar e instalar Subversion. Este es el enlace a la página de descargas para Windows:

http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91

Una vez instalado el servidor, añadir a la variable de entorno PATH la ruta a la carpeta bin donde
hayamos instalado el Subversion (normalmente C:\Archivos de programa\Subversion\bin).
Es necesario asociar un editor de texto al servidor de Subversion para poder visualizar ciertas
informaciones que luego se comentarán (en este caso yo he elegido el notepad de Windows para
hacerlo más sencillo). Para ello crearemos una variable de sistema con el nombre SVN_EDITOR y
el valor C:\Windows\notepad.exe.

2. Configuración de Subversion
Nuestro primer paso con el servidor va a ser el de crear un repositorio. Este comando creará una
carpeta en la ruta física que le pasemos como parámetro entre comillas. Abrimos la consola y
escribimos la siguiente sentencia:

svnadmin create "{dirección del repositorio}"

Para que el repositorio pueda ser accedido es necesario modificar un par de ficheros. Para ello
vamos a la carpeta recién creada (con el explorador) y abrimos el fichero /conf/svnserve.conf.
Buscamos el bloque general y dentro de este bloque hay que descomentar las siguientes líneas:

[general]
anon-access = read
auth-access = write
password-db = passwd

En la misma carpeta abrimos el fichero /conf/passwd, buscamos el bloque users y descomentamos
las siguientes líneas:

[users]
harry = harryssecret
sally = sallyssecret

Cabe decir que si no queremos que nuestros usuarios se llamen harry y sally sólo tenemos que
cambiarlos. Para las contraseñas (que son el texto que aparece a la derecha del signo = ) el
procedimiento es el mismo.

3. Primeros pasos con Subversion
Ahora vamos a comprobar que el servidor de Subversion está funcionando. Para ello vamos a
probar a iniciar el servidor. En una consola escribiremos:

svnserve --daemon --root "{dirección del repositorio}"

Si todo ha ido bien deberíamos poder crear un proyecto. Abrimos otra consola distinta (en el caso
de que no hayamos ejecutado el comando para arrancar el servidor en background, para eso hay que
añadir ” /background” al final del comando anterior pero sin comillas) y escribimos:

svn mkdir svn://localhost/miproyecto

Se abrirá un notepad (o el editor que hayamos configurado en el paso 1) con 2 líneas escritas.
Podemos escribir antes de ellas lo que queramos a modo de descripción del proyecto. Guardamos
los cambios y cerramos el editor de texto. Entonces en la consola en la que hemos ejecutado el
comando para crear el proyecto se nos pedirá que nos autentifiquemos. Primero pide la contraseña
del usuario que está ejecutando el servicio (en este caso es el usuario de Windows con el que hemos
iniciado sesión). Luego nos pide el nombre de usuario con el que nos conectamos (harry, sally o
uno que hayamos puesto en el fichero de configuración /conf/passwd) y a continuación su
contraseña. Si todo ha ido bien nos dirá:

Committed revision 1.

Ya hemos hecho un cambio en el servidor de Subversion.

4. Creación de un servicio de Windows para Subversion
Como tener que iniciar el servidor de Subversion cada vez desde una consola resulta engorroso,
ahora vamos a ver la posibilidad de iniciarlo como un servicio de Windows. Paramos el servidor
haciendo CTRL + C en la consola en la que lo teníamos funcionando. Para mayor seguridad
creamos el usuario SvnDaemon en el sistema con la contraseña P@ssw0rd por poner un ejemplo.
Para ello vamos a:

Panel de Control --> Herramientas Administrativas --> Administración de equipos -->
Usuarios locales y grupos.

Hacemos click con el botón derecho del ratón sobre Usuarios y luego en Usuario nuevo… y
rellenamos los campos. Es importante dejar marcadas sólo las opciones El usuario no puede
cambiar la contraseña
y La contraseña nunca caduca. Una vez creado, cerramos la ventana y
vamos a la opción Grupos. Al hacer doble click sobre el grupo Usuarios se abre el listado de
usuarios que lo compone y eliminamos el usuario SvnDaemon de este grupo. Luego vamos a:

Panel de Control --> Herramientas Administrativas --> Configuración de seguridad local -->
Directivas locales --> Asignación de derechos de usuario

y le aplicamos la directiva de seguridad local Iniciar sesión como servicio al usuario SvnDaemon.
Para ello hacemos doble click en la directiva indicada, luego hacemos click en Agregar usuario o
grupo…
, luego pinchamos en Avanzadas, seguidamente en Buscar ahora y finalmente
seleccionamos el usuario creado anteriormente y hacemos click en Aceptar.
Nos vamos de nuevo a la consola y escribimos lo siguiente:

sc create svnsvc binPath= "\"C:\Archivos de programa\Subversion\bin\svnserve.exe\"
--service -r \"D:\Proyectos\"" DisplayName= "Subversion Service" depend= Tcpip
start= auto obj=Server\SvnDaemon password= P@ssw0rd

Ahora explicamos lo que es cada cosa. La primera ruta es la carpeta donde tenemos el Subversion
instalado y la segunda es la dirección del repositorio que hemos creado en el punto 2. Hay que
destacar el hecho de tener que poner las \ antes de las comillas en las rutas siempre que alguna de
las carpetas que haya que atravesar contenga espacios en el nombre. El DisplayName es el nombre
que aparecerá en el listado de servicios de Windows. Las opciones depend y start son las
dependencias que tiene el servicio (en este caso le decimos que dependerá del servicio de control de
TCP/IP para poder ser accesible desde una red local) y que arranque de modo automático,
respectivamente. En la opción obj hay que indicar el equipo o el dominio donde está la cuenta de
usuario que ejecutará el servicio y el nombre de dicha cuenta separados por una \ . Por último
tenemos que indicar la contraseña de la cuenta de usuario para que pueda arrancar el servicio sin
problemas.

* No hay que olvidar dar permisos de Control Total al usuario en la carpeta del repositorio.

Arrancamos el servicio escribiendo en la consola:

net start svnsvc

Vamos a comprobar que ha arrancado correctamente escribiendo:

svn ls svn://localhost/

Si todo va bien, debería aparecer el proyecto que hemos creado en el punto 3.

5. Instalación y configuración de TortoiseSVN
Usar el TortoiseSVN es bastante sencillo. Primero vamos a ir a la página web del proyecto Tortoise
a descargarnos el programa para instalarlo posteriormente:

http://tortoisesvn.tigris.org/download.html

Una vez instalado el programa nos vamos a la carpeta donde queramos almacenar los ficheros de
los proyectos con los que vamos a trabajar. Creamos una carpeta vacía porque va a ser ahí donde
vamos a descargarnos el proyecto. Para ello, hacemos click con el botón derecho sobre la carpeta y
luego click en SVN Checkout… . Se abrirá una ventana con varios campos. En URL of repository
escribimos la dirección de la carpeta del proyecto que hemos creado en el punto 3:

svn://localhost/miproyecto/

Hay que tener en cuenta que si vamos a acceder a un servidor que no se encuentra en nuestro
equipo en vez de localhost habrá que introducir la dirección IP del servidor de Subversion.
En Checkout directory debe aparecer el directorio en el que estamos. Hacemos click en OK y
comenzará el proceso de descarga del contenido del proyecto.
Veamos ahora los usos más normales. Para añadir ficheros al proyecto hay que hacer click con el
botón derecho sobre el fichero o ficheros y dentro de la opción de menú TortoiseSVN hacemos click
en Add… . Luego hacemos click con el botón derecho sobre la carpeta y le damos a SVN Commit… .
De esta forma podemos ir añadiendo ficheros conforme los vayamos creando y enviarlos todos
juntos al servidor en una sola operación.
Para modificar los ficheros basta con editarlos y hacer el commit al terminar.
Para actualizar nuestros ficheros con las últimas versiones que tenga el servidor de Subversion
podemos hacer click con el botón derecho sobre la carpeta raíz del proyecto (o simplemente sobre
un fichero o una carpeta determinada del proyecto) y hacer click en la opción SVN Update.

6. Instalación y configuración de Subclipse
Vamos ahora con la configuración de Subclipse para trabajar con el servidor de Subversion. Esto es
básicamente la traducción de la guía de instalación del propio plugin que se puede encontrar en:

http://subclipse.tigris.org/install.html

Una vez tengamos abierto el eclipse nos vamos a la opción de menú:

Help → Software Updates → Find and Install...

y en la ventana que se abre seleccionamos Search for new features to install y hacemos click en
Next. Nos aparecerá una lista de sitios en los que buscar actualizaciones o nuevos plugins para el
eclipse. Nuestro siguiente paso es hacer click en New Remote Site…. Hay que tener en cuenta que si
estamos detrás de un proxy y el eclipse falla al realizar la búsqueda se puede descargar la versión
comprimida del Subclipse desde la página oficial y buscar entonces haciendo click en New Local
Site…
.
En la ventana que se nos abre debemos indicar un nombre y una URL para buscar las
actualizaciones y plugins. Dependiendo de la versión de eclipse que tengamos hay que poner una
dirección de las siguientes (los nombres son una recomendación):

Name: Subclipse 1.4.x (Eclipse 3.2+)
URL: http://subclipse.tigris.org/update_1.4.x
Name: Subclipse 1.2.x (Eclipse 3.2+)
URL: http://subclipse.tigris.org/update_1.2.x
Name: Subclipse 1.0.x (Eclipse 3.0/3.1)
URL: http://subclipse.tigris.org/update_1.0.x

Una vez hayamos rellenado los dos campos y le hagamos click en OK, seleccionamos el sitio que
acabamos de añadir pues no estará seleccionado. Luego hacemos click en Next y en la siguiente
pantalla nos aparecerá desplegamos el árbol de actualizaciones disponibles en el sitio y tras
seleccionar el elemento deseado (que tendrá como nombre Subclipse {versión}) hacemos click de
nuevo en Next. En la siguiente pantalla aceptamos los términos de la licencia y posteriormente
elegimos la carpeta en la que vamos a instalar el plugin. Una vez elegida hacemos click en Finish y
es posible que nos aparezca una pantalla de confirmación ya que el plugin no está firmado
digitalmente (se puede desactivar este tipo de confirmaciones en eclipse para que no las muestre).
Hacemos click en Install o Install All y comenzará la instalación, que una vez terminada nos pedirá
reiniciar el eclipse.
Una vez reiniciado el eclipse sólo nos quedará acceder al servidor de Subversion. Para ello vamos a
la opción de menú:

Window → Open Perspective → Other...

y seleccionamos la perspectiva SVN Repository Exploring. Ahora desde esta perspectiva hacemos
click con el botón derecho sobre la pestaña SVN Repository y hacemos click en:

New → Repository Location...

En el campo URL introducimos la dirección del proyecto que hemos creado en el punto 6:

svn://localhost/miproyecto/

Luego hacemos click en Finish y se descargará los ficheros del proyecto. Para añadir o modificar ficheros hay que
hacer click con el botón derecho sobre los ficheros en cuestión y seleccionar la opción de menú:

Team → Commit...

Una vez aquí podemos añadir un comentario para cada archivo que vayamos a enviar al servidor o
uno general si se envían varios simultáneamente.
Para actualizar nuestros ficheros con las últimas versiones que tenga el servidor de Subversion
podemos hacer click con el botón derecho sobre el proyecto (o simplemente sobre un fichero o una
carpeta o un package del proyecto) y hacer click en la opción:

Team → Update.

* Es importante destacar que tanto con TortoiseSVN como con Subclipse se pueden enviar al
servidor varios ficheros realizando la opción de Commit sobre una carpeta, un package o sobre el
proyecto.
La información para la instalación del servidor de Subversion en Windows y el uso de TortoiseSVN
ha sido sacada de:

http://blogs.vertigosoftware...under_Windows.aspx