AOWS

Just another adrian’s weblog

Archivo para la categoría "Uncategorized"

Inyección de dependecias con @Autowired, @Qualifier y @Resource

sin comentarios

Spring proporciona dos anotaciones para la inyección de dependencias: @Autowired y @Qualifier.

@Autowired funciona por tipo, y es que ella sola se encarga de buscar un bean de la clase correspondiente:

@Autowired
private ExampleService exampleService;

La gran limitación de esta anotación es que no es posible hacer inyección por nombre (¿qué pasa si tenemos varios beans del mismo tipo?), por lo que la solución pasa por complementarla con @Qualifier:

@Autowired
@Qualifier("exampleService")
private ExampleService exampleService;

Mientras no llega la versión 3.0 de Spring, una alternativa menos verbosa sería usar la anotación @Resource (perteneciente al JSR-250):

@Resource(name="exampleService")
private ExampleService exampleService;

Escrito por adrian

3 Noviembre, 2009 a 10:25

Escrito en Uncategorized

Etiquetado con ,

Google Collections

sin comentarios

Una de las cosas más irritantes de Java es su API de colecciones. Es verdaderamente frustante tener que usar tal cantidad de verbosidad y ceremonia para simplemente inicializar una lista, y no digamos ya para realizar operaciones más complejas como filtrar los elementos.

Si el cambiar a un lenguaje dinámico no es solución, quizá ayude la librería del buscador gigante Google Collections.

Un par de ejemplos rápidos, primero incializando una lista:

List<Integer> list1 = Lists.newArrayList(1, 2, 3); // nótese que List es de tipo java.util.List
System.out.println(Joiner.on(", ").join(list1)); // imprime "1, 2, 3"

y otro utilizando un filtro:

List<Integer> list = Lists.newArrayList(1, 2, 3, null);
Iterable<Integer> filter = Iterables.filter(list, new Predicate<Integer>() {
   public boolean apply (Integer input) {
      return input == null || (input > 2);
   }
});
System.out.println(Joiner.on(", ").useForNull("100").join(filter)); // imprime 3, 100

Google Collections está disponible en la versión 1.0-rc2 a través de Maven:

<dependency>
    <groupId>com.google.collections</groupId>
    <artifactId>google-collections</artifactId>
    <version>1.0-rc2</version>
</dependency>

o en descarga directa desde su web.

Como vemos no pretende reemplazar a las colecciones nativas de Java, sino que las complementa, las extiende e incluso proporciona alguna nueva.

Enlace | Google Collections
Vídeo presentación | Parte 1 (~40min) y Parte 2 (~53min)

Escrito por adrian

14 Septiembre, 2009 a 22:56

Escrito en Uncategorized

Etiquetado con , ,

Aprendiendo Groovy && Grails

con un comentario

Ya hacía tiempo (algo así como 3 meses) que no escribía nada; el verano, la jornada intensiva y una mudanza tienen parte de culpa :) .

El caso es que después de hacer el examen de SCJP veo Java por todas las esquinas, así que he decidido que es hora de aprender algo nuevo. Mi primera opción siempre fue Ruby, pero tras varios intentos infructuosos he acabado dejándolo y apostando por Groovy (al menos el cambio no es tan brusco).

Ahora mismo estoy enfrascado con Grails in Action, y estoy realmente sorprendido con el lenguaje y con el framework (aunque de Grails sólo he visto un par de cosas). Basta un ejemplo para hacerse una idea:

def sortItems(items, property) {
    items.sort { a, b -> a."${property}" <=> b."${property}" }
}
class Person { String name }
people = [ new Person(name: "Adrián"), new Person(name: "Rubén"), new Person(name: "Lucas") ]
sortItems(people, "name").each { print it.name + " " }
// salida: "Adrián Lucas Rubén"

En las escasas 5 líneas de aquí arriba:

  • Se declara un método para ordenar una colección según una propiedad de los objetos. Esto mismo en Java supondría unas cuantas líneas más (clase anónima implementando Comparator, introspección…).
  • Se declara una clase Person con una única propiedad. No hay getters ni setters, se construyen automáticamente.
  • Se crea una lista con 3 personas. Todo en una sola línea, sin necesidad de crear una colección indicando su interfaz, su implementación concreta, y luego añadir de uno en uno los elementos (o crear un array para añadirlos todos).
  • Se ordena la lista anterior según el nombre de las personas, y se imprime esta propiedad.

Buena muestra del potencial del lenguaje, que no olvidemos se ejecuta sobre la JVM y se puede usar sin problemas en nuestros proyectos Java, al que por el momento sólo veo ventajas.

En definitiva, aconsejado echarle un vistazo para todos aquellos que trabajen con la plataforma Java (y sin olvidar otros lenguajes más que interesantes, como Clojure o Scala). Seguiremos informando.

Escrito por adrian

20 Agosto, 2009 a 22:20

Escrito en Uncategorized

Etiquetado con ,

Sobreescribir métodos estáticos en Java

con un comentario

Menudo título más puñetero para este post… y es que los métodos estáticos no se pueden sobreescribir en Java, en realidad se ocultan. Aunque esta cuestión es algo compleja.

Empecemos con los ejemplos:

class A {
    static void method1() {
        System.out.println("method1 from A");
    }
}

class B extends A {
    static void method1() {
        System.out.println("method1 from B");
    }
}

Si ahora creamos instancias de cada una de estas clases, vemos como parece que el método de B sobreescribe a A:

A a = new A();
a.method1(); // imprime "method1 from A"

B b = new B();
b.method1(); // imprime "method1 from B"

Pero la gran y enorme diferencia entre sobreescribir y ocultar sale a la luz cuando queremos hacer uso del polimorfismo:

void someMethod(A a) {
    a.method1();
}

// ...

B b = new B();
someMethod(b); // imprime "method1 from A"

Si el método estuviera realmente redefinido por B, entonces el código anterior debería imprimir "method1 from B". Pero como vemos esto no ocurre…

Lo que realmente está pasando guarda relación con el “fallo” de diseño de Java en el acceso a los miembros estáticos. La llamada a method1 se hace sobre el tipo sin importar si la variable tiene una referencia a una instancia o no ni de qué tipo sea ésta. Y someMethod sólo sabe que la variable es de tipo A, por lo que se ejecuta el método estático de esta clase.

Este tipo de llamadas deberían hacerse siempre sobre la clase y no sobre una instancia:

void someMethod(A a) {
    // a.method1(); <- NO
    A.method1();
}

Por otra parte, si queremos acceder al method1 de A desde B tenemos dos opciones, la primera la acabamos de ver y la segunda es utilizando super (desde un método no estático, claro):

class B extends A {
    static void method1() {
        A.method1(); // imprime "method1 from A"
        super.method1(); // error! no se puede acceder desde un método estático
        method1(); // ups, bucle infinito!
    }
    void method2() {
        A.method1(); // imprime "method1 from A"
        super.method1(); // imprime "method1 from A"
        method1(); // imprime "method1 from B"
    }
}

Ya por último un par de notas. Un método de instancia no puede sobreescribir ni ocultar a otro estático, y viceversa un método de clase no puede sobreescribir ni ocultar a otro de instancia. Cualquiera de estas situaciones se traduce en un error de compilación.

¿Enrevesado? Pues acabamos de empezar… welcome to Java world!

Escrito por adrian

21 Mayo, 2009 a 20:46

Escrito en Uncategorized

Log con plantillas de código en Eclipse

con 5 comentarios

Lo más fácil para usar un logger en nuestras clases en Eclipse es crear una plantilla de código que inserte automáticamente el código y las importaciones necesarias.

Para crear una plantilla o “template” tenemos que entrar en Preferencias -> Java -> Editor – > Templates:

Plantillas de código en Eclipse

Creamos entonces una nueva plantilla para declarar e instanciar nuestro logger:

${imp:import(org.slf4j.Logger,org.slf4j.LoggerFactory)}
private static final Logger log = LoggerFactory.getLogger(${enclosing_type}.class);

Ojo: los imports automáticos están disponibles a partir de Eclipse Ganymede (3.4).

Y ya que estamos, creamos otra plantilla con una función de guarda para depuración:

if (log.isDebugEnabled())
	log.debug("${cursor}");

Programar mediante autocompletado, qué bonito es.

Escrito por adrian

21 Mayo, 2009 a 19:28

Escrito en Uncategorized

Accediendo a miembros estáticos de una clase desde una instancia

con un comentario

En Java es posible acceder a miembros estáticos (ya sean métodos o propiedades) de una clase desde una instancia de la misma (al contrario de lo que ocurre en C# o Ruby, por ejemplo). Nada mejor que mostrarlo en código para verlo:

String cadena = "cadena";
// el método valueOf es un método estático de la clase String
cadena.valueOf("otra cadena");

Esto está permitido, aunque el compilador lanza un warning para advertir de la situación; es algo que debería evitarse y que muchos piensan es un error de diseño de Java.

Lo curioso y algo que puede llevar a malentendidos es que no hace falta que la variable tenga una referencia a una instancia, ya que el acceso al método estático se hace a través del tipo de la variable.

public class Test {

    static String cadena;

    public static void main(String[] args) {
        System.out.println(cadena.valueOf("cadena")); // imprime "cadena"
    }
}

O más chocante (aunque viene a ser lo mismo de arriba):

String cadena = null;
cadena.valueOf("cadena"); // funciona!

Un ejemplo con enumerados (los valores de un enumerado son instancias estáticas del tipo del enumerado):

enum Animals { MONKEY, DONKEY }
Animals a;

void doSomething() {
    System.out.println(a.MONKEY.DONKEY.MONKEY); // y así podríamos seguir...
}

Escrito por adrian

20 Mayo, 2009 a 19:00

Escrito en Uncategorized

Etiquetado con

Redefiniendo toString() con ToStringBuilder

con un comentario

El método toString es más que útil al imprimir logs y/o depurar una aplicación; sin embargo el redefinirlo en cada uno de nuestros objetos puede ser un verdadero coñazo.

Una forma fácil de hacerlo es utilizar la clase ToStringBuilder, de los commons de Apache.

@Override
public String toString() {
    return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}

Mediante reflexión este método accede a todas las propiedades del objeto y las imprime en un formato que podemos elegir. Si sólo queremos imprimir unos atributos determinados, podemos indicarlo del siguiente modo:

@Override
public String toString() {
    return ToStringBuilder(this).append("name", name).append("age", age).toString();
}

Escrito por adrian

19 Mayo, 2009 a 16:42

Escrito en Uncategorized

Etiquetado con

Cuidado al sobreescribir el método hashCode()

con 4 comentarios

Modificar los métodos equals y hashCode de nuestros objetos no es algo trivial, y puede traer efectos secundarios no muy buenos para nuestra aplicación.

Para qué sirve el código hash

Por defecto, hashCode devuelve un entero diferente para cada objeto basándose en la dirección del mismo (aunque esto depende de la implementación). Su uso principal es la optimización de las colecciones basadas en hashtables, como pueden ser HashMap o HashSet.

De modo gráfico, imaginemos una colección como una serie de cajas. En la caja 1 guardaremos los objetos que tengan hashcode 1, en la caja 2 los que tengan un hashcode 2… y así respectivamente. Cuando busquemos un objeto, sólo tenemos que mirar en la caja donde debería estar (mediante su hashcode).

En esta caja puede haber más objetos; por ejemplo, si sobreescribimos el método hashCode para que devuelva la longitud de un string:

private class CustomObject {
    private String attribute;

    public void setAttribute(String attribute) {
        this.attribute = attribute;
    }

    @Override
    public int hashCode() {
        return this.attribute.length();
    }

}

y tenemos dos objetos, uno con attribute="a" y otro con attribute="b", ambos irán a parar a la caja 1. Por tanto una vez dentro de la caja correspondiente debemos buscar el objeto mediante el método equals.

Esto es más eficiente que recorrer todos los elementos de la colección (siguiendo con el ejemplo anterior, sólo buscaremos en los strings de longitud 1, descartando el resto de elementos nada más empezar) como pasaría en un ArrayList, por ejemplo.

Peligro, ¡cuidado al sobreescribir!

En condiciones normales no deberíamos (ni necesitaremos, seguramente) sobreescribir el método hashCode. El problema viene cuando redefinimos equals (por ejemplo, para ejecutar tests), lo cual implica que también debemos hacer lo mismo con hashCode para mantener la coherencia (dos objetos iguales según equals deben tener el mismo código hash, sino puede ocurrir que por ejemplo tengamos dos instancias idénticas en un conjunto, cuando esto no puede -o no debería- ocurrir).

Dos objetos distintos según equals pueden producir el mismo código hash; por ejemplo:

    @Override
    public int hashCode() {
        return 2;
    }

Este código sería válido pero ineficiente, todos los objetos irían a parar a la misma caja, por lo que las búsquedas posteriores serían secuenciales perdiendo la principal ventaja de usar hashtables.

Otro gran peligro que existe al sobreescribir el método hashCode es el siguiente:

// creamos una colección de tipo HashSet
Set<CustomObject> testSet = new HashSet<CustomObject>();

// creamos un objeto de tipo CustomObject
// y lo añadimos a la colección
CustomObject customObject = new CustomObject();
customObject.setAttribute("attribute");
testSet.add(customObject);

// comprobamos que esté en el conjunto
System.out.println(testSet.contains(customObject)); // true

// modificamos su atributo y comprobamos
// de nuevo que esté en la colección
customObject.setAttribute("another attribute");
System.out.println(testSet.contains(customObject)); // false

Como vemos, al modificar la variable privada de customObject el código hash del objeto cambia (se utiliza en el cómputo), y cuando queremos comprobar si el objeto pertenece a la colección el método contains busca en la caja que no es. El objeto ya no está en la colección.

En definitiva, no tocar

Esto se puede complicar todavía mucho más si ponemos sobre la mesa objetos serializables y variables transient (no debemos utilizar variables de este tipo en el método hashCode, ya que al recuperar el objeto serializado tendrán el valor por defecto).

Este tema es importante y está presente en muchas situaciones, por ejemplo en las entidades de Hibernate (que puede completar los objetos de una colección con valores autogenerados cambiando el hashcode de los mismos y provocando el lío que vimos anteriormente) y los tests.

Lo mejor es, mientras no sea estrictamente necesario, no tocar.

Escrito por adrian

18 Mayo, 2009 a 23:08

Escrito en Uncategorized

Etiquetado con

Wicket en Google App Engine

sin comentarios

A pesar de las limitaciones de la “nube” de Google, parece que en general los frameworks web van funcionando… Después de ver cómo hacer funcionar Struts en AppEngine, ahora le toca el turno a Wicket.

Lo primero es activar el soporte de sesiones, algo esencial en este framework con estado. Para ello debemos escribir la siguiente línea en el archivo appengine-web.xml:

<sessions-enabled>true</sessions-enabled>

Siguiendo con las sesiones, también debemos decirle a Wicket que las almacene en memoria. Sobreescribimos pues el método newSessionStore en el objeto de configuración de la aplicación:

public class ExampleApp extends WebApplication {

    public ExampleApp() { }

    @Override
    protected ISessionStore newSessionStore() {
        return new HttpSessionStore(this);
    }

}

Por último, ya sólo nos queda inhabilitar el thread que recarga los recursos (html y demás), ya que como sabemos GAE no permite que las aplicaciones creen nuevos hilos.

public class ExampleApp extends WebApplication {

    public ExampleApp() { }

    @Override
    protected ISessionStore newSessionStore() {
        return new HttpSessionStore(this);
    }

    @Override
    protected void init() {
        super.init();
        this.getResourceSettings().setResourcePollFrequency(null);
    }

}

Y con esto, todo listo. No debería haber mayores problemas, aunque parece que con Ajax no todo funciona como debería (más info).

Escrito por adrian

14 Mayo, 2009 a 23:15

Escrito en Uncategorized

Etiquetado con , , ,

Caché en las “wrapper classes” de Java

sin comentarios

Una wrapper class (o clase envoltorio) es una clase que contiene a un tipo primitivo. Cada tipo tiene su clase correspondiente: Byte (byte), Short (short), Integer (int), Long (long), Float (float), Double (double), Boolean (boolean) y Character (char). Utilizando estas clases (y sobre todo gracias al autoboxing) podemos trabajar con tipos primitivos como si de objetos se trataran, además por supuesto de añadir métodos de conversión y similares.

Estas clases incorporan un mecanismo de caché y tienen ya precargados algunos objetos en memoria. Por ejemplo, al arrancar la máquina virtual se crean 256 objetos de tipo Integer (que representan los valores entre -127 y 128) o 2 de tipo Boolean (true y false). Como muestra el código fuente de IntegerCache (en la clase Integer):

private static class IntegerCache {
    private IntegerCache() { }
    static final Integer cache[] = new Integer[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Integer(i - 128);
    }
}

Los objetos se crean en el inicializador estático y se usan en el método valueOf:

public static Integer valueOf(int i) {
    final int offset = 128;
    if (i >= -128 && i <= 127) { // must cache
        return IntegerCache.cache[i + offset];
    }
    return new Integer(i);
}

Conocer esta característica puede ser más que interesante pues evitaremos el crear objetos innecesariamente. Valga el siguiente código para ver cómo podemos sacarle partido:

Integer i1 = new Integer(1);
Integer i2 = 1;
Integer i3 = Integer.valueOf(1);

Estas 3 formas de crear un objeto Integer que contiene al entero primitivo 1 son equivalentes. O mejor dicho, casi equivalentes, y es que la primera creará un objeto nuevo cada vez que la ejecutemos, mientras las otras dos harán uso de la caché como hemos visto anteriormente.

System.out.println( i1==i2 ); // false
System.out.println( i1==i3 ); // false
System.out.println( i2==i3 ); // true

Como vemos el operador == nos confirma que i2 e i3 son el mismo objeto. Sin embargo:

Integer i1 = 200;
Integer i2 = 200;
System.out.println( i1==i2 ); // false

Integer i3 = Integer.valueOf(200);
Integer i4 = Integer.valueOf(200);
System.out.println( i3==i4 ); // false

el valor 200 no está cacheado, por lo que se crean nuevas instancias de Integer.

Una buena práctica, por lo tanto, es crear estas clases envoltorio utilizando el método valueOf o asignando el literal para así evitar la creación de objetos extra.

Escrito por adrian

11 Mayo, 2009 a 19:23

Escrito en Uncategorized

Etiquetado con