miércoles, 16 de abril de 2008

Instalar Jdk y Tomcat

Aun que es un tema menor, no falta el que pregunta "..oye, como instalo java.." [ack] ¬¬
bueno... descarga el Jdk de http://java.sun.com/javase/downloads/index.jsp busca el que dice JDK6 Update N°

ya descargado, lo ejecutamos y lo movemos a un directorio del sistema

$ chmod +x jdk-6u6-linux-i586.bin
$ ./jdk-6u6-linux-i586.bin
#mv jdk1.6.0_06 /usr/local


Luego establecimos las variables en el sistema (/etc/profile) para que encuentre le directorio de instalación

# vi /etc/profile
(Y agregamos estas lineas al final del archivo)

export JAVA_HOME=/usr/local/jdk1.6.0_06
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib


Incorporamos las variables:

# source /etc/profile


Lo mismo para Tomcat. Lo bajamos de http://archive.apache.org/dist/tomcat/ la última version

$ tar -xzvf apache-tomcat-6.0.16.tar.gz
$ cd apache-tomcat-6.0.16/bin
$ ./startup.sh


Se puede comprobar en el navegador, abriendo la dirección http://localhost:8080/


:wq

viernes, 7 de marzo de 2008

Corregir la extension de la CLST (Chile)

Como ya sabrán el gobierno de Chile anunció un paquete de medidas para soportar la crisis de hidro-abastecimiento que pasa nuestro Chilito. Entre las que se cuenta la reducción del voltaje (suministradas por las distribuidoras) hasta en un 10% de la tensión nominal, flexibilizar el uso de los hídro-recursos a partir del 15 de Febrero y la extensión del horario de verano hasta el último sábado de Marzo.

Es ésta última medida la que da trabajo a los administradores de sistemas, ya que los sistemas operativos juran de guata que el cambio va el 8 de Marzo.

$ zdump -v Chile/Continental | grep 2008
Chile/Continental Sun Mar 9 02:59:59 2008 UTC = Sat Mar 8 23:59:59 2008 CLST isdst=1
Chile/Continental Sun Mar 9 03:00:00 2008 UTC = Sat Mar 8 23:00:00 2008 CLT isdst=0
Chile/Continental Sun Oct 12 03:59:59 2008 UTC = Sat Oct 11 23:59:59 2008 CLT isdst=0
Chile/Continental Sun Oct 12 04:00:00 2008 UTC = Sun Oct 12 01:00:00 2008 CLST isdst=1

Entonces lo que hay que hacer es bajar los archivos con las reglas de las zonas horarias, hacer los cambios correspondientes y compilarlas.

# wget ftp://elsie.nci.nih.gov/pub/tzdata2007k.tar.gz
# tar xzvf tzdata2007k.tar.gz
africa
antarctica
asia
australasia
europe
northamerica
southamerica
pacificnew
etcetera
factory
backward
systemv
solar87
solar88
solar89
iso3166.tab
zone.tab
leapseconds
yearistype.sh
# chmod +w southamerica


Aplicamos estos cambios:

--- southamerica 2008-03-07 09:50:53.000000000 -0300
+++ southamerica.new 2008-03-07 09:53:16.000000000 -0300
@@ -789,7 +789,9 @@
Rule Chile 1998 only - Sep 27 4:00u 1:00 S
Rule Chile 1999 only - Apr 4 3:00u 0 -
Rule Chile 1999 max - Oct Sun>=9 4:00u 1:00 S
-Rule Chile 2000 max - Mar Sun>=9 3:00u 0 -
+Rule Chile 2000 2007 - Mar Sun>=9 3:00u 0 -
+Rule Chile 2008 only - Mar 29 3:00u 0 -
+Rule Chile 2009 max - Mar Sun>=9 3:00u 0 -
# IATA SSIM anomalies: (1992-02) says 1992-03-14;
# (1996-09) says 1998-03-08. Ignore these.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]

Compilamos

# zic -l America/Santiago southamerica


Y comprobamos los cambios

# zdump -v America/Santiago |grep 2008
America/Santiago Sat Mar 29 02:59:59 2008 UTC = Fri Mar 28 23:59:59 2008 CLST isdst=1 gmtoff=-10800
America/Santiago Sat Mar 29 03:00:00 2008 UTC = Fri Mar 28 23:00:00 2008 CLT isdst=0 gmtoff=-14400
America/Santiago Sun Oct 12 03:59:59 2008 UTC = Sat Oct 11 23:59:59 2008 CLT isdst=0 gmtoff=-14400
America/Santiago Sun Oct 12 04:00:00 2008 UTC = Sun Oct 12 01:00:00 2008 CLST isdst=1 gmtoff=-10800

Listo !!

lunes, 11 de junio de 2007

Reportes con JasperReports

Para la generación de reportes estudié e implementé JasperReport. Esta es una herramienta libre y 100% escrito en Java. Los reportes pueden contener listados, gráficos, imágenes, subreportes, entre otros.

Hay dos formas que utilicé para realizar un reporte con DataSource de Hibenate. La primera (la que explico detalladamente a continuación) es con una Hibernate connection directa y la otra es enviando el mismo List que retorna el query, hacia el reporte.

El proceso de generación de un reporte con una Hibernate Connection es el siguiente:

  1. Se debe crear un archivo .jrxml (de la familia de xml basado en el dtd de JasperReport). Esto lo hará iReport. Lo podemos encontrar en http://jasperforge.org -> [iReport -> Download].

    Al abrirlo nos mostrará un entorno para la fabricación de un reporte

    Aquí tenemos que configurar algunas cosas:

  • Ruta de los programas para visualizar el reporte: Options -> Settings -> External Programs.

  • Options -> settings -> Compiler . Activamos aquí, sino la carpeta donde están los binarios se nos llenará de archivos temporales

  • Options -> Classpath : Esto en muy importante ya que le indicaremos donde tiene que buscar los recursos.

    Aquí se deben agregar las carpetas donde se encuentra todos los archivos de mapeo, los java, además del driver manager jdbc de postgres

  • Luego definimos el data source del reporte: Data -> Connections/Data Sources y creamos un HibernateConnection.

  • Listo. Para comenzar crearemos un reporte con el asistente e ingresamos el hql.

  • Seguimos click click click .. En :Build -> [ pdf | html | xls | etc] seleccionamos el tipo de reporte

  • Para ver final mente el reporte: Build -> Execute (with a active connection). Al guardarlo veremos lo ha hecho en un archivo jrxml.

  • Podemos apreciar la estructura del reporte:

    • Title : Título del reporte. Lo pone solo en la primera página del reporte

    • PageHeader : Pié de página superior. Aquí podría ir el nombre del usuario que lanzó e reporte.

    • ColumnHeader : Nombre de la columna. Se repite en todas las páginas.

    • Detail : Detalle. No dejar aquí objetos, ej. un gráfico, por que puede repetirse (todo el obj.)

    • ColumnFooter : Algún detalle al final de la columna. ej. Suma total.

    • PageFooter : Pié de página. número de hoja, hora, etc

    • LastPageFooter : Este pié de pagina solo va en la última página

    • Summary : Este espacio va entre el ColumnFooter y PageFooter. y se repite en todas las págs.

  • Luego podremos personalizar el diseño del reporte. Lo principal se encuentra aquí:

    • Fields: estas son las columnas que nos trajo la consulta

      Nota: para modificar la consulta: Data -> Report query. No podemos hacer consultas con join fetch, pero podemos agregar las columnas que faltan, navegando por el árbol de relaciones que aparece al lado y pinchar en Add Selecte

    • Variables: Son variables generadas por el propio iReport. ej el número de página, número de columna, etc.

    • Parameters: estos parámetros son enviados desde el proyecto hacia el reporte. ej. si queremos que en el PageHeader aparezca el nombre del proceso de postulación, creamos un parámetro (en iReport) ej. procesoPostulacion de tipo java.lang.String y en el código se lo enviamos así:




Map parameters = new HashMap();
parameters.put("procesoPostulacion", procesoPost);


  1. Con el jrxml dentro del proyecto nos queda agregar las siguientes librerías al mismo:

    • iReport.jar

    • itext-2.0.0.jar

    • jasperreports-1.3.1.jar

    • jfreechart-1.0.5

    • jcommon-1.0.0.jar

    • poi-2.5.1-final-20040804.jar

  • Para finalizar la prueba creamos un botón jsp que ejecute un método como el siguiente.




    <af:commandbutton id="reporte" text="Reporte" action="#{institucionesBean.reporte}">
    <af:setactionlistener from="#{prmGlobal.tipoPdf}" to="#{institucionesBean.tipoReporte}">


    public String reporte() {
    try{
    URL url = this.getClass().getResource("/reportes/instituciones.jrxml");
    String jrxml = url.getPath();
    Map parameters = new HashMap();
    JasperReportsToBrowser.reportConnection(jrxml, parameters, tipoReporte);
    }catch(Exception e){
    e.printStackTrace();
    }
    return null;
    }


    </af:setactionlistener></af:commandbutton>



      • <af:setActionListener from="#{prmGlobal.tipoPdf}" to="#{institucionesBean.tipoReporte}" />

        Este parámetro indica el formato del reporte; hasta el momento está "tipoPdf" y "tipoExcel"

        tipoReporte es una variable String de la clase del Backing.

      • String jrxml = this.getClass().getResource( "/reportes/instituciones.jrxml");

        es la ruta completa del jrxml

      • Map parameters = new HashMap(); con este hasMap agregamos los parámetros que definimos en el jrxml.

      • JasperReportsToBrowser.reportConnection(jrxml, parameters,tipoReporte);

        He creado esta clase y método estático y la he agregado al paquete util, donde se completan los pasos en la generación del reporte y entregarlo a través del navegador. Se le debe pasar cadena que contiene el path completo (del sistema) del archivo jrxml; y el hashMap al que le hemos agregado los parámetros que recibirá el reporte.



    Reportes con gráficos.



    Para generar reportes con gráficos, hacemos click aquí , luego lo dibujamos en el reporte y lo localizaremos en el summary. Para graficar necesitaremos dos variables, para este ejemplo utilicé instituciones, así que crearé la variable $F{Tipo} que representa los tipos de instituciones (colegio, salud, administrativo, iglesia, etc) y la variable $F{Total}, que contiene el total de cada tipo.




    Vamos a ingresar la consulta en Data -> Report Query:

    select ti.nombre as Tipo, count(*)as Total

    from Institucion i ,Tipoinstitucion ti

    where i.tipoinstitucion = ti.codigo

    group by ti.nombre


    Salimos y vamos a las propiedades del gráfico -> chart -> edit chart properties -> char data -> details e ingresamos las variables.


    Guardamos e incorporamos el reporte al proyecto.


    El proceso de generación de reporte por medio de un List.

    Para este método tenemos que crear un jrxml de la misma forma como se menciono anteriormente, de hecho, podemos utilizar el mismo, la diferencia está en el método.




    public String reporte() {
    try{
    URL url = this.getClass().getResource("/reportes/instituciones.jrxml");
    String jrxml = url.getPath();
    List list = InstitucionCT.getInstituciones(campoInstitucion,tipoInstitucion,null,codestructuraiasd);
    Map parameters = new HashMap();
    JasperReportsToBrowser.reportList(jrxml, parameters,list,tipoReporte);
    }catch(Exception e){
    e.printStackTrace();
    }
    return null;
    }


    Como se puede apreciar se envía la misma consulta que se solicita para mostrar el listado, que se aprecia en el ABM de Institución.

    JasperReportsToBrowser.reportList(jrxml, parameters, list,tipoReporte);


    Este método es el que construye el reporte basado en el listado y lo sirve a través del navegador.




  • Adjunto la clase JasperReportsToBrowser

    /*
    * Genera y entrega el reporte a través del browser
    * @author Rene Vielma
    *
    */
    package unach.util;

    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.io.StringWriter;
    import java.sql.Connection;
    import java.util.List;
    import java.util.Map;

    import javax.faces.context.ExternalContext;
    import javax.faces.context.FacesContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletResponse;

    import net.sf.jasperreports.engine.JRException;
    import net.sf.jasperreports.engine.JasperCompileManager;
    import net.sf.jasperreports.engine.JasperExportManager;
    import net.sf.jasperreports.engine.JasperFillManager;
    import net.sf.jasperreports.engine.JasperPrint;
    import net.sf.jasperreports.engine.JasperReport;
    import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
    import net.sf.jasperreports.engine.export.JRXlsExporter;
    import net.sf.jasperreports.engine.export.JRXlsExporterParameter;

    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.Transaction;

    import unach.hibernate.SessionFactory;
    import unach.util.beans.ParametrosGlobales;


    public class JasperReportsToBrowser extends HttpServlet{

    public static ParametrosGlobales prmGlobal;

    // Methods

    /**
    * Crea un reporte y lo sirve a través del browser
    * @param path
    * @param parameters
    * @param tipo
    * @throws ServletException
    * @throws IOException
    */
    public static void reportConnection(String path,Map parameters,String tipo) throws ServletException, IOException{

    HttpServletResponse response = null;
    Session session = null;
    Transaction tx = null;

    try
    {
    session = null;
    tx = null;
    session = SessionFactory.getSession();
    tx = session.beginTransaction();

    Connection connection = SessionFactory.getSession().connection();

    parameters.put("HIBERNATE_SESSION", session);

    JasperReport report = JasperCompileManager.compileReport(path);
    JasperPrint print = JasperFillManager.fillReport(report,parameters,connection);

    ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
    response = (HttpServletResponse)ectx.getResponse();
    OutputStream out = response.getOutputStream();

    if(tipo == prmGlobal.getTipoPdf()){

    byte[] bytes = JasperExportManager.exportReportToPdf(print);

    response.setHeader("Content-disposition", "attachment; filename=ListadoPDF");
    response.setContentType(tipo);
    //response.setHeader("Cache-Control", "private");
    //response.setHeader("Pragma", "");
    response.setContentLength(bytes.length);
    out.write(bytes);
    out.flush();
    out.close();
    }

    if(tipo == prmGlobal.getTipoExcel()){

    ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();

    JRXlsExporter exporterXLS = new JRXlsExporter();

    exporterXLS.setParameter(JRXlsExporterParameter.JASPER_PRINT, print);
    exporterXLS.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, arrayOutputStream);
    exporterXLS.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);
    exporterXLS.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
    exporterXLS.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
    exporterXLS.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
    exporterXLS.exportReport();


    response.setHeader("Content-disposition", "attachment; filename=ListadoPDF");
    response.setContentType("application/vnd.ms-excel");
    //response.setHeader("Cache-Control", "private");
    //response.setHeader("Pragma", "");
    response.setContentLength(arrayOutputStream.toByteArray().length);
    out.write(arrayOutputStream.toByteArray());
    out.flush();
    out.close();

    }


    FacesContext.getCurrentInstance().responseComplete();

    }
    catch (JRException e){

    // display stack trace in the browser
    StringWriter stringWriter = new StringWriter();
    PrintWriter printWriter = new PrintWriter(stringWriter);
    e.printStackTrace(printWriter);
    response.setContentType("text/plain");
    response.getOutputStream().print(stringWriter.toString());
    }

    catch (HibernateException e) {
    if (tx != null)
    tx.rollback();
    throw e;
    }

    finally {
    session.close();
    }
    }
    /**
    * Envía el List en el reporte y lo sirve a través del browser
    * @param path
    * @param parameters
    * @param list
    * @throws ServletException
    * @throws IOException
    * @author Rene Vielma
    */
    public static void reportList(String path,Map parameters,List list,String tipo) throws ServletException, IOException{

    HttpServletResponse response = null;

    try{
    JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(list);

    JasperReport report = JasperCompileManager.compileReport(path);
    JasperPrint print = JasperFillManager.fillReport(report,parameters,ds);

    ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
    response = (HttpServletResponse)ectx.getResponse();
    OutputStream out = response.getOutputStream();

    if(tipo == prmGlobal.getTipoPdf()){

    byte[] bytes = JasperExportManager.exportReportToPdf(print);

    response.setHeader("Content-disposition", "attachment; filename=ListadoPDF");
    response.setContentType(tipo);
    //response.setHeader("Cache-Control", "private");
    //response.setHeader("Pragma", "");
    response.setContentLength(bytes.length);
    out.write(bytes);
    out.flush();
    out.close();
    }

    if(tipo == prmGlobal.getTipoExcel()){

    ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();

    JRXlsExporter exporterXLS = new JRXlsExporter();

    exporterXLS.setParameter(JRXlsExporterParameter.JASPER_PRINT, print);
    exporterXLS.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, arrayOutputStream);
    exporterXLS.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);
    exporterXLS.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
    exporterXLS.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
    exporterXLS.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
    exporterXLS.exportReport();


    response.setHeader("Content-disposition", "attachment; filename=ListadoPDF");
    response.setContentType("application/vnd.ms-excel");
    //response.setHeader("Cache-Control", "private");
    //response.setHeader("Pragma", "");
    response.setContentLength(arrayOutputStream.toByteArray().length);
    out.write(arrayOutputStream.toByteArray());
    out.flush();
    out.close();

    }

    FacesContext.getCurrentInstance().responseComplete();
    }
    catch (JRException e){

    // display stack trace in the browser
    StringWriter stringWriter = new StringWriter();
    PrintWriter printWriter = new PrintWriter(stringWriter);
    e.printStackTrace(printWriter);
    response.setContentType("text/plain");
    response.getOutputStream().print(stringWriter.toString());
    }
    }

    }

    miércoles, 18 de abril de 2007

    Cambiar chartset de archivos en proceso batch

    Ayer me surgió la necesidad de cambiar un montón de archivos java, de un proyecto, con un charset cp1252 y enviarlos a UTF-8. Esta fue mi solución.

    $svn update
    $for i in `find . -name *.java`;do iconv -f CP1252 -t UTF-8 $i > $i"na";mv $i"na" $i;done
    $svn commit -m "cambio de charset, de los archivos java, de cp1252 a UTF-8"
    Enviando
    src/test/Prueba.java Enviando
    src/test/TestFormatoNombre.java Enviando
    src/unach/admision/backing/ContactoBK.java
    .
    .
    .
    src/unach/general/controls/TipoDirCT.java Enviando
    src/unach/general/hibernate/AbstractPersona.java Enviando
    src/unach/general/hibernate/Divpolitica.java Enviando
    src/unach/pestudio/controls/EstudioCT.java Enviando
    src/unach/seguridad/backing/InfoUsuarioBK.java Enviando
    src/unach/seguridad/controls/MenuCT.java Enviando
    src/unach/util/ControlHibernate.java Enviando
    src/unach/util/FormatoFechaHora.java Enviando
    src/unach/util/FormatoNombre.java Enviando
    src/unach/util/JSFUtils.java Enviando
    src/unach/util/JasperReportsToBrowser.java Enviando
    src/unach/util/beans/ParametrosGlobales.java Enviando
    src/unach/util/servlets/Welcome.java
    Transmitiendo contenido de archivos .................................................................................................
    Commit de la revisión 558.

    Listo