pcollaog

pcollaog

(20 comments, 173 posts)

This user hasn't shared any profile information

Home page: http://blog.pcollaog.cl

Jabber/GTalk: pcollaog@gmail.com

Posts by pcollaog
wpid-IMG_20110818_122837.jpg

Nieve en Santiago

0
Las Condes

Las Condes

 

 

Los creativos

Los creativos

¿Por que FactoryBean<T> es útil?

1

En este post voy a tratar de explicar porque FactoryBean<T> es increíblemente útil para alambrar (aplicar DI) aplicaciones hechas con Spring Framework.

La interfaz de FactoryBean dice lo siguiente:

public interface FactoryBean<T> {
 
	T getObject() throws Exception;
 
	Class<?> getObjectType();
 
	boolean isSingleton();
}

La utilidad de la implementación de esta interfaz y su posterior declaración como Bean dentro del contexto de la aplicación, es que puede ser usada (como su nombre lo indica) como Factory para inyectar algún valor en alguna propiedad de otro Bean.

¿Dónde y cómo funciona? Dentro del ciclo de vida de la carga del Contexto de spring, la ejecución de la implementación de esta interfaz, esta justo antes de hacer los setters de las propiedades de un Bean. El funcionamiento es simple, siempre se ejecutará el método getObject() que retornará la instancia del tipo T.

Veamos una implementación simple y una configuración de contexto de spring:

public class RandomNumberFactoryBean implements FactoryBean<Integer> {
 
	public Integer getObject() throws Exception {
		return Integer.valueOf(new Random().nextInt());
	}
 
	public Class<?> getObjectType() {
		return Integer.class;
	}
 
	public boolean isSingleton() {
		return true;
	}
 
}

Esta simple implementación de FactoryBean retorna un Integer en el método getObject(), simplemente eso (obviamente en este método debes poner todo tu talento para resolver el valor que andas buscando, esto es un ejemplo simple).

El método getObjectType() es usado internamente por el framework para validar que el retorno de getObject() sea correcto o que este dentro de la jerarquía de clases, esto es en caso de que quieras restringir por tipo.

El último método isSingleton() es si quieres que esta clase (no importa la cantidad de declaraciones que tengas, siempre será la misma), es un tanto dificil de entender pero les sugiero que lean sobre el concepto de Singleton que tiene SpringFramework. En el ejemplo de configuración espero que les quede claro, de lo contrario, bienvenidas las preguntas.

Esta es la definición del Bean de ejemplo, en donde se hará uso del FactoryBean:

public class ExampleBean {
 
	private Integer _randomValue;
 
	public final Integer getRandomValue() {
		return _randomValue;
	}
 
	public final void setRandomValue(Integer randomValue) {
		_randomValue = randomValue;
	}
 
}

Aquí las configuraciones de contexto de spring.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd">
 
 
	<!-- Ejemplo 1 -->
	<bean id="exampleBean1" class="cl.pcollaog.factory.ExampleBean">
		<property name="randomValue">
			<bean class="cl.pcollaog.factory.RandomNumberFactoryBean" />
		</property>
	</bean>
 
	<!-- Ejemplo 2 -->
	<bean id="randomNumberFactoryBean" class="cl.pcollaog.factory.RandomNumberFactoryBean" />
 
	<bean id="exampleBean21" class="cl.pcollaog.factory.ExampleBean">
		<property name="randomValue" ref="randomNumberFactoryBean" />
	</bean>
 
	<bean id="exampleBean22" class="cl.pcollaog.factory.ExampleBean">
		<property name="randomValue" ref="randomNumberFactoryBean" />
	</bean>
 
</beans>

Ejemplo 1:

Se declara el Bean exampleBean1 y que tiene como propiedad el atributo randomValue y cuyo valor será producto de la ejecución del Bean RandomNumberFactoryBean en el momento que el contexto de Spring es cargado. En este caso se utiliza la técnica de InnerBean, es decir, no se tiene una instancia del Bean para ser reutilizada sino que esta en la misma declaración del setter del atributo.

Ejemplo 2:
Este ejemplo hace lo mismo indicado arriba, sólo que no se aplica InnerBean sino que se extrae y es reutilizado en el bean exampleBean21 y exampleBean22. En este ejemplo entra en juego el método isSingleton(), si es true, quiere decir que el valor que entregará el FactoryBean siempre será el mismo para ambos Beans. Ahora bien, si se cambia a false, por cada setter, es decir, para exampleBean21 y exampleBean22 se realizara la ejecución de RandomNumberFactoryBean 2 veces. (En este caso, nos entregará dos valores aleatorios para cada bean)

En pocas palabras para cada Bean del ejemplo 2 habrá dos instancias de RandomNumberFactoryBean que entregará cada una un Integer para los atributos de los beans declarados.

Algo interesante de las implementaciones de FactoryBean es que luego de la carga del contexto, estas instancias son desechadas.

Espero les sea útil y cualquier pregunta sera bienvenida.

Java7: null-safe y null-default

0

Seguramente les ha pasado y mucho que tienen que llenarse de validaciones contra NullPointerException cuando los métodos retornan null, hay una propuesta para poder manejar este tipo de problemas. Veamos uno ejemplos:

Null-Default

Hoy en dia:

String maybeNull = metodoNull();
 
if (null == maybeNull) {
    maybeNull="Ahora no es null";
}
 
// Otra Opcion
 
String nullVar = metodoNull();
nullVar = (nullVar != null ? nullVar : "Ahora no es null");

Ahora la propuesta es la siguiente:

String maybeNull = metodoMaybeNull();
maybeNull =  maybeNull ?: "Ahora no es null";

Como verán nos ahorramos unas cuantas líneas de código. Ahora veamos el otro esquema

Null-safe

Hoy en dia:

  String result = null;
  Foo foo = getFooMayBeNull();
  if (foo != null) {
    Bar bar = foo.getBarMayBeNull();
    if (bar != null) {
      result = bar.getResult();
    }
  }

Con la propuesta de null-safe quedaría así:

String result = getFooMayBeNull()?.getBarMayBeNull()?.getResult();

Esto hasta el dia de hoy seguía en propuesta y por lo que veo en las Características de Java7 no viene, así que a esperar. (Estoy bajando el jdk7 para probar, luego updates)

Estas modificaciones al lenguaje (sintaxis) vienen de los operadores que tiene Goovy.

Más información sobre esta propuesta de mejora al lenguaje en:

Algunas API’s Java que te pueden servir: commons-io

2

commons-io trae un montón de clases que te pueden servir al momento de utilizar lecturas y escrituras de archivos, entre otras cosillas.

Por si no lo sabías una de las malas practicas mas recurrentes programando con java es, no cerrar los Stream y ciertos Readers adecuadamente, o te complicas mucho con los try/catch, vamos a ver un par de ejemplos clásicos:

Primero agregamos la dependencia de maven, ojo que las versiones 2.x están escritas para Java 1.5 y las 1.x para java 1.3 y 1.4:

<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.0.1</version>
</dependency>

Caso 1: finally que asegura cerrar el Reader con el método close()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void closeWithFinally(String filename) throws IOException {
	BufferedReader reader = new BufferedReader(new FileReader(filename));
	try {
		StringBuilder sb = new StringBuilder();
		String line = null;
		while ((line = reader.readLine()) != null) {
			sb.append(line);
		}
		String contentFile = sb.toString();
		System.out.println(contentFile);
	} finally {
		// Cerrar el reader
		reader.close();
	}
}

Caso 2: Creando la instancia de BufferedReader dentro del try y validando si es null al momento de cerrar:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void closeWithFinallyNullCheck(String filename) throws IOException {
	BufferedReader reader = null;
	try {
		reader = new BufferedReader(new FileReader(filename));
		String line = null;
		StringBuilder sb = new StringBuilder();
		while ((line = reader.readLine()) != null) {
			sb.append(line);
		}
		String contentFile = sb.toString();
		System.out.println(contentFile);
	} finally {
		// Cerrar el reader
		if (null != reader) {
			reader.close();
		}
	}
}

Caso 3: Usando commons-io y la clase IOUtils se reduce bastante el código y quedaría algo así:

1
2
3
4
5
6
7
8
9
public void closeWithFinallyCommonsIO(String filename) throws IOException {
	BufferedReader reader = new BufferedReader(new FileReader(filename));
	try {
		String contentFile = IOUtils.toString(reader);
		System.out.println(contentFile);
	} finally {
		IOUtils.closeQuietly(reader);
	}
}

Mas información en el maven site del proyecto:

Mas adelante escribiré un par de ejemplos con otras clases de commons-io que son bastante útiles.

Cómo iterar un Map con Java 1.5

1

A pedido del Sr: @perrefe les dejo un tip de performance para iterar sobre Map<K,V>:

Supongamos que nuestro Map tiene como key un String y como value un Integer, declarado de esta forma:

1
Map<String,Integer> map = new HashMap<String,Integer>();

Ahora podemos iterar el Map de la siguiente forma:

1
2
3
4
for (Entry<String, Integer> entry : map.entrySet()) {
	System.out.println("Key [" + entry.getKey() + "]");
	System.out.println("Value [" + entry.getValue() + "]");
}

Si ve por ahí algún iterador sobre un Map al cual le sacan primero la lista de keys y después iteran el Map para sacar el value, no pierda tiempo escribiendo código de más y haciendo que su aplicación ande mas lenta.

Por favor no haga esto!!!

1
2
3
4
5
6
7
Set<String> keys = map.keySet();
 
for (String key : keys) {
	Integer value = map.get(key);
	System.out.println("Key [" + key + "]");
	System.out.println("Value [" + value + "]");
}

Espero les sirva.

pcollaog's RSS Feed
Go to Top