Anotaciones y Decoradores en Java

Las anotaciones o decoradores sobre el código se han vuelto muy comunes en los últimos tiempos. Permiten al programador añadir información útil extra ya sea para comentar mejor el código o para modificar la forma de compilar/ejecutar una clase concreta. Son una extensión a Java para permitir la programación orientada a aspectos.

We have three types of annotations based on the moment of usage:

Información para el Compilador

Estas anotaciones permiten al compilador indicar si debe o no omitir errores y warnings o qué hacer con ellos. A nada que se haya trabajado con un IDE Java (como eclipse) probably you would have used this type of annotations. For example, you can use usando @Override on a function to indicate that you are overwriting a method defined on a parent class. 

This annotation is completely optional, but allows both the compiler and the developer to check that they are indeed overwriting existing hierarchical functionality.

Por ejemplo:

public class Parent {     
    public void do(){
        System.out.println("Parent");
     }
}

public class Son extends Parent{     
    usando @Override
    public void do(){
        System.out.println("Son");
     }
}
Anotaciones en Tiempo de Compilación y Despliegue

These annotations allow the compiler to add extra information about how to generate the code. By adding or modifying functionality from that in the source code you can alter how a class behaves. Also to create new classes (based on a file descriptor), etc …

These annotations will only be visible at this point. They are not compiled to the .class files. Therefore they are not available at runtime.

Anotaciones en Tiempo de Ejecución

You can use this annotations on runtime and they work on a very similar way as an interface.

Veamos directamente un ejemplo de cómo crear una anotación Runtime y cómo se puede utilizar. La anotación MyAnnotation se podrá aplicar a elementos de tipo field, es decir, a atributos de una clase:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
     public @interface MyAnnotation {
}

Ahora podemos crear una clase que esté anotada con esta anotación:

public class myObject
 {
 @MyAnnotation
 public String field;
 }

De esta forma, en cualquier otra parte del código, podemos comprobar mediante reflexión si un objeto tiene un campo marcado con la anotación:

Class<?> res = objeto.getClass();
for (Field f : res.getFields()) {
     if (f.isAnnotationPresent(MyAnnotation.class)) {
          System.out.println("OK");
      }
}

Más información:

Notes of the gvSIG 2.0 workshop

Estos son los apuntes que tomé sobre gvSIG 2.0 en las últimas Jornadas GvSIG.

Pre-Requisitos

  • Java
  • Eclipse
  • Ant (opcional)
  • Maven (opcional)
  • gvSIG (esto es recursivo :))

La principal ventaja de gvSIG 2.0 es que puedes crear un plugin sin saber cómo funciona gvSIG ni tener que compilarlo. Tenemos una instalación de gvSIG que despliega unos binarios que genera el workspace.. But we don’t have to change the source code. Unless, of course, something doesn’t work (bugs) or we have to add some new functionality to the core. Better if you don’t touch it, ask the developers and they will take care.

Creating the workspace

With the binary, there is a wizard which creates an Eclipse workspace with a default template. That leaves all set up but to compile our extension. It also includes a wizard to easily generate installables. These wizards are accessible through the application, at the application menu.

Org.gvsig.tools is the basic infrastructure library to develop plugins. The main functionality is focused on the registration of extension points, utilities to separate API, implementations, SPI (service provider), and monitoring tasks (which in version 1.0 used to freeze the application). This library also supports events, persistence, etc …

gvSIG Plugins

Una biblioteca es un fichero jar. Cuando nuestra aplicación contiene el archivo jar, org.gvsig.tools prepara e inicializa esta biblioteca dentro del núcleo. Las clases en la biblioteca implementan la interfaz Library (AbstractLibrary).

Los managers (PluginsManager) son el punto de entrada a las funcionalidades. Son como factorías (singletons) (al menos uno por librería) que levanta instancias de las funcionalidades incluídas dentro de la librería. También guarda la configuración del módulo.

Los locators (PluginsLocator) permiten registrar implementaciones de managers. Nos permiten recuperar la implementación de manager de un API en concreto. "Dame el manager de esta librería."

Un plugin es una pieza que aporta una funcionalidad: botones y barras de herramientas, opciones de menús, proveedores de datos y tipos de documentos. Andami no ha evolucionado mucho desde la versión 1.x. Andami es el marco para los complementos.

El plugin siempre tendrá al menos dos ficheros:

  • config.xml que indica las clases que implementan el plugin, las dependencias y los menús
  • package.info que indica la versión, el nombre, el build,... del plugin.

gvSIG Extensions

Una extensión (IExtension) es un conjunto de herramientas asociadas con un complemento dentro de una barra de herramientas o menú y funcionan en conjunto. Un grupo de plugins, puedes decir. La extensión que implementa ExclusiveUIExtension especifica qué herramientas son o no visibles, sin tocar el código del núcleo.

Para crear un nuevo complemento, utilizamos la herramienta de generación de menús de complementos disponibles en la versión de desarrollo. Esto genera el espacio de trabajo automáticamente e instala el complemento desde el cual generamos el complemento. Si no tienes una versión de desarrollo, tendrás que compilar gvSIG de los fuentes..

Conviene ir haciéndolo mientras se leen estos apuntes o puedes perderte.

440/5000 El complemento consta de dos proyectos de maven: org.gvsig.plugin y org.gvsig.plugin.app. org.gvsig.plugin proporciona la funcionalidad de la biblioteca independientemente de gvSIG (lógica de negocios). Puede tener dependencias de biblioteca, pero debe poder operar sin tener que abrir la aplicación. Es decir, no requiere nada de Andami, por ejemplo. En org.gvsig.plugin.app.mainplugin (dentro de org.gvsig.plugin.app) implementaremos la funcionalidad.

Los paquetes "api" deben contener interfaces y los paquetes "impl" deben contener implementaciones.

Ahora el espacio de trabajo está listo para trabajar con Eclipse si importamos el proyecto con el complemento de Maven. Si tomamos una plantilla adecuada para generar las fuentes de los complementos, se realiza casi todo el trabajo (excepto la lógica de negocios exacta de nuestro complemento).

Consejos Finales

Es importante tener un proyecto java para probar nuestro plugin con su propio main, sin tener que iniciar gvSIG. También se recomienda que la biblioteca tenga pruebas unitarias. Es decir, podemos hacer una aplicación con todo el poder de gvSIG, pero sin usar gvSIG en sí, es decir, como si fuera una poderosa biblioteca GIS. Conclusión: si lo hacemos bien, incluso podríamos usar nuestro complemento en otra aplicación sin aplicación ... como GoFleet.

Each plugin contains own installer, which created by a wizard inside the application.

Alta Concurrencia

When facing high concurrency applications, we often find a number of generic problems. In this article I will focus on the problems of resources (CPU and memory). For now on, I will focus on the most typical and most direct solutions.

When we discover threads and the advantages of parallel processing it can happen that we end up abusing their use. We have a lot of threads (100 ¿? 1000?) simultaneously, and the processor will be jumping from one to another without stopping, not letting them finish, no matter how fast is their real excution. And over time there will be more and more threads only slowing down the process. To the cost of execution of each thread, we must consider also the added cost of creating and destroying threads. It can can become significant when we talk about so many threads at once.

High Concurrency with the Thread Pool Pattern
High Concurrency with the Thread Pool Pattern

Threads: the holy grail

En este caso, al primer método al que debemos recurrir es al Patrón Thread Pool . Este patrón consiste en limitar el número de hilos que hay ejecutándose en un momento dado.
En vez de crear hilos nuevos, creamos tareas, que esperan apiladas. Así mismo, tendremos un pool de hilos que irán cogiendo esas tareas y ejecutándolas lo más pronto posible. Un ejemplo clásico de este patrón se encuentra en la clase SwingWorker. Si queremos implementar "a mano" este patrón, conviene que le echemos un vistazo a la interfaz ExecutorService.

Si tenemos un hilo en background que está haciendo un uso muy intensivo del procesador, pero no nos importa ralentizar su ejecución, podemos hacer uso del comando sleep ( Thread.sleep (...)) to periodically release the thread processor, allowing other threads to run faster .

This is useful for threads running in maintenance mode, which must be kept running but do not have to respond in real time. Another way to temporarily stop a running thread while another is using the method join ( Thread.Join () ), que hace que un hilo espere hasta que el otro hilo termine. Aunque más útil en caso de que tengamos un hilo claramente más prioritario que otro, no es viable si no podemos tener una referencia al hilo más prioritario desde el menos prioritario para indicarle a qué hilo tiene que esperar.

High Concurrency issues

Pero la alta concurrencia no viene dada sólo por el uso del procesador. Puede ocurrir que varios hilos necesiten acceder a grandes cantidades de información de forma casi simultánea. Estos hilos no sólo estarán repitiendo la información en memoria sino que muchas veces estarán repitiendo todo el proceso de extraer dicha información.

Este problema suele estar resuelto en la mayoría de librerías de acceso a datos (base de datos mayormente). Por ejemplo, podemos encontrarnos con el caso de ehcache , que utiliza hilos para almacenar información ( Thread-Specific Storage Pattern ). This way, access and storage of this information is shared. Thus decreasing both the memory usage required and the processor time required to extract and shape information. As the threads wants to process this information, they will be asking ehcache for the data, which will optimize these hits.

Para mejorar esta solución tenemos las colecciones concurrentes. This allow different threads to use the same objects without any problems of concurrency.

There are more solutions to improve the high turnout (without going into optimizations to the code itself). But those described here are usually good ideas to start.

Referencias Útiles: