Instalando y usando JRebel en Eclipse IDE & Tomcat

PASO 1: Instalando JRebel en Eclipse

Eclipse 3.6 Helios (y posteriores) – Instalación a través de Eclipse Marketplace

Para instalar JRebel en Eclipse, abriremos Eclipse Marketplace (Help » Eclipse Marketplace…) y buscaremos “jrebel”. Haremos click en el botón “Install” que aparecerá al lado.

1-market place

Eclipse 3.3, 3.4 & 3.5 – Instalación a través del Update Manager

La instalación a través del Update Manager es similar a la descrita anteriormente. Abriremos “Help » Install New Software… y pegaremos la siguiente URL: http://zeroturnaround.com/update-site/

2-update manager

Para que el proceso de instalación vaya más rápido, podemos deseleccionar la opción “Contact all update sites…” si ya tenemos todos los prerequisitos. Por ejemplo, el paquete “Eclipse IDE for Java EE Developers” ya contiene todo lo necesario, incluyendo WTP.

PASO 2: Seleccionando opciones y acabando el proceso de instalación

Seleccionaremos las opciones que queramos instalar. El plugin JRebel es requerido y deberá ser instalado por todo el mundo. Esto es lo que incluye:

  • El plugin contiene una instalación completa de JRebel, la última versión, para que no tengamos que bajarlo por separado – sólo necesitaremos una licencia después de la instalación.
  • El plugin también incluye el Eclipse Debugger Integration que ayuda al debugger del IDE para reconocer nuevo código y poder establecer breakpoints.

El plugin JRebel for Java EE es opcional pero seguramente también lo queramos instalar. El plugin es recomendado si queremos utilizar WTP (Web Tools Platform) en proyectos con JRebel.

JRebel m2eclipse está disponible si instalamos a través del update site. Este plugin permite generar el archivo de configuración jrebel.xml en builds con m2eclipse y jrebel-maven-plugin.

PASO 3: Configurar JRebel y añadir licencia

Después de reiniciar Eclipse, si no tenemos una licencia de JRebel instalada, el plugin mostrará una notificación para que procedamos al registro. Haremos click en el enlace del pop-up para proceder a la configuración de la licencia.

3-notification

El enlace nos va a llevar a la ventana de activación de JRebel donde tendremos que seleccionar la licencia que queremos: licencia de evaluación de 14 días, licencia OSS/Scala/Social o comprar una nueva licencia.

4-jrebel config centre

Si ya disponemos de una licencia, la podemos copiar directamente en el área de texto que nos aparece. En caso contrario, podemos seleccionar la opción de evaluación que nos direccionará a la página de JRebel para rellenar el formulario de registro. Una vez enviado el formulario, nos proporcionará la licencia que deberemos copiar. La licencia se verificará y se guardará en un archivo jrebel.lic en el directorio {user.home}./jrebel.

PASO 4: Usando JRebel en Eclipse

Paso 4.1: Habilitar el modo “Build Automatically”

Comprueba que Project » Build automatically está habilitado:

5-build automatically

Paso 4.2: Añadir la naturaleza JRebel al proyecto

Para que JRebel pueda hacer su trabajo, tiene que saber donde están las clases y los recursos. Añadiremos un archivo de configuración jrebel.xml para especificarlo. Esto es necesario para desplegar la aplicación en un WAR/EAR. Deberemos tener un jrebel.xml en cada módulo, esto incluye módulos web y EJB. El archivo de configuración jrebel.xml se deberá poner en el directorio WEB-INF/classes en caso de los módulos web y en la raíz del jar en módulos EJB. El archivo jrebel.xml se genera automáticamente cuando activamos JRebel Nature.

6-JRebel Nature

Si usamos Maven podemos utilizar el plugin JRebel Maven que generará el jrebel.xml según el módulo pom.xml tal y como se describe en el manual de configuración del plugin para Maven.

En el 99% de los casos, probablemente tengamos un solo módulo. Es estos casos, el archivo jrebel.xml generado automáticamente debería ser suficiente. Si el proyecto es una de las excepciones, podremos editar manualmente el archivo tal y como describe el manual de instalación.

Si queremos utilizar la configuración en jrebel.xml para todo el equipo, empezaremos con el jrebel.xml generado, y seguidamente reemplazaremos todas las rutas absolutas a nuestro workspace por una propiedad del sistema. JRebel reemplazará expresiones como “${myProject.root}” en jrebel.xml por una propiedad del sistema que podemos pasar al contenedor de aplicaciones de la siguiente manera: -DmyProject.root=/Users/salmar/myProject. Esto permite usar una única configuración para todo el mundo y personalizarla cuando iniciamos el servidor.

Si todos los componentes del equipo usa Eclipse con un workspace similar, podemos incluso evitar utilizar una propiedad propia ya que todas las aplicaciones arrancadas con JRebel en Eclipse tienen una propiedad rebel.workspace.path definida en el workspace  y se puede usar como “${rebel.workspace.path}” directamente en el jrebel.xml.

Paso 4.3: Arrancar la aplicación con JRebel

Cuando arrancamos una aplicación podemos habilitar JRebel para esa configuración específica de arranque. Esto quiere decir que cuando lo habilitamos, -javaagent:your_location/jrebel.jar se añadirá automáticamente a los flags de arranque. Si seleccionamos la casilla de debug, se generará un fichero jrebel.log en el directorio de metadatos en el workspace de Eclipse o en la ubicación del fichero jrebel.jar

Para habilitar / deshabilitar JRebel navegaremos a la pestaña JRebel en la configuración de ejecución y marcaremos las casillas.

7- Run Configuration

Paso 4.4: Configurar WTP

La publicación automática deberá ser deshabilitada en la configuración del servidor. Haciendo doble click en el nombre del servidor se mostrará la página de configuración. En la sección Publishing seleccionaremos la opción Never publish automatically tal y como se muestra en la siguiente imagen.

8-Tomcat publishing

Paso 4.5: Éxito!

Para comprobar que la instalación se ha llevado a cabo con éxito, accederemos a una página que use alguna clase, cambiamos la clase en el IDE y la guardamos. Cuando accedamos a la página nuevamente, deberíamos ver los siguientes mensajes en consola:

9-Tomcat console
Ahora que ya lo tenemos todo configurado, podemos programar sin necesidad de hacer redeploy. Si tienes cualquier duda específica de JRebel, el foro es el mejor sitio para preguntar, así otras personas podrán ver la respuesta también.

Spring Puzzler #01 Solution

I guess it’s time for the solution of the first Spring Puzzler. I’ve received a total of 79 votes, 35% got it right.

The solution was: Bienvenido a Spring Puzzlers Sergi.

In case you want to download the code, you can find it here: https://github.com/salmar/SpringPuzzlers

Explanation

The first thing to notice is that SpanishWelcomePrinter was not annotated, that means the component scan will never pick it up and there won’t be any SpanishWelcomePrinter in the Application Context. Only one implementation of LocalizedWelcomePrinter will exist, the EnglishWelcomePrinter.

We can now safely discard the NoSuchBeanDefinitionException. But this was not the trap…even if we had the @Named in the SpanishWelcomePrinter, we would have gotten the same output.

The catch was in the ConsoleWelcomeService where we try to inject a static field. Static fields are omitted for dependency injection, in our case we are going to stick with SpanishWelcomePrinter, instantiated with the new operator and no DI will happen. We can discard the possibility to get the message in English now. NullPointerException cannot happen at any point…

The next Spring Puzzler will be published the 13th Oct.

Happy hacking!

Extending handler method argument resolution in Spring MVC

Spring MVC data binding is really flexible and powerful, it can bind request parameters, URI templates variables, cookie values, HTTP headers… directly into your domain objects, but what if you want a custom resolution mechanism?

I will show you how to do it with a simple example. Imagine you want to get the user country name directly in you controller. The handler method I want to have looks like the following:

@RequestMapping(value="/", method=RequestMethod.GET)
public String home(@Country String userCountry, Model model) {
    ...
}

Notice that we have a new annotation called @Country, this is our custom annotation that we are gonna use to know where to inject the country name. Let’s create the annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Country {
}

Don’t forget to set the retention to runtime, otherwise the annotation won’t be available. Now it’s time to define how we want to resolve the argument annotated with @Country. The HandlerAdapter takes care of this resolution but it delegates to the WebArgumentResolvers for this task. We’ll implement our custom WebArgumentResolver:

public class CountryWebArgumentResolver implements WebArgumentResolver {

    private static final String WS_URL = 
        "http://api.ipinfodb.com/v3/ip-city/?key={apiKey}&ip={userIp}&format=xml";
    private static final String API_KEY = "yourKey";
	
    private RestTemplate restTemplate = new RestTemplate();
	
    public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest nativeWebRequest) throws Exception {
        // Get the annotation		
        Country countryAnnotation = 
            methodParameter.getParameterAnnotation(Country.class);

        if(countryAnnotation != null) {
            HttpServletRequest request = 
                (HttpServletRequest) nativeWebRequest.getNativeRequest();
			
            // Get user IP
            String userIp = request.getRemoteAddr();
			
            // Call geolocalization web service
            HttpHeaders requestHeaders = new HttpHeaders();
            requestHeaders.set("Accept", "text/xml");

            HttpEntity<UserInfo> userInfo = restTemplate.exchange(WS_URL, HttpMethod.GET, new HttpEntity<UserInfo>(requestHeaders), UserInfo.class, API_KEY, userIp);

            return userInfo.getBody().getCountryName();
        }
		
        return UNRESOLVED;
    }
}

As you can see, it’s quite straightforward, we just need to implement a single method. What this resolver is doing, is basically checking if the parameter is annotated with @Country, getting the user IP and calling a web service to get geolocalization data of the user IP (notice that an extra class has been created, UserInfo, in order to bind the web service parameters). I’ll be using IPInfoDB as the geolocalization service.

We just have one step left: define our new resolver in the handler adapter. Our custom web argument resolver will kick in before any Spring MVC default resolver.

	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
		<property name="customArgumentResolver">
			<bean class="com.sergialmar.customresolver.web.support.CustomWebArgumentResolver"/>
		</property>
	</bean>

Note: if you are using the Spring 3 MVC namespace (

<mvc:annotation-driven/>

), remember to place your handler adapter definition on top of it.

In Spring 3.1, you can user the mvc namespace to register the argument resolver:

	<mvc:annotation-driven>
		<mvc:argument-resolvers>
			<bean class="com.sergialmar.customresolver.web.support.CustomWebArgumentResolver"/>
		</mvc:argument-resolvers>
	</mvc:annotation-driven>

We are now ready to use the @Country annotation in our controller 🙂

	@RequestMapping(value="/", method=RequestMethod.GET)
	public String home(@Country String userCountry, Model model) {
		
		String message = null;
		
		if(userCountry.equals("SPAIN")) {
			message = "It seems you are in the same country as I am, up for a beer?";
		} else {
			message = "It seems we are not close to each other, will let you know when I am in " + userCountry;
		}
		
		model.addAttribute("message", message);
		
		return "home";
	}

Monitorizando aplicaciones y sistemas con Hyperic HQ

Después de un largo silencio, os voy a dar a conocer a Hyperic HQ para el monitoreo de vuestras aplicaciones y sistemas. Una de las características más interesantes de éste, es el autodescrubrimiento de los servicios y recursos con soporte para más de 75 tecnologías diferentes. Tenemos disponible la versión Open Source y la versión Enterprise, así que vamos a utilizar la versión open source en este artículo y veremos lo simple que es.

Vamos a monitorizar un servidor A con un Tomcat y un PostgreSQL desde un servidor B. En el servidor B vamos a instalar el servidor HQ y en el servidor A instalaremos el agente HQ. Todas las descargas para todos los sistemas operativos las vais a poder encontrar en la siguiente dirección: http://www.hyperic.com/downloads/hyperic-hq-open-source-downloads.html.

Instalando el servidor HQ

Bajamos el instalador para el servidor, en mi caso la versión Linux:

wget http://downloads.sourceforge.net/hyperic-hq/hyperic-hq-installer-4.2.0-1260-x86-linux.tgz

Descomprimimos y ejecutamos el instalador. Seguir los pasos que se indican:

tar xvzf hyperic-hq-installer-4.2.0-1260-x86-linux.tgz
cd hyperic-hq-installer/
./setup.sh

Arrancamos el servidor:

/home/hyperic/server-4.2.0/bin/hq-server.sh start

A partir de ahora tendremos instalado el servidor que se encontrará accesible en http://nombredelserver:7080 con las credenciales por defecto, usuario: hqadmin y password: hqadmin. Deberíamos ver un dashboard como el siguiente:

Instalando el agente HQ

Para cada sistema que queramos monitorizar, deberemos instalar el agente. Vamos a bajar el agente en el servidor A (tiene instalado un Tomcat y un Postgres), en mi caso la versión para Linux:

wget http://downloads.sourceforge.net/hyperic-hq/hyperic-hq-agent-4.2.0-1260-x86-linux.tgz

Descomprimimos:

tar xvzf hyperic-hq-agent-4.2.0-1260-x86-linux.tgz
mv hyperic-hq-agent-4.2.0 /home/hyperic/

Arrancamos el agente para que puede enviar los datos al servidor. La primer vez que lo arranquemos no pedirá la configuración:

cd /home/hyperic/hyperic-hq-agent-4.2.0/bin/
./hq-agent.sh start

Starting HQ Agent...
[ Running agent setup ]
What is the HQ server IP address: 192.168.0.192 // Cambiar por la ip del servidor donde habéis instalado el servidor
Should Agent communications to HQ always be secure [default=no]:
What is the HQ server port     [default=7080]: 
- Testing insecure connection ... Success
What is your HQ login [default=hqadmin]: 
What is your HQ password: 
What IP should HQ use to contact the agent [default=192.168.0.193]: 
What port should HQ use to contact the agent [default=2144]: 
- Received temporary auth token from agent
- Registering agent with HQ
- HQ gave us the following agent token
    1263142571701-3269978360446657677-1867024831687386027
- Informing agent of new HQ server
- Validating
- Successfully setup agent

Configurando los recursos

Teniendo el agente corriendo, vamos a echarle un vistazo al dashboard de nuestro servidor. Nos daremos cuenta, que en el portlet de autodescubrimiento, aparecen todos los recursos que se han podido encontrar. En nuestro caso, se han encontrado el Tomcat, el Postgres y el agente HQ. Voy a descartar el agente HQ y monitorizar los otros dos recursos.
Nota: Si intentáis descubrir un PostgreSQL 8.4 no os lo descubrirá, pero lo podréis añadir de forma manual.

Si pasamos a la opción “Resources” del menú, veremos todo lo que tenemos monitorizado. Tendremos los recursos categorizados (Plataformas, Servidores, Servicios…) y para cada uno de ellos la configuración de métricas y alertas. Aquí un ejemplo de los servidores y servicios que tenemos hasta ahora:

Si os fijáis, en el Tomcat y Postgres, nos aparece un icono de interrogación de color gris en la parte derecha. Vamos a tener que hacer alguna tarea adicional, para tener el completo monitorio de estos recursos.

Configurando Tomcat para monitoreo

Para poder monitorizar nuestro Tomcat, deberemos habilitar JMX. Modificaremos el archivo catalina.sh para añadir estos parámetros en la variable CATALINA_OPTS (en el ejemplo no se utiliza autenticación, pero lo podéis añadir en la configuración):

vim /usr/local/tomcat/bin/catalina.sh
export CATALINA_OPTS="-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=6969 \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false"

Reiniciamos el tomcat:

/usr/local/tomcat/bin/shutdown.sh
/usr/local/tomcat/bin/startup.sh

Una vez hecho esto, nos picharemos a nuestro recurso monintorizado Tomcat de la lista y configuraremos las propiedades(en caso de hacerlo de la manera detallada, sólo tendréis que pinchar OK) :

En breve se mostrará el icono verde junto al Tomcat en la lista. A continuación podéis ver algunas estadísticas de nuestro Tomcat:

Sólo nos falta añadir alguna alerta, así que vamos añadir una alerta simple de notificación cuando nuestro Tomcat no esté disponible. Si pincháis en la pestaña “Alerts”, os va a aparecer un botón en forma de submenu “Configure” que una vez pinchado nos dará la opción de crear una nueva alerta, así que vamos a ello.

Simplemente se generará una alerta cuando la métrica “Availability” sea igual a 0. Podéis probarlo parando el Tomcat y viendo que la alerta os aparece en el dashboard inicial.

Configurando PostgreSQL para monitoreo

Para el monitoreo del Postgres voy a crear un nuevo usuario llamado hyperic:

postgres@salmar-server:/home/sergi$ psql
psql (8.3.8)
Type "help" for help.

postgres=# CREATE USER hyperic WITH PASSWORD 'postgresHQ';
CREATE ROLE

A continuación, pinchando el Postgres en la lista de servidores, vamos a añadir la configuración de acceso:

Ahora si que en nuestra lista tenemos nuestros servidores accesibles como muestra el icono verde:

Happy monitoring!

Probando Spring Roo: Primera parte

Este año me fue imposible asistir a SpringOne debido a la coincidencia de fechas con el curso de Spring impartido en Madrid, pero sin duda uno de los términos que más corrían esos días por Twitter era Spring Roo.

Spring Framework, por si solo, aumenta la productividad del desarrollador encargándose de todo ese “boilerplate code”, como lo llaman en la lengua de Shakespeare, pero si a esto le añadimos generación de código y configuración, la productividad se puede ver incrementada sustancialmente. Aquí es donde entra Spring Roo, aún en fase alpha (versión en el momento de escribir este artículo 1.0.0A2), por lo que no vamos a ser demasiado críticos.

Aprovechando el anuncio que SpringSource Tool Suite pasa a ser gratuito, me he bajado la nueva milestone 2.1.0.M1 que incluye integración con la consola de Spring Roo.

Creando un proyecto Roo

Para crear un proyecto con Spring Roo, deberéis seleccionar File > New > Other y escoger Template Project dentro de SpringSource Tool Suite:

Nuevo Proyecto Roo

En la siguiente pantalla simplemente escoger el template Roo Simple y a continuación deberéis introducir el nombre del proyecto y el paquete para finalizar el proceso.

Template Roo Simple

Con esto, vamos a tener una estructura de proyecto basado en maven, con 3 archivos de configuración básicamente:

  1. applicationContext.xml: Un aplication context básico que da soporte para el uso de anotaciones y escaneado de componentes.
  2. web.xml:Configuración para Log4j, registro de un DispatcherServlet, registro de un ResourceServlet (Spring JS, para servir el contenido estático) y un OpenEntityManagerInViewFilter para JPA.
  3. {nombreDelProyecto}-servlet.xml: Un aplication context para el contexto del DispatcherServlet configurado en el web.xml con escaneo de componentes(@Controller), un ExceptionResolver y un ViewResolver(para JSPs).

Añadiendo clases persistentes

Una vez tenemos la estructura del proyecto, nos interesará añadir algunas clases de nuestro dominio. Para ello vamos a habilitar primero JPA en nuestra aplicación. Esto lo vamos a hacer utilizando la consola de Roo que la podemos habilitar con un simple CTRL + R:

Consola Roo

En nuestro caso vamos a suponer que utilizamos PostgreSQL y Hibernate para JPA. El comando a utilizar es tan simple como:

install jpa -database POSTGRESQL -provider HIBERNATE

¿Que nos va a generar esto?

  1. persistence.xml: Creación de la persistence unit con una configuración básica
  2. database.properties: Creación de un archivo properties con la información de conexión a la BD (driver, url, usuario y password), el cual deberemos rellenar con la información adecuada.
  3. En el applicationContext.xml: creación de un Data Source con la configuración del archivo database.properties accedido por un PropertyPlaceHolder, un Transaction Manager y finalmente una factoría de EntityManager.
  4. Actualización de las dependencias Maven.

Bien, ya estamos preparados para usar JPA, vamos a por las clases de nuestro dominio. Usaremos para ello la siguiente instrucción (la ~ sirve para asignar el paquete que le hemos especificado al proyecto):

new persistent class jpa -name ~.Persona

Y para los atributos de la clase:

add field number -fieldName id -type java.lang.Integer
add field string -fieldName nombre

En este punto es cuando ha venido mi sorpresa: Spring Roo genera 5 archivos!

Created SRC_MAIN_JAVA/Persona.java
Created SRC_MAIN_JAVA/Persona_Roo_Plural.aj
Created SRC_MAIN_JAVA/Persona_Roo_Entity.aj
Created SRC_MAIN_JAVA/Persona_Roo_ToString.aj
Created SRC_MAIN_JAVA/Persona_Roo_Configurable.aj

La clase java que genera es simple, sólo contiene los atributos sin ningún método, pero podemos ver que Spring Roo ha añadido 3 anotaciones a nivel de clase. Esto le va a servir para coger la información de los archivos que ha generado adicionalmente:


 @Entity
@RooEntity
@RooJavaBean
@RooToString
public class Persona {

 private Integer id;

 private String nombre;
}

Pero, ¿dónde está todo lo otro? En los archivos adicionales .aj que ha creado. ¡Ahí está la magia! Cada vez que añadimos un atributo, Spring Roo actualiza esos archivos con la información adicional. Pero no sólo añade getters y setters, sino que también crear un archivo para acceder automáticamente a métodos transaccionales de persistencia como persist(), findPersona(id), y más cosas…Para que os hagáis una idea, veamos la pinta tiene el Persona_Roo_ToString.aj (como su propio nombre indica, va a contener el método toString de la clase):


privileged aspect Persona_Roo_ToString {

 public java.lang.String Persona.toString() {    
 StringBuilder sb = new StringBuilder();        
 sb.append("id: ").append(getId()).append(", ");        
 sb.append("version: ").append(getVersion()).append(", ");        
 sb.append("id: ").append(getId()).append(", ");        
 sb.append("nombre: ").append(getNombre());        
 return sb.toString();        
 }    

}

Más en la segunda parte, hasta aquí por ahora 😉

Libro de Spring Web Flow 2

Para los interesados en Spring Web Flow, recientemente ha salido un nuevo libro con las actualizaciones de la última versión: Spring Web Flow 2 Web Development.

El contenido del libro muestra como diseñar, desarrollar y probar aplicaciones web usando Spring Web Flow 2, enriquecer nuestras aplicaciones con AJAX, integración con Spring Security y Spring Faces. Durante el transcurso del libro se desarrolla una aplicación (un bug tracker) con explicaciones claras y concisas.

Personalmente, lo acabo de encargar hoy, en cuanto lo tenga leído voy a postear la crítica. Para los que queráis ver un poco de contenido, ofrecen un capítulo gratuito: Chapter 4 – Spring Faces.