lunes, 13 de junio de 2011

Drupal y Google: SiteMap, Analytics y AdSense

El principal cometido de un sitio web no es otro que dar promoción a alguna entidad a través de un medio tan global como es la red. Esta promoción necesita lógicamente las visitas de internautas que se cruzan con nuestro sitio por cualquier tipo de necesidad que nosotros podemos solucionar. Si además, podemos sacar rendimiento económico a esas visitas, mejor que mejor.

Nuestra página en Drupal nos puede ayudar gracias a algunos módulos a gestionar todo lo que hemos visto anteriormente, ya que la podremos combinar y promocionar en un buscador tan potente como Google que nos puede proporcionar numerosas visitas.

Vamos a ver como tres módulos nos puede ayudar a gestionar las visitas a nuestro espacio e intentar sacarle algún eurillo a nuestro sitio.

SiteMap

Si hay algo que valora el buscador Google a la hora de indexar una página es su orden y la capacidad de actualización y crecimiento en contenidos de la misma. Del crecimiento depende la voluntad del webmaster o de las necesidades informativas o de actualización del sitio. Del orden se ocupará el módulo SiteMap. Este módulo nos permitirá generar un Mapa Web de nuestro sitio de manera automática sin tener que escribir una sóla línea de código, amén de poder actualizar el mismo simplemente añadiendo o modificando los contenidos de nuestra página, es decir, si añado un nuevo apartado automáticamente SiteMap me lo ubicará en el mapa del sitio.

Instalar y poner a andar SiteMap es extremadamente fácil. Lo descargas (la url la tienes en el enlace de arriba), lo descomprimes, lo subes a tu sites/all/modules y lo activas. Si pones http://misitioDrupal/sitemap , ¡voilá! ahí tenemos nuestro mapa web. Más fácil y mejor imposible. En la administración del módulo podremos configurar si deseamos que algunas partes de nuestra web no aparezcan en el mapa.

Analytics

Una vez tenemos nuestro 'índice' del sitio web, Google nos facilita una herramienta para gestionar todo lo que rodea al tráfico web de nuestra aplicación. Tráfico, páginas vistas, ficheros descargados, media de tiempo de visita, motores de búsqueda desde los que se accede... es decir, con esta herramienta podrías ver desde donde obtienes más visitantes (Google, Bing, ...), que partes de la página son más visitadas y, por tanto, más interesantes para los visitantes, etc, etc. Interesante, ¿no?. 'Toneladas' de información que puedes obtener de tu sitio que 'dejan' los visitantes. Si quieres profundizar sobre esta herramienta y hacer auténticas 'virguerías' pueden entrar en Trucos Google Analytics

Una vez te has registrado en Google Analytics y has dado de alta tu sitio (no profundizaremos demasiado, ya que no es complicado), nos bajamos el módulo para Drupal llamado Google Analytics , lo descomprimimos, lo subimos a nuestro directorio de módulos y lo habilitamos. Accedemos a la administración del mismo y añadimos el ID para el sitio que hemos dado de alta en analytics indicando 'Único Dominio' y le indicamos que añada a todos los roles el seguimiento. Guardamos la configuración y en el plazo de un día (seguramente menos) cuando accedamos a nuestro Panel de Control de Google Analytics observaremos que empezamos a ver resultados, es decir, al lado de nuestro perfil del sitio veremos la señal de visto bueno verde y empezaremos a ver las visitas subir.

AdSense

Ya que tenemos organizado nuestro sitio y tenemos controlado y estudiado todo el tráfico que transcurre por él, es buena idea intentar sacarle rendimiento económico. Google AdSense es otra herramienta integrable en Analytics que te permitirá colocar anuncios en tu web y proporcionarte beneficios por clic.


Deberás darte de alta en Google AdSense, rellenar tus datos y esperar a que el programa de AdSense dé de alta tu solicitud. 

Cuando estés dado de alta, accediendo a tu panel de AdSense podemos ver todas las opciones y para empezar es recomendable crear un anuncio. En la pestaña "Mis Anuncios" podremos crear un panel con anuncios de diferentes tamaños y estilos personalizados, para que los podamos adaptar a la apariencia de nuestro sitio. Una vez creado, te saldrá en tu listado de Anuncios. La pantalla del listado de anuncios nos será útil en un futuro


Ahora vamos a integrar todo en Drupal. Nos bajamos el módulo AdSense, lo descomprimimos, lo subimos a nuestra localización de módulos y lo activamos (es necesario activar el módulo del Core Profile para poder activar AdSense). 

Pues vamos al menu de administración y entramos en el Apartado AdSense para incluir nuestro Id de usuario en la pestaña 'Publisher ID'.


A continuación, marchamos a la configuración y creamos un bloque (llámalo como quieras pero recuerda el nombre, recomiendo algo referente a AdSense). En el Body del bloque vamos a añadir el código que nos proporciona el listado de AdSense de anuncios para un anuncio creado, por ejemplo:



<script type="text/javascript"><!--
google_ad_client = "ca-pub-0000000000000000";
/* Bloque1 */
google_ad_slot = "0000000000";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>

Quítale los comentarios // y /* y publica el bloque. Ponlo en una zona visible y asegurate de que para tí no está activado, es decir, sólo para usuarios anónimos, por ejemplo. Así, no prodrás picar ni te aparecerán los anuncios, Google es muy escrupuloso con la gente que pica en sus propios anuncios, no es recomendable hacerlo.



Al rato, se activarán los anuncios en tu sitio y podrás empezar a ganar dinero por clic. 


Una vez realizadas todas estas operaciones tienes un sitio con anuncios que te rentan, con herramientas de seguimiento de visitas, buscadores, etc y una organización como si de un sitio profesional se tratara. Opcionalmente, tendrás la opción de profundizar en las herramientas de Google, que tienen muchísima "chicha" y con las que se puede jugar muchísimo, pero eso os lo dejo a vosotros, :P

martes, 7 de junio de 2011

Relleno de PDF Editables con iText 2.1.7

La librería iText tiene bastantes usos entre los que se encuentran las herramientas y métodos necesarios para la generación de un archivo pdf a partir de una información. Podemos decir que es la responsable última de crear el archivo PDF.


Sin embargo, nos hemos encontrado con un problema:


  • La librería de generación de informes, implementada en base a DynamicJasper, mostraba los informes a través de la clase JasperViewer, la cual daba opciones de exportación diversas (ODT, PDF, XLS,...). Sin embargo, con la versión antigua de iText (2.0.1) daba una excepción:

1   java.lang.NoSuchMethodError: com.lowagie.text.pdf.PdfWriter.setRgbTransparencyBlending(Z)V

  • Lógico es pensar en actualizar la librería. Actualizando a la última versión estable 2.1.7, arreglamos el problema anterior, pero a la hora de rellenar ficheros PDF que disponen de campos rellenables (Certificados de paternidad, de incapacidad temporal, ...) obteníamos el siguiente error:

1   com.lowagie.text.exceptions.BadPasswordException: PdfReader not opened with owner password

Explicamos las implementaciones con las que se ha solucionado el error.


Implementación para iText 2.0.1


Para el relleno de un formulario PDF con campos editables hemos seguido un algoritmo sencillo con el que no hay ninguna pega:


 1 public static void printPDFFields(String pathIN, String pathOUT) throws IOException, DocumentException {

 2    PdfReader reader = new PdfReader(pathIN);
 3    // Creamos el pdf de salida
 4    PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(pathOUT));

 5    // Rellenamos los campos
 6    //Obtenemos el formulario
 7    AcroFields form1 = stamp.getAcroFields();
 8    //Obtenemos los campos

 9    HashMap map = form1.getFields();
10    //Obtenemos el conjunto de claves de los campos que no es más que el nombre de los mismos
11    Set s = map.keySet();
12 

13    int i = 0;
14    //Recorremos todos las claves
15    for (Iterator it = s.iterator(); it.hasNext();) {

16         String key = (String) it.next();
17         int j = i++;
18         //Grabamos en el campo el valor de un contador
19         form1.setField(key, new Integer(j).toString());

20         if (form1.getFieldType(key) == AcroFields.FIELD_TYPE_CHECKBOX) {
21             //Comprobación de si el campo es un check
22             form1.setField(key, "");
23         }

24    }
25 
26    stamp.setFormFlattening(true);
27    stamp.close();
28 }

Esto sería un ejemplo para crear un pdf en 'pathOUT' a partir del formulario que se encuentra en la ruta 'pathIN' y cuyos campos estarían rellenos con un número que se iría incrementando. Esto da la excepción que hemos visto arriba si lo lanzamos con iText 2.1.7



NOTA: Para encontrar los valores válidos de un check hay que abrir el pdf como texto plano y buscar la etiqueta >>/N<< y a la derecha de ella se encontrará el valor que toma el check.



Implementación para iText 2.1.7



Para el relleno de un formulario PDF con campos con la siguiente versión de iText seguimos el siguiente método teniéndo en cuenta el atributo OWNER que hemos creado.



 1 private static final byte[] OWNER = "inss".getBytes();

 2 
 3 public static void printPDFFields(String pathIN, String pathOUT) throws IOException, DocumentException {

 4    PdfReader reader = new PdfReader(pathIN, OWNER);
 5    // Creamos el pdf de salida
 6    PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(pathOUT));

 7    // Rellenamos los campos
 8    //Obtenemos el formulario
 9    AcroFields form1 = stamp.getAcroFields();
10    //Obtenemos los campos

11    HashMap map = form1.getFields();
12    //Obtenemos el conjunto de claves de los campos que no es más que el nombre de los mismos
13    Set s = map.keySet();
14 
15    int i = 0;

16    //Recorremos todos las claves
17    for (Iterator it = s.iterator(); it.hasNext();) {
18         String key = (String) it.next();

19         int j = i++;
20         //Grabamos en el campo el valor de un contador
21         form1.setField(key, new Integer(j).toString());
22         if (form1.getFieldType(key) == AcroFields.FIELD_TYPE_CHECKBOX) {

23             //Comprobación de si el campo es un check
24             form1.setField(key, "");
25         }
26    }
27 

28    stamp.setFormFlattening(true);
29    stamp.close();
30 }

Así evitamos la excepción, pues con el OWNER le estamos proporcionando el ownerPassword del documento al constructor del PdfReader. Pero, ¿cómo obtenemos ese password?: Existen numerosas aplicaciones por la red que te ayudan a desencriptar o recuperar contraseñas de archivos PDF de este tipo. En particular, podemos usar la denominada Recovery PDF Password que nos dirá cual es la cadena de la que debemos obtener los bytes para pasarsela a OWNER y así poder trabajar correctamente con nuestro PDF editable

miércoles, 30 de marzo de 2011

Java: SCJP 310065: Aprueba en un mes

En esta entrada voy a describir el proceso que he seguido para aprobar el examen de certificación de Java (SCJP 310065). Te indico y te proporciono todo el material que he usado. No te aseguro que apruebes, pero si sigues estas indicaciones lo tendrás bastante encarrilado.

Paso 1: Teoría


Para empezar lo suyo es que le des una lectura rápida o una lectura a los resúmenes del libro de la editorial McGraw Hill de Kathy Sierra. Está muy bien y abarca todos los objetivos que se pide en el examen SCJP. Lo dicho, lo suyo es que te lo leas (aunque son 890 páginas) porque ahí viene todo y bien explicado. Lo puedes encontrar aquí

Paso 2: Afianzar Conocimientos

A continuación, haz ejercicios de http://www.javaranch.com/game/game2.jsp . Es un jueguecito donde te ponen preguntitas teóricas, no se parecen en nada a las del examen, pero para afianzar conocimientos está bastante bien, con preguntas sobre aspectos teóricos básicos y preguntas-trampa bastante interesantes. Te recomiendo que cada pregunta que falles la apuntes para luego ir repasando. Aquí tienes también las preguntas y respuestas en PDF que me curré tras crackear el applet del juego.

Paso 3: Exámenes

Sigue el método anterior y apúntate las preguntas que falles para luego repasarlas.

Te recomiendo las preguntas de JavaCertifications.net (están aquí) y los examenes de Marcus Green ( http://www.jchq.net/mockexams/exam1.htm , http://www.jchq.net/mockexams/exam2.htm , http://www.jchq.net/mockexams/exam3.htm )

Cuando hayas hecho todos estos exámenes te recomiendo que hagas los ejercicios del libro de Kathy Sierra para rematar. Están por capítulos y vienen las respuestas a continuación, están bastante bien y son similares a lo que te puedes encontrar en el examen.

Opcionalmente (yo sólo hice uno) y si quieres ver como es el examen, hay una aplicación que se llama ExamLab que contiene 5 exámenes con el formato del examen real, es decir, el examen que hagas ahí es como el examen que vas a hacer para la certificación. Son bastante complicados, aunque lo positivo es que encontrarás, una vez finalices cada examen, las respuestas y una explicación pregunta a pregunta. La aplicación está en http://examlab.tk/scjp6.html .

Pues eso, como te darás cuenta son muchas cosas. Pero en un mes intensivo te da tiempo a todo y llegas más o menos preparado al examen.

viernes, 30 de abril de 2010

Drupal: Mandar correos con PHPMailer

Mandar correos electrónicos tras realizar una operación es algo bastante común en cualquier aplicación informática. En Drupal no es una excepción, pero muchas veces tendremos problemas con la configuración PHP de nuestro servidor. Muchos servidores gratuitos deshabilitan la función mail() que envía correos vía PHP para evitar el spam.

Nosotros para superar esta complicación usaremos PHPMailer, un módulo desarrollado para Drupal que nos facilitará el envío de correos electrónicos.

Para empezar nos descargamos la versión para Drupal de PHPMailer. Extraemos la carpeta y observaremos que dentro de ella existe otra carpeta llamada "phpmailer". En esa carpeta debemos añadir los ficheros class.phpmailer.php, class.smtp.php y class.pop3.php que se encuentran en la implementación de la clase PHPMailer que se puede descargar aquí (descargar PHPMailer_v5.1.tar.gz).

Una vez hemos completado la descarga del módulo lo añadimos en %ROOT_SITIO%/sites/all/module.

Accedemos a nuestra distribución de Drupal y accedemos a Administer -> Site Building -> Modules y habilitamos el PHPMailer.

Marchamos a la configuración del módulo y activamos la casilla de enviar correos usando PHPMailer y completamos (ejemplo para usar SMTP de Gmail):

General

Primary SMTP server: smtp.gmail.com
SMTP Port: 465
Use Secure Protocol: SSL

SMTP Autenticathion

Username: Tu cuenta de gmail (incluyendo "gmail.com")
Password: Tu password

En Advanced SMTP Settings sólo es necesario añadir el nombre del que envía el correo y en Test Configuration se añaden los correos para enviar los email de prueba.

Salvamos la configuración y se enviará el correo de prueba.

Sin embargo, si estás usando un Apache Local puede que tengas un problema. No puedes elegir en "Use Secure Protocol" otra opción que no sea "No" y eso impide enviar correos por SMTP desde Gmail, Hotmail, ...

Debes acceder a dos archivos:

1.- El httpd.conf de nuestro servidor Apache en el que se debe descomentar la siguiente línea


LoadModule ssl_module modules/mod_ssl.so


2.- El php.ini donde deberemos descomentar la siguiente línea


extension=php_openssl.dll


Ahora el desplegable de Protocolos debería tener: No, SSL y TLS.

jueves, 11 de marzo de 2010

Drupal: Crear una galería embebida en un contenido

Vamos a crear una galería embebida en un contenido con Ajax de manera que en el contenido podremos navegar sobre todas las fotos que hemos subido de ese contenido



Para realizar este tutorial he usado la versión 6.16 de Drupal y los módulos:

Vamos a partir de una instalación limpia de Drupal con estos módulos contenidos en ella.

Video:

miércoles, 10 de marzo de 2010

Cómo hacer un backup en local de nuestra página Drupal

Esta es una pregunta que me estaba haciendo bastantes veces por el miedo a que estos hostings gratuitos de hoy en día se fueran al garete en el momento menos pensado. De hecho, tenía pensado hacerlo pero hasta que no he tenido problemas de verdad no me he centrado en hacerlo.

Para empezar a hacer nuestra copia de seguridad de un sitio Drupal que tengamos publicado en la web (se puede hacer a la inversa) tenemos que tener en cuenta que debemos hacer dos copias de seguridad, del sitio en sí (ficheros) y de la base de datos.

Backup del sitio

En primer lugar vamos a hacernos una copia del sitio. Nos copiamos todo lo que tenemos subido, es decir, archivos originales de la instalación, módulos que hayamos agregado y archivos adicionales del uso de la página, fundamentalmente imágenes.

- Accedemos como queramos a donde tenemos el sitio (FTP, explorador si lo tenemos en local, etc) y vamos a la raíz, que es el directorio donde se encuentra index.php, update.php, cron.php, ...
- Ese directorio y todos los que contiene los copiamos, es decir, nos los bajamos a nuestros local.

Una vez hecho esto ya tenemos nuestra copia de seguridad del sitio.

Backup de la Base de datos

Para hacer una copia de la base de datos vamos a tener que hacer uso de alguna herramienta.

Normalmente todos los alojamientos disponen de una llamada phpMyAdmin que permite administrar las bases MySQL que tengamos alojadas en un servidor. Una de las capacidades de esta herramienta se encuentra en el apartado "Exportar" y nos permite obtener algún fichero de la extensión que le digamos con todos los datos de nuestra base.

Nosotros normalmente haremos un backup de la base con inserts extendidos y con extensión sql. Obtendremos un archivo "basededatos.sql" con todo el contenido de la base de datos que ha ido manipulando drupal a medida que hemos ido trabajando en ella.

Es recomendable antes de realizar este backup borrar la caché de datos de drupal para no hacer copias de datos innecesarios.

Integrar las copias en nuestro local

Para integrar las copias en nuestro local vamos a necesitar dos herramientas:

  • Un servidor Apache para los ficheros php del sitio. Existen varios que cumplen este requisito como AppServ, WebServ o Xampp. Algunos contienen una distribución de MySQL integrada para que no sea necesario descargarla
  • Un paquete de herramientas administrativas para operar con bases de datos MySQL por lo que, efectivamente, debemos tener instalado MySQL en nuestro equipo. Yo, particularmente uso MySQL GUI Tools
Empezaremos por migrar la base de datos.

  • Debemos crear una base de datos dentro de MySQL, lo que viene siendo crear un nuevo esquema. Por ejemplo, lo creamos con el MySQL Administrator del paquete que indicamos anteriormente. Pongámosle, por ejemplo, "drupallocal"
  • Abrimos el MySQL Query Browser (importante seleccionar como default schema -esquema por defecto- el recién creado drupallocal) y marchamos a File -> OpenScript... . Ahí se nos abrirá un explorador donde seleccionaremos el archivo sql que obtuvimos de nuestro backup generado por phpMyAdmin. Se nos mostrará el contenido del backup y le daremos a "Execute" recordando que debe estar marcado como default drupallocal.
  • Una vez hemos ejecutado y si no ha habido ningún problema deberíamos tener nuestra base de datos migrada. Podemos comprobarlo mirando en el esquema si se han creado tablas y tienen datos dentro.
Ahora vamos a migrar el sitio.

  • Tenemos que instalar el servidor apache para que pueda interpetrar los ficheros php de los que se compone el sitio Drupal.
  • Tenemos que mover los ficheros que nos hemos bajado del sitio a una carpeta específica del servidor. En el caso de AppServ es %ruta_instalacion_AppServ%/www/ , por ejemplo.
  • Una vez copiado en la carpeta que sea debemos acceder a la carpeta %ruta_instalacion_AppServ%/www/drupallocal/sites/default/ y modificar el fichero settings.php. Tenemos que cambiar la entrada poniendo nuestro usuario, password, host y el nombre de la base de datos (en nuestro caso drupallocal):


    $db_url = 'mysql://user:pass@localhost/drupallocal';

Una vez realizados estos pasos tenemos copiada la página en nuestro local y si nuestro servidor está corriendo accediendo a http://localhost/drupallocal/ (en caso de AppServ) entraremos en nuestra página en drupal exactamente igual que como la tenemos en publicada. Al acceder a nuestro link "Noticias" vemos como... ¿error 404?. Sí, es posible que pase una vez hemos migrado la página a local.

Tenemos que hacer un par de cositas más para que funcione:

  • Ejecutamos http://localhost/drupallocal/update.php que podremos ejecutar si tenemos en el fichero settings.php anterior la entrada (si la tenemos, ejecutamos el update y cambiamos esta propiedad a FALSE)


    $update_free_access = TRUE;

  • Una vez hemos hecho esto, ejecutamos http://localhost/drupallocal/cron.php
Probamos de nuevo nuestra web y... sigue fallando. Lo más probable es que en nuestro espacio publicado tuviéramos activadas las Clean URLs de Drupal, que en principio no están soportadas por nuestro servidor Apache. Si accedemos a http://localhost/drupallocal/?q=admin/settings/clean-urls y las desactivamos. Ahora funcionará todo, pero nosotros, realmente lo queremos tener exactamente igual que nuestro espacio publicado. Entonces debemos hacer una cosita más.

El servidor Apache al iniciarse carga diversos módulos que necesita para su funcionamiento. Uno de ellos, llamado mod_rewrite, permite reescritura de URL's al vuelo (definición de andar por casa) pero, por defecto, Apache no lo carga. Normalmente este módulo si se carga en los servidores de los hosting gratuitos por lo que se observará que las URL limpias no dan problemas en sitios Drupal en remoto, pero sí en local. Debemos buscar un archivo llamado httpd.conf y buscar donde se encuentra la carga de módulos (LoadModule ...). Pues debemos descomentar la parte que pone:

LoadModule rewrite_module modules/rewrite_module.so

Después de reiniciar el servidor, volvemos a la página de Clean-URLs y las activamos para que, por fin, tengamos todo tal y como está en nuestro espacio publicado.

miércoles, 3 de marzo de 2010

Dynamic Jasper

El objetivo primordial de este artículo es describir una herramienta que puede resultar bastante útil a la hora de algo tan común como es realizar un informe. Vamos a entrar en aspectos básicos de cara a su rápida utilización y aplicación.

¿Qué es Dynamic Jasper?

Dynamic Jasper es una librería que corre sobre JasperReports y que nos simplifica enormemente la realización de informes. Las posibilidades son enormes (posibilidad de agregar Charts, encadenar reportes, añadir códigos de barras a las columnas de un informe, …) además de usos totalmente básicos. En este artículo nos centraremos en conceptos introductorias que podemos ir combinando para obtener resultados cada vez mejores y más elegantes a la vez de poder sumar aspectos más complejos.

Su funcionamiento básico de DJ se centra en hacer más amigable e intuitivo el uso de JasperReports que para nosotros será una caja negra. Es decir, DJ actuará como un disfraz, aunque realmente seguiremos usando JasperReports, pero ahorrándonos todos los engorrosos pasos que supone usarlo.

La web del proyecto contiene un amplio abanico de documentación y ejemplos que nos pueden ser útiles de cara a realizar elegantes informes.



Entorno de integración

Dynamic Jasper es una librería escrita 100% en Java con lo que es fácilmente integrable en proyectos que empleen el lenguaje Java.

No es necesaria ninguna herramienta adicional o “plug-in” al margen de nuestro entorno de desarrollo (IDE) preferido.

Herramientas necesarias o Dependencias

En la página web de la librería podemos observar las dependencias. Aquí indicaremos que librerías vamos a necesitar integrar en nuestros proyectos para poder usar DJ en nuestro proyecto

  • La librería propia de DJ
  • Las librerías que componen Jasper Reports teniendo en cuenta que desde DJ 3.0.5 se necesita Jasper Reports 3.5.
  • Dependencias: Commons BeanUtils, Commons Collections, Commons Logging, Compilador de Eclipse jdt-core.
  • Para exportar a PDF necesitamos la librería iText
  • Para exportar a Excel necesitamos la librería JExcel API y el conjunto de librerías POI de Apache. Esta última librería no está soportada en su versión beta 3.5, es decir, para que no existan problemas necesitamos la versión 3.2
  • Para exportar a XML necesitamos la librería Commons Digester
  • Luego librerías propias de generación de Charts (JFreeChart , JCommon) o de generación de Barcotes o códigos de barra (barbecue 1.1)

Nuestro primer reporte

Una vez sabemos que tenemos que tener montado en nuestro espacio de trabajo sólo nos queda empezar a desarrollar para empezar a ver los primeros resultados. Vamos a hacer un primer informe para observar los primeros resultados.

Definir esqueleto

La idea de realizar un informe es partir de una especie de esqueleto que iremos rellenando añadiendo cosas.

Este esqueleto se puede definir de varias formas como pueden ser las siguientes:


FastReportBuilder drb = new FastReportBuilder();

DynamicReportBuilder drb = new DynamicReportBuilder();

De este modo ya tenemos el esqueleto en la variable ‘drb’. Ahora procederemos a añadirle cosas. Veremos que las posibilidades que hay y la cantidad de añadidos son bastante interesantes.

Hagámonos a la idea de que si generáramos el informe de estos esqueletos obtendríamos un informe en blanco, sin nada que mostrar. Eso es lo que vamos a ir haciendo ahora, añadir datos.

Añadir Primeros Detalles

DJ nos da la posibilidad de añadir detalles que nos resultarán útiles de cara a facilitar determinada información o añadir aspectos elegantes al informe.

Podemos añadir un título a informe


drb.setTitle("Equipos");
Definición de márgenes en la página
drb.setLeftMargin(margen).setRightMargin(margen).setTopMargin(margen).setBottomMargin(margen);
Definimos la anchura de cabecera del informe y del detalle del informe.
drb.setDetailHeight(anchura).setHeaderHeight(anchura);
Podemos hacer que la página se divida en varias columnas y ahí insertar los datos
//Si optamos por más de una columna podemos definir la separación entre ellas
drb.setColumnsPerPage(columnasPorPagina, separacion);
//Definimos una columna por página
drb.setColumnsPerPage(1);
Podemos añadir autotextos
//Insertamos una Fecha en la cabecera a la izquierda
drb.addAutoText(sdf.format(new Date()), AutoText.POSITION_HEADER, AutoText.ALIGMENT_LEFT);

//Insertamos “Pagina X/Y” en la cabecera a la derecha
drb.addAutoText(AutoText.AUTOTEXT_PAGE_X_SLASH_Y, AutoText.POSITION_HEADER, AutoText.ALIGMENT_RIGHT);
Como vemos podemos usar más autotextos cuyo tipo será definido en el primer parámetro:

  • AutoText.AUTOTEXT_CREATED_ON : Nos indicará la fecha de creación del reporte
  • AutoText. AUTOTEXT_PAGE_X_SLASH_Y: Página X/Y
  • “Texto cualquiera”
Además de colocarlo donde queramos en la página.

Como hemos comentado con anterioridad, en la página de la librería podemos obtener muchísima más información acerca añadir bastantes más cosas al reporte.


Añadir Columnas


Vamos a comenzar a definir los datos que queremos mostrar en nuestro informe. Supongamos en nuestro ejemplo que tenemos una Collection de objetos de la siguiente clase:

public class Equipo {

private int id;
private String nombre;
private String fundacion;
private String presidente;
private String entrenador;
private LinkedList<Jugador> jugadores;
private String rutaEscudo;
private InputStream escudo;


public Equipo() {
}

public Equipo(int id, String nombre, String fundacion, String presidente, String entrenador, LinkedList<Jugador> jugadores) {
this.id = id;
this.nombre = nombre;
this.fundacion = fundacion;
this.presidente = presidente;
this.entrenador = entrenador;
this.jugadores = jugadores;
}

public InputStream getEscudo() {
return escudo;
}

public String getRutaEscudo() {
return rutaEscudo;
}

public void setRutaEscudo(String rutaEscudo) {
this.rutaEscudo = rutaEscudo;
try {
File fileIn = new File(rutaEscudo);
this.escudo = new FileInputStream(fileIn);
} catch (Exception e){
e.printStackTrace();
}
}

/*resto de Getters and Setters */

Queremos un informe que muestre el listado de datos de esa Collection.

Vamos a definir un informe donde podamos ver los datos en columnas, por tanto, tenemos que definir esas columnas. Veamos como esto nos va a resultar bastante sencillo:


AbstractColumn c1 = ColumnBuilder.getInstance().setColumnProperty("id", Integer.class.getName()).setTitle("ID").setWidth(10).build();

AbstractColumn c2 = ColumnBuilder.getInstance().setColumnProperty("nombre", String.class.getName()).setTitle("Nombre").setWidth(30).build();

AbstractColumn c3 = ColumnBuilder.getInstance().setColumnProperty("fundacion", String.class.getName()).setTitle("Fundacion").setWidth(30).build();

AbstractColumn c4 = ColumnBuilder.getInstance().setColumnProperty("presidente", String.class.getName()).setTitle("Presidente").setWidth(30).build();

//Añadimos las columnas al informe
drb.addColumn(c1);
drb.addColumn(c2);
drb.addColumn(c3);
drb.addColumn(c4);


Para crear las columnas indicamos nombre del atributo, cadena que representa la clase del atributo (class.getName()), el título que queremos mostrar en el informe y la anchura (medida proporcional) de la columna. Existen muchas más opciones que podemos añadir a la columna a la hora de crearla.

También podemos crear las columnas de la siguiente manera


drb.addColumn("TITULO", "id", Integer.class.getName(),10);

Una vez hemos realizado esto tenemos el informe disponible para ser visualizado. Debemos realizar una serie de operaciones antes que veremos en el siguiente apartado.


Generación del Reporte

Una vez hemos formado el informe debemos realizar unas últimas comprobaciones de cara a poder visualizarlo. A parte de estas comprobaciones deberemos indicarle de donde va a sacar los datos para mostrar, es decir, también deberemos indicarle cual es el DataSource origen. Adicionalmente podemos indicar algunas opciones finales antes de realizar estos pasos, por ejemplo:
drb.setUseFullPageWidth(true);
Indicamos que queremos usar todo el ancho de la página a la hora de mostrar el informe.

Ahora realizamos la compilación del esqueleto rellenado para comprobar si hay algún problema y no se puede continuar con el mostrado del informe.


DynamicReport dr = drb.build();

Una vez que se ha realizado el compilado y todo es correcto procedemos a añadirle la Collection que contiene los datos


//Definimos la fuente de datos
JRDataSource ds = new JRBeanCollectionDataSource(l);

//Generamos el informe como JasperPrint con los datos ya añadidos.
JasperPrint jp = DynamicJasperHelper.generateJasperPrint(dr, new ClassicLayoutManager(), ds);

//Podemos también añadir un mapa de parámetros que hayamos definido anteriormente
//JasperPrint jp = DynamicJasperHelper.generateJasperPrint(dr, new ClassicLayoutManager(), ds, map);

Una vez todos estos procesos se han realizado correctamente con el objeto JasperPrint podemos hacer multitud de operaciones: podemos mostrarlo usando la herramienta JasperViewer, podemos exportarlo a otros formatos (apartado 6), ...

JasperViewer es un visor que proporciona la librería que muestra el informe además de permitirnos la exportación de los datos a través de él a PDF, XML, ODT, ...


//Mostramos el reporte mediante el visor JasperViewer. Con el false, indicamos que no
//cierre la aplicación al cerrar el JasperViewer
JasperViewer.viewReport(jp, false);

El resultado debería ser algo parecido a esto:


Reportes con Plantillas

Ya hemos visto que realizar un reporte simple a fin de cuentas no es más que crear un objeto DynamicReportBuilder o FastReportBuilder, añadirle columnas, compilarlo, asociarle un DataSource y mostrarlo. Ahora bien, pongámonos en el caso de que queremos seguir un formato específico de informe o plantilla. Por ejemplo, una ficha de empleado o, como en el caso de ejemplo, una especie de ficha con los datos de los equipos (los que hemos visto en el apartado anterior). Veremos que con DJ es bastante fácil de realizar.

Definir una plantilla

Para definir o crear una plantilla debemos usar alguna herramienta que nos permita la edición de las mismas y la creación de archivos JRXML. Un programa que realiza este tipo de plantillas es el iReport, bastante intuitivo y fácil de manejar. No vamos a entrar en profundidad en el manejo de esta herramienta, sólo describiremos la plantilla que hemos realizado para realizar este elemento.



  • Podemos observar que hemos colocado siete elementos en la banda de detalle ('detail'): tres etiquetas o 'label' que son elementos estáticos del informe, tres campos TextField que contendrán tres Fields y un campo Image.
  • Definiciones de Fields de la plantilla. Vemos como hemos definido tres Field de tipo String (nombre, fundación y presidente) y un field de tipo InputStream (escudo). Veremos en el siguiente apartado para que sirven estos Fields.
Nota: En versiones nuevas de iReport se generan las plantillas con un atributo en las bandas que pueden dar problemas. Al seleccionar una banda vemos que posee un atributo llamado 'Split Type' que por defecto tiene el valor 'Strecht'. Para solucionar el problema podemos poner en ese atributo el valor '<Default>'.

Agregar campos y asociar plantilla

Una vez hemos creado la plantilla debemos guardarla con formato JRXML. Lo ideal sería guardarla dentro del proyecto ya que para futuras modificaciones o traslados del proyecto no se nos olvide mover dicha plantilla.

Una vez guardada la plantilla debemos asociarla a nuestro informe para indicarle que debe ajustarse a ella a la hora de mostrar los datos. Asignar una plantilla a un informe es tan fácil como poner la siguiente instrucción:


//Asociamos una plantilla al informe
drb.setTemplateFile("resources/equipos.jrxml");
Ya que le hemos asociado una plantilla debemos crear una 'conexión' entre los datos que tenemos en la aplicación y la plantilla. Como hemos visto anteriormente habíamos creado unos Fields en la plantilla. Ahora crearemos unos campos (Fields) en el informe. Esos campos serán el nombre de los atributos y definiremos su tipo. Vemos como lo hemos realizado en el código.

drb.addField("escudo", InputStream.class.getName());
drb.addField("nombre", String.class.getName());
drb.addField("presidente", String.class.getName());
drb.addField("fundacion", String.class.getName());
A modo de resumen podemos decir que en la plantilla hemos representando gráficamente como mostrar el objeto indicando donde aparecen los atributos y definiendo éstos en la misma. Del mismo modo asociamos esa plantilla al informe y en éste definimos los atributos del objeto.

Generación del Reporte

Una vez hemos realizado estos pasos, sólo nos queda generar el informe. Esta generación es la misma que seguimos en el informe del listado, no existe diferencia alguna. Una vez se ha lanzado el JasperViewer veremos que obtenemos el siguiente informe.


Subreportes

Realizar subreportes con Jasper Reports es bastante confuso y enrevesado. Sin embargo, vamos a ver como realizar subinformes usando la librería DJ es mucho más simple y útil.

Para empezar, vamos a definir la estrategia para realizar este informe.


Paso 1 : Definición Informe

Nuestro objetivo final es definir un informe como subinforme de otro, por tanto, para empezar definiremos dos informes inicialmente independientes. Vamos a crear un informe de tipo plantilla que va a contener un informe de tipo listado (la plantilla contendrá los datos de los equipos y el listado mostrará los jugadores del equipo)

Por tanto, procedemos a definir ambos informes.


  • Informe de Plantilla (Equipo)

public static FastReportBuilder initMainReport() throws Exception {
FastReportBuilder report = new FastReportBuilder();

report.setTitle("EQUIPOS");
report.setMargins(margen, margen, margen, margen);

report.setTemplateFile("resources/equipos.jrxml");

report.addField("id", Integer.class.getName());
AbstractColumn c1 = ColumnBuilder.getInstance().setColumnProperty("id", Integer.class.getName()).setTitle("ID").setWidth(10).build();
report.addColumn(c1);

report.addField("nombre", String.class.getName());
report.addField("fundacion", String.class.getName());
report.addField("presidente", String.class.getName());
report.addField("entrenador", String.class.getName());
report.addField("escudo", InputStream.class.getName());

return report;
}


Importante: Podemos observar como hemos definido una columna en el informe a pesar de ser de tipo plantilla. En el siguiente apartado explicaremos la razón.


  • Informe de Listado

public static FastReportBuilder initSubreport() throws Exception {
FastReportBuilder report = new FastReportBuilder();

AbstractColumn c1 = ColumnBuilder.getInstance().setColumnProperty("id", Integer.class.getName()).setTitle("ID").setWidth(10).build();
AbstractColumn c2 = ColumnBuilder.getInstance().setColumnProperty("dorsal", Integer.class.getName()).setTitle("Dorsal").setWidth(30).build();
AbstractColumn c3 = ColumnBuilder.getInstance().setColumnProperty("nombre", String.class.getName()).setTitle("Nombre").setWidth(30).build();
AbstractColumn c4 = ColumnBuilder.getInstance().setColumnProperty("posicion", String.class.getName()).setTitle("Posicion").setWidth(30).build();

report.addColumn(c1);
report.addColumn(c2);
report.addColumn(c3);
report.addColumn(c4);

report.setUseFullPageWidth(true);

return report;
}

Como vemos, nada extraño respecto a lo que explicamos en el apartado de informes de tipo listado

Paso 2 : Agrupación

Definimos sobre que campo queremos agrupar el subinforme.

Bien, hemos visto que se ha creado una columna en el informe de plantilla que realmente no es necesaria pues hemos añadido un Field con ese atributo pero, ¿por qué hacemos esto?.

A la hora de colocar el subinforme debemos indicar un campo significativo para colocar el subinforme, es decir, necesitamos un identificador del objeto para añadir el subinforme. Veamoslo en el ejemplo: Tenemos equipos que poseen un entero llamado 'id' que es el identificador. A la hora de crear el informe para cada valor de ese 'id' se añadirá un subinforme con los datos correspondientes al objeto de ese id.

La agrupación de puede realizar creando un grupo o como veremos en el siguiente apartado


Paso 3 : Asociación

Asociamos un informe como subinforme del otro. Veamos como lo hacemos:

private static DynamicReport definirSubreport(FastReportBuilder report, FastReportBuilder subreport, String atributoColeccion, String claseColeccion) throws Exception {
report.addField(atributoColeccion, claseColeccion);
report.addGroups(1).setGroupLayout(1, GroupLayout.EMPTY);

report.addSubreportInGroupFooter(1, subreport.build(),
new ClassicLayoutManager(), atributoColeccion,
DJConstants.DATA_SOURCE_ORIGIN_FIELD,
DJConstants.DATA_SOURCE_TYPE_COLLECTION);

report.setUseFullPageWidth(true);

return report.build();
}
Para empezar definimos un Campo en el informe 'padre' que no es necesario que sea definido en la plantilla. Ese campo contiene el nombre del atributo del objeto (equipo en nuestro caso) de la colección que mostraremos en el subinforme. Esa colección actuará de DataSource del subinforme.

Definimos el grupo, con la función 'addGroups(1)' donde el parámetro indica el número de columnas que cogeremos para agrupar. En nuestro caso, la primera y única columna definida para el informe con plantilla.

Una vez realizado esto, usamos la función 'addSubreportInGroup(Header|Footer)' para asociar ambos informes. Los parámetros que se pueden observar son: el primero (número 1) es el número del grupo que usamos para agrupar, en este caso el primero; el subreport compilado, es decir, DynamicReport del subinforme; un Layout, nosotro usaremos el clásico; el nombre del atributo de la clase que alimenta a modo de DataSource al subinforme; constante que indica que el DataSource proviene de un campo/field del informe y constante que indica que el tipo del DataSource es una colección.

Una vez realizado esto compilamos el informe y realizamos la generación del informe y obtendremos los siguiente:


Formas de Mostrar un reporte

La herramienta JasperViewer es bastante útil de cara a realizar una especie de previsualizado y desde ella realizar una exportación. Muchas veces nos interesa exportar directamente informes en nuestro máquina o en la máquina del cliente, por ejemplo, si generamos informes masivamente y queremos exportarlos a varios ficheros ya que sería bastante engorroso que JasperViewer nos mostrara todos los informes y nosotros los exportaramos.

Exportación PDF, HTML, XML

DJ proporciona métodos para exportar nuestros informes a formatos conocidos y comunes. Tenemos la posibilidad de exportar a PDF, HTML y XML, entre otros.

La ventaja que proporciona DJ es que exportar a cualquiera de estos formatos nos cuesta una sóla línea. Simplemente, en lugar de notificar a JasperViewer lo que queremos mostrar usaremos una clase llamada 'JasperExportManager' que nos proporcionará soluciones de cara a las exportaciones. Vemos que métodos podemos usar:


 //Exportación a formato HTML
JasperExportManager.exportReportToHtmlFile(jp, EXPORT_PATH + "exportacionHTML.html");
//Exportación a formato PDF
JasperExportManager.exportReportToPdfFile(jp, EXPORT_PATH + "exportacionPDF.pdf");
//Exportación a formato XML, sin embeber imágenes
JasperExportManager.exportReportToXmlFile(jp, EXPORT_PATH + "exportacionXML.1.xml", false);
//Exportación a formato XML, embebiendo imágenes
JasperExportManager.exportReportToXmlFile(jp, EXPORT_PATH + "exportacionXML.2.xml", true);

Como vemos la exportación es bastante simple, una sóla línea nos proporciona un fichero o la información del informe.

Exportación a Excel

La exportación a Excel es ligeramente más compleja que las que hemos visto anteriormente ya que realmente no existe una mecanización por parte de DJ de exportación a este tipo de archivo. La documentación de DJ si que nos da información acerca de como exportar un informe a XLS.

Vamos a incluir un ejemplo de método para exportar un objeto JasperPrint (el jp que hemos mostrado anteriormente) a un archivo Excel.


private static void exportToExcel(JasperPrint jp) throws Exception {

//Creamos una instancia del objeto JRXlsExplorer que se encuentra en la librería jasperreports-X.X.X.jar
JRXlsExporter exporter = new JRXlsExporter();
//Si queremos definir varios Sheet lo hacemos en un array de cadenas que posteriormente la añadiremos por parámetros.
String[] sheetNames = {"Hoja 1"};

//Creamos el fichero de salida donde exportaremos el informe a Excel
File outputFile = new File(EXPORT_PATH + "exportacionEXCEL.xls");
FileOutputStream fos = new FileOutputStream(outputFile);

//Empezamos a definir los parámetros de la exportacion
//Indicamos el objeto JasperPrint que deseamos exportar
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jp);
//Indicamos el fichero donde vamos a exportar el informe
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, fos); //and output stream

//Excel specific parameter
//Indicamos si queremos una página por Sheet
exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);
//Indicamos si deseamos eliminar los espacios vacíos entre filas
exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
//Indicamos si quremos mostrar una página en blanco como fondo
exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);

//Definimos los nombres de los Sheet que es el Array de String que definimos arriba
exporter.setParameter(JRXlsExporterParameter.SHEET_NAMES, sheetNames );

//Usamos la función exportReport para crear el nuevo Excel.
exporter.exportReport();
}

Todos estos atributos los podemos ver en la documentación de Jasper Reports, o podemos verlo en el Javadoc que podemos encontrar en la red.

Nota: Indicar que para que podamos realizar la exportación a EXCEL las últimas versiones de DJ no soportan la exportación con las librerías del POI de Apache 3.5, ya que según el equipo de desarrollo de DJ hasta que no dejara de estar POI 3.5 en fase beta no se adaptaría DJ a dicha librería.

Enlaces