viernes, 12 de diciembre de 2014

Spring Web: Obtener request actual y generar URL de la aplicación

Una forma sencilla de generar el URL base acorde con el contexto de ambiente de la aplicacion a partir del objeto request:

protected static String getBaseEnvLinkURL() {

   String baseEnvLinkURL=null;
   HttpServletRequest currentRequest =
      ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
   baseEnvLinkURL = "http://" + currentRequest.getLocalName(); // lazy about determining protocol
   if(currentRequest.getLocalPort() != 80) {
      baseEnvLinkURL += ":" + currentRequest.getLocalPort();
   }
   if(!StringUtils.isEmpty(currentRequest.getContextPath())) {
      baseEnvLinkURL += currentRequest.getContextPath();
   }            
   return baseEnvLinkURL;
}

jueves, 13 de noviembre de 2014

Ubuntu: Resolviendo problema de instalación con aptitude

Tratando de instalar el reproducto VLC en mi Ubuntu Linux 14 me daba este error usando el comando:

sudo apt-get install vlc

Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 vlc : Depends: vlc-nox (= 2.2.0~rc1-1ppa1~trusty) but it is not going to be installed
       Depends: libavcodec56 (>= 7:2.4~) but it is not going to be installed
       Recommends: vlc-plugin-notify (= 2.2.0~rc1-1ppa1~trusty) but it is not going to be installed
       Recommends: vlc-plugin-samba (= 2.2.0~rc1-1ppa1~trusty) but it is not going to be installed
E: Unable to correct problems, you have held broken packages.


Después de intentar muchos comandos para limpiar los paquetes quebrados, finalmente instalé aptitude y corrí el comando:

sudo aptitude install vlc

Y listo, todos mis problemas de paquetes los resolvió aptitude y pude instalar mi reproductor favorito.

martes, 4 de noviembre de 2014

Herramienta para captura y edición de capturas de pantalla (screenshots)

Tenía la necesidad de agregar unas flechas a unas capturas de pantalla usando mi Ubuntu. Intenté hacerlo con Gimp pero resultó más complicado de lo que pensaba. Así que instalé está recomendación: http://shutter-project.org/.

Se puede instalar con el comando: sudo apt-get install shutter


martes, 9 de septiembre de 2014

ORA-28002: the password will expire within X days


Para un ambiente de desarrollo normalmente no es importante que las contraseñas de base de datos expiren. Me estaba dando ese mensaje de que mi contraseña para el usuario 'system' iba a expirar. Así que para evitar esto en el futuro y dejar la misma contraseña, ejecuté los siguientes comandos:

SQL> ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;
SQL> ALTER USER SYSTEM IDENTIFIED BY <password>;

martes, 3 de junio de 2014

GREP tips


Solamente coleccionando magia grep


Busque ocurrencia de manera recursiva en el directorio actual, ignorando mayúsculas/minúsculas (case) y cuente el número de líneas.

grep -Ri "search_term" . | wc -l


Agrupa las ocurrencias de un path en el web-access log y cuenta las ocurrencias.

grep -Eo "/wrapper-app-api(/\w+/\S*)" web-access.log | sort | uniq -c

3056 /wrapper-app-api/internal/graphitedump
 146635 /wrapper-app-api/internal/health.check
 152045 /wrapper-app-api/wrapper/community
  27183 /wrapper-app-api/wrapper/csrf
  37473 /wrapper-app-api/wrapper/get
    134 /wrapper-app-api/wrapper/left/all-writers
      1 /wrapper-app-api/wrapper/left/exercises
      4 /wrapper-app-api/wrapper/left/food-and-recipes
      2 /wrapper-app-api/wrapper/left/gethinmusclenutrition
      2 /wrapper-app-api/wrapper/left/Mind
      2 /wrapper-app-api/wrapper/left/Nutrition
     11 /wrapper-app-api/wrapper/left/root
      7 /wrapper-app-api/wrapper/left/Supplements
    135 /wrapper-app-api/wrapper/left/Training_Main
    204 /wrapper-app-api/wrapper/locale
     35 /wrapper-app-api/wrapper/notstore

    593 /wrapper-app-api/wrapper/proxy.html


martes, 15 de abril de 2014

Java: URL de archivo localizado en el classpath


Una manera de averiguar el URL de un archivo localizado en el classpth (útil en casos como tests de unidad de classes que consumen datos por la web):

getClass().getClassLoader();
String url = ClassLoader.getSystemResource("path/to/file").toString();

miércoles, 9 de abril de 2014

Eclipse Maven: 'Updating Maven Project' has encountered a problem.




'Updating Maven Project' has encountered a problem. 
An internal error ocurred during 'Updating Maven project'.
java.lang.NullPointerException

De repente comencé a tener este error con uno de mis proyectos de Maven. La mejor solución que encontré fue:


  1. Borrar el proyecto de Eclipse (no los archivos)
  2. Borrar el .project y el .settings/ del proyecto
  3. Re imporar el proyecto
  4. Convertirlo a un proyecto Maven 

martes, 18 de marzo de 2014

MongoDB Tips


Actualizar todos los documentos de una colección para agregar un nuevo campo:

db.<COLLECTION>.update({}, {$set: {<NEW_FIELD>:<VALUE>} }, {multi:true})

Renombrar el nombre de una columna/campo

db.<COLLECTION>.update({}, {$rename: {'<OLD_FIELD_NAME>': '<NEW_FIELD_NAME>'}}, false, true);

Exportar/Importar una colección

mongoexport -d <DATABASE> -c <COLLECTION> -o <FILE_PATH>
mongoimport -d <DATABASE> -c <COLLECTION> --file <FILE_PATH>

Remover una columna/atributo en todos los documentos de la colección

db.<COLLECTION>.update({}, {$unset: {<FIELD>:""} }, {multi:true})

Consultar todos los documentos donde un arreglo tiene tamaño mayor a 0

db.<COLLECTION>.find({ $where: "this.FIELD.length > 1" } )

Consultar por tamaño de un arreglo mayor a n

db.getCollection(<COLLECTION>).find({ $where: "this.<ARRAY_FIELD>.length > 8" })

viernes, 14 de marzo de 2014

Log4j: Tips

Cambiar el nivel de log para un paquete o clase 

En el log4j.properties:

log4j.rootLogger=INFO,Stdout
log4j.logger....=DEBUG

SLF4J: Multiple bindings were found on the class path logback

En el proyecto que estoy trabajando utilizamos SLF4J como framework de logging. Estaba teniendo un problema en el cual mis llamados para registrar entradas en el log no estaban apareciendo. Al principio pensé que era un problema con el archivo de log4j ya que esta era la implentación final que se estaba utilizando. Sin embargo luego me dí cuenta de unos mensajes apareciendo al principio del arranque de la aplicación:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/atg-dev/.m2/repository/ch/qos/logback/logback-classic/0.9.28/logback-classic-0.9.28.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/atg-dev/.m2/repository/org/slf4j/slf4j-log4j12/1.6.2/slf4j-log4j12-1.6.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
2014-03-13 21:30:46.718:INFO:/search-indexer:Initializing Spring root WebApplicationContext


Los mensajes estaban indicando que habían varios bindings, es decir, varias implementaciones de logging dentro del classpath. En específico pude ver que aparte de Log4j estaba LogBack, el cual no encontré ninguna referencia en el pom.xml. Había que descubrir la dependencia indirecta/transitiva.

La mejor manera para hallar la dependencia transitiva fue una idea de un compañero de utilizar el plugin de Maven en Eclipse que permite ver la jerarquía de dependencias.



De esa manera pude ubicar la dependencia que incluía al logback y agregar la exclusión:



        <dependency>
            <groupId>com.xxx.content</groupId>
            <artifactId>content-dao-jar</artifactId>
            <version>xx.xx.x.x</version>
            <exclusions>                
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

martes, 11 de marzo de 2014

Git: Lista de comandos útiles

Revertir cambios locales del branch al contenido remoto

git reset --hard origin/<branch>

Fusionar branch2 en branch1

git checkout branch1
git merge branch2

Enviar un branch local al servidor remoto

git push origin branc

Mostrar branches locales

git branch

Borrar branch remoto

git push origin --delete branchname

Borrar branch local

git branch -D the_local_branch

jueves, 6 de marzo de 2014

JMeter: Primeros pasos probando rendimiento de aplicaciones web

Una gran herramienta en la caja de herramientas de todo buen desarrollador de software, es aquella que te permite evaluar el rendimiento de una aplicación. En el caso de aplicaciones web es extremadamente necesario hacer estas pruebas de rendimiento simulando una alta concurrencia de usuarios  debido a la naturaleza concurrente de la web.

Una gran herramienta open source para realizar este tipo de pruebas se llama JMeter de Apache. Con ella puedo crear múltiples solicitudes a una dirección web y medir la respuesta para examinar el compartamiento en términos de rendimiento.


Apache JMeter

Pasos para crear un plan de pruebas sencillo:


  1. Descargar JMeter del sitio web oficial de Apache. En Ubuntu se puede instalar usando el comando: apt-get install jmeter
  2. Agregue un Thread Group al Test Plan: Clic derecho en el test plan ->Add->Threads (Users)->Thread Group
  3. Edite los campos del Thread Group como el número de usuarios y la cantidad de ciclos, entre otros.
  4. Agregamos un HTTP Request: Clic derecho en el Thread Group->Add->Sampler->HTTP Request
  5. Editamos los campos requeridos de acuerdo al tipo de request
  6. Agregamos un listener de acuerdo al tipo de reporte que desemos: Clic derecho en Test Plan->Add->Listener->Graph Results
  7. Damos Start y observamos nuestro gráfico crecer
  8. Interpretamos los resultados y/o ajustamos el plan para obtener la información que requerimos

miércoles, 12 de febrero de 2014

Tridion y sus bloques de construcción



Siempre es bueno guardar conceptos claves de las tecnologías que uno ha usado en el pasado. El aprender a reconocer debilidades y  fortalezas de una tecnología es vital para desarrollar un criterio ingenieril o arquitectural que nos ayuda a tomar mejores decisiones técnicas.

Hace un tiempo trabajé con un administrador de contenido propietario llamado Tridion de SDL. Sinceramente no me agradó mucho por algunas razones que no vienen al caso mencionar ahora, pero hubieron varios conceptos que me agradaron y que comentaré brevemente en algunas entradas de blog.

Unos de los conceptos que me llamó la atención es la manera muy clara en que separan el contenido de la presentación, y como lo hacen de una manera escalonada por medio de sus "bloques de construcción". Esta separación es sumamente importante en un buen administrador de contenido o CMS (Content Management System). Es altamente deseable que el contenido en un sistema de contenido se pueda preservar mientras su presentación evoluciona con el tiempo adaptando las nuevas tendencias de presentación web.

Esta facilidad permite también una excelente separación de roles donde tenemos editores de contenido que no se preocupan porque el contenido luzca agradable, y por otra parte los diseñadores web que maquillan el sitio web acorde a las tendencias de moda.

En organizaciones muy grandes, esta característica permite además imponer una serie de formatos, y/o plantillas para mantener uniformidad en sitios (o gama de sitios) web grandes y complejos donde muchas personas editan contenido.

La manera en que lo hace Tridion es definiendo los siguientes bloques de construcción de páginas web.

Los esquemas (schemas) definen los metadatos de un componente como lo son los nombres de los campos, sus tipos y si son mandatorios o no. En el ejemplo graficado abajo se muestra un esquema de comida con campos como título y subtítulo de tipo texto, y imagen de tipo imagen.

Luego un componente (component) es como la instancia de un esquema. Es decir, llenar los campos de un esquema con valores específicos. En el ejemplo se llena el esquema de comida con datos de una pizza.

La plantilla del componente (component template) viene a definir la disposición y estilos básicos de los distintos campos del componente. Un componente podría disponer de diferentes plantillas de acuerdo a las distintas necesidades de presentación. Por ejemplo, en el gráfico se muestra una alineación hacia la derecha de la imagen de la comida con el título y subtítulo encabezando a la izquierda, seguidamente del cuerpo del texto. Uno podría disponer otra plantilla que quizás se utilice para resultados de búsquedas donde la imagen se omite y solo se muestra el título con el texto de la descripción de la comida truncado.

La plantilla de la página (page template) establece los elementos globales de una plantilla web particula. Típicos casos de menús de navegación, encabezados, pies de página, etc.

La presentación del componente (component presentation) es la unión de un componente particular con una plantilla de componente. El resultado final es la presentación del contenido del componente en su forma agradable para el usuario.

Finalmente cuando se une la plantilla de la página con uno o más componentes de presentación tenemos finalmente una página web (web page).


Sin duda esta separación de contenido y presentación implica mucho trabajo al inicio con la definición de esquemas, plantillas y componentes, pero la retribución final es satisfactoria al explotar la gran flexibilidad que se alcanza con este modelo.