Entradas

Anular caché de los navegadores

Los navegadores guardan todos los archivos que se han accedido. En internet explorer se llama "archivos temporales de internet"... lo cuál se refiere al caché de internet. (tanto nombre!) Pero si estamos en una página que requiere autenticarse, y al deslogear regresa a la página autenticada, pues el navegador mostrará la página por más que el usuario haya cerrado la sesión. Lo mejor es que cada página que el navegador no se guarde en el caché. Para ello colocaremos las siguientes sentencias (ya sea en jsp o en un servlet): response.setHeader("Cache-control","no-cache"); response.setHeader("Pragma","no-cache"); response.setDateHeader ("Expires", 0); Y Listo

Generar XLS

Para generar XLS generalmente se usa el Jakarta POI (en java), pero para web es mejor engañar al navegador. El navegador recibe como cabecera el tipo del archivo (mime-type) que está recibiendo y sabrá qué programa abrir. Si es de tipo text/html, abrirá el mismo navegador, pero si es un video tendrá otro tipo y le pedirá al sistema operativo abrir el reproductor de vídeo correspondiente. Para el caso de XLS es lo mismo, y como el Excel puede abrir hasta html, entonces lo engañaremos con más facilidad: Al inicio del JSP colocaremos esta línea: <%@page contentType="application/vnd.ms-excel"%> Con esto, cuando se acceda al .jsp abrirá el contenido con el excel. Pero si se estuviese usando el Internet Explorer, el xls saldrá incrustado en el navegador. Esto puede ser molestoso. Lo que podemos hacer es que se le pregunte al navegador si desea abrirlo o descargarlo. Colocaremos las siguientes líneas: <%@page contentType="application/vnd.ms-excel"%> <%respon

Configuración de Tomcat (conectando al Apache utilizando AJP)

Imagen
El Tomcat utiliza - por omisión - el puerto 8080 para mostrar los contenidos web. Se puede cambiar el puerto de salida en el archivo $CATALINA_HOME/conf/server.xml de 8080 a 80, para que el acceso sea más simple y evitar escribir un "apellido" como http://midominio :8080 /sistemaweb/. Pero quizás en nuestro host también estemos utilizando el apache para publicar otras aplicaciones que no son necesariamente jsp/servlet. Es posible hacer que todas las peticiones que reciba el apache a un determinado "directorio" sea redireccionado al tomcat, para que este lo atienda y envie su respueta al cliente através del Apache. Hay dos maneras para lograr esto: con el ProxyHTTP y con el conector AJP. En este mensaje mostraré cómo se utiliza el AJP. En este diagrama se muestra como funciona el AJP. Por omisión utiliza el puerto 8009 localmente. Paso 0: descargar el conector: El conector se puede encontrar en el sitio web de Tomcat . Debemos escoger el jk1.2( el jk2 es obsoleto). S

Configuración de Tomcat (módulos web)

"Normalmente", cuando un newbie en desarrollo hace su aplicación web y lo quiere publicar, suele colocarlo junto con los documentos del servidor web. Por ejemplo, si se tratase de PHP en Apache, lo coloca dentro de DocumentRoot; y si es Tomcat, en $CATALINA_HOME/webapps. Esto es normal, pero es algo desordenado tener la aplicación dentro del sistema que lo ejecuta. (Recuerdo que los perfiles de usuario en Windows NT estaban dentro del directorio Windows, si se instalaba nuevamente el sistema operativo, todos los perfiles se borraba. A partir del Windows 2K, los perfiles se guardan en un directorio a parte llamado "c:\Document and Settings"). Esto se puede hacer en Tomcat. Si deseamos cambiar de contenedor web (a una versión superior, o cambiar de propietario), los módulos web seguirán en el mismo sitio. Lo principal es tener todos los módulos web en un directorio aparte, que lo podamos identificar tan fácilmente como el "Document and Settings" del Windows.

Tiles en Struts 1.3

Comencé a migrar una aplicación hecha con Struts 1.2 para que utilizará Struts 1.3 Simplemente (pensé) sería copiar el contenido del struts-config.xls (manteniendo el DTD), obviamente usar los .jar respectivos, utilizar el mismo tiles-defs.xml, pero... no funcionó. Respondía el error 404 (no encuentra página). Después de un día perdido,revisé la documentación http://struts.apache.org/1.3.8/struts-tiles/installation.html y pues la solución era sencilla (algo nuevo con respecto al struts 1.2): Agregar el siguiente parámetro de inicialización del Action Servlet. <init-param> <param-name>chainConfig</param-name> <param-value>org/apache/struts/tiles/chain-config.xml</param-value> </init-param> hora, todo funciona como debería ser. ... no olvidar, siempre leer la documentación.

Menu contextual (con clic "derecho")

Cuando se hace clic 'derecho', se muestra un menú con las opciones propias del objeto que se está seleccionando. Si se hace clic 'derecho' sobre un icono, se debería mostrar opciones propias que se debe trabajar con ese ícono. En Windows esto se llama 'Menú Contextual' o 'Menú del contexto'. El término clic 'derecho' no debería llamarse 'derecho'. En sistemas operativos en donde se ha cambiado la posición de los botones del ratón para zurdos, la funciones de los botones - obviamente - cambian. Los botones se les llamaría como "Botón principal & botón secundario" para referencirse al clic 'izquierdo' y clic 'derecho'. (Por ahí oí que le decían también "clic & anti-clic"..... no sabia que un botón podría inhibir o estar en contra de lo que haga el botón). Pues bien, aquí un ejemplito bien sencillo de cómo mostrar el menú contextual con Java Swing. package diesil.swing; import java.awt.event.Mou

Struts 2 en Eclipse (parte 1)

Imagen
Pues, no utilizaré Eclipse, sino JBuilder 2007 que es lo mismo (me descepcionó la "mejora" que hizo Borland por este IDE) Creando una nueva aplicación Descargar el Struts de la web: http://struts.apache.org/download.cgi . Preferible si es la distribución completa. Descomprimir el archivo en un directorio. En el Eclipse (o JB2007), entrar el menú "File | Import...". Seleccionar Web > War File: Seleccionar el archivo struts2-blank.war que se encuentra en el directorio $STRUTS2/apps/. Además, escribir un nombre para el nombre del proyecto web nuevo: Clic en Finish. Examinando el proyecto El Struts2 viene con mejoras significativas. Prácticamente es otro framework, pero mantiene el espíritu principal de Struts: Actions + Forms. Ya no usa un Servlet, sino un Filter. Eso lo podemos ver en el archivo web.xml. El archivo de configuración ya no está en WEB-INF, sino es un recurso del proyecto. Podemos encontrar el archivo struts.xml en el directorio de fuentes .java (src

Authenticacion Web con JSP/Servlet

Yo creía que la authentication tipo Realm era únicamente en la configuración del contenedor, // para ver si se autenticó String auth = request . getHeader ( "Authorization" ); //si no se autenticó... if (auth == null ) { //... responder al cliente que no está autorizado... response . setStatus ( response . SC_UNAUTHORIZED ); //... y pedir que se autentique. response . setHeader ( "WWW-Authenticate" , "Basic realm=\"Esbas\"" ); } else { // si se auténtico.. //obtenemos el par usuario/contrasenia encriptada //... pero se antepone la palbra Basic String cad = auth.substring( 6 ).trim(); //.. la clave está encriptada en BASE64.. sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder(); //... asi que lo decodificaremos String clave = new String(decoder.decodeBuffer(cad)); //..

JSP Invisibles (con Struts)

No es buena idea que se accedan directamente a los JSP. Debería hacerse a través de un Action, o un forward: <html:link action="/algunAction">...</html:link> Y para asegurarnos de que no lo va hacer, es mejor protegerlo desde la configuración de la aplicación web: <web-app> ... <security-constraint> <web-resource-collection> <web-resource-name>no_access</web-resource-name> <url-pattern>*.jsp</url-pattern> </web-resource-collection> <auth-constraint> </auth-constraint> ... </security-constraint> </web-app>

Tomcat Native Library

La documentación del Tomcat Native dice que se puede encontrar esa biblioteca en el directorio $TOMCAT_HOME/bin.. pero cada vez que inicio el tomcat me aparece la advertencia "se encontró la versión 1.1.3, considere actualizarlo a una versión superior al 1.1.4"... pero debería venir eso con el tomcat!.. je, encontré un servidor mirror con esos archivos: http://tomcat.heanet.ie/ Aunque ahora que lo pienso... creo que debí examinar su sección " browse download area " de la sección " Tomcat connectors downloads ". ¡AH! no olvidar bajar el APR ( Apache Portable Runtime ) y compilarlo antes de compilar el Tomcat Native Library . Asegurarse que sea la última versión. Si viene el APR de un RPM (como en CentOS o Fedora), desinstalarlo antes.

String to XML

Necesitaba una función que me permitiera convertir una cadena en un objeto para manipular XML. Lo que hacía era crear un archivo .xml, le colocaba la cadena, lo cerraba y lo abría después con el objeto Document. Pero aquí tengo otra función mejor String xmlString = request.getParameter("PARAM1"); //obtengo la cadena DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //un factory DocumentBuilder builder = factory.newDocumentBuilder(); //el documento Document document = builder.parse(new InputSource(new StringReader(xmlString))); //aqui le paso al Document

SCJP 5 - Genericos

Estudiando para dar mi examen de SCJP 5 encontré algo que llaman "genéricos". Recordarás que ahora las colecciones ahora pueden ser con tipo: ArrayList perros=new ArrayList (); perros.add(new Perro("Fido")); se ve bonito, y luego bueno de esto es que el compilador no permitirá algo como esto: perros.add(new Integer(1)); Así, también se cumple la herencia: List perros=new ArrayList (); Pero esto no se puede hacer: import java.util.*; class Animal{} class Perro extends Animal{} public class Test { public static void main(String[] args){ List< Animal > animales=new ArrayList< Perro >(); } } ¿Por qué? ¡si Perro ES-UN animal! Pues bien, esto corrige un problema que tienen los arreglos comunes: import java.util.*; class Animal{} class Perro extends Animal{} class Gato extends Animal{} public class Test { public static void main(String[] args){ Perro[] perros=new Perro[]{new Perro()}; //arreglo de perros agre

Vergüenza de programador

Para el escale utilicé al principio Hibernate, pero me fue pesado aprender HQL, y los reportes que emitia se cortaban. Así que pasé a iBatis Mapper y me fue más fácil, flexible y rápido.. incluso usé iBatis DAO por su idependencia de implementación DAO. Pero desde que lo puse, no recuerdo qué mes, el procesador se satura con el java... llegaba a ocupar casi el 100% del procesador... y mandaba error de Java Heap Memory (no indicaba la línea) Continuamente reiniciaba el tomcat, modifiqué el pool de conexiones, aligeré código de consultas... y nada. Incluso puse en un cron para que se reinicié el tomcat cada 2 horas..... y nada. Encontré en la web que el kernel de linux que usaba (2.4) provocaba ese error con java.. así que cambié a CentOS 4.4 Y nada. Prácticament al día tenía que reiniciarlo manualmente 6 veces. Supuse que el diseño de la página estaba mal, xq hacia llamadas recursivas para mostrar el menú de opciones.. así que con mi compañero nos pusimos a pasar todas las páginas a

Leyes del programador

Imagen
Hace tiempo encontré esto, me parece muy bueno. Todo programa que empieza bien, acaba mal. Todo programa que empieza mal, acaba peor. Siempre trabaja en equipo al hacer algún programa, esto da oportunidad de echarle la culpa a otro. Si el Debuggear es el proceso de remover Bugs, entonces el programar debe ser el proceso de ponerlos Por cada Bug que elimines en un programa, aparecen tres más. Programar es como el sexo, un error y hay que soportarlo para el resto de la vida. Las dos frases más repetidas y más falsas en la programación: "Esta ocasión si correrá bien" y "Acabo de encontrar el último Bug". Todos los programadores en esencia son optimistas, hasta que terminan su programa. Cada programa interesante tiene cuando menos una variable, un procedimiento, un loop.....y de hecho un bug. Las computadoras siempre tienen una excusa, los programadores no. No importando cuanto tiempo hayas probado la versión final de un programa, los bugs aparecerán en la

iBatis Datamapper (sql maps) parte 1

El framework iBatis DataMapper (también conocido como SQL Maps) permite reducir significativamente la codificación en java para una aplicación que maneja base de datos relacional. Quizás la primera impresión que uno tenga es que sea igual a Hibernate (que es un mapeador de objetos con tablas relacionales – ORM). Ibatis es diferente. Como veremos en este tutor, iBatis mapea las consultas SQL y permite interactuarlas con JavaBeans tanto como parámetros de entrada y como salidas. Manos a la obra Para comenzar, obtendremos el framework de la página de ASF: http://ibatis.apache.org/ El archivo que habremos bajado (iBATIS_DBL-2.1.7.XX.zip) contendrá tres archivos .jar. En este tutor solo usaremos ibatis-common-2.jar y ibatis-sqlmap-2.jar. No necesita de algún otro .jar, al menos para este capítulo. Definiendo la estructura de los datos Crearemos nuestro JavaBean Categoria con la siguiente estructura. package com.jugperu.tutores.ibatis.beans; public class Categoria { private int id; // p