Flower

Archivos por mes July, 2009

Vamos a tratar la gestión de beans de spring dentro de GWT. En principio no tiene nada de especial. Solo hay que arrancar el contexto de spring para poder solicitar los beans que queramos.

Despues de navegar mucho, pero que mucho, he encontrado 3 metodos:

El primero y más simple, cargar el archivo de configuración xml en cualquier momento

org.springframework.beans.factory.access.BeanFactoryLocator beanFactoryLocator = org.springframework.context.access.ContextSingletonBeanFactoryLocator.getInstance(“Archivo-configuracion.xml”);

beanFactoryReference = beanFactoryLocator.useBeanFactory(“BeanId”);

(org.springframework.context.ApplicationContext)beanFactoryReference.getFactory();

Esto puesto en algún singleto y en un método synchronized, es posible que no de muchos problemas, lo único es que en cada servicio habría que llamarlo explícitamente para usar los beans de spring, no siendo muy automatico.

Usando el ContextLoaderListener

Con unos pequeños cambios podemos hacer que sea la propia aplicación web quien carge el contexto al iniciar la aplicación.

Para ello, solo hay que poner el nuestro web.xml el siguiente código:

<context-param>

	<param-name>contextConfigLocation</param-name>

		<param-value>

        /WEB-INF/applicationContext.xml

		classpath:applicationContext.xml

	</param-value>

</context-param>

Teneis las dos formas de cargar el archivo, si esta en el contexto de la aplicación, directamente por su path. O si lo tenemos en algún paquete de nuestro classpath. El ya lo busca y lo carga.

Y después:

<listener>

	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

Que ya se encarga de cargar el archivo de configuración.Despues podemos solicitar el Bean de spring utilizando la siguiente instrucción.

ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

(MyService)context.getBean(“myservice”);

No hace falta decir que esto ha de hacerse desde un servlet en el servidor, para poder tener acceso al contexto de la aplicación.

Para no tener que llamarlo constantemente en cada servlet, podemos extender RemoteServiceServlet de GWT y montarlo en llamadas que nos den los servicios.

public class SpringRemoteServiceServlet extends RemoteServiceServlet{

	private ApplicationContext getContext(){

		ServletContext sc = getServletContext();

		return WebApplicationContextUtils.getWebApplicationContext(sc);

	}

	protected MyService getMyService(){

		return (MyService)getContext().getBean("myService");

	}

}

Así solo tenemos que llamar en nuestro servlet al metodo del servicio correspondiente. Aun asi, no deja de ser un poco intrusivo, y el hecho de tener una llamada en medio de nuestro servlet del tipo getServicio(), marea un poco.

Inyección de dependencias

Este es el que más me gusta, cumple con la filosofía de inyección de dependencias de spring, y lo hace todo muy transparente. Este lo he encontrada de aquí. Esta en ingles, pero se entiende muy bien. Pero hare un resumen:

Al igual que hacíamos en el anterior punto, extendemos RemoteServiceServlet de GWT:

import java.lang.reflect.Field;

import java.util.HashSet;

import java.util.Set;

import org.apache.log4j.Logger;

import org.springframework.beans.factory.NoSuchBeanDefinitionException;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.context.support.WebApplicationContextUtils;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**

 * {@link RemoteServiceServlet} that automatically injects IoC dependency.

 * "org.springframework.beans.factory.annotation.Autowired" annotation is used

 * for marking which fields to inject into. Uses

 * {@link SpringApplicationContextLoader} to retrieve beans by name.

 *

 * Note that the current implementation will only inject "declared" fields, and

 * not inherited fields. Fields can be private, protected, package or public.

 * 

 * @author See Wah Cheng

 * @created 27 Jun 2008

 */

@SuppressWarnings("serial")

public class DependencyInjectionRemoteServiceServlet extends

		RemoteServiceServlet {

	protected static Logger logger = Logger

			.getLogger(DependencyInjectionRemoteServiceServlet.class);

	@Override

	public void init() throws ServletException {

		super.init();

		doDependencyInjection();

	}

	/**

	 * Carries out dependency injection. This implementation uses Spring IoC

	 * container.

	 * 

	 * @exception NoSuchBeanDefinitionException

	 *                if a suitable bean cannot be found in the Spring

	 *                application context. The current implementation looks up

	 *                beans by name

	 */

	protected void doDependencyInjection() {

		for (Field field : getFieldsToDependencyInject()) {

			try {

				boolean isFieldAccessible = field.isAccessible();

				if (!isFieldAccessible) {

					field.setAccessible(true);

				}

				field.set(this, WebApplicationContextUtils

						.getWebApplicationContext(getServletContext()).getBean(

								field.getName()));

				if (!isFieldAccessible) {

					field.setAccessible(false);

				}

				logger.debug("Dependency injection successful: "

						+ this.getClass().getName() + "." + field.getName());

			} catch (IllegalArgumentException e) {

				throw new RuntimeException(e);

			} catch (IllegalAccessException e) {

				throw new RuntimeException(e);

			}

		}

	}

	/**

	 * Find annotated fields to inject.

	 * 

	 * @return a list of all the annotated fields

	 */

	private Set getFieldsToDependencyInject() {

		Set fieldsToInject = new HashSet();

		Field[] fields = this.getClass().getDeclaredFields();

		for (Field field : fields) {

			if (field.getAnnotation(Autowired.class) != null) {

				fieldsToInject.add(field);

			}

		}

		return fieldsToInject;

	}

}

Esta es la clase que deberemos heredar en todos nuestros servicios. Y en el servicio en concreto debemos marcas la dependencia, en este ejemplo utilizan una anotación de spring, @Autowired. Si nos fijamos, cuando solicita los campos de la clase, utiliza reflection para buscar esa marca, y después busca el servicio en el contexto de spring que tiene en el contexto del servlet y lo asigna. Muy limpio y fácil de utilizar.

8.7.2009 | App Engine

appengine_lowres

Llevo ya unos meses jugando con la nueva plataforma como servicio (PAAS) de Google. Para empezar explicare un poco por encima que es una PAAS. No es más que una plataforma basada en un lenguaje, donde ya tienes montado y configurado el servidor de aplicaciones, la base de datos y el servidor web. Tu solo tienes que realizar tus aplicaciones en ese lenguaje y desplegarlo en su plataforma.

No voy a entrar cuales son las ventajas e inconvenientes de tener una infraestructura en la nube, hay cientos de páginas que hablan de ello. Por dejarlo clara mi postura solo diré que estoy totalmente a favor de ellas.

El tema que me trae ahora es el de las aplicaciones multi-tenant. Es la cualidad que tiene un software de soportar multitud de usuarios y empresas sobre la misma infraestructura. Tenéis un post mucho mejor explicado de Martin y en este otro de Saasmania tenéis los diferentes niveles y modelos.

Como estaba jugando con App Engine, me preguntaba cual sería la mejor manera de hacerlo.

  • Diferentes bases de datos: Teniendo en cuenta que no controlas tú la base de datos, ya que no hay una base de datos relacional detrás, esta opción resulta difícil.
  • Diferentes servidores: igual que antes, solo tenemos un dominio y un contexto, y hay va todo. Tampoco veo la forma.

Así que me he puesto a buscar que hacen algunos para estos casos. Ni que decir tiene que en español no hay apenas información relevante sobre el tema. Así que con mi muy defectuoso ingles me he puesto a mirar alternativas. Pido un poco de comprensión por si entiendo mal las cosas.

En el grupo Google de AppEngine hablan precisamente de esto. Hare un resumen de las ideas que comentan.

  • Implementación propia de DatastoreService: Añadir un campo que sea el namespace, para poder filtrar los datos de las peticiones. Aunque advierten de que puede dar mucho trabajo. Es la primera aproximación que se me había ocurrido.
  • Una aplicación por cada inquilino: Los de Datanueclears hablan de una nueva funcionalidad para poder hacer esto mismo, con cada alta se instancia todo en un nuevo dominio. Aunque en AppEngine ya estas limitado a 10 aplicaciones.
  • Y por ultimo parece que los chicos de Google tienen pensado permitir un cierto multi-Tenant. Aunque no está claro.

Estaba bastante ilusionado con AppEngine en java, pero ahora que lo veo con más detenimiento puede que no sea tan bonito.
¿Conocéis alguna forma de salvar el escollo? ¿Alguna alternativa?

Hace tiempo recibí un correo donde comparaban estas dos grandes profesiones.

  1. Generalmente trabajas hasta tarde. ¡Como las prostitutas!
  2. Generalmente eres más productivo por la noche. ¡Como las prostitutas!
  3. Te pagan para mantener al cliente feliz. ¡Como las prostitutas!
  4. Cobras por hora pero tu tiempo se extiende hasta que termines. ¡Como las prostitutas!
  5. Si eres bueno, nunca QUEDAS SATISFECHO de lo que haces. ¡Como las prostitutas!
  6. Te recompensan por satisfacer las fantasías de tus clientes. ¡Como las prostitutas!
  7. Es difícil tener y mantener una familia. ¡Como las prostitutas!
  8. Cuando te preguntan en que trabajas no lo puedes explicar. ¡Como las prostitutas!
  9. Tus amigos se distancian de ti y tu solo andas con otros Iguales que tu. ¡Como las prostitutas!
  10. El cliente paga tu cuenta del hotel y por horas trabajadas. ¡Como las prostitutas!
  11. Evalúan tu “capacidad” con horribles pruebas. ¡Como las prostitutas!
  12. El cliente siempre quiere pagar menos y encima quiere que hagas maravillas. ¡Como las prostitutas!
  13. Cada día al levantarte dices “NO VOY A HACER ESTO TODA MI VIDA!”. ¡Como las prostitutas!
  14. Sin conocer nada de su problema los clientes esperan que les des el consejo que necesitan. ¡Como las prostitutas!
  15. Si las cosas salen mal es siempre culpa tuya. ¡Como las prostitutas!
  16. Tienes que brindarles servicios gratis a tu jefe, amigos y familiares. ¡Como las prostitutas!
  17. Siempre tienes que trabajar cuando lo necesitan tus clientes de afán y a última hora porque es urgente. ¡Como las prostitutas!

Sin despreciar una profesión tan antigua, con sus mas y sus menos, hay una cosa que si nos diferencia, cuando te vas a meter a puta creo que todas estas cosas las tienes bastante claras, pero cuando uno decide meterse en informática no es esto, ni muchísimo menos, lo que tiene en mente. Por desgracia en muchos casos es en lo que terminas.

En mi caso particular, cuando recibí este correo pasaba por una situación bastante desagradable y me afecto mucho, tanto fue así que tuvieron que pasar varios días y varias duchas hasta que deje de sentirme sucio.