Archivo mensual: marzo 2013

Moving log4js-ext development from Windows to Linux -while keeping Windows dev supported

I have been moving my development environment from Windows to Linux, step by step, and the time for moving log4js-ext has arrived.

Log4js-ext is a pure javascript + Java project, and therefore source code portability is not a big issue: the only portability issues that arose were due to the build tools I use to create the deliverables, and the ant build file.

Issues

Here is my main issues list:

  • Differences in OS conventions, including directory separator, etc., make tools fail.
  • Can’t use good old CMD to run command line tools.
  • Some tools are not available in the Linux world.
  • Other nuisances.

Differences in OS conventions, including directory separator character, etc.

There are differences in the way Linux and Windows names things, case sensitivity or the directory separator.

Being aware of that, and knowing that Windows supports both ‘\’ and ‘/’ as directory separators, I’ve been using ‘/’ for ages, so that did not pose a problem.

Besides, some file paths changed (i.e., the Tomcat config directory location), but that was an easy thing to spot and fix, and I moved those paths to ant properties to make them easier to deal with.

Thankfully, no other issues appeared in this area.

Can’t use good old CMD to run command line tools

While the project was hosted in Windows, I added calls to external tools to generate Javascript API documentation, optimize image size, etc,. invoking cmd.exe with the ant exec task.

For example, this is the relevant part of the ant code I used to generate the API documentation:

<exec executable="cmd" dir="${lib.basedir}/src" >
  <arg line="/c jsduck .../>
</exec>

I had to modify the exec to make it work both in Windows and Linux, as follows:

<!-- Ok, executables are called differently in Windows and Linux... -->
<condition property="jsduck.cmd" value="cmd.exe">
  <os family="windows"/>
</condition>
<property name="jsduck.cmd" value="jsduck"/>

<condition property="jsduck.cmd.extraparams" value="/c jsduck">
  <os family="windows"/>
</condition>
<property name="jsduck.cmd.extraparams" value=""/>

<exec executable="${jsduck.cmd}" dir="${lib.basedir}/src" >
  <arg line="${jsduck.cmd.extraparams} .../>
</exec>

As you can see, I had to provide slightly different commands to exec. It was easy, but I have to admit that ant makes this verbose and to look like a big thing -which it is not.

Another annoyance was running java to minify the consolidated javascript file that includes all of log4js-ext. In Windows, I used an exec task to call Java, passing the YUI minifier jar, as follows

<exec executable="cmd">
  <arg line="/c java -jar ${yui.jar}
   ${pack.tmpdir}/${lib.project}-all-dev.js
   -o ${pack.tmpdir}/${lib.project}-all.js"/>
</exec>

Now, I decided to use the ant java task instead, as it looked easier to use it in a portable way:

<java classpath="${log4j.jar}" jar="${yui.jar}"
  spawn="true" fork="true">
  <arg line="${pack.tmpdir}/${lib.project}-all-dev.js -o
     ${pack.tmpdir}/${lib.project}-all.js"/>
</java>

However, I discovered that I had to fork the java task in order to invoke a jar, and that meant that other operations were executed *in parallel*…and therefore were called before the java task output they required was available, failing.

The workaround was to add the following lines immediately after the java task, so that it waited until the generated file was available, or 30 seconds, whatever came first:

<waitfor maxwait="30" maxwaitunit="second">
  <available file="${pack.tmpdir}/${lib.project}-all.js"/>
</waitfor>

Thank God, the problem with parallel execution was easily repeatable and I was able to find the problem in no time. Had it manifested itself only from time to time, it would had been a real pain.

Some tools are not available in the Linux world

Too bad, but it is true: some tools that are readily available in the Windows world are not there in the Linux world.

That was the case with the tools I use to optimize PNG, GIF and JPG images, pngslim and pngout.

Well, since log4js-ext is very mature when it comes to the front-end, there is no real need to optimize new images, which will probably never come into being. The smart thing to do was to ignore the problem, and not to look for alternatives ūüôā

So, that’s what I placed at the beginning of the corresponding ant task:

<fail message="NOT PORTED TO LINUX TOOLS: if the need arises to add new images, then it will make a lot of sense to look for alternatives that work in Linux"/>

Call me pragmatic!

Other issues

Whenever you move or install a complex development environment, it is always hard to reproduce it exactly, unless you go to great lengths.

Log4js-ext being a personal project, that was asking too much, and I just installed the latest versions of the different tools in Linux.

That meant I found the typical problems due to my Windows environment using version x.y.1 of JSDuck and Linux apt-get installing x.y.2: in fact, I had not one, but two problems related to using a newer version of JSDuck.

I know, this is not related to Windows vs Linux per se, but it is worth taking into account because it will happen. For big projects this can be a real problem, and I tend to be very, very strict with the exact version of tools and libraries I use.

A non-trivial ant build file that works in Linux *and* Windows

Just for the sake of it, I run the new ant file in Windows and performed several tests to check the results: everything worked, so I called it a day.

All in all, making my build and test scripts work in Windows and Linux was not as much of a chore as I had anticipated, and I was pleased with the time it took to migrate and the result.

Anuncios

Log4js-ext 2.0 is out!

I have added a major feature to log4js-ext, remote logging support, that allows sending log data to your remote web server.

There is built-in support for all major Java logging frameworks: Log4j, Slf4j and Apache Commons Logger. To learn how to use it, visit this link.

Another major addition to log4js-ext 2.0 is a powerful search & highlight feature to log4js-ext log window: now, it is possible for you to filter logs, and then perform fine grained searches for specific values.

If you click the image below, you will see that there is a new search toolbar, and that the logged text is highlighted in several log entries: this is a real time saver when digging into a ton of data.

search and highlight

To make life easier I am hosting the API documentation online.

Log4js-ext is developed using Test Driven Development, to guarantee is is a high quality product. Want proof? Take a look at the test results for version 2.0.

Log4js-ext is Open Source, you can download and start using it now, free of charge.

Enjoy!

Introducci√≥n al control de versiones, usando Git: Pragmatic version control with Git

Ahora mismo, si alguien me pidiera opini√≥n sobre qu√© control de versiones usar, y qu√© libro utilizar para iniciarse en el uso de un sistema de control de versiones, la respuesta ser√≠a “usa Git, y echale un vistazo a Pragmatic version control using Git“.

El libro va al grano, sin perderse por vericuetos, y sobre todo sin perder de vista que un sistema de control de versiones es un medio para un fin: primero, pues, viene la necesidad concreta, y después lo que un sisteam como git nos ofrece para satisfacer esa necesidad.

Demasiado a menudo nos cuentan el cómo sin que se vislumbre el por qué:  no es el caso de ese libro, que nunca pierde de vista el por qué de las cosas.

Por otro lado, si ya tienes experiencia con el uso de un sistema de control de versiones, tampoco te ir√° mal un libro que une muy rapidamente la necesidad concreta (¬Ņc√≥mo creo una rama aparte para “trastear”?) con lo que git proporciona para satisfacerla.

Finalmente, si eres un super experto…busca en otro lado. Estamos ante un libro de poco m√°s de 150 p√°ginas, simplemente no puede serlo para todo el mundo.

Una introducción excelente tanto a los sistemas de control de versiones como a git, ideal para programadores que tengan ninguna o poca experiencia con ambas cosas.

Remote logging for log4js-ext 2.0

The biggest new feature in log4js-ext 2.0 is its support for remote logging to Java web apps.

Providing this feature means that you can perform logging in your ExtJs javascript code, and send it to the server too, where logs will be routed to Log4j, Slf4j or the Apache Commons Logger. All of them are supported.

Configuration: the server side

Steps to add server side support to your Java web app:

  1. Add log4js-ext-remoting-xxx.jar to your Java app -yes, xxx is the library version
  2. Configure the remote logging servlet, as follows:
    <servlet>
      <servlet-name>Log4jsExtServlet</servlet-name>
      <servlet-class>com.softwarementors.log4jsext.remote.Log4jsExtServlet
      </servlet-class>
    
      <servlet-mapping>
        <servlet-name>Log4jsExtServlet</servlet-name>
        <url-pattern>/remotelogrequest</url-pattern>
      </servlet-mapping>
    </servlet>
    

That’s it!

Of course, you will have to provide the logging jars for Log4j, Slf4j or the Apache Commons Logger -but you already knew that!

Configuration: the client side

You can keep your current logs as they are, there is no need to modify your logging code in the client side. That transparency is one of the reason why you are using log4js-ext for your logging needs.

All you need to do is register one or more of the new appenders: they know how to send log data to your remote application.

Here is source code that registers appenders for Log4js, Slf4j and Apache Commons Logger with the root logger: this causes all client side logs to go to the remote web app by default.

// Configure simple remote logging
Sm.log.Logger.getRoot().addAppender(
  Sm.log.remote.RemoteAppender.createLog4jAppender(
    "/log4js-ext/remotelogrequest") );
Sm.log.Logger.getRoot().addAppender(
  Sm.log.remote.RemoteAppender.createSlf4jAppender(
    "/log4js-ext/remotelogrequest") );
Sm.log.Logger.getRoot().addAppender(
  Sm.log.remote.RemoteAppender.createApacheCommonsLoggingAppender(
    "/log4js-ext/remotelogrequest") );

Now, if this has not convinced you of the power of log4js-ext, I don’t know what will do…

Cambio de discos y reinstalaci√≥n de GRUB2 en el MBR

Este mes ha tocado renovar infraestructura, e instalar un SSD más grande para las máquinas virtuales con mis proyectos, que siempre tengo en un disco extraíble conectado vía eSata/USB 3.0: de este modo siempre puedo trabajar en casa, con mi portátil, o en máquinas de terceros.

El nuevo SSD es un Sandisk Extreme de 480 Gb, con el doble de espacio que el Samsung 830 donde resid√≠an las m√°quinas virtuales, que ha ido a convertirse en el disco principal, sustituyendo al “viejo” Intel X25-M de 160 Gb.

Migración a un nuevo disco

La migración del disco viejo al nuevo ha ido sin problemas, tanto las particiones de Windows como las de Linux.

Para migrar el disco utilicé Paragon Backup & Recovery, escogiendo hacer una copia completa de todo el disco, ya que la copia partición a partición me dio problemas.

El √ļnico inconveniente fue tener que restaurar Grub en el MBR, que es quien se encarga de permitirme decidir si arranco con un sistema operativo o con otro.

Reinstalar Grub

Para restaurar Grub tuve que dar los siguientes pasos:

  • Arrancar con el CD del Linux que tengo instalado e irme a la l√≠nea de comandos.
  • Averiguar cu√°l es el disco donde se encuentra Linux: para ello, basta con listar los dispositivos, con ls /dev/sd?. En mi caso, el disco era sda
  • Averiguar cu√°l es la partici√≥n donde reside Linux: para ello, basta con mirar las particiones del disco, con cfdisk /dev/sda. En mi caso era sda5
  • Montar dicha partici√≥n: install -d /mnt/z y luego mount /dev/sda5 /mnt/z
  • Reinstalar grub: para ello, grub-install --root-directory=/mnt/z /dev/sda

Una vez hecho esto, bastó con arrancar de nuevo, y voilá -a pesar de algunos mensajes de queja del sistema.

Rendimiento

Tengo que confesar que no he notado ninguna diferencia en la velocidad entre el Sandisk, el Samsung (ambos SATA III) y el Intel, este √ļltimo de una generaci√≥n anterior y SATA II.

Y es que los SSDs de las dos/tres √ļltimas generaciones, aunque bastante diferentes en prestaciones en la teor√≠a, no muestran ninguna diferencia notable en el d√≠a a d√≠a de un desarrollador, ni a√ļn cuando tengo dos o tres m√°quinas virtuales en marcha.

A decir verdad, no es algo que no esperase: de hecho, el cambio de discos ha venido motivado por la necesidad de tener mayor espacio, no por un tema de rendimiento.

Medir consumos de energ√≠a con el ZM31

Como estoy jugando con la idea de poner una máquina que me haga de NAS y servidor web 24 horas al día, me ha parecido buena idea comprar un medidor de consumo para ver cuánto consume dicha máquina, y ver el efecto real de poner el equipo en suspensión, apagar los monitores automáticamente, etc.

Y es que si no se va con cuidado, al final del a√Īo y con un funcionamiento 24×7 puede resultar m√°s caro tener tu m√°quina que pagar un hosting decente.

La cosa es que las instrucciones del medidor han venido solo en alem√°n, y encontrar el manual en ingl√©s ha sido una aut√©ntica odisea, con el a√Īadido de que el ingl√©s deja mucho que desear.

As√≠ que aqu√≠ est√°n las instrucciones del medidor de consumo Interterk ZM31 (o ZM 31), con c√≥digo de fabricante IN16618B. Igual alg√ļn otro comprador en apuros las encontrar√°, y de paso yo tambi√©n tendr√© las instrucciones a mano dentro de unos meses.

¬ŅQu√© puedo medir con el ZM31?

Pues se pueden ver varias cosas, y se cambia de ‚Äúvista‚ÄĚ pulsando el bot√≥n MODE. Las “vistas” que hay son:

  • kWh: kilowatios hora consumidos desde que empezamos a registrar. Ver m√°s abajo esto del registro de informaci√≥n.
  • costs: coste de lo consumido, puede usar dos tarifas distintas que se pueden modificar. Ver m√°s abajo.
  • W: watios que se est√°n consumiendo en este momento.
  • W LO: watios m√°ximos consumidos desde que empez√≥ a registrar.
  • W HI: watios m√≠nimos consumidos desde que empez√≥ a registrar.

¬ŅC√≥mo empiezo a registrar datos de kwh, consumo y registro de watios m√°ximos/m√≠nimos, y c√≥mo pongo a cero estos valores de nuevo?

Para comenzar a registrar consumo: pulsar STA/STP. Las lecturas de kwh y los consumos se acumularán, y las lecturas mínima y
m√°xima de potencia (watios) se ir√°n actualizando.

Para poner a cero/resetear y parar de registrar datos: pulsar MODE + STA/STP durante 2 segundos. Hasta que volvamos a poner en modo registro no se volverá a registrar ni consumo ni valores máximo/mínimo de potencia (W).

Lógicamente, para algo como ver la potencia máxima y mínima que consume tu ordenador u otro aparato, conéctalo primero y poner en funcionamiento, y solo entonces resetea el medidor de consumo: de lo contrario, la lectura mínima de potencia siempre será cero.

¬ŅCu√°nto tiempo se ha estado conectado a la corriente vs cu√°nto tiempo he estado registrando el consumo, a√ļn desconectado?

Pulsando el bot√≥n ON TIME se conmuta entre el tiempo que llevamos registrando (en la pantalla aparece ‘REC’) y el tiempo que realmente ha estado conectado el dispositivo (en la pantalla aparece ‘ON’), que ser√° el mismo o menos, l√≥gicamente.

Es posible detener/continuar el registro pulsando STA/STP. Atención, que esto para el tiempo registrado *y* el tiempo de conexión.

¬ŅC√≥mo cambio la tarifa, para que calcule correctamente el consumo?

Pulsar MODE + ON TIME + STA/STP durante 4 segundos: entrará en modo edición de consumo.

Mientras estamos en este modo, podemos usar ON TIME y STA/STP para cambiar el valor de un dígito y para pasar de un dígito a otro. No he anotado cuál es cuál, así que os tocará hacer I+D.

Cuando terminemos, pulsar MODE, y se grabar√° la tarifa.

Hay dos tarifas distintas, ¬Ņc√≥mo escojo una u otra?

Cuando se est√© en la ‚Äúvista‚ÄĚ de consumo (costs), pulsar MODE 4 segundos, y veremos que conmuta a la otra tarifa.

Cloud Foundry y Micro Cloud Foundry para desarrolladores Spring

Las √ļltimas semanas he estado colaborando en un interesante proyecto, una prueba de concepto que inclu√≠a entre otras cosas el uso la infraestructura de Cloud Foundry para proyectos con Spring en el backend -parte de la que se ha encargado un servidor.

¬ŅQu√© es Cloud Foundry, sin marketing y para un desarrollador?

Cloud Foundry es una iniciativa detr√°s de la que est√° VMware como gran esponsor, y que ofrece soporte para ‘cloudificar’ nuestras aplicaciones con la consiguiente escalabilidad, estandarizaci√≥n de la infraestructuda y todo eso.

Dejando aparte los discursos de estrategia y m√°rketing, y centr√°ndonos en el impacto para los desarrolladores Spring, la cosa apenas se complica mucho por ello. Y esa es la gran virtud.

Cloud Foundry proporciona una infraestructura estable y est√°ndar (p.ej. Java 1.6 o 1.7, tc Server/Tomcat, Spring, etc.) que incluye diversos servicios (MySql 5.1, Redis, etc.), contra la que podemos desarrollar y desplegar nuestras aplicaciones.

Para los desarrolladores existe la posibilidad de usar como sustituto de la cosa real una m√°quina virtual que proporciona toda la infraestructura y servicios de Cloud Foundry, y que podemos usar para desarrollar en local. B√°sicamente es a esto es a lo que se llama Micro Cloud Foundry, ni m√°s ni menos.

Vale, pero ¬Ņc√≥mo afecta todo esto a mi c√≥digo Spring? Pues en muchos casos el impacto es cero: por ejemplo, en nuestra aplicaci√≥n se ataca una base de datos MySql, digamos ‘killer_demo’, con el usuario ‘myUser’ y la password ‘pwd’. ¬ŅQu√© cambios hice con respecto a una aplicaci√≥n Spring a desplegar en nuestro propio entorno? Cero. En mi caso utilic√© Spring beans para atacar MySql, usando la siguiente configuraci√≥n

    <beans:bean id="springDataSource" 
     class="org.apache.commons.dbcp.BasicDataSource">
       <beans:property name="driverClassName" 
          value="com.mysql.jdbc.Driver" />
       <beans:property name="url" 
          value="jdbc:mysql://localhost/killer_demo" />
       <beans:property name="username" value="myUser" />
       <beans:property name="password" value="pwd" />
    </beans:bean>

    <beans:bean id="springEmf"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <beans:property name="persistenceUnitName" 
           value="killer_demo_pu"/>
        <beans:property name="persistenceProviderClass" 
           value="org.hibernate.ejb.HibernatePersistence"/>
        <beans:property name="dataSource" 
           ref="springDataSource"/>
    </beans:bean>

La cosa es que cuando enviamos la aplicaci√≥n a un sistema que soporte Cloud Foundry, el correspondiente mecanismo autom√°gico le echa un vistazo a los Spring beans y los reconfigura. As√≠, el sistema ve que tenemos una fuente de datos que utiliza un usuario ‘myUser’ y una contrase√Īa ‘pwd’: si no existe una base de datos la crea autom√°ticamente, con un nombre que se saca de la manga, y por supuesto trabaja con usuarios y contrase√Īas generados del mismo modo.

Y lógicamente sustituye los valores proporcionados por nosotros por los valores que se ha sacado de la manga en los propios beans.

Obviamente, si la configuraci√≥n de la aplicaci√≥n se complica o deseamos un mayor control, puede llegar a ser necesario dar informaci√≥n espec√≠fica a Cloud Foundry, informaci√≥n que se proporcionar√° v√≠a configuraci√≥n de Spring. A√ļn as√≠, el impacto en el resto del c√≥digo fuente ser√° cero.

Como os podéis imaginar, la cosa funciona de forma similar si en lugar de usar Java+Spring se usa otra infraestructura soportada, como Scala, Grails, Node.js, etc.

¬ŅY c√≥mo configuro o despliego aplicaciones en Cloud Foundry?

Para tareas tales como desplegar y configurar la aplicaci√≥n (¬Ņcu√°nta memoria le vamos a dar?) y los servicios que usa, deberemos utilizar vmc o el correpondiente plugin de Eclipse.

Por ejemplo, para instalar myApp.war por primera vez, tendremos que ejecutar

vmc push myApp

O, para ver las aplicaciones instaladas, bastar√° con

vmc apps

Desde luego, puede ser necesario controlar el entorno de manera mucho más fina por parte de un administrador, y este puede obtener acceso a los distintos servicios mediante tunneling, algo que no tiene por qué afectar al código fuente.

Micro Cloud Foundry est√° muy bien, pero…

… eso de tener que enviar un war con los cambios mientras desarrollas no es que favorezca el desarrollo √°gil, la verdad.

Personalmente prefiero desarrollar mis aplicaciones en local, dado que me permite un desarrollo mucho, mucho más ágil: si se hace con cuidado, se puede desarrollar sin problemas la aplicación contra un Tomcat local, una base de datos local y cualesquiera otros servicios locales, y luego moverla a Micro Cloud Foundry para verificar que no hemos hecho nada raro.

Un detalle puntual: dado que Micro Cloud Foundry instala nuestra aplicación como si fuera la ROOT de Tomcat, no importa cómo llamemos al WAR que desplegamos, será conveniente que configuremos nuestra aplicación y el Tomcat local para que tenga esto en cuenta: aquí hay información relevante al respecto.