Sobre el código del ejemplo anterior añadiremos una nueva funcionalidad para permitir que los usuarios identificados en la aplicación puedan introducir unos datos y generar un informe en PDF (invocando un método de negocio de momento vacío).
Haremos un informe meteorológico que constará de tres campos introducidos por el usuario :
- Ciudad sobre la que se realiza el informe
- Temperatura mínima del día actual
- Temperatura máxima del día actual
También añadiremos nosotros automáticamente la fecha del informe, que será la fecha de hoy.
Para ello necesitaremos implementar una nueva "rama" :
- jsp/generarInforme.jsp – Una jsp de entrada de la que recoger el formulario introducido por el usuario.
- es.lycka.holamundoStruts138Jasper.model.Informe – Un objeto de modelo que represente el informe.
- es.lycka.holamundoStruts138Jasper.form.InformeForm – Un actionForm asociado
- es.lycka.holamundoStruts138Jasper.action.InformeAction – Un action que atienda la petición
- es.lycka.holamundoStruts138Jasper.negocio.InformeBO – Una clase de negocio que nos devuelva el informe en formato PDF
- Configurar Struts para que todo esto funcione
Me habré dejado algo en el tintero ? Probemos.
Vista
En el jsp que ven los usuarios identificados (jsp/indexIdentificado.jsp) añadimos un enlace a nuestra nueva funcionalidad:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Zona Identificada</title>
</head>
<body>
<h2>Bienvenido a la zona de administración</h2>
<p>Su identificador de usuario es : <bean:write scope="session" name="usuario" property="identificador" /></p>
<p>Usted puede realizar las siguientes operaciones:</p>
<ul>
<li><html:link href="jsp/generarInforme.jsp">Generar Informe</html:link></li>
</ul>
</body>
</html>
Se vería así :
Y ahora tenemos que implementar una nueva página JSP (jsp/generarInforme.jsp) que permita al usuario introducir unos datos y enviarlos al servidor para que genere el informe.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Generar Informe</title>
<script>
function enviar (){
document.informeForm.submit();
}
</script>
</head>
<body>
<h2>Generación de Informe</h2>
<html:form action="generarInforme">
<div>
<span style="text-aling:rigth">Ciudad</span>
<span> <html:text property="informe.ciudad" /></span>
</div>
<div>
<span style="text-aling:rigth">Temperatura Máxima Hoy</span>
<span> <html:text property="informe.temperaturaMaxima" /></span>
</div>
<div>
<span style="text-aling:rigth">Temperatura Mínima Hoy</span>
<span> <html:text property="informe.temperaturaMinima" /></span>
</div>
<div> </div>
<div>
<input type="button" value="Generar Informe" onclick="javascript:enviar();" />
</div>
</html:form>
</body>
</html>
El resultado sería algo parecido a :
Modelo
Necesitamos crear un bean que modele nuestro informe, es.lycka.holamundoStruts138Jasper.model.Informe :
package es.lycka.holamundoStruts138Jasper.model;
public class Informe {
private String ciudad;
private String temperaturaMaxima;
private String temperaturaMinima;
public String getCiudad() {
return ciudad;
}
public void setCiudad(String ciudad) {
this.ciudad = ciudad;
}
public String getTemperaturaMaxima() {
return temperaturaMaxima;
}
public void setTemperaturaMaxima(String temperaturaMaxima) {
this.temperaturaMaxima = temperaturaMaxima;
}
public String getTemperaturaMinima() {
return temperaturaMinima;
}
public void setTemperaturaMinima(String temperaturaMinima) {
this.temperaturaMinima = temperaturaMinima;
}
}
Controlador
El formulario asociado (es.lycka.holamundoStruts138Jasper.form.InformeForm) es muy sencillo, sólo lleva un informe (objeto Informe) :
package es.lycka.holamundoStruts138Jasper.form;
import org.apache.struts.action.ActionForm;
import es.lycka.holamundoStruts138Jasper.model.Informe;
public class InformeForm extends ActionForm {
private Informe informe = new Informe ();
public Informe getInforme() {
return informe;
}
public void setInforme(Informe informe) {
this.informe = informe;
}
}
La clase action que necesitamos (es.lycka.holamundoStruts138Jasper.action.InformeAction) no es muy complicada, así que vamos a introducir nostros una complicación. Sabemos que por defecto Struts ejecuta el método execute de nuestro action. Pero y si queremos tener varios métodos en el mismo action ? Por ejemplo si queremos asociar varias acciones al mismo tipo de objetos : listar Informes, obtener Informe, insertar Informe, actualizar Informe, borrar Informe…
Una solución sencilla es tener varios métodos en el mismo action y utilizar uno u otro según la configuración de la acción (en el struts-config.xml). Por eso crearemos el método:
package es.lycka.holamundoStruts138Jasper.action;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import es.lycka.holamundoStruts138Jasper.form.InformeForm;
import es.lycka.holamundoStruts138Jasper.negocio.InformeBO;
public class InformeAction extends Action {
public ActionForward execute (ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
InformeForm informeForm = (InformeForm) form;
String destino = "ERROR";
try {
byte[] informePDF = InformeBO.generarInforme (informeForm.getInforme ());
mostrarInforme (informePDF, response);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("mensaje", "Error interno. Por favor, inténtelo otra vez en unos minutos.");
}
return mapping.findForward(destino);
}
}
Negocio
Creamos un objeto de negocio (es.lycka.holamundoStruts138Jasper.negocio.InformeBO) pero no implementamos todavía el método.
package es.lycka.holamundoStruts138Jasper.negocio;
import es.lycka.holamundoStruts138Jasper.model.Informe;
public class InformeBO {
public static byte[] generarInforme (Informe informe) throws Exception {
return null;
}
}
Configurar todo esto
En la etiqueta <form-beans> declaramos nuestro nuevo formulario :
<form-bean name="informeForm" type="es.lycka.holamundoStruts138Jasper.form.InformeForm" />
Y en la etiqueta <action-mappings> declaramos la nueva acción. Utilizamos parameter para indicar qué método del action se ejecutará.
<action path="/generarInforme" type="es.lycka.holamundoStruts138Jasper.action.InformeAction"
name="informeForm" scope="request" validate="false" parameter="generar">
<forward name="SUCCESS" path="/jsp/indexIdentificado.jsp" />
<forward name="ERROR" path="/jsp/indexIdentificado.jsp" />
</action>
Finalmente la estructura del proyecto quedaría así (pincha en la imagen para verla ampliada) :
