Generando XML dinámico con JSP

La tecnología Java Server Pages (JSP) se utiliza normalmente para crear páginas HTML con contenido dinámico. Sin embargo, podemos utilizar esta tecnología para generar contenido dinámico en otros formatos, como XML. Este artículo mostrará como programar páginas JSP como un template XML cuyo contenido se especifica en tiempo de ejecución. Este artículo sirve también para entender numerosos conceptos básicos de JSP, o bien para refrescarlos.

Los desarrolladores de aplicaciones Web han utilizado JSP tradicionalmente para crear páginas HTML dinámicamente al incluir código Java en sus fuentes HTML. Sin embargo, podemos utilizar esta misma metodología para generar contenido dinámico en otros formatos que no sean HTML, de un modo relativamente sencillo. Podemos construir una página JSP utilizando un documento XML que servirá de template para la salida, y luego reemplazar las porciones que deben ser generadas dinámicamente basados en la lógica de negocios a emplear. Podemos utilizar código Java, ya sea dentro del mismo JSP o llamándolo externamente desde la página, para generar porciones dinámicas del documento.

Controlaremos cuánta parte de ese documento es generado. Por ejemplo, podemos utilizar código Java para generar valores entre tags XML, para generar porciones del árbol XML (tanto tags como los valores), o para generar el documento XML completamente.

El código Java es eliminado de la página, procesado en un servlet (conocido como el page servlet), y ejecutado por el Java Application Server (por ejemplo, Tomcat) como resultado del pedido para la página JSP. El resultado es XML puro.

Una introducción a la tecnología JSP

Comencemos hablando un poco sobre cómo funcionan las páginas JSP. Lo haremos solo desde lo sencillo, y focalizándonos en lo básico.

En el sentido tradicional, las páginas JSP se asemejan sobremanera a las páginas HTML, con algunos tags extra. Estos tags permiten que el diseñador inserte código Java (no JavaScript) en la misma página. Un Web Application Server (como IBM WebSphere Application Server, o Tomcat), interceptará las llamadas a las páginas JSP. Se da cuenta de su existencia por la extensión de la página solicitada: .jsp (no .html). Luego, el Web Application Server preprocesa la página JSP, eliminando los tags JSP y todo código Java embebido, dejando solamente el HTML. Los JSP tags y el código Java extraído se utilizan para construir un Java Servlet (JSP Page Servlet) que ejecuta el código e inserta los resultados en la página original donde los JSP tags estaban ubicados. El resultado final es HTML puro. El código Java se extrajo y se ejecutó en el servidor antes de que el browser cliente que solicitó la página vea resultado alguno.

Podemos aplicar el mismo principio a una página XML. Antes de que el solicitante de la página JSP, que contiene XML, logre ver el resultado XML (ya sea en un browser o alguna otra aplicación B2B), el código Java se extrae de la página JSP y se utiliza para generar contenido adicional, que es insertado en la página en el mismo lugar donde los JSP tags residían. Esta funcionalidad nos ofrece la posibilidad de controlar exactamente donde se insertará el nuevo contenido, hasta el detalle más mínimo.

Veremos cómo lograr esto en pocos segundos. Primero, consideremos lo siguiente: ¿porqué desearíamos crear contenido dinámico utilizando XML? ¿Porqué no simplemente escribimos una aplicación Java o un servlet para generar el documento entero? La razón más importante, suponiendo que solo porciones del documento XML son dinámicas, es que no tiene sentido regenerar el contenido estático para cada pedido cliente. Utilizando una página JSP, el contenido XML estático que está en la página actúa como template que se llena con el contenido dinámico. Nuestro código Java será el encargado de generar el contenido que cambiará con el tiempo, logrando así una metodología más eficiente.

Ofreciendo una metodología realmente práctica, las páginas JSP nos permiten separar tareas de las cuales serán responsables diferentes perfiles de desarrolladores. En particular, nos permiten separar de un mejor modo la información de la vista, permitiéndonos agregar nuevas presentaciones sin afectar la lógica. Imaginemos un Java Servlet que implementa la lógica de negocio y redirecciona la información resultante a una página JSP según la naturaleza del requerimiento. Podría también redireccionar la información a un JSP conteniendo HTML para solicitudes de browser estándares.

El mecanismo

Veamos un ejemplo en donde un documento XML es convertido a una página JSP, y partes de su contenido se re-escriben para ser generados dinámicamente. El ejemplo está basado en un ejemplo XML entregado como parte del IBM WebSphere Transcoding Publisher y llamado FlightInfo. Este documento XML representa la información sobre el itinerario de vuelo de una aerolínea específica. Ahora queremos lograr que parte de el contenido de ese XML sea generado dinámicamente.

A continuación se cita el documento XML original (el DTD ha sido omitido):

<?xml version="1.0" encoding="ISO-8859-1"?>
<Flights>
<AirCarrier>AA</AirCarrier>
<FlightNumber>700</FlightNumber>
<FlightSegment>
<DepartingInfo>
<City>DFW</City>
<Date>30Mar</Date>
<Scheduled>0630A</Scheduled>
<Status>ON TIME</Status>
<Time>0632A</Time>
<Gate>C16</Gate>
<OffGateTime>0644A</OffGateTime>
<OffGroundTime>0632A</OffGroundTime>
</DepartingInfo>
<ArrivingInfo>
<City>LGA</City>
<Date>30Mar</Date>
<Scheduled>1040A</Scheduled>
<Status>ON TIME</Status>
<Time>1043A</Time>
<Gate>D5</Gate>
<Baggage>B</Baggage>
<OnGroundTime>1043A</OnGroundTime>
</ArrivingInfo>
</FlightSegment>
</Flights>

Renombrar el archivo utilizando extensión .jsp

Primero, necesitamos renombrar el archivo especificándole una extensión .jsp para que el Web Server se entere qué hacer con el archivo. Los Web Servers tienen reglas para actuar sobre ciertos patrones URL o extensiones de archivo, tales como .html o .gif. Cuando un Web Application Server se agrega a un Web Server, el Application Server agrega reglas a la lista de patrones URL y extensiones archivos del Web Server. Cuando el Web Server recibe el pedido de un archivo con extensión .jsp, pasará esa petición al Web Application Server, quien la procesará.

Agregar la directiva de página

Luego, necesitamos indicar al compilador de páginas JSP cuál será el formato del contenido generado. Por defecto, el compilador de páginas asumirá que el contenido es HTML. Para cambiar esto, el tag de directiva de página JSP debe ser agregado para setear el tipo de contenido a retornar. Para JSP 1.0, la directiva de página se asemeja a lo siguiente:

<%@ page contentType="text/xml;charset=ISO-8859-1" %>

Es importante notar que el compilador de páginas JSP removerá solo los caracteres que son parte del tag y su contenido. Si ubicamos el tag JSP en una nueva línea, el compilador de página eliminará todo excepto la nueva línea (debido a que no es parte del tag). Por ejemplo, supongamos que agregamos el tag de tipo de contenido de página a nuestro JSP del siguiente modo:

<%@ page contentType="text/xml;charset=ISO-8859-1" %>
<?xml version="1.0" encoding="ISO-8859-1"?>
<Flights>
<AirCarrier>AA</AirCarrier>
<FlightNumber>700</FlightNumber>
<FlightSegment>
...

En este caso, el compilador de página removerá la directiva de página de la primera línea, dejando la línea en blanco existente antes del <?xml...?> (resultante del avance de línea existente justo al final de la primera línea, donde se encuentra la directiva de página). En los doumentos XML, el tag de versión XML debe encontrarse en la primera línea, por lo que este ejemplo crearía un error en el parser XML. Para remediarlo, debemos agregar la directiva de página a la segunda línea, o concatenar el tag de versión XML con el tag de contenido. Realmente no importa en qué parte del documento se ubica la directiva porque el compilador de páginas agregará la instrucción al comienzo del método service del servlet resultante ignorando su ubicación en la página JSP. Para una mejor estructuración, sin embargo, deberíamos considerar agregarlo como la segunda línea, según se muestra a continuación:

<?xml version="1.0" encoding="ISO-8859-1"?>
<%@ page contentType="text/xml;charset=ISO-8859-1" %>
<Flights>
<AirCarrier>AA</AirCarrier>
<FlightNumber>700</FlightNumber>
<FlightSegment>
...

Agregar el código Java

Ahora lo único que falta es agregar el código Java para personalizar parte del contenido del XML. Agregamos el código Java al archivo entre tags de script JSP (). El compilador de páginas interpretará lo que se encuentre entre estos tags como código Java puro y lo ageegará, sin modificarlo, al método service() del servler resultante.

Todo el código definido entre los tags de script JSP se agregará al método service() en el orden en el que aparece en la página JSP. El alcance del código agregado es la página completa, y consecuentemente el método service(). Por lo que si definimos una variable en un bloque JSP (sentencias especificadas entre los tags de script JSP) ubicado, por ejemplo, al comienzo del archivo, podremos referenciarla más abajo en el mismo archivo utilizando un bloque de código JSP diferente. Podemos imponer un alcance al utilizar las llaves ({…}) alrededor de la definición de variables. Estas llaves pueden incluso comenzar y finalizar en diferentes bloques JSP.

En el siguiente ejemplo, reemplazaremos alguna de las fechas estáticas del archivo XML original con código Java utilizando la clase Calendar ubicada en el paquete java.util. El código utiliza la fecha actual y le agrega horas y minutos para crear entradas de tiempo apropiadas para varios de los tags XML. El código Java está en negrita. Los números de línea se agregaron para referencias posteriores.

1. <?xml version="1.0" encoding="ISO-8859-1"?>
2. <%@ page contentType="text/xml;charset=ISO-8859-1" %>
3. <% java.util.Calendar cal = java.util.Calendar.getInstance(); %>
4. <Flights>
5.   <AirCarrier>AA</AirCarrier>
6.   <FlightNumber>700</FlightNumber>
7.   <FlightSegment>
8.     <DepartingInfo>
9.       <City>DFW</City>
10.      <Date>30Mar</Date>
11.      <Scheduled>
12.      <% out.print(cal.getTime().toString()); %>
13.      </Scheduled>
14.      <Status>ON TIME</Status>
15.      <% cal.add(java.util.Calendar.MINUTE, 10);
16.         out.print("<Time>" + cal.getTime().toString() +
17.         "</Time>"); %>
18.      <Gate>C16</Gate>
19.      <OffGateTime>0644A</OffGateTime>
20.      <OffGroundTime>0632A</OffGroundTime>
21.    </DepartingInfo>
22.    <ArrivingInfo>
23.      <City>LGA</City>
24.      <Date>30Mar</Date>
25.      <Scheduled>
26.      <% cal.add(java.util.Calendar.HOUR_OF_DAY, 4);
27.         out.print(cal.getTime().toString());
28.         cal.add(java.util.Calendar.MINUTE, 2); %>
29.      </Scheduled>
30.      <Status>ON TIME</Status>
31.      <Time><%= cal.getTime().toString() %></Time>
32.      <Gate>D5</Gate>
33.      <Baggage>B</Baggage>
34.      <OnGroundTime>1043A</OnGroundTime>
35.    </ArrivingInfo>
36.  </FlightSegment>
37.</Flights>

He aquí lo que estamos haciendo en el segmento de código:

Línea 2: la directiva de página se agrega para indicar que la respuesta generada por el page servlet contendrá XML.

Línea 3: la variable cal del tipo Calendar se define conteniendo la fecha y hora actual.

Línea 12: usando el objeto global out, podemos imprimir directamente en la posición actual de la página que está siendo enviada como respuesta. Imprimimos la fecha y hora actual en la página. Nótese que cuando la respuesta es generada, este código JSP se reemplazará con la fecha y hora actual.

Línea 15-17: agregamos 10 minutos a la hora actual e imprimimos el resultado en la página como el contenido del tag XML que define la fecha y hora de salida.

Línea 26-28: agregamos 4 horas a la hora actual para derivar la hora de llegada agendada del vuelo, que luego es impresa en la página utilizando el objeto out. Luego, agregamos otros 2 minutos para crear el horario de llegada real.

Línea 31: El signo igual en los tags de script JSP (<%=…%>) causarán que el resultado de lo que esté contenido entre los tags sean impresos en la página. La línea en el ejemplo es equivalente a la siguiente línea utilizando los tags de script JSP estándares:

<% out.print(cal.getTime().toString()); %>

Nótese que el objeto cal es global a la página completa; aún cuando se usa en un bloque JSP diferente a donde ha sido definido. Como vimos anteriormente, si no utilizamos las llaves ({…}) para forzar el alcance, la declaración de variables es global a la página completa desde el punto de declaración.

El código Java en este ejemplo se utiliza primariamente para generar datos entre tags XML. Podríamos también haber utilizado código Java para generar árboles enteros de elementos en cualquier documento XML. El código simplemente debería imprimir los tags XML además de los datos. Esto es lo que hacen las líneas 15-17.

Agregando componentes JavaBeans

La sintaxis JSP soporta el agregado de componentes JavaBeans a la página y accediéndolos como cualquier otro objeto. El tag especial <jsp:useBean> es utilizado para declarar e instanciar el bean. El compilador de página utilizará los atributos del tag <jsp:useBean> para construir código Java en el page servlet, que es necesario para instanciar el bean y cargarlo con datos desde el request.

Debido a que los componentes JavaBeans generalmente se destinan a efectuar una tarea, es fácil el ver cómo pueden ser utilizados para realizar o interactuar con lógica de negocio compleja, moviendo el código Java complejo fuera de la página JSP. Un ejemplo es el componente Integration Object JavaBean. Este bean se desarrolló utilizando IBM WebSphere Host Publisher, que encapsula interacciones con fuentes de datos propietarias, tales como aplicaciones 3270 o bases de datos, y simplemente retorna sus datos. Imaginemos entonces el utilizar un Integration Object que interactúa con una aplicación existente en el host de una aerolínea dedicado al agendamiento, para proveer la informaciónd e salida y llegada en nuestro ejemplo. Como usuarios del Integration Object, simplemente debemos solicitar los datos de itinerario de él, sin necesitar conocer las complejas comunicaciones e interacciones con la aplicación host que ocurren en background.

He aquí nuestro ejemplo re-escrito para utilizar el bean.

1. <?xml version="1.0" encoding="ISO-8859-1"?>
2. <%@ page contentType="text/xml;charset=ISO-8859-1" %>
3. <jsp:useBean id="flightInfo"
class="IntegrationObject.FlightInfo"/>
4. <% flightInfo.doHPTransaction(request, response); %> 5. <Flights> 6. <AirCarrier>AA</AirCarrier> 7. <FlightNumber>700</FlightNumber> 8. <FlightSegment> 9. <DepartingInfo> 10. <City>DFW</City> 11. <Date>30Mar</Date> 12. <Scheduled> 13. <% out.print(flightInfo.getScheduledDeparture()); %> 14. </Scheduled> 15. <Status>ON TIME</Status> 16. <% out.print("<Time>" +
flightInfo.getActualDeparture() +
17. "</Time>"); %> 18. <Gate>C16</Gate> 19. <OffGateTime>0644A</OffGateTime> 20. <OffGroundTime>0632A</OffGroundTime> 21. </DepartingInfo> 22. <ArrivingInfo> 23. <City>LGA</City> 24. <Date>30Mar</Date> 25. <Scheduled><%= flightInfo.getScheduledArrival() %> 26. </Scheduled> 27. <Status>ON TIME</Status> 28. <Time><%= flightInfo.getActualArrival() %></Time> 29. <Gate>D5</Gate> 30. <Baggage>B</Baggage> 31. <OnGroundTime>1043A</OnGroundTime> 32. </ArrivingInfo> 33. </FlightSegment> 34.</Flights>

Observemos más profundamente qué está sucediendo en este ejemplo.

Línea 3: contiene el tag <jsp:useBean> que define e instancia el bean IntegrationObject.FlightInfo como flightInfo.

Línea 4: contiene código que llama al método doHPTransaction() de flightInfo, haciendo que este se conecte a la aplicación host de información de vuelo y reciba la información pertinente.

Líneas 13, 16, 25, y 28: simplemente insertan los resultados en el documento XML.

Obviamente podremos utilizar otros tipos de beans del mismo modo, quizás llamando algún otro método diferente a doHPTransaction() que efectúe el trabajo. Podemos incluso agregar varios beans al mismo documento, creando datos en el documento XML que provienen de diferentes fuentes.

Conclusión

La tecnología JavaServer Pages ha sido un estándar abierto por varios años y ha sido adoptado universalmente para generar documentos HTML dinámicamente. Pocos se han percatado que la misma flexibilidad existente al embeber código Java en un documento HTML puede ser aprovechada para generar documentos XML. Consideremos las posibilidades. Podríamos desarrollar comunicaciones B2B al construir dinámicamente la información que ha sido modificada. Podríamos construir varias representaciones de estos datos desde un data source, no solo HTML y XML, pero también WML y HDML para los protocolos inalámbricos.

XML ha sido adoptado claramente como el formato común para el intercambio de datos. Utilizando la tecnología JavaServer Pages contaremos también con una poderosa herramienta para enviar información a través de la Web en XML de un modo sencillo e intuitivo.

Marshall Lamb
http://cricava.com/java/detalleArticulos.php?id=115

Leave A Comment?