Hasta ahora, las aplicaciones que he desplegado eran muy básicas, hechas con jsp y acceso a base de datos a base de jdbc plano.
Estas tecnologías no estan mal (y de hecho son la base de todo lo posterior), pero lo más normal es utilizar frameworks para el desarrollo de aplicaciones Java.
La quinta práctica del libro de Java para Heroku es un despliegue de aplicaciones hechas con Spring Roo en Heroku. Spring Roo es un framework que viene a ser como Rails para Ruby. Simplifica el desarrollo con funciones tan básicas como crear el toString o el equals automáticamente o tan avanzadas como generar el CRUD de una base de datos directamente.
Así que con esta práctica voy a matar dos pájaros de un tiro, voy a probar Spring Roo y voy a desplegar un artefacto más complejo en Heroku. A ello.
Instalación de Spring Roo
Lo primero es descargar el framework de aquí. Después sigo las instrucciones de instalación:
- Descomprimir el archivo, en mi caso en $HOME/Java/spring-roo-1.1.5.RELEASE
- Crear enlace simbólico: sudo ln -s /home/case/Java/spring-roo-1.1.5.RELEASE/bin/roo.sh /usr/bin/roo
- Probar que funciona:
cd Java/spring-roo-1.1.5.RELEASE/
mkdir roo-test
roo quit
Si todo ha ido bien, debe haber salido Roo así en ASCII art monísimo. Ya esta instalado Spring Roo y puedo borrar roo-test, hala a retomar el tema.
Quinta Práctica
El objetivo de esta práctica es más bien sencillo, se va a usar Spring Roo para crear un ejemplo clásico, el Pet Clinic y se va a preparar esta aplicación creada con Roo para desplegar en Heroku.
Pasos:
- Crear la aplicación con Roo.
- Preparar el pom.xml añadiendo las dependencias adecuadas y la configuración correcta para su despliegue en Heroku.
- Crear una clase que arranque Jetty (el servidor integrado).
- Configurar la base de datos PostgreSQL en la aplicación.
- Probar la aplicación en local.
- Desplegar en Heroku.
Paso 1
Crear la aplicación es más bien sencillo:
cd Heroku
mkdir petclinic
cd petclinic
roo script --file clinic.roo
Me escupe un montón de logs por la consola y en teoría, listo. Examinando un poco la aplicación, pues nada, es una aplicación Java que sigue la estructura de Maven, con su pom.xml y nada, todo perfecto, sus entidades, sus controladores… su páginas web, tiene pinta de estar hecho con Spring MVC… vale, al lío.
Paso 2
En este paso, lo primero es añadir Jetty y PostgreSQL al pom.xml:
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>7.4.4.v20110707</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-2.1-glassfish</artifactId>
<version>2.1.v20100127</version>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.0-801.jdbc4</version>
</dependency>
Ahora cambio el scope de servlet-api de provided a compile. Si se usa Tomcat, Tomcat incluye la librería servlet.jar (la API de Servlet), pero Jetty no, así que hay que descargarla. Hay que cambiar igual el scope de org.springframework.roo.annotations, si la ejecuto en local con Roo, estará la librería de anotaciones de Roo, pero claro, en Heroku no esta.
Siguiente paso, añadir el plugin appassembler para que genere el script con el que arrancar la aplicación:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>assemble</goal></goals>
<configuration>
<assembleDirectory>target</assembleDirectory>
<extraJvmArguments>-Xmx512m</extraJvmArguments>
<programs>
<program>
<mainClass>com.springsource.petclinic.PetclinicMain</mainClass>
<name>webapp</name>
</program>
</programs>
</configuration>
</execution>
</executions>
</plugin>
Y por último, hay que quitar la línea de packaging para que genere un jar en vez de un war, listo.
Paso 3
Ahora hay que crear la clase Main.java en src/main/java, exactamente igual que la que puse en la primera práctica, tampoco tiene más historia.
Paso 4
Para configurar la aplicación para que use PostgreSQL hay que tocar el applicationContext.xml, que es el archivo de configuración de Spring. Se encuentra en src/main/resources/META-INF/spring. Aquí, hay que cambiar las propiedades username, password y url por tan solo url de la siguiente manera:
Que es el parseo para la cadena de conexión a PostgreSQL que ya ví. En el applicationContext.xml veo que el driver de conexión a la base de datos está parametrizado, así que tengo que cambiarlo, en el mismo directorio esta un archivo database.properties en el que esta la propiedad que me interesa, database.driverClassName, lo dejo así:
database.driverClassName=org.postgresql.Driver
Por último, en el persistence.xml (que esta en src/main/resources/META-INF), hay que cambiar el valor del hibernate.dialect, a org.hibernate.dialect.PostgreSQLDialect.
Paso 5
Todo listo, ahora toca probar en local:
export REPO=~/.m2/repository/
export DATABASE_URL=postgres://helloheroku:helloheroku@localhost/helloheroku
mvn install
sh target/bin/webapp
Listo, entro en http://localhost:8080 y ahí esta el PetClinic con Spring Roo y contra PostgreSQL. Genial
Paso 6
Para el despliegue de la aplicación en Heroku, primero hay que crear el Procfile con la definición de la actividad web:
gedit Procfile
Y añado:
web:sh target/bin/webapp
Lo añado todo a un repositorio de git, creo el entorno de Heroku, lo subo todo a Heroku y GitHub y abro la aplicación:
git init
git add pom.xml Procfile src/
heroku create --stack cedar
git push github master
git push heroku master
heroku open
Y listo, funcionando!
Código en GitHub
Conclusiones
Este ejemplo es, de lejos, el más interesante, ya que demuestra tres cosas:
- Que Heroku parece ser capaz de trabajar sin problemas con los frameworks mayoritarios de Java.
- Que realmente, los frameworks de Java son tremendamente potentes si se sabe como usarlos, aportando una gran flexibilidad.
- Y por último, creo que mi primera impresión estaba justificada. Tenemos un entorno capaz de acercar el mundo Java EE a la mayoría de desarrolladores... con todo lo que ello implica. Ahora es cosa nuestra aprovecharlo o no.
Y con esto, he terminado con Heroku de momento, me sigue quedando pendiente clarificar el tema de dynos, bds, etc… A ver si me pongo…