martes, 25 de octubre de 2011

Expression Language (EL): Activación


El "expression language" es un tipo de notación en JSP que permite navegar sobre beans de una manera más simplificada y sencilla.

Si tengo por ejemplo un bean "Foo" con una propiedad llamada "prop" y a su vez esta contiene otra propiedad llamada prop2, la forma anticuada de accesar la propiedad sería:

"myFoo.getProp1().getProp2()"

Con EL podemos omitir los "get" de esta forma:

"${myFoo.prop1.prop2}"

Recientemente estaba teniendo un conflicto porque el JSP no me interpretaba el EL. Lo que me estaba faltando era un buena declaración del web.xml que indicara que estamos usando la versión 2.4 de Servlets:

<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

Quería dejar esto documentato porque me tomó rato averiguar como se activaba.

lunes, 24 de octubre de 2011

Sin temor a lucir "fuera de onda"


A veces pareciera que el mundo del desarrollo de software se comporta parecido al mundo de la moda. No lo digo porque piense que esté sujeto completamente a condiciones triviales como la influencia de una estrella pop sobre las jóvenes adolecentes, pero en menor escala, los frameworks estrella más populares tienden a monopolizar la atención de los ingenieros de software con recetas, a veces al punto de pensar que cualquier cosas distinta de la receta está fuera de moda.

Frameworks como Struts, Spring o Hibernate son herramientas exelentes para muchos de los desarrollos de software. El problema considero que comienza cuando un desarrollador cría un esquema en su mente, de que todos los proyectos deben implementarse con la receta estandar "para todas la tallas" que él utiliza. Si alguien más sugiere hacer algo diferente, o solamente menciona en alguna conversación amistosa a otro colega que está utilizando una técnica diferente, el chico receta framework podría verlo como el fuera de onda o inclusive hasta molestarlo por ser un dinosaurio a su parecer.

He estado viendo las exposiciones de la reciente conferencia de Java Zone 2011. Dos presentaciones en particular llamaron mi atención por su valentía para cuestionar el “status-quo”. Una expone un acercamiento diferente a la inyección de dependencias:


Dependency injection when you only have one dependency from JavaZone on Vimeo.

Y la otra, particularmente la que disfruté más, es la de esta entusiasta ingeniera, que con buenos argumentos, se para firme ante su negativa de utilizar Hibernate en sus desarrollos con persitencia en bases de datos.


Hibernate should be to programmers what cake mixes are to bakers: beneath their dignity. from JavaZone on Vimeo.

No estoy tomando partido en ninguna de estas dos presentaciones. Debo confesar que me falta experiencia como para tomar una posición informada en los tópicos mencionados, pero realmente admiro a estos dos por mostrar sin ningún titubeo, dos formas alternativas a técnicas actuales del desarrollo de software. La innovación aparece frequentemente en situaciones donde alguien se aparta de los demás.

Creo que como latinoamericanos tenemos mucho que aprender de estos dos ejemplos. Estamos muy acostumbrados a ser consumidores de tecnologías pero no a ser productores de ellas. Debemos tener la mente abierta para experimentar con nuevas alternativas, utilizando un criterio racional y mucha humildad para examinarlo todo, y ejercitar el jucio informático, el cual es clave en nuestro desarrollo profesional.

martes, 20 de septiembre de 2011

Servlet para descargar archivos

Dejo a disposición como utilizar un servlet para descargar archivos.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.activation.MimetypesFileTypeMap;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* A simple Servlet to download a file.
* @author gabriel.solano
*
*/
public class DownloadServlet extends HttpServlet{

private static final long serialVersionUID = 4440011247408877539L;

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
downloadFile(resp,
this.getServletContext().getRealPath("/WEB-INF/myFile.pdf"));
}

protected void downloadFile(HttpServletResponse response, String filePath)
throws ServletException, IOException {

File fileToDownload = new File(filePath);
FileInputStream fileInputStream = new FileInputStream(fileToDownload);

ServletOutputStream out = response.getOutputStream();
String mimeType = new MimetypesFileTypeMap().getContentType(filePath);

response.setContentType(mimeType);
response.setContentLength(fileInputStream.available());
response.setHeader( "Content-Disposition", "attachment; filename=\""
+ fileToDownload.getName() + "\"" );

int c;
while((c=fileInputStream.read()) != -1){
out.write(c);
}
out.flush();
out.close();
fileInputStream.close();
}
}

martes, 6 de septiembre de 2011

Parser de HTML con Java

Quería compartir un código de ejemplo mostrando como "analizar gramaticalmente" (esa fue la traducción que me dio Google Translate para el verbo "parse", de ahora en adelante me quedo con el incorrectamente-usado-pero-mejormente-conocido-verbo: "parsear") una página HTML utilizando la librería de código abierto: HTML Parser. Me ha tocado utilizar esta librería en el pasado para un proyecto en donde necesitábamos extraer todos los enlaces de un sitio, y ahora me tocar usarla para otro proyecto donde necesito validar unas reglas de código en ciertas páginas HTML.
Así que vamos a asumir que necesitamos encontrar todos los enlaces absolutos de una página de un sitio. Primeramente creamos nuestra clase parseadora:
import java.io.IOException;
import java.net.URL;
import org.htmlparser.Node;
import org.htmlparser.Tag;
import org.htmlparser.lexer.Lexer;
import org.htmlparser.util.ParserException;

/**
* Parses the HTML code of the page specified by it's URL.
* @author gabriel.solano
*
*/
public class URLHTMLParser {

/*
* Tag handler that will be used to process the tags.
* (This could be improved by implementing an observer
* pattern to be able to add more than one TagHandler)
*/
private TagHandler tagHandler;

/**
* Constructor.
* @param tagHandler
*/
public URLHTMLParser(TagHandler tagHandler) {
this.tagHandler = tagHandler;
}

/**
* Scans the specified URL.
* @param url
* @throws ParserException
* @throws IOException
*/
public void scanURL(URL url) throws ParserException, IOException {
Lexer lexer = new Lexer(url.openConnection());
extractHTMLNodes(lexer);
}

/**
* Extracts the HTML nodes and lets the TagHandler to do something
* with the tags.
* @param lexer
* @throws ParserException
*/
private void extractHTMLNodes(Lexer lexer) throws ParserException {
Node node;

while (null != (node = lexer.nextNode(false))) {
if (node instanceof Tag) {
Tag tag = (Tag) node;
tagHandler.handleTag(tag);
}
}
}
}


Como podrán notar, la última función de esta clase es la encargada de moverse a través de todos los nodos HTML de la página. Simplemente dejo a la clase "TagHandler" hacer lo que tenga que hacer con la etiqueta que encuentra.
Esta es la interface TagHandler:

import org.htmlparser.Tag;

/**
* Defines the interface for a TagHandler.
* @author gabriel.solano
*
*/
public interface TagHandler {

/**
* Handles the process of an HTML tag.
* @param tag
*/
public void handleTag(Tag tag);

}



Y aquí está la implementación para procesar las etiquetas de ancla:

import java.util.HashSet;
import java.util.Set;
import org.htmlparser.Tag;

/**
* Handles the event when an anchor tag is found while parsing
* HTML code of a page.
* This class has a functionality to count all absolute URLs
* found in the parsing process.
* @author gabriel.solano
*
*/
public class AnchorTagHandler implements TagHandler{

private Set<String> absoluteURLs; // All URLs found.

/**
* Constructor.
*/
public AnchorTagHandler() {
absoluteURLs = new HashSet<String> ();
}

/**
* Gets the found absolute URLs.
* The collection is filled only during the scanning process
* of an HTML page.
* @return
*/
public Set<String>getAbsoluteURLs() {
return absoluteURLs;
}

/**
* Handles the tag only if it is an anchor tag.
*/
public void handleTag(Tag tag) {
if (tag.getTagName().equalsIgnoreCase("a")) {
// Process only if it's an anchor tag.
processTag(tag);
}
}

/**
* Processes the anchor tag. In this case
* adds all absolute URL's found.
* @param tag
*/
private void processTag(Tag tag) {
String href = tag.getAttribute("href");

if (href != null) {
href = href.toLowerCase();
if (href.startsWith("http://") || href.startsWith("https://")) {
// Add all URLs with HTTP protocol.
absoluteURLs.add(href);
}
}
}
}


La función "processTag" simplemente extrae el atributo "href" y verifica si es un URL absoluto. Finalmente creamos la clase principal para correr este código:
import java.net.URL;
import java.util.Set;

public class FindAbsoluteURLs {

public static void main(String[] args) {

AnchorTagHandler anchorTagHandler = new AnchorTagHandler();
URLHTMLParser htmlParser = new URLHTMLParser(anchorTagHandler);

try {
htmlParser.scanURL(new URL("http://www.crjug.org/"));
Set<String>urls = anchorTagHandler.getAbsoluteURLs();

for(String url : urls) {
System.out.println(url);
}

} catch (Exception e) {
e.printStackTrace();
}
}
}

Usando el sitio de la comunidad de usuarios de Java de Costa Rica obtenemos los siguientes URLs:

http://www.facebook.com/pages/costa-rica-jug/107081646760
http://www.oreilly.com/
http://www.java.net/

Esta es la dependencia de Maven en caso necesiten utilizar esta útil librería:
<dependency>
<groupId>org.htmlparser</groupId>
<artifactId>htmlparser</artifactId>
<version>1.6</version>
</dependency>