Archive for julio, 2008

Encontrar la ruta absoluta de un jar de mi aplicación

Hola, tenía uno de esos problemas tontos de los que uno está seguro que tiene que existir una solución más sencilla o elegante, pero que no encuentra.

Buscaba la ruta absoluta de un jar de mi aplicación para posteriormente leer una propiedad dentro de su descriptor MANIFEST.MF.

El caso es que a través del ClassLoader se puede localizar un recurso dentro del classpath de nuestra aplicación, pero claro, un jar en sí es parte del classpath pero no está dentro del classpath.

Para solucionar esto, lo que he hecho es localizar una clase en concreto del jar que quiero localizar:


URL url = ClassLoader.getSystemResource("org/apache/commons/pool/BaseObjectPool.class");

Esto nos da una ruta del estilo de:


jar:file:/D:/lib/jakarta-commons/commons-pool-1.2.jar!/org/apache/commons/pool/BaseObjectPool.class

Por lo que ahora bastará eliminar las partes sobrantes, el jar: del principio y la referencia a la clase que hemos utilizado para encontrar el jar. Con ello ya tenemos la referencia al jar y podemos leer la propiedad que buscamos del MANIFEST.

String url2 = url.toString().substring(4, url.toString().indexOf("!"));
JarFile ficheroJar = new JarFile(new File(new URL(url2).toURI()));
String version = (String)ficheroJar.getManifest().getMainAttributes().getValue("Implementation-Version");

Eso es todo. Sólo decir que seguramente existan mejores maneras de hacer esto. Si conoces una o encuentras una mejor, por favor,compártelo con todos mediante un comentario en esta entrada.

21 julio 2008 at 4:12 pm 3 comentarios

Joda Time: rediseñando las librerías de fechas en Java

Aunque había oído hablar hace tiempo de Joda Time, acabo de profundizar algo más en esta librería para el manejo de fechas en Java gracias a este buen artículo de OCI ( en inglés).

La utilización de fechas en Java siempre ha tenido algunos problemas asociados, desde la molesta aunque salvable asignación de los meses desde cero (el mes 1 es febrero) hasta la complejidad para realizar algunos cálculos relativamente simples como el cálculo de días entre dos fechas.

Para solucionar estos problemas nació Joda Time y además ahora ha sido el punto de partida del JSR 310 (Java Specification Request) por lo que algún día lo podríamos encontrar como el estándar en el lenguaje.

Joda Time define los llamados instantes, que representan un día y hora determinados en un lugar y calendario determinados. Es decir, una definición sin posibilidad de confusión. La clase más utilizada para definir un instante es DateTime.

Un segundo concepto que define Joda Time son los parciales, compuestos por partes de un instante, y que por tanto no definen univocamente una fecha. Por ejemplo LocalDateTime no incluye información referente a la zona horaria o el calendario.

Otro cocepto importante en Joda Time son los intervalos, definidos por dos instantes.

Finalmente, los últimos conceptos que vamos a ver son la duración y los periodos. Duración representa una cantidad de milisegundos, mientras que un periodo puede estar definido en días, meses u otras unidades (o un conjunto de ellas).

Bueno, y como al final siempre es mejor una imagen (o un trozo de código) que mil palabras, pues vamos a mostrar algunos ejemplos.

public void daysBetween() {
		//Instante actual en la cronología por defecto
		//y en la zona horaria del sistema
		DateTime today = new DateTime();

		//Instante a medianoche del 1 de enero de 2008
		DateMidnight jan01 = new DateMidnight(2008, 1, 1);

		System.out.println("Días desde el 1 de enero: " + Days.daysBetween(jan01, today).getDays());
	}

Como vemos, es bastante sencillo calcular los días entre dos instantes determinados.

Vamos a ver con otro ejemplo lo sencillo que resulta calcular nuevas fechas, olvidándonos de cálculos de días por mes u otras complicaciones.

public void incrementDates() {
		//Instante a medianoche del 11 de junio de 2008
		DateMidnight jun11 = new DateMidnight(2008, 6, 11);
		
		//Le añadimos 5 días
		DateMidnight plus5Days = jun11.plusDays(5);
		//Le añadimos un mes
		DateMidnight plusMonth = jun11.plusMonths(1);
		//Le añadimos 6 meses
		DateMidnight plus6Month = jun11.plusMonths(6);
		
		System.out.println("Fecha inicial: " + jun11.toString());
		System.out.println("Fecha más 5 días: " + plus5Days.toString());
		System.out.println("Fecha más 1 mes: " + plusMonth.toString());
		System.out.println("Fecha más 1 mes: " + plus6Month.toString());
	}

Esto produce la siguiente salida:

Fecha inicial: 2008-06-11T00:00:00.000+02:00
Fecha más 5 días: 2008-06-16T00:00:00.000+02:00
Fecha más 1 mes: 2008-07-11T00:00:00.000+02:00
Fecha más 1 mes: 2008-12-11T00:00:00.000+01:00

Fijaos en el +2 debido a que mi zona horaria es GMT+1 y estamos en horario de verano (daylight savings), pero que en noviembre ya estamos fuera del horario de verano.

Por último, vamos a ver alguna facilidad más que nos da Joda Time:

public void checkFeatures() {
		DateTime today = new DateTime();
		
		DateTime.Property month = today.monthOfYear();
		System.out.println("Mes: " + month.getAsShortText());
		System.out.println("Mes: " + month.getAsText());
		System.out.println("Mes: " + month.getAsText(Locale.ENGLISH));
		
		DateTime.Property week = today.weekOfWeekyear();
		System.out.println("Semana: " + week.getAsText());
	}

Que provoca la siguiente salida:

Mes: jul
Mes: julio
Mes: July
Semana: 29

Y hasta aquí llega mi pequeña revisión de esta librería que nos puede facilitar bastante el trabajo con fechas en Java.

15 julio 2008 at 12:05 pm 6 comentarios

Mi primera aplicación CakePHP (1)

Tras hacer una presentación y ver su instalación, empezaremos a realizar una aplicación de ejemplo utilizando CakePHP. Me he decidido a empezar un gestor de enlaces al estilo de delicious o mister wong.

No voy a utilizar algunas utilidades de CakePHP como la herramienta de línea de comando bake (a la que espero dedicar una entrada en el futuro).

Lo primero que hacemos es crear una tabla en la base de datos para nuestros enlace. Para ello entramos en phpMyAdmin con el usuario que creamos en el paso de instalación y creamos una tabla. Nos queda algo así:

Hay que destacar algunas características en la tabla creada:

  • El nombre de la tabla no es negociable. Es el plural (en inglés) del modelo al que representa.
  • La clave primaria id es obligatoria. El nombre tampoco es negociable.
  • El campo created también es de nombre fijo.

En general estas limitaciones son salvables, pero si seguimos el estándar de CakePHP será todo más sencillo y ahorraremos líneas de código.

Lo primero creamos el modelo (por convención lo guardamos en app/models como link.php):

class Link extends AppModel {
	var $name = 'Link';

	var $validate = array(
        'title' => array(
            'rule' => array('maxLength', '30'),
            'allowEmpty' => false,
            'message' => 'Titulo no valido'
		),
        'url' => array(
			'rule' => 'url',
            'required' => true,
            'message' => 'Debe introducir un email correcto'
		)
    );
}

Como podemos ver, un modelo en principio es bastante sencillo. La parte que más líneas acapara es la validación, una de las facilidades que nos aporta CakePHP. En este caso, al título le damos una longitud máxima y a la url le forzamos a que sea una url 🙂 .

Ahora vamos con el controlador (igualmente por convención lo guardamos en app/controllers como links_controller.php):

class LinksController extends AppController {

	var $name = 'Links';

	function add() {
		if (!empty($this->data)) {
			if ($this->Link->save($this->data)) {
				$this->flash('Enlace añadido.','/links');
			}
		}
	}

	function index() {
		$this->set('links', $this->Link->findAll());
	}
}

El controlador probablemente sea la parte más compleja de nuestra aplicación. En este caso hemos definido dos acciones, una que hemos llamado index (acción por defecto de ese controlador) que nos mostrará todos los enlaces y add que nos permitirá añadir un enlace. Destacamos los siguientes puntos:

  • Con !empty($this->data) comprobamos si hemos recibido el formulario de añadir enlace con información.
  • Cuando se hace referencia a $this->Link, estamos haciendo referencia al modelo, y utilizamos sus métodos, tanto para guardar un nuevo enlace (save) como para recuperar los enlaces existentes (find('all')).
  • Con $this->set() le pasamos información a la vista correspondiente.
  • $this->flash() es un método bastante utilizado en CakePHP para hacer una transición a otra página tras mostrar un mensaje.

Por último necesitaremos dos vistas, una por cada acción del controlador. Ambas las pondremos en app/views/links y serán add.thtml e index.thtml. Primero vemos el index:

<h1>Enlaces disponibles</h1>
<?php foreach ($links as $link): ?>

<a href="<?php echo $link&#91;'Link'&#93;&#91;'url'&#93;; ?>"><?php echo $link&#91;'Link'&#93;&#91;'title'&#93;; ?></a>

Añadido: <?php echo $link&#91;'Link'&#93;&#91;'created'&#93;; ?>
<?php endforeach; ?>

<?php echo $html->link('Añadir enlace', '/links/add');?>

Destacamos la utilización de $links suministrado por el controlador mediante el método set(). También la utilización del Helper html, en este caso para crear un enlace ($html->link()).

Y finalmente la vista de añadir:

Añadir
<?php
echo $form->create('Link');
echo $form->input('title');
echo $form->input('url');
echo $form->end('Agregar');
?>

Aquí destacamos la utilización del Helper de formularios, para la creación de todos los elementos del formulario.

Si ahora apuntamos nuestro navegador al proyecto CakePHP y añadimos /links/ al final de la ruta (en CakePHP una ruta /controller/action hace referencia al controlador controller método action) nos dirigimos a la acción por defecto del controlador links y obtenemos:

Destacamos algunas cosas:

  • El diseño de cabecera y pie nos lo ha colocado CakePHP. Esto lo modificaremos creando un layout en /app/views.
  • En la parte inferior nos aparece información sobre las querys ejecutadas. Esto se debe al nivel de debug que tenemos seleccionado. Mientras desarrollamos yo aconsejo no cambiarlo. Para un sitio en producción lógicamente pondremos el nivel a 0.
  • Tenemos un enlace que apunta a la acción add del controlador links (/links/add).
  • La lista de enlaces está vacía. Claro, ¡CakePHP tampoco hace magia!.

Si pinchamos en el enlace de añadir, vemos nuestro formulario de añadir:

Podemos hacer algunas pruebas de la validación que CakePHP nos aporta y que nosotros hemos indicado en el modelo (incluido el mensaje que aparece). Cuando finalmente introducimos unos valores válidos llegamos a:

Esta es la pantalla que nos ha generado el $this->flash() que vimos en el controlador. Su funcionamiento también depende del nivel de debug. En el nivel de desarrollo, el mensaje que aportamos es un enlace a la ruta también indicada en $this->flash().

Finalmente ya tenemos el listado de enlaces con contenido:

En la siguiente entrada de esta serie, continuaremos con nuestro gestor de favoritos: solucionaremos algunas pegas que han aparecido hasta ahora, añadiremos comentarios sobre los enlaces de la lista y alguna cosa más.

¡Manteneos en línea!

Actualización: Segunda parte

1 julio 2008 at 9:36 am 40 comentarios


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