Dagi3d v4

Generar documentos pdf con Rails y Flying Saucer

En la aplicación que estaba haciendo en RoR necesitaba generar documentos en formato pdf a partir de los formularios rellenados por el usuario. Había comenzado a hacerlos usando la librería para ruby PDF::Writer y aparentemente funcionaba bastante bien pero resultaba un infierno el tener que maquetar toda la presentación desde código, aparte de que no me gustaba mucho la idea de hacerlo así de cara a posibles cambios de la plantilla.
De casualidad, a través de un enlace en Devzone di con un árticulo sobre la generación de pdf's en java usando las librerías Flying Saucer e iText.
Flying Saucer es una librería para renderizar documentos xhtml y css 2.1 y que ahora trabaja de manera conjunta a iText, que sirve para generar documentos pdf.
Así que la opción de tratar de integrar esta librería en la aplicación para así convertir la vista generada desde Rails en el pdf, era más que tentadora.

Para hacerlo, lo primero era descargar la librería Flyin Saucer(que ya viene con iText incluida) y generar la aplicación en Java que se encargase de convertir el documento xhtml en pdf(está copiada casi tal cual de un ejemplo del artículo):

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.xhtmlrenderer.pdf.ITextRenderer;
import com.lowagie.text.DocumentException;


public class Xhtml2Pdf {

    /**
     * @param args
     */
    public static void main(String[] args) throws IOException, DocumentException {
       
        if (args.length != 2) return;
       
        String inputFile = args[0];
        String url = new File(inputFile).toURI().toURL().toString();
       
        String outputFile = args[1];
       
        OutputStream os = new FileOutputStream(outputFile);

        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocument(url);
        renderer.layout();
        renderer.createPDF(os);

        os.close();
    }
}

Luego escribí una sencilla función en ruby que se encargase de ejecutar la clase hecha en java pasándole como parámetros el archivo de origen con el documento xhtml y el archivo de destino donde se generaría el pdf(lo único que tiene así de 'chicha' es que genera el classpath de manera dinámica):

def xhtml2pdf(input_file, output_file)
  
  java_dir = File.join(File.expand_path(File.dirname(__FILE__)), "java")
  jar_dir = File.join(java_dir, "jar")
  
  class_path = ".:#{java_dir}"
  
  Dir.foreach(jar_dir) do |jar|
    class_path << ":#{jar_dir}/#{jar}" if jar.match(/\.jar/)  
  end
  
  command = "java -cp #{class_path} Xhtml2Pdf #{input_file} #{output_file}"
  system(command)
end

Para poder utilizar la librería desde el controlador, tan sólo quedaba copiar el fichero en ruby dentro la carpeta lib/ del proyecto Rails, la clase en java en lib/java y los jar's necesarios para ésta, en lib/java/jar:

Y en el controlador tan sólo tenía que generar la vista y guardarla en un fichero, convertirlo en pdf y mandarlo al cliente:

require 'xhtml2pdf'

class FooController < ApplicationController
 
  def generate_pdf
        
    @document = Document.find(params[:id])
    
    xhtml = "/tmp/foo.xhtml"
    pdf = "/tmp/foo.pdf"
    
    File.open(xhtml, "w") do |file|
      file << render_to_string(:template => "pdf/document", :layout => "../pdf/pdf")
    end

    xhtml2pdf(xhtml, pdf)
    
    send_file pdf,
      :filename => "document.pdf",
      :type => "application/pdf"
  end
end

Y si quisieramos ir viendo en el navegador cómo va a quedar sin necesidad de generar el pdf, bastaría con comentar el contenido de esta función(o hacer una nueva) y generar la vista como hariamos normalmente:

render :template => "pdf/document", :layout => "../pdf/pdf"

Por último, comentar que para que Flying Saucer pueda acceder a las imágenes y hojas de estilo del documento xhtml, las rutas de estos elementos deben estar de manera absoluta apuntando a un recurso local(file://<rutadelfichero>) o bien de manera relativa a dónde se encuentre físicamente el xhtml, por lo que igual habría que hacer un helper que modificase la ruta de los recursos dependiendo de si se está previsualizando desde el navegador o se está volcando en disco.

Aunque PDF::Writer parecía funcionar bastante bien e iba más rápido ya que escribe directamente el pdf sin necesidad de parsear un documento xhtml y sus hojas de estilo, creo que en este caso compensa tener un pequeño híbrido en rails y java por el tiempo ahorrado en maquetar el pdf directamente desde ruby.

Java vs. Ruby On Rails

Sin palabras face-smile.png

Que conste que a mi java me encanta, pero tal vez sea cierto que para hacer cosas que hoy en día se podrían considerar elementales dentro del desarrollo web, haya que complicarse en exceso si lo comparamos frente a otras alternativas.

Java Expo 06

Entre los días 21 y 23 de marzo, Sun organiza Java Expo 06, una serie de jornadas donde se desarrollarán en torno a 50 ponencias acerca de las nuevas tecnologías y modelos de desarrollo relacionados con Java, como Ajax, JavaServer Faces, SOA, NetBeans, OpenSolaris, GlassFish, servicios web… Además de las ponencias, se organizarán talleres eminentemente prácticos.

Esta es la agenda prevista:

DÍA 1 – Martes 21 de marzo

  • Java EE y programación en Web 2.0 utilizando Blueprints.
  • Solaris, OpenSolaris y Sun Studio: Cambiando el juego.
  • Java SE en el Desktop: Maquillaje Extremo en el GUI
  • NetBeans Extremo: Matisse, CVS, Profiling y plug-ins.
  • Técnicas de persistencia para aplicaciones en Java SE y EE con EJB 3.0.
  • Interoperabilidad utilizando servicios web avanzados y el pack para desarrolladores Java Web Services.
  • Seminario sobre programación de nivel web: JavaServer Faces.
  • Desenmarañando los hilos: concurrencia de Java y utilidades de sincronización.
  • Seminario sobre programación de nivel web: AJAX.
  • Monitorización y administración en Java SE 5.0
  • Taller práctico: creación de aplicaciones GUI de calidad utilizando NetBeans GUI Builder (Matisse)
  • Taller práctico: Iniciación a Sun Java Studio Enterprise 8.

DÍA 2 – Miércoles 22 de marzo

  • Desarrollo rápido de aplicaciones web con Sun Java Studio Enterprise y Creator.
  • Colaboración y comunidades abiertas: Mustang, GlassFishSM y java.net
  • SOA, JBI, BPEL: Estrategia, diseño y buenas prácticas.
  • Diseño de aplicaciones Java ME de moda para usuarios particulares y corporativos.
  • Seminario: Optimización integral del rendimiento de las aplicaciones Java.
  • Seminario: Seguridad en la empresa: seguridad de aplicaciones web y servicios web.
  • Taller práctico: Creación de aplicaciones web reales de forma fácil y rápida, con Sun Java Studio Creator. Taller práctico: Cómo mejorar el rendimiento de las aplicaciones con NetBeans Profiler.

DÍA 3 – Jueves 23 de marzo

  • ¿Qué hace que NetBeans sea el mejor?
  • Desarrollo de plug-ins y plataforma cliente enriquecida.
  • ¿Qué hace de NetBeans el mejor IDE para desarrollar en J2ME?
  • ¿Qué hace de NetBeans el mejor IDE para desarrollar en J2EE?
  • Solaris 10 y OpenSolaris.
  • Sun Studio 11 – La herramienta definitiva para el desarrollo de aplicaciones con Solaris. Contenedores Solaris – Espacios de sistemas operativos virtuales.
  • Service Management Facility (SMF) de Solaris.
  • APIs y herramientas de seguridad Solaris.
  • APIs y herramienta Multithreaded Solaris.
  • Solaris Dynamic Tracing (DTrace) – Inmersión profunda.
  • Incremento del rendimiento con completa observabilidad del software

El registro para participar en el evento es totalmente gratuito y si por si fuera poco, sortearán varias estaciones Sun y terminales Nokia entre los asistentes.

Más info aquí

java se 6 beta

Sun acaba de sacar la primera beta de la nueva versión de la plataforma java: Java SE 6 (también conocida como Mustang).
Parece que están haciendo un esfuerzo por acercar java al escritorio ya que han mejorado el look & feel de los componentes Swing e integrado en el entorno de ventanas del usuario, tanto para Windows como en GTK para Linux, realizando llamadas a la API nativa del sistema operativo, tal como hace SWT.
A ver si por lo menos dejan que se termine de asentar la versión 5, ya que parece que por la cantidad de novedades que trajo y la amplia implantación de la 1.4 no se terminó de asentar.

Aquí se puede ver la lista con el resto de mejoras y descargar la beta: http://java.sun.com/javase/6/

Actualización:

Acabo de bajar la beta y ejecutado el SwingSet2 y la verdad es que tiene muy buena pinta, ya que si se utiliza el look & feel de GTK, ya no toma la apariencia standard de los widgets tal como hacía antes, si no que usa el tema que se esté ejecutando en ese momento, además de tener un comportamiento más fluido.

Con este cambio, tendrá sentido seguir utilizando SWT?

Patrón Plug-In

(Aviso, este post me ha salido un poco largo y no hay dibujitos face-smile.png )

Hoy con todos ustedes, el patrón plug-in.

La utilización de este patrón permite crear objetos en tiempo de ejecución, teniendo como requisito que la clase que acabamos de instanciar, implemente una determinada interfaz para poder tratar las distintas clases plugin-in por igual.

¿Y esto para que sirve? Con esto conseguiremos enchufar nuevas clases a la aplicación sin necesidad de modificar …

leer más