Cometas en el cielo – Khaled Hosseini
Agarré esta novela por recomendación ya que la había visto varias veces en el estante pero no me había llamado la atención. No conocía al autor y no había nada de ella que me atrajera, hasta que me dijeron que el autor era afgano (no lo conocía) y que la novela reflejaba mucho de la idiosincrasia y costumbres del lugar. Creo que eso fue lo único que me invitó a leerla.
La historia está buena, tiene sus vueltas de tuerca y está bien pensada. Una novela buena digamos. Sin embargo lo que más me atrajo fue el reflejo de las costumbres y la forma de pensar y actuar de los personajes. Si bien la novela no se centra para nada en ello, leer entre lineas y ver como las acciones de los protagonistas están influidas por sus tradiciones, por sus costumbres resulta verdaderamente interesante y de cierta manera ayuda a entender porqué son como son y porque actúan como actúan.
Novela liviana, fácil de leer y que hace un buena aporte a la visión que tenemos de aquellos remotos parajes del mundo.
Machete
Después de algo de espera para ver esta película y unos cuantos días para escribir el comentario por pura falta de tiempo, acá va mi rápido y somero comentario sobre Machete. Creo que la mejor forma de transmitir lo que es la película es mirar la imagen, saber que el realizador es Robert Rodriguez y que el protagonista es Danny Trejo. Eso me diría que es una película de pocas palabras y bastante sangre saltando para todos lados arrancada a machetazos sin ton ni son. Bueno, no dista mucho de eso pero además se agrega una historia (bastante linea por cierto) pero bien contada.
No esperaba una historia sino mas bien de un policía mejicano que se va ilegalmente a Estados Unidos escapando de la mafia política y policial para caer una vez más en las mafias pero además buscando venganza. Robert de Niro y Steven Segal hacen muy buenos papeles al igual que Jessica Alba y Michelle Rodriguez (Ana Lucia en Lost). Todo bien conjugado para, como quien no quiere la cosa, meterse en la política que rodea la inmigración ilegal a Estados Unidos y el famoso muro que se levanta en la frontera con Méjico.
Una película para pasar el rato en donde vuela un poco más de sangre de lo debido y con chicas con metralleta. No es para un Oscar pero se deja ver.
Integración de JasperReports en aplicaciones Java
Lo más complicado de integrar JasperReports en una aplicación Java es encontrar buena documentación de como hacerlo. JasperReports es muy potente y a la vez complejo que las alternativas que brinda son muchísimas. Fui encontrando distintos ejemplos y pequeños tutoriales que realmente no me sirvieron. Esta entrada está basada en el libro JasperReports 3.5 for Java Developers de David R. Heffelfinger. Para aquellos que no quieran comprar el libro, acá va un muy somero tutorial de como hacer funcionar esto. Básicamente es el tutorial que no pude encontrar en mi lucha y que hago como ayuda-memoria para mí y quizás sirva a alguien. Realmente recomiendo comprar el libro ya que es muchísimo más amplio que esta pequeña guía y muestra el uso de muchas más opciones y alternativas que simplemente voy a omitir. Se supone que el código que aparece en esta entrada debería ser correcto y funcionar, pero si encuentran algún error háganme saber y será corregido.
Todo el software necesario puede conseguirse en http://www.jaspersoft.com/
Otros links de interés:
iReport http://sourceforge.net/projects/ireport/files/
jFreeChart http://sourceforge.net/projects/jfreechart/
Breve introducción
Hay un par de conceptos que deben tenerse presentes a la hora de utilizar JasperReports para que no se convierta todo en un gran dolor de cabeza. Los pasos que daremos para alcanzar nuestro objetivo son los siguientes:
- crear una plantilla para el reporte (jrxml file)
- compilar la plantilla
- generar el reporte (a un archivo jrprint o a un pdf o por pantalla)
Creando la plantilla para el reporte
Esta parte es una de las más simples. Para la generación de la plantilla utilizamos iReport (yo estoy usando la versión 3.7.5). iReport tiene un muy buen wizard para la creación de plantillas y muchas opciones para cambiar el layout. Las plantillas pueden incluir elementos estáticos y dinámicos y tener embebidas las consultas sql necesarias para obtener los datos de una base de datos. También existe la posibilidad de pasar los datos programáticamente al reporte. Los ejemplos que están a continuación asumen que la consulta está embebida en el reporte y solo se hará referencia al objeto de datos que puede pasarse al reporte.
Las plantillas de reportes son archivos de extensión jrxml. El formato del archivo es en realidad un xml estándar con otra extensión.
Compilando el reporte
JasperReports no utiliza las plantillas de reportes tal como son guardadas por iReport sino que las compila. Durante este proceso el xml es parseado y la información se guarda como objetos serializados en archivos de extensión jasper. No me puse a escarbar aún en estos archivos así que no puedo decir mucho de ellos.
En la medida que las plantillas no cambien no tienen porque ser compiladas cada vez que necesitamos el reporte, sino que usaremos como entrada los archivos .jasper ya compilados.
El siguiente fragmento de código compila una plantilla (.jrxml) para convertirla en un reporte .jasper
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
public class compileReport {
public static void main(String[] args) {
try {
System.out.println("Compiling report...");
JasperCompileManager.compileReportToFile("firstTestReport.jrxml");
System.out.println("Done!");
} catch (JRException e) {
e.printStackTrace();
}
}
La clase JasperCompileManager provee varios métodos para compilar las plantillas ya sea utilizando archivos o streams como salida. En este caso estamos mandando la salida a un archivo el cual tendrá el mismo nombre que la plantilla con extensión .jasper.
Generando el reporte a un archivo pdf
Una vez que tenemos nuestra plantilla compilada podemos llenar el reporte y utilizar distintas formas de salida para el mismo, ya sea un archivo pdf, html, excel, un visor en pantalla y una larga lista de etcéteras. El siguiente fragmento de código genera un archivo pdf
import java.io.File;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.util.JRLoader;
public class exportToPdf {
public static void main(String[] args) {
File file = new File("firstTestReport.jrprint");
try {
JasperPrint jasperPrint = (JasperPrint) JRLoader.loadObject(file);
JRPdfExporter pdfExporter = new JRPdfExporter();
pdfExporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
pdfExporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, "firstTestReport.pdf");
System.out.println("Exporting report...");
pdfExporter.exportReport();
System.out.println("Done!");
} catch (JRException e){ }
}
}
Generando el reporte a pantalla
Ya mencionamos que los reportes podían generarse y enviarse a distintas salida, la pantalla es un muy buena alternativa para la pre visualización de reportes, así que acá va el fragmente de código que genera el reporte y lo envía a pantalla
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Properties;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.view.JasperViewer;
public class reportView {
public static void main(String[] args) {
try {
JasperPrint print;
String url = "jdbc:postgresql://miserver/midatabase/";
Properties props = new Properties();
props.setProperty("user","miuser");
props.setProperty("password","mipassword");
props.setProperty("port", "5432");
Connection conn = DriverManager.getConnection(url, props);
print = JasperFillManager.fillReport("firstTestReport.jasper", new HashMap(), conn);
JasperViewer view = new JasperViewer(print);
view.setVisible(true);
} catch (JRException ex) {}
catch ( SQLException e ){}
}
}
En este caso estamos pasando una conexión al método fillReport, la cual será utilizada para conectarse a la base de datos y ejecutar las sentencias sql embebidas en la plantilla. El método también soporta, en lugar de una conexión, una fuente de datos que contenga los valores necesarios para el reporte. JasperReports provee de un data source vacio (JREmptyDataSource) que puede ser utilizado para probar los reportes sin datos.
Instalando true type fonts en Ubuntu
Algunas aplicaciones pueden requerir la instalación de las Ms True Type fonts en Linux. En particular, estaba necesitando las fuentes para usar iReport y no estaban disponibles para la JVM así que aquí vamos.
Esto es poco mas que un ayuda-memoria porque la instalación sobre Ubuntu es realmente muy sencilla usando apt-get
De aquí en más se asume que se está trabajando como root:
root@csomma-laptop:/home/csomma# apt-get install msttcorefonts
….. después de descargar los paquetes y ejecutar la instalación…
All done, no errors.
All fonts downloaded and installed.
Updating fontconfig cache for /usr/share/fonts/truetype/msttcorefonts
No CIDSupplement specified for Dotum-Bold, defaulting to 0.
No CIDSupplement specified for Batang-Regular, defaulting to 0.
No CIDSupplement specified for Batang-Bold, defaulting to 0.
No CIDSupplement specified for Dotum-Regular, defaulting to 0.
Updating fontconfig cache for /usr/share/fonts/truetype/msttcorefonts
Así de simple, fácil y rápido. Hasta la próxima entrada…
Persons unknown
Llega al final la primer temporada de Persons Unknown, una serie que llegó recomendada a través de Microsiervos. La cosa va de un grupo de siete personas que despiertan un día en un pueblo fantasma en el medio de la nada, sin saber como llegaron ahí y sin conocerse entre ellos. Cada rincón del pueblo está cuidadosamente vigilado por cámaras de seguridad y un poco personal que provee los servicios mínimos en el lugar, parece no saber nada sobre lo que sucede.
Los 7 desconocidos son sometidos a diferentes desafíos físicos y mentales que los llevan a enfrentarse y desconfiar unos de otros. Si bien el comienzo parece explotar la misma idea de Lost (un grupo de personas desconocidas en un lugar desconocido), la trama cobra vida propia a los pocos episodios y diferentes personajes comienzan a cobrar vida tanto dentro como fuera del pueblo.
Si bien aún me quedan por ver dos episodios de la primera temporada, es una serie recomendable, entretenida y que verdaderamente engancha al espectador. No espero gran desenlace de esta temporada sino que una preparación para la próxima que ansiosamente esperaré.
Jornada de integración y escalada
El sábado 14 hicimos con la gente del grupo de escalada de La Muralla una jornada de integración en Las Canteras del Parque Rodó. Participaron chicos del INAU, de la Asociación Down, los voluntarios de La Muralla y algo de público que se acercó hasta el lugar. Hubo muchas actividades para todas la edades, para quienes sabían y no sabían escalar. Por suerte el día acompañó mucho y los gurises pasaron muy bien.
Desde muy temprano en la mañana algunos de los compañeros de La Muralla estuvieron armando las actividades, así que un reconocimiento para ellos que desinteresadamente dedicaron su día a éstos chicos. La jornada se va repetir todos los segundos sábados de cada mes (si todo sigue según lo planeado). Los mantendré al tanto a través de twitter.com/claudiosomma
Les dejo algunas fotos…
Canal 12 hizo una cobertura del evento que se puede ver acá
Reseteando la contraseña en postgres
Esto más que una entrada es un ayuda memoria para mí. Cada vez que me olvido o por algún otro motivo tengo que resetear la contraseña del usuario postgres tengo que salir en búsqueda de las notas de como hacerlo y por las leyes de murhpy éstas nunca aparecen.
Las ubicaciones de los archivos a continuación son válidas para Posgres 8.4 en Ubuntu 10.4 con la instalación por defecto.
Paso 1 – Habilitar el login del usuario postgres sin contraseña.
Para esto agregamos al archivo /etc/postgresql/8.4/main/pg_hba.conf la siguiente línea (en realidad modificamos una linea muy similar que hay en el archivo):
local all postgres trust
Paso 2 – Reiniciar el servidor postgres
/etc/init.d/postgresql-8.4 restart
Paso 3 – Nos autenticamos con el usuario postgres (sin password) y lo modificamos
#psql -U postgres template1
> alter user postgres with password ‘password’;
Paso 4 – Volver a la configuración original
Volvemos el archiv pg_hba.conf a su estado original y una vez más reiniciamos el servidor
Un buen titulo en El Observador
Sabado de canteras
Estuvimos en las Canteras del Parque Rodó preparando la jornada del 14 de Agosto. Tremendo despliegue para armar unos cuantos divertimentos…
PostgreSQL, Java y fechas
Trabajando para un proyecto tuve que cambiar de mi querida MySQL a PosgreSQL y me encontré como era de esperar con unos cuantos problemas. Entre ellos, el que más dolores de cabeza me dio y sobre el que más variantes tuve que probar hasta encontrar con la más adecuada para las necesidades del momento fue el del almacenamiento y recuperación de fechas.
Evalué varias alternativas y vi mucha cosa al respecto y me quedé con la solución que a continuación presento, y que describo para salvar mis problemas de memoria y quizás para ayudar un poco a algún eventual lector que ande tras una solución para ese mismo problema.
La tabla
Las fechas son guardadas en campos de tipo timestamp without time zone. En el siguiente ejemplo solo se muestran dos columnas de la tabla y omití todo lo que no viene al caso.
CREATE TABLE trabajo ( nombre character varying(50) fecha timestamp without time zone );
La aplicación
La aplicación almacena las fechas en variables de tipo GregorianCalendar que es un objeto de Java muy flexible para el manejo de fechas.
class Trabajo {
private String nombre;
private GregorianCalendar fecha;
}
Además de los getters y setters habituales, escribí un par de métodos que permiten setear las fechas a partir de un String y recuperarlas como un String, lo cual es muy práctico al momento de mostrarlas o de setear fechas a partir del valor obtenido de un date picker.
public String getFechaAsString() {
SimpleDateFormat sdf = new SimpleDateFormat(“dd-MM-yyyy HH:mm”);
return( sdf.format( (this.fecha).getTime() ) );
}
El formato de fecha elegido está hardcoded pero en este caso no es una limitación. La clase SimpleDateFormat es muy flexible a la hora de parsear fechas con lo que el código anterior puede ser fácilmente modificable para soportar cualquier formato. En caso de quererse formatos más flexibles que se correspondan con las preferencias del usuario en el sistema operativo, tendrás que echar mano a la clase TimeZone. En el ejemplo no se manejan posibles errores al parsear la fecha (asumo que this.fecha siempre tiene un valor válido, el setter debería encargarse de eso).
public void setFechaAsString( String fecha ) {
if( fecha.length() != 0 ) {
SimpleDateFormat sdf = new SimpleDateFormat(“dd-MM-yyyy HH:mm”);
try {
java.util.Date d = sdf.parse( fecha );
(this.fecha) = new GregorianCalendar();
(this.fecha).setTime( d );
} catch ( ParseException e ) {
e.printStackTrace();
}
}
Las fechas son seteadas a partir de un String, el cual es parseado y en caso de no verificar exactamente el formato necesario, tira una excepción (en el ejemplo imprimo el stack trace, aunque en la realidad la excepción se maneja de manera un poquito más feliz).
La clase SimpleDateformat devuelve un objeto de tipo java.util.Date (no confundir con java.sql.Date) a partir del cual podemos establecer la fecha en nuestro GregorianCalendar.
Guardando fechas
Guardar las fechas es muy simple si echamos mano a nuestra clase getFechaAsString().
sql = “INSERT INTO trabajo (nombre,fecha) values(‘”+ this.nombre+”‘,’”+this.getFechaAsString()+”‘)”;
(Ojo con las comillas) y ese sql lo mandamos a la base de datos.
Recuperando fechas
Recuperar las fechas tiene tambien su truqito, veamos..
sql = “SELECT * FROM trabajo”;
ResultSet rs = st.executeQuery( sql ); donde st es un Statement valido conectado a la base de datos
Iteramos sobre el resultado
…
java.sql.Date d = rs.getDate(“fecha”);
if( d1 != null ) {
GregorianCalendar gc1 = new GregorianCalendar();
gc1.setTimeInMillis( d1.getTime() );
this.fecha = gc1;
…
Observar que getDate devuelve un objeto de java.sql.Date, pero igualmente podemos crear un GregorianCalendar a partir de él pasando la fecha a un timestamp.
Conclusiones
No es el más flexible de los métodos para almacenar y mostrar fechas, pero es lo suficientemente flexible si manejamos las fechas en un formato que no dependa de la configuración regional del usuario. Sin embargo, podemos mostrar las fechas en cualquier formato utilizando SimpleDateFormat para formatearlas de la manera que mas nos convenga.




Comentarios recientes