Posts tagged ‘Java’

Redondeando en Java

Si os habéis encontrado alguna vez con la necesidad de redondear un número en Java, habréis visto que no existe un método directo para hacerlo

A veces se hace multiplicando pasando a entero y dividiendo, pero no es una forma fiable.

La forma de hacerlo sería mediante el método setScale de la clase java.math.BigDecimal:


public static double round(double value, int decimalDigits) {
	BigDecimal bd = new BigDecimal(value);
	bd = bd.setScale(decimalDigits, BigDecimal.ROUND_HALF_UP);
	return bd.doubleValue();
}

Tenemos varias opciones a la hora de redondear que podemos ver en la documentación de BigDecimal.

Espero que os ayude.

27 febrero 2010 at 12:54 am Deja un comentario

Error en la comparación de String con la librería de tags de Struts2

Os voy a comentar un pequeño error que nos puede descolocar un poco cuando tratamos de comparar cadenas mediante la librería de etiquetas de Struts2 en nuestras páginas JSP.

Si hacemos una comparación con Strings al estilo de:

<s:if test="propiedad == 'SI'">
  <div>Mostrar texto</div>
</s:if>

obtendremos el resultado esperado (mostrará el texto si nuestra propiedad vale “SI”), pero si la comparación es:

<s:if test="propiedad == 'S'">
 <div>Mostrar texto</div>
</s:if>

veremos que aunque nuestra propiedad valga “S” no aparece el texto. Es decir, que cuando hacemos comparaciones de Strings de un sólo carácter nos falla. La responsable es la librería OGNL que evalúa las expresiones ya que al encontrar se un sólo carácter lo toma como un tipo Char y no un String.

Para solucionarlo nos basta cambiar las comillas:

<s:if test='propiedad == "S"'>
  <div>Mostrar texto</div>
</s:if>

o bien escapar las comillas dobles:

<s:if test="propiedad == \"S\"">
  <div>Mostrar texto</div>
</s:if>

Espero que le pueda servir a alguien.

17 diciembre 2009 at 11:12 am 5 comentarios

JUnit: Herramienta indispensable para el desarrollo Java

Hoy voy a hablar de una herramienta que debería ser de uso común para el desarrollo. Estoy hablando de JUnit, la librería de pruebas unitarias más utilizado en entornos Java.

Las pruebas unitarias consisten en desarrollar código para probar una determinada funcionalidad de nuestra aplicación.

Vamos a ver un pequeño ejemplo. Supongamos que estamos haciendo una librería matemática que incluye una funcion para calcular el factorial de un número. Podría ser una clase parecida a la siguiente:

package org.tcymu.util;

public class MathLibrary {
	public static int factorial(int n) throws IllegalArgumentException {
		int response = 1;

		if (n < 0) {
			throw new IllegalArgumentException();
		}

		if (n > 0) {
			response = n * factorial(n - 1);
		}

		return response;
	}
}

En esta entrada voy a utilizar las facilidades que da Eclipse gracias a su integración con JUnit. Para ello en la vista package sobre la clase que queremos probar hacemos botón dereco -> “New” -> “JUnit Test Case”.

Nuevo Test JUnit

Nos aparece la siguiente ventana en la que seleccionamos “New JUnit 4 test” (tened en cuenta que JUnit 4 necesita Java 1.5 o superior).

junit_2_320x360

Podemos ver que nos propone un nombre para la clase de pruebas, así como un paquete y una carpeta de fuentes (por defecto propone el mismo paquete que las fuentes, aunque podríamos elegir otro). También podemos seleccionar que nos cree los siguientes métodos de apoyo para preparar el entorno de los test o liberar recursos:

– Métodos setUp y tearDown. Los ejecuta antes de llamar a cada método de prueba en esa clase. La secuencia sería setUp, metodo1Test, tearDown, setUp, metodo2Test, tearDown.

– Métodos setUpBeforeClass y tearDownAfterClass. Estos métodos se ejecutan antes y después de todos los métodos de la clase. La secuencia sería setUpBeforeClass, metodo1Test, metodo2Test, tearDownAfterClass.

A continuación nos pide los métodos que queremos probar. En este ejemplo seleccionamos el método que queremos probar (factorial) y ninguno de los métodos de apoyo (en nuestro sencillo ejemplo no necesitamos crear ni liberar nada).

junit_3_320x360

Tras finalizar y si no tenemos la librería JUnit 4 en el Build Path nos la añade. Y por último crea el esqueleto de la clase de prueba:

package org.tcymu.util;

import static org.junit.Assert.*;

import org.junit.Test;

public class MathLibraryTest {

	@Test
	public void testFactorial() {
		fail("Not yet implemented");
	}

}

Hay que destacar que lo que realmente convierte al método en un test que ejecutará JUnit es la anotación Java @Test, al igual que lo que marcaría a los métodos de apoyo serían anotaciones como @BeforeClass, @AfterClass, @Before y @After.

Podemos observar que el método testFactorial sólo contiene la línea fail("Not yet implemented"); , por lo que si ejecutamos el test (mediante botón derecho sobre la clase de pruebas y “Run As” -> “JUnit Test” se nos abre la vista de JUnit con el siguiente resultado:

junit_4

Por tanto es hora de implementar nuestra prueba para pasar la barra al ansiado color verde. Básicamente se hacen comprobaciones de los resultados esperados frente a los recibidos mediante la clase org.junit.Assert (documentación Javadoc de JUnit).

package org.tcymu.util;

import static org.junit.Assert.*;

import org.junit.Assert;
import org.junit.Test;

public class MathLibraryTest {

	@Test
	public void testFactorial() {
		Assert.assertEquals(1, MathLibrary.factorial(0));
		Assert.assertTrue(1 == MathLibrary.factorial(1));
		Assert.assertEquals(24, MathLibrary.factorial(4));
		Assert.assertEquals(720, MathLibrary.factorial(6));

		boolean excepcionLanzada = false;
		try {
			MathLibrary.factorial(-1);
		} catch (IllegalArgumentException e) {
			excepcionLanzada = true;
		}
		Assert.assertTrue(excepcionLanzada);
	}

}

Vemos que utilizamos varios métodos para comprobar que se obtiene el resultado esperado. También podemos ver cómo probamos que se lanza la excepción esperada cuando el argumento no es válido (creo haber leído en algún sitio que se iba a mejorar la prueba de excepciones en próximas versiones, pero no consigo localizar la noticia).

Una vez que se ejecutan la prueba con éxito (la barrita verde) sabemos que el método funciona como nosotros esperamos. Ahora tras cualquier cambio en el código volveríamos a ejecutar JUnit para comprobar que no hemos roto nada. Esto nos da una gran seguridad a la hora de meter mano o refactorizar métodos complejos.

Por último no quisiera terminar la entrada sin nombrar un par de temas relacionados con las pruebas unitarias.

– Una buena prueba debe ser repetible (se debe de poder lanzar cuantas veces queramos sin afectar a nada). Por ello cada vez más se automatizan las pruebas en los procesos de integración continua de forma que antes de generarse una versión de una aplicación se corren todas las pruebas para dicha aplicación.

– Existe un modelo de desarrollo que promueve que primero se escriban las pruebas y después el código. Es el llamado Desarrollo Guiado por Pruebas o Test Driven Development (TDD).

Espero que os haya gustado esta pequeña introducción.

23 octubre 2009 at 8:51 am Deja un comentario

Descripción de iBatis: ¿Qué es?, ¿para qué sirve?

iBatis es un framework de persistencia para Java, aunque con bastantes diferencias respecto a Hibernate, el gran dominador en este segmento.

ibatis

La principal diferencia entre iBatis e Hibernate es que iBatis no es un ORM (Mapeo Objeto Relacional). Por lo tanto Hibernate genera el SQL para mapear objetos a tablas de la base de datos, mientras que en iBatis el SQL lo tendremos que escribir nosotros. Si tenemos un modelo de datos (nuestras tablas de BBDD) bastante diferente a nuestro modelo de negocio (nuestras clases Java) Hibernate nos puede dar bastantes dolores de cabeza.

Lo que sí hace iBatis es lo siguiente:

  • Ejecuta el SQL escrito por nosotros mediante JDBC[] (Java DataBase Connectivity), por lo que nos olvidamos de los múltiples try/catch.
  • Mapea propiedades de objetos a parámetros para las PreparedStatement (sentencias SQL parametrizables).
  • Mapea los resultados de una query a un objeto o una lista de objetos.

En esta entrada ahora podría poner un pequeño ejemplo de utilización de iBatis, pero eso es lo que podemos encontrar en la documentación de iBatis en español.

Como resumen de lo que se puede ver en dicah documentación comentar:

  • Tendremos un fichero de configuración de iBatis (SqlMapConfig.xml habitualmente) en el que indicaremos algunos parámetros de iBatis (como si está activo el cacheado), el DataSource (soporta varios tipos de DataSource) y los distintos mapeos SQL.
  • Tendremos al menos un fichero de mapeo xml, en el que se indican las sentencias SQL, los parámetros a mapear o los resultados a mapear.
  • Tendremos una clase que implementa SQLMapClient que es el interface que contiene los métodos para realizar las sentencias SQL (queryForObject, queryForList o delete entre otros muchos). Esta clase la habremos obtenido mediante SqlMapClientBuilder.

Otro punto fuerte de iBatis es su integración con Spring. Para trabajar con iBatis integrado en Spring los pasos a seguir serían los siguientes:

  • El DataSource lo definiremos como un Bean en los archivos de definición de Spring. El resto del SqlMapConfig.xml y los xml de mapeo seguirían igual.
  • Spring proporciona el SqlMapClientFactoryBean y SqlMapClientTemplate. A la factoría le proporcionaremos el DataSource y al template le proporcionamos la factoría. Ese template es la clase que nos proporciona los mismo métodos que el SQLMapClient visto anteriormente.

También quiero nomrar en esta entrada a Ibator, que es una herramienta para generar código para iBatis. A partir de una tabla de base de datos es capaz de generar el xml de mapeo, las clases Java que representan al modelo de datos e incluso los DAO (Objetos de Acceso a Datos). Viene incluido un plugin para Eclipse. Aunque no la he utilizado, puede ser una herramienta útil en ocasiones.

Y por último decir que aunque sólo he hablado de iBatis para Java, desde la página del proyecto nos podemos descargar versiones para .Net o Ruby.

24 junio 2009 at 11:05 pm 3 comentarios

Introducción a Terracotta (y 2)

En la anterior entrada sobre Terracotta pusimos un pequeño ejemplo con un servidor y tres clientes (un productor de tareas y dos consumidores), aunque todo corriendo en la misma máquina. Además también dejamos el ejemplo dando un feo aviso porque todos los clientes intentaba utilizar el mismo archivo de log.

En esta pequeña continuación vamos a utilizar el mismo ejemplo pero lo iremos mejorando, primero eliminando el aviso de los logs y después utilizando varias máquinas.

terracotta

Para llevar a cabo esta tarea vamos a utilizar un único tc-config.xml, que lo cargará el servidor y los clientes lo tomarán de él. Para ello es necesario arrancar el servidor (start-tc-server) desde el directorio en el que tenemos el tc-config.xml o mediante la opción -f:

start-tc-server.bat -f /ruta/al/fichero/tc-config.xml (será .bat o .sh según estemos en Windows o Unix)

Pero antes vamos a hacer unos cambios en el archivo de configuración. Le vamos a añadir la lista de servidores y le vamos a configurar el directorio de logs en función de una variable de entorno. En la web de Terracotta tenemos una guía y referencia de la configuración en la que podemos ver las descripciones de esos campos y muchos otros.

<?xml version="1.0" encoding="UTF-8"?>
<tc:tc-config xmlns:tc="http://www.terracotta.org/config">
  <servers>
    <server host="169.254.122.220"/>
  </servers>
  <clients>
    <logs>logs-%(tcymu_name)</logs>
  </clients>
  <application>
    <dso>
      <roots>
        <root>
          <field-name>org.tcymu.terracotta.TasksQueue.queue</field-name>
        </root>
      </roots>
      <instrumented-classes>
        <include><class-expression>org.tcymu.terracotta.Task</class-expression></include>
      </instrumented-classes>
    </dso>
  </application>
</tc:tc-config>

Como vemos hemos añadido la sección de servidores y la de clientes. En la de servidores ponemos la dirección IP de nuestro único servidor. En la parte de clientes configuramos el nombre del fichero de logs en función de la variable de entorno tcymu_name.

Ya podemos arrancar el servidor como hemos visto un poco más arriba. También arrancamos el generador de tareas con el comando mostrado a continuación:

dso-java.bat -Dtc.config=169.254.122.220:9510 -Dtcymu_name=creator -cp classes org.tcymu.terracotta.TaskCreator

Las diferencias con respecto al que utilizamos en la primera parte son:

  • Se le pasa la dirección del servidor (con su puerto por defecto en este caso) de la que va a tomar el tc.config.xml.
  • Se le pasa la variable de entorno que se utiliza para nombrar el archivo de logs.

Utilizaremos un comando similar para arrancar el primero de los consumidores de tareas, variando sólo la clase a arrancar y el valor de la variable de entorno para el fichero de logs.

Por supuesto al tomar el tc.config.xml de un servidor a través de una dirección IP podemos arrancar el segundo consumidor en otra máquina (en este caso un openSUSE virtualizado sobre VirtualBox):

dso-java.sh -Dtc.config=169.254.122.220:9510 -Dtcymu_name=resolver2 -cp classes org.tcymu.terracotta.TaskResolver

terracotta2_1

Con esto terminamos esta pequeña continuación.

16 abril 2009 at 12:39 pm Deja un comentario

Introducción a Terracotta: cluster a nivel máquina virtual

En esta entrada voy a presentaros Terracotta. Terracotta se distribuye bajo una doble licencia libre-comercial. Terracotta es una herramienta de cluster a nivel de máquina virtual Java (JVM) o como dicen en su web una memoria distribuida en red o NAM (Network Attached Memory por similitud con Network Attached Storage). Esto quiere decir que podemos compartir objetos o parámetros de objetos entre distintas máquinas virtuales Java, incluso corriendo en distintas máquinas. Esto se logra mediante una arquitectura cliente-servidor (transparente a nuestra aplicación) por un lado y un cargador de clases (ClassLoader) especial. Terracotta también permite “clusterizar” ese servidor que hemos nombrado para entornos de alta disponibilidad. Señalar también que Terracotta no utiliza la serialización Java si no un intercambio de los parámetros que se modifican en cada caso, de forma que se minimice el tráfico en la red. Tras esta pequeña introducción teórica vamos a ver un pequeño ejemplo. Creamos una pequeña clase que representa una tarea a realizar por nuestra aplicación:

package org.tcymu.terracotta;

public class Task {
	private long duration;
	private long id;

	public Task(long id, long duration) {
		this.id = id;
		this.duration = duration;
		System.out.println("Nueva tarea " + id + " de duracion " + duration);
	}

	public void run() {
		System.out.println("Iniciando tarea " + id + " de duracion " + duration);
		try {
			Thread.sleep(duration);
		} catch (Exception e) {}
		System.out.println("Finalizando tarea " + id);
	}

}

y una que representa la cola con las tareas que hay que realizar:

package org.tcymu.terracotta;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class TasksQueue {
	private static TasksQueue instance;
	private BlockingQueue queue = new LinkedBlockingQueue(5);

	public static TasksQueue getInstance() {
		if (instance == null) {
			instance = new TasksQueue();
		}
		return instance;
	}

	private TasksQueue() {
	}

	public BlockingQueue getQueue() {
		return queue;
	}
}

Finalmente, creamos otras dos clases, una crea tareas y otra las resuelve:

package org.tcymu.terracotta;

import java.util.Random;

public class TaskCreator {
	private static long id = 1;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Random random = new Random();
		TasksQueue tasksQueue = TasksQueue.getInstance();
		tasksQueue.getQueue().clear();
		while (true) {
			//Duracion aleatoria 1 a 10 segundos
			long duraction = (random.nextInt(10) + 1) * 1000;
			try {
				tasksQueue.getQueue().put(new Task(id++, duraction));
				Thread.sleep(3000); //Una tarea cada 3 segundos
			} catch (InterruptedException e) {}
		}
	}
}
package org.tcymu.terracotta;

public class TaskResolver {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		TasksQueue tasksQueue = TasksQueue.getInstance();
		while (true) {
			try {
				Task task = tasksQueue.getQueue().take();
				task.run();
			} catch (InterruptedException e) {}
		}
	}
}

Como podemos ver, son clases normales, sin nada especial que resaltar. Eso sí, si ejecutamos el creador de tareas o el consumidor, lógicamente vemos que no se relacionan entre ellas. Las vamos a relacionar mediante Terracotta, y el vínculo entre ellas será la cola que es el elemento común.

Lo primero que necesitamos es descargarnos la edición libre (ES) desde la sección de descargas de Terracotta. Yo he utilizado la versión ES 2.7.3. Aparte de eso, lo único que he hecho es añadir el directorio bin de Terracotta al path para poder utilizar sus comandos más cómodamente. Como hemos dicho, Terracotta necesita un servidor y es el momento de arrancarlo. Para ello abrimos una consola y ejecutamos el script start-tc-server (está en el directorio bin que hemos añadido al path y existe en versión windows y versión unix/linux).

terracotta_1

Ahora creamos el archivo de configuración que le indica a Terracotta cuáles son los que se guardan en la memoria de red. El fichero lo llamo tc-config.xml y lo voy a poner en el raíz  de mi proyecto Eclipse, aunque podría ir en cualquier sitio:

<?xml version="1.0" encoding="UTF-8"?>
<tc:tc-config xmlns:tc="http://www.terracotta.org/config">
  <application>
    <dso>
      <roots>
        <root>
          <field-name>org.tcymu.terracotta.TasksQueue.queue</field-name>
        </root>
      </roots>
      <instrumented-classes>
        <include><class-expression>org.tcymu.terracotta.Task</class-expression></include>
      </instrumented-classes>
    </dso>
  </application>
</tc:tc-config>

Primero le indicamos el objeto raíz que forma el cluster (cualquier cosa que se obtenga a partir de ese objeto también forma parte del cluster). También le indicamos las clases que Terracotta tiene que controlar (instrumented-classes), la clase Task al formar parte del cluster debe ser instrumentalizada. Para arrancar el creador de tareas ejecuto el siguiente comando en una consola situada en el raíz del proyecto:

dso-java -cp classes org.tcymu.terracotta.TaskCreator

El comando dso-java es un comando de Terracotta que tras preparar el entorno para la ejecución en cluster llama al comando java de manera normal. Por eso con esa línea estamos fijando el classpath (a classes en este caso) y ejecutando la clase TaskCreator.

Hay que señalar que dso-java (y también  start-tc-server) toman el fichero tc-config.xml del directorio desde el que se llama (aunque hay otras opciones de trabajar con los ficheros de configuración de Terracotta). Por eso ejecuto el comando lo he ejecutado en el raíz del proyecto donde está el tc-config y el directorio classes con la compilación de las clases que hace Eclipse. Sin embargo el servidor lo he ejecutado desde cualquier consola, de forma que arranca sin tomar ese tc-config. El resultado de la ejecución en el que podemos ver cómo se crean tareas es:

terracotta_2

Y ahora arrancamos el consumidor de tareas, también desde una consola situada en el raíz del proyecto. Utilizamos el siguiente comando:

dso-java -cp classes org.tcymu.terracotta.TaskResolver

terracotta_3

Podemos ver que lo único que cambia es la clase a ejecutar. Nos aparece un aviso respecto a que el archivo de logs está en uso, lo que se debe a que hemos arrancado varios nodos en la misma máquina. De momento no me preocupo por ello.  Nuestro consumidor empieza a resolver tareas, aunque muy probablemente no a una velocidad suficiente. Es el momento de escalar nuestra aplicación y arrancar un segundo consumidor. Abrimos otra consola nuevamente en el directorio raíz y volvemos a ejecutar el comando de arranque del consumidor. Ahora vemos que los consumidores van resolviendo tareas simultáneamente, lo que sin duda es una forma bastante fácil de escalar.

Con esto termino este pequeño ejemplo que no pretende nada más que mostrar las bondades de Terraccotta con un ejemplo funciona. Más adelante ya lo complicaremos.

31 marzo 2009 at 6:31 pm 1 comentario

Apache Felix Web Console

En este blog ya ha aparecido Apache Felix en varias de las entradas relacionadas con OSGi. Hemos visto varios de sus comandos e instalado y arrancado módulos. Siempre con su interfaz de línea de comandos que es la que se utiliza normalmente.

Pero dando una vuelta por la web de Felix, he visto el subproyecto Apache Felix Web Console, que como su nombre indica pretende ser una interfaz web para Felix. En esta entrada os cuento cómo la he hecho funcionar. Para abrir boca os muestro el resultado final.

felixwebconsole_1_640x470

En la página del subproyecto aparece casi toda la información necesaria. Se nos indica que la única dependencia obligatoria es tener un Http Service instalado y nos muestra algunas alternativas. El Http Service de Felix todavía no tiene una versión publicada por lo que yo me decidí por OPS4J Pax Web (por cierto, curioso e interesante el proyecto OPS4J en su conjunto).

Tras descargar pax-web-service-0.5.2.jar (como se explica en su sitio web, el pax-web-service incluye ya el jetty y todo lo necesario), lo instalé en Felix (install file:////d:/felix-1.4.0/bundle/pax-web-service-0.5.2.jar) y lo intenté arrancar, pero me apareció el siguiente error:

org.osgi.framework.BundleException: Unresolved constraint in bundle 22: package; (package=javax.servlet)

Esto se soluciona si descargamos e instalamos el módulo org.osgi.compendium-1.2.0.jar desde la web de Felix. Este módulo es sólo una agrupación de clases de OSGi. De hecho es casi lo mismo que contiene el módulo osgi.cmpn.jar descargable desde la web de OSGi (requiere registro). Tras instalarlo tendremos esa dependencia cumplida y podremos arrancar el OPS4J Pax Web.

Ahora podemos descargar el módulo con la consola web (org.apache.felix.webconsole-1.2.2.jar), instalarlo y arrancarlo. Un apunte respecto a la configuración del módulo. En el archivo config.properties de nuestra instalación de Felix, aparece una propiedad (org.osgi.service.http.port) que realmente es configuración del servicio de Http. En ella se indica el puerto a escuchar (el 8080 por defecto).

Yo no he dado valor a ninguna otra de las propiedades de configuración, ni de Pax Web Service ni de We Console.

Ahora apuntamos nuestro navegador a http://localhost:8080/system/console (la ruta se podría modificar mediante configuración) y entramos con admin/admin (también modificable por configuración) y ya vemos el aspecto de nuestra consola web.

En la pestaña de módulos (“bundles”) vemos que podemos parar, arrancar, instalar actualizar o desinstalar módulos. También podemos ver información detallada sobre cada módulo (versión, paquetes exportados e importados, etc.). En otras pestañas podemos ver el estado de la configuración (“Configuration Status”), ver la licencia de los módulos instalados (“Licenses”), tener acceso a una línea de comandos en la página (“Shell”) o ver información y controlar el sistema en sí (“System Information”).

También tenemos una pestaña para la gestión de repositorios de módulos. En el mismo archivo config.properties que hemos comentado con anterioridad se añade el repositorio de Felix (propiedad obr.repository.url). Yo para que se pudiera conectar al servidor he tenido que añadir durante el arranque las propiedades del proxy tras el que estoy (-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -Dhttp.proxyAut=user:pass), tal como se explica en la página del OSGi Bundle Repository de Felix. Desde esta pestaña se pueden añadir nuevos repositorios o instalar módulos desde los repositorios instalados.

felixwebconsole_2_640x472

Por último, señalar que tenemos otras pestañas (“Configuration”, “Deployment Packages” o “Event Admin”) cuya funcionalidad se ve limitada si no tenemos el servicio correspondiente instalado. Pero para hablar de esos servicios ya habrá otras entradas.

16 marzo 2009 at 9:49 pm Deja un comentario

Entradas antiguas


Mi perfil

View Miguel Orbegozo's profile on LinkedIn

Feedjit

Feeds

Otros…

BlogESfera Directorio de Blogs Hispanos - Agrega tu Blog

Bitacoras.com

Add to Technorati Favorites