Esta es la cuarta entrega de esta serie de tutoriales sobre JasperReports. En la primer parte, vimos cómo generar reportes haciendo uso de una conexión a base de datos como nuestro DataSource. Después, en la segunda parte, aprendimos a hacer esto mismo pero con un DataSource propio, lo que nos evita en tener las consultas SQL directamente en nuestro reporte y tener que pasarle posteriormente un objeto de tipo “java.sql.Connection”. Finalmente, en la tercer parte, vimos cómo hacer uso de parametros y variables para hacer nuestros reportes más dinámicos.
Ahora, en esta cuarta parte, veremos cómo hacer que un usuario pueda descargar o ver en su navegador estos reportes haciendo uso de Servlets y JSPs respectivamente.
Para este tutorial usaremos el reporte que creamos en el tutorial anterior. Así que si no lo tienen pueden ver cómo crearlo en la segunda parte del tutorial de JasperReports.
Usaremos solo el archivo "reporte2.jasper" y el código que ya habíamos creado lo pasaremos a un Servlet un poco más adelante.
Para comenzar con este tutorial lo primero que debemos hacer es abrir nuestro IDE de trabajo. Los que han seguido este blog saben que el IDE que más me gusta para trabajar con Java es el NetBeans. Así que será el que usaremos en este tutorial (y para todos los demás ^_^).
Al final del tutorial de instalación de plugins en NetBeans vimos cómo configurar Tomcat para usarlo como contenedor de Servlets y JSPs; y servidor web. Usaremos el Tomcat para este proyecto, así que si no lo tienen instalado o configurado sigan los pasos indicados en este tutorial.
Ahora creamos un nuevo proyecto web yendo al menú “File -> New Project”. En la ventana que se abre seleccionamos la categoría "Java Web" y seleccionamos "Web Application".
Hacemos clic en el botón "Next". En el siguiente paso le damos un nombre (que en mi caso será "ReporteWeb") y una ubicación al proyecto. Hacemos clic en el botón "Next". Para terminar seleccionamos el servidor que vamos a usar. En este caso, y como dije antes, usaremos el Tomcat 6, por lo que lo seleccionamos y hacemos clic en el botón "Finish". Con esto debe aparecer nuestro proyecto en la ventana "Projects", y un archivo llamado "index.jsp" en la ventana del editor.
Ahora agregamos la biblioteca de “JasperReports” que creamos en el primer tutorial de la serie, como lo hemos venido haciendo ("Add Library" en el nodo "Library" del panel "Projects").
Además también debemos copiar el archivo "reporte2.jasper" al directorio "web/WEB-INF" debajo de la raíz del proyecto. Esto es muuuuy importante porque este archivo debe poder ser encontrado por los componentes web (Servlets) de nuestra aplicación, y lo mejor es colocarlos en esta ubicación para poder obtener la ruta absoluta de dónde está, usando los métodos que nos proporcionan los Servlets. Lo colocamos dentro de “WEB-INF” para que nuestro servidor no lo envíe al usuario como lo hace, por ejemplo, con las páginas web o con las imágenes.
En el tutorial anterior usamos una clase "Participante", y eran los valores de los atributos de las instancias de esta clase los que se mostraban en el reporte. Como estamos usando la misma plantilla de reporte (“reporte2.jasper”), también usaremos la misma clase para almacenar los datos que se mostrarán. Por lo que creamos una nueva clase "Participante" (colocándola en el paquete "pruebas.reportes.jasperreports.web") y copiamos el código que ya teníamos al nuevo archivo. Para que no se regresen al tutorial anterior a ver el código, lo dejo aquí:
Ahora crearemos un nuevo Servlets, que será el componente desde el que generaremos el reporte. Para eso hacemos clic derecho sobre el nodo "Source Package" del panel "Projects" y en el menú contextual que se abre seleccionamos "New -> Other...". En la ventana que se abre seleccionamos la categoría “web” y como tipo de archivo “Servlet”:
Escribimos "ServletReporte" como nombre del Servlet y lo colocamos en el paquete "pruebas.reportes.jasperreports.web":
Hacemos clic en el botón "Finish" y tendremos nuestro nuevo Servlet en la ventana del editor. Este Servlet contendrá tres métodos generados desde las plantilla de Servlets:
La funcionalidad para generar el reporte la colocaremos en este último método, así que lo primero que haremos es borrar el código que ya contiene, dejándolo vacio, principalmente porque el método utiliza un “java.io.PrintWriter”, que es un objeto para generar respuestas en texto, y nosotros usaremos un “javax.servlet.ServletOutputStream”, que es un objeto para generar respuestas binarias, que en este caso será el reporte:
Como el reporte que regresaremos estará en formato PDF, y este es un formato binario, (todo lo que no pueda abrirse con un bloc de notas, o cualquier editor de texto plano, y entenderse directamente es un archivo binario) la única forma que existe para regresarlo de forma correcta al cliente es haciendo uso de un Stream, en este caso de un “ServletOutputStream”. Es también por esta razón que debemos hacer uso de un Servlet y no de una JSP, ya que la llamada al método que regresa el “ServletOutputStream” solo es permitida dentro de un Servlet.
Lo primero que haremos dentro de nuestro Servlet es indicar el tipo de contenido que regresaremos (que por default es "text/html"). Como se trata de un archivo PDF el tipo de retorno es "application/pdf". Indicamos esto con el método "setContentType" del objeto "HttpServletResponse" que recibimos como segundo argumento, de la siguiente forma:
Este método se encarga de establecer las cabeceras adecuadas en la respuesta regresada al cliente para que este sepa cómo tratar los datos que está recibiendo. En este caso esperamos que abra el reporte con su aplicación habitual para leer archivos PDF (Acrobat Reader o algún otro). Es importante establecer este valor antes de obtener el “ServletOutputStream”, de lo contrario podríamos obtener algún error inesperado al enviar la respuesta.
Ahora que el Servlet ya conoce el tipo de respuesta que regresará podemos proceder a obtener el “ServletOutputStream” correspondiente para enviar la respuesta al cliente:
Ahora generamos el reporte como lo hemos estado haciendo hasta ahora, haciendo unos pequeños cambios: como ahora el archivo de la plantilla del reporte no se encuentra en la raíz del proyecto, sino dentro del directorio web, debemos indicar la ruta completa en la que se encuentra este archivo. Por lo que es necesario cambiar la línea
Por:
Además, como ahora el reporte no será generado en un archivo, sino que será enviado directamente al cliente, debemos cambiar la línea:
Por:
En realidad la línea anterior es la que hace el truco. El flujo del reporte es dirigido al flujo que es regresado al cliente, logrando así que este vea el reporte directamente en su navegador.
El resto del código de “processRequest” es igual al que ya hemos visto en los tutoriales anteriores, y queda de la siguiente forma:
Si ahora ejecutamos el proyecto (den algún tiempo para que el Tomcat se levante, hasta que vean el mensaje "INFO: Server startup in ***** ms" en el panel del salida) e ingresamos a la siguiente dirección:
Veremos que el reporte generado se muestra directamente en la pantalla del navegador:
Aunque esto es muy útil tal y como esta, algunas veces es mejor que el usuario decida si quiere guardar este reporte en su máquina o abrirlo con alguna otra aplicación en vez de usar directamente el navegador. Para poder lograr esto es necesario agregar una cabera llamada "Content-Disposition" a la respuesta. Esta cabecera tiene como valor "attachment; filename=" y el nombre que queremos darle a nuestro reporte. Para establecer esta cabecera usamos el método "setHeader" del objeto "HttpServletResponse", de la siguiente forma:
Ahora compilamos y ejecutamos nuevamente nuestra aplicación y veremos que en esta ocasión se nos pregunta qué acción queremos realizar: abrir el reporte con alguna aplicación que seleccionemos, o guardarlo en nuestra máquina (tal vez será necesario que detengan y vuelvan a reiniciar su servidor para que tome los cambios):
Para evitar que nuestro navegador guarde el archivo en cache podemos establecer, como se indica en esta página del sitio jGuru, las siguientes cabeceras:
Aunque el darle al usuario la oportunidad de abrir o guardar el archivo es también bastante útil, algunas veces nos gustaría poder mostrar este archivo como parte de la información de nuestra página JSP embebiéndolo en la misma. Hacer esto es bastante sencillo, como se menciona en este artículo de flash colony. Solo hay que agregar la etiqueta <object>, con algunos atributos de configuración, en nuestra página JSP.
Si agregamos la siguiente etiqueta en nuestro archivo "index.jsp":
e ingresamos a la dirección:
Obtendremos el siguiente resultado:
Lo cual también puede sernos de mucha utilidad ^-^.
El código del método “processRequest” queda finalmente de la siguiente forma:
Y el código del archivo “index.jsp” queda así:
Bien, este es el final de este cuarto tutorial sobre el uso de JasperReports. Espero que les sea de utilidad. No olviden dejar sus dudas, comentarios y sugerencias.
Saludos.
Descarga los archivos de este tutorial desde aquí:
Entradas Relacionadas:
Ahora, en esta cuarta parte, veremos cómo hacer que un usuario pueda descargar o ver en su navegador estos reportes haciendo uso de Servlets y JSPs respectivamente.
Para este tutorial usaremos el reporte que creamos en el tutorial anterior. Así que si no lo tienen pueden ver cómo crearlo en la segunda parte del tutorial de JasperReports.
Usaremos solo el archivo "reporte2.jasper" y el código que ya habíamos creado lo pasaremos a un Servlet un poco más adelante.
Para comenzar con este tutorial lo primero que debemos hacer es abrir nuestro IDE de trabajo. Los que han seguido este blog saben que el IDE que más me gusta para trabajar con Java es el NetBeans. Así que será el que usaremos en este tutorial (y para todos los demás ^_^).
Al final del tutorial de instalación de plugins en NetBeans vimos cómo configurar Tomcat para usarlo como contenedor de Servlets y JSPs; y servidor web. Usaremos el Tomcat para este proyecto, así que si no lo tienen instalado o configurado sigan los pasos indicados en este tutorial.
Ahora creamos un nuevo proyecto web yendo al menú “File -> New Project”. En la ventana que se abre seleccionamos la categoría "Java Web" y seleccionamos "Web Application".
Hacemos clic en el botón "Next". En el siguiente paso le damos un nombre (que en mi caso será "ReporteWeb") y una ubicación al proyecto. Hacemos clic en el botón "Next". Para terminar seleccionamos el servidor que vamos a usar. En este caso, y como dije antes, usaremos el Tomcat 6, por lo que lo seleccionamos y hacemos clic en el botón "Finish". Con esto debe aparecer nuestro proyecto en la ventana "Projects", y un archivo llamado "index.jsp" en la ventana del editor.
Ahora agregamos la biblioteca de “JasperReports” que creamos en el primer tutorial de la serie, como lo hemos venido haciendo ("Add Library" en el nodo "Library" del panel "Projects").
Además también debemos copiar el archivo "reporte2.jasper" al directorio "web/WEB-INF" debajo de la raíz del proyecto. Esto es muuuuy importante porque este archivo debe poder ser encontrado por los componentes web (Servlets) de nuestra aplicación, y lo mejor es colocarlos en esta ubicación para poder obtener la ruta absoluta de dónde está, usando los métodos que nos proporcionan los Servlets. Lo colocamos dentro de “WEB-INF” para que nuestro servidor no lo envíe al usuario como lo hace, por ejemplo, con las páginas web o con las imágenes.
En el tutorial anterior usamos una clase "Participante", y eran los valores de los atributos de las instancias de esta clase los que se mostraban en el reporte. Como estamos usando la misma plantilla de reporte (“reporte2.jasper”), también usaremos la misma clase para almacenar los datos que se mostrarán. Por lo que creamos una nueva clase "Participante" (colocándola en el paquete "pruebas.reportes.jasperreports.web") y copiamos el código que ya teníamos al nuevo archivo. Para que no se regresen al tutorial anterior a ver el código, lo dejo aquí:
public class Participante
{
private int id;
private String nombre;
private String username;
private String password;
private String comentarios;
private int puntos;
public Participante()
{
}
public Participante(int id, String nombre, String username, String password, String comentarios)
{
this.id = id;
this.nombre = nombre;
this.username = username;
this.password = password;
this.comentarios = comentarios;
}
public String getComentarios()
{
return comentarios;
}
public void setComentarios(String comentarios)
{
this.comentarios = comentarios;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getNombre()
{
return nombre;
}
public void setNombre(String nombre)
{
this.nombre = nombre;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public int getPuntos()
{
return puntos;
}
public void setPuntos(int puntos)
{
this.puntos = puntos;
}
}
Ahora crearemos un nuevo Servlets, que será el componente desde el que generaremos el reporte. Para eso hacemos clic derecho sobre el nodo "Source Package" del panel "Projects" y en el menú contextual que se abre seleccionamos "New -> Other...". En la ventana que se abre seleccionamos la categoría “web” y como tipo de archivo “Servlet”:
Escribimos "ServletReporte" como nombre del Servlet y lo colocamos en el paquete "pruebas.reportes.jasperreports.web":
Hacemos clic en el botón "Finish" y tendremos nuestro nuevo Servlet en la ventana del editor. Este Servlet contendrá tres métodos generados desde las plantilla de Servlets:
- doGet (para atender la peticiones HTTP GET)
- doPost (para atender las peticiones HTTP POST)
- processRequest que es llamado por los dos métodos anteriores
La funcionalidad para generar el reporte la colocaremos en este último método, así que lo primero que haremos es borrar el código que ya contiene, dejándolo vacio, principalmente porque el método utiliza un “java.io.PrintWriter”, que es un objeto para generar respuestas en texto, y nosotros usaremos un “javax.servlet.ServletOutputStream”, que es un objeto para generar respuestas binarias, que en este caso será el reporte:
public class ServletReporte extends HttpServlet
{
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
processRequest(request, response);
}
@Override
public String getServletInfo()
{
return "Short description";
}
}
Como el reporte que regresaremos estará en formato PDF, y este es un formato binario, (todo lo que no pueda abrirse con un bloc de notas, o cualquier editor de texto plano, y entenderse directamente es un archivo binario) la única forma que existe para regresarlo de forma correcta al cliente es haciendo uso de un Stream, en este caso de un “ServletOutputStream”. Es también por esta razón que debemos hacer uso de un Servlet y no de una JSP, ya que la llamada al método que regresa el “ServletOutputStream” solo es permitida dentro de un Servlet.
Lo primero que haremos dentro de nuestro Servlet es indicar el tipo de contenido que regresaremos (que por default es "text/html"). Como se trata de un archivo PDF el tipo de retorno es "application/pdf". Indicamos esto con el método "setContentType" del objeto "HttpServletResponse" que recibimos como segundo argumento, de la siguiente forma:
response.setContentType("application/pdf");
Este método se encarga de establecer las cabeceras adecuadas en la respuesta regresada al cliente para que este sepa cómo tratar los datos que está recibiendo. En este caso esperamos que abra el reporte con su aplicación habitual para leer archivos PDF (Acrobat Reader o algún otro). Es importante establecer este valor antes de obtener el “ServletOutputStream”, de lo contrario podríamos obtener algún error inesperado al enviar la respuesta.
Ahora que el Servlet ya conoce el tipo de respuesta que regresará podemos proceder a obtener el “ServletOutputStream” correspondiente para enviar la respuesta al cliente:
ServletOutputStream out = response.getOutputStream();
Ahora generamos el reporte como lo hemos estado haciendo hasta ahora, haciendo unos pequeños cambios: como ahora el archivo de la plantilla del reporte no se encuentra en la raíz del proyecto, sino dentro del directorio web, debemos indicar la ruta completa en la que se encuentra este archivo. Por lo que es necesario cambiar la línea
JasperReport reporte = (JasperReport) JRLoader.loadObject("reporte2.jasper");
Por:
JasperReport reporte = (JasperReport) JRLoader.loadObject(getServletContext().getRealPath("WEB-INF/reporte2.jasper"));
Además, como ahora el reporte no será generado en un archivo, sino que será enviado directamente al cliente, debemos cambiar la línea:
exporter.setParameter(JRExporterParameter.OUTPUT_FILE, new java.io.File("reporte2PDF_2.pdf"));
Por:
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
En realidad la línea anterior es la que hace el truco. El flujo del reporte es dirigido al flujo que es regresado al cliente, logrando así que este vea el reporte directamente en su navegador.
El resto del código de “processRequest” es igual al que ya hemos visto en los tutoriales anteriores, y queda de la siguiente forma:
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setContentType("application/pdf");
ServletOutputStream out = response.getOutputStream();
List listaPariticipantes = new ArrayList();
for (int i = 1; i <= 10; i++)
{
Participante p = new Participante(i, "Particpante " + i, "Usuario " + i, "Pass " + i, "Comentarios para " + i);
p.setPuntos(i);
listaPariticipantes.add(p);
}
try
{
JasperReport reporte = (JasperReport) JRLoader.loadObject(getServletContext().getRealPath("WEB-INF/reporte2.jasper"));
Map parametros = new HashMap();
parametros.put("autor", "Juan");
parametros.put("titulo", "Reporte");
JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, parametros, new JRBeanCollectionDataSource(listaPariticipantes));
JRExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
exporter.exportReport();
}
catch (Exception e)
{
e.printStackTrace();
}
}
Si ahora ejecutamos el proyecto (den algún tiempo para que el Tomcat se levante, hasta que vean el mensaje "INFO: Server startup in ***** ms" en el panel del salida) e ingresamos a la siguiente dirección:
http://localhost:8080/ReporteWeb/ServletReporte
Veremos que el reporte generado se muestra directamente en la pantalla del navegador:
Aunque esto es muy útil tal y como esta, algunas veces es mejor que el usuario decida si quiere guardar este reporte en su máquina o abrirlo con alguna otra aplicación en vez de usar directamente el navegador. Para poder lograr esto es necesario agregar una cabera llamada "Content-Disposition" a la respuesta. Esta cabecera tiene como valor "attachment; filename=" y el nombre que queremos darle a nuestro reporte. Para establecer esta cabecera usamos el método "setHeader" del objeto "HttpServletResponse", de la siguiente forma:
response.setHeader("Content-Disposition","attachment; filename=\"reporte.pdf\";");
Ahora compilamos y ejecutamos nuevamente nuestra aplicación y veremos que en esta ocasión se nos pregunta qué acción queremos realizar: abrir el reporte con alguna aplicación que seleccionemos, o guardarlo en nuestra máquina (tal vez será necesario que detengan y vuelvan a reiniciar su servidor para que tome los cambios):
Para evitar que nuestro navegador guarde el archivo en cache podemos establecer, como se indica en esta página del sitio jGuru, las siguientes cabeceras:
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
response.setDateHeader ("Expires", 0);
Aunque el darle al usuario la oportunidad de abrir o guardar el archivo es también bastante útil, algunas veces nos gustaría poder mostrar este archivo como parte de la información de nuestra página JSP embebiéndolo en la misma. Hacer esto es bastante sencillo, como se menciona en este artículo de flash colony. Solo hay que agregar la etiqueta <object>, con algunos atributos de configuración, en nuestra página JSP.
Si agregamos la siguiente etiqueta en nuestro archivo "index.jsp":
<object type="application/pdf" data="http://localhost:8080/ReporteWeb/ServletReporte" width="500" height="650"></object>
e ingresamos a la dirección:
http://localhost:8080/ReporteWeb/
Obtendremos el siguiente resultado:
Lo cual también puede sernos de mucha utilidad ^-^.
El código del método “processRequest” queda finalmente de la siguiente forma:
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setHeader("Content-Disposition", "attachment; filename=\"reporte.pdf\";");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("application/pdf");
ServletOutputStream out = response.getOutputStream();
List listaPariticipantes = new ArrayList();
for (int i = 1; i <= 10; i++)
{
Participante p = new Participante(i, "Particpante " + i, "Usuario " + i, "Pass " + i, "Comentarios para " + i);
p.setPuntos(i);
listaPariticipantes.add(p);
}
try
{
JasperReport reporte = (JasperReport) JRLoader.loadObject(getServletContext().getRealPath("WEB-INF/reporte2.jasper"));
Map parametros = new HashMap();
parametros.put("autor", "Juan");
parametros.put("titulo", "Reporte");
JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, parametros, new JRBeanCollectionDataSource(listaPariticipantes));
JRExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
exporter.exportReport();
}
catch (Exception e)
{
e.printStackTrace();
}
}
Y el código del archivo “index.jsp” queda así:
<%@page contentType="text/html" pageEncoding="UTF-8">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h1>Este es el archivo</h1>
<object type="application/pdf" data="http://localhost:8080/ReporteWeb/ServletReporte" width="500" height="650"></object>
</body>
<html>
Bien, este es el final de este cuarto tutorial sobre el uso de JasperReports. Espero que les sea de utilidad. No olviden dejar sus dudas, comentarios y sugerencias.
Saludos.
Descarga los archivos de este tutorial desde aquí:
Entradas Relacionadas:







hola he probrado, pero no me muestra nada mi servlet, q puede estar mal
ResponderEliminarHola. Eso me ocurrió en una ocasión al estar creando el tutorial y resulta que, aunque no me habia dado cuenta, se estaba lanzando una excepción de que el archivo .jasper especificado no se encontraba, ya que habia escrito mal el nombre. ¿Has revisado la salida de la consola para ver si no te ocurre algo parecido?.
ResponderEliminarSaludos.
Hola, el tutorial es muy bueno, pero no se si me podrías ayudar con el siguiente error:
ResponderEliminarINFO: Marcando el servlet ServletReporte como no disponible
27-abr-2009 9:26:34 org.apache.catalina.core.ApplicationContext log
GRAVE: Error loading WebappClassLoader
delegate: false
repositories:
/WEB-INF/classes/
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@1c282a1
pruebas.jasperreports.web.ServletReporte
java.lang.ClassNotFoundException: pruebas.jasperreports.web.ServletReporte
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1386)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1232)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1068)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:791)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:127)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Unknown Source)
27-abr-2009 9:26:34 org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Excepción de reserva de espacio para servlet ServletReporte
java.lang.ClassNotFoundException: pruebas.jasperreports.web.ServletReporte
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1386)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1232)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1068)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:791)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:127)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Unknown Source)
Hola programador Java:
ResponderEliminarOye no se que pasa le pongo al servlet:
response.setHeader("Content-Disposition","inline; filename=reporte.pdf");
response.setContentType("application/pdf");
y no me general la ventanita para que el usuario decida si quiere abrir el archivo pdf o guardarlo, me abre directamnte el reporte en el explorador que puede ser???
Hola;
ResponderEliminarPuede ser por dos razones, la primera es que estas poniendo
"Content-Disposition","inline; filename=reporte.pdf"
cambialo por
"Content-Disposition","attachment; filename=reporte.pdf";"
(cambia el inline por attachment)
La otra razón puede ser que tu navegador guardó en caché la página que se obtiene de la dirección de donde obtienes el reporte. Prueba borrando el caché de tu navegador. Para eso son estas líneas:
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
response.setDateHeader ("Expires", 0);
para que no tengas que borrarlo manualmente cada vez y te asegures de que siempre consulta el sitio en vez de su caché (aunque si ya lo ha guardado deberás borrarlo manualmente).
Prueba con las dos soluciones y avisame que pasa, sino buscamos qué otra cosa puede estar ocurriendo.
Saludos.
este es mi codigo:
ResponderEliminarprotected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws IOException,ServletException
{
response.setHeader("Content-Disposition","attachment; filename=\"reporte.pdf\"");
response.setContentType("application/pdf");
Connection conexion = new Conexion().getConexion();
ServletContext application = this.getServletContext();
ServletOutputStream outputStream = response.getOutputStream();
short claveDelegacion = ((Usuario)request.getSession().getAttribute("usuarioActual")).getCveDel();
String periodo = (String)request.getSession().getAttribute("periodo");
Map parametros = new HashMap();
parametros.put("imagen",application.getRealPath("reporte//LogoPA2.gif"));
parametros.put("periodo",periodo);
File archivoReporte = new File(application.getRealPath("reporte//ReporteBienesCatalogados.jasper"));;
if(request.getParameter("operacion").equals("reportebc")) {
try {
parametros.put("claveRequisicion",Integer.toString(new GestionBienesCatalogados().getClaveRequisicion(claveDelegacion,periodo)));
parametros.put("delegacion",new ValidarUsuario().getDelegacion(claveDelegacion));
}
catch(SQLException e) {
e.printStackTrace();
}
}
System.out.println("se manda a llamr el servlet reporte");
try {
JasperReport reporte = (JasperReport)JRLoader.loadObject(archivoReporte.getPath());
JasperPrint print = JasperFillManager.fillReport(reporte,parametros,conexion);
JRExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT,print);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM,outputStream);
exporter.exportReport();
}
catch(Exception e) {
e.printStackTrace();
}
outputStream.flush();
outputStream.close();
}
Prueba poner la línea
ResponderEliminarresponse.setContentType
antes de
response.setHeader
(qué sea la primer línea de tu método). Si no mal recuerdo las cabeceras se resetean cuando cambias el contentType
Hola tengo un problema, quiero mostrar mi reporte en una aplicacion web conectandome a una base de datos, pero por alguna razon la pagina me carga sin el Pdf alguien mi podria ayudar. Este es mi codigo. Gracias
ResponderEliminarpublic class NewServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException, JRException
{
response.setContentType("application/pdf");
ServletOutputStream out = response.getOutputStream();
try{
Class.forName("org.postgresql.Driver");
Connection conexion = DriverManager.getConnection("jdbc:postgresql://localhost:5432/PruebaReportes", "postgres", "postgres");
JasperReport reporte2 = (JasperReport)
JRLoader.loadObject(getServletContext().getRealPath("CertificadoPrueba2.jasper"));
JasperPrint jasperPrint = JasperFillManager.fillReport(reporte2, null, conexion);
JRExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT,jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
exporter.exportReport();
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
response.setDateHeader ("Expires", 0);
}
catch( Exception e ){
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
processRequest(request, response);
} catch (JRException ex) {
Logger.getLogger(NewServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
processRequest(request, response);
} catch (JRException ex) {
Logger.getLogger(NewServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public String getServletInfo() {
return "Short description";
}
}
Hola Lisbeth;
ResponderEliminarEn general veo bien tu código con excepción de las líneas
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
response.setDateHeader ("Expires", 0);
Las cuales me parecen deben de ir antes de que hagas
ServletOutputStream out = response.getOutputStream();
También podrías ver si estas obteniendo alguna excepción en la consola y ponerla?
Saludos
Hola,
ResponderEliminarNecesito restringir que el usuario solo pueda imprimir una sola copia del reporte, ¿Como puedo hacer esto?
saludos.
Excelente!
ResponderEliminarTodo perfecto, solo añadir una cosa, por si a alguien más le pasa.
ResponderEliminarSi incluimos imágenes y le ponemos una ruta relativa hay que añadir esta ruta como parámetro al principio de la clase Java de la siguiente manera, mi ruta donde tengo las imágenes es /web/Jasper/
String reportsDirPath = getServletContext().getRealPath("/Jasper/");
File reportsDir = new File(reportsDirPath);
if (!reportsDir.exists()) {
throw new FileNotFoundException(String.valueOf(reportsDir));
}
parametros.put(JRParameter.REPORT_FILE_RESOLVER, new SimpleFileResolver(reportsDir));
Con esto ya le indicamos a JasperReports donde se encuentran nuestros ficheros, yo tuve problemas ya que por defecto creo que los busca en el classpath, y en principio no me interesa incluir las imágenes en el mismo.
Saludos y el tutorial es buenísimo, muchas gracias.
Hola.. muy buen tutorial. quisiera saber como visualizar directamente el reporte en formato pdf, y no con el visor de jasperviewer.
ResponderEliminar@Hector
ResponderEliminarHola jqui, esto también aplica para subretportes?
Gracias!!!
@lalucas_183
ResponderEliminarHola lalucas,
Para esto debes ir a menú superior "Preview" y seleccionas "PDF preview".
Y para especificar los programas que abriran los reportes según el formato vas a el menu "Herramientas" -> "Opciones" y en la pestania "Viewers" cargas los ejecutables de los programas para visualizar los reportes como excel, Foxit reader, acrobat reader, etc...
Excelente material el que has creado, felicitaciones, es una gran base de conocimiento! muchas gracias.
ResponderEliminarFelicitaciones por estos tutoriales tan bien estructurados.
ResponderEliminarGracias por compartirnos tus conocimientos.
Hola Alex... necesito generar un reporte en una aplicacion web con struts y mostrarlo en en el navegador... sujerencias o ejemplos?? es un poco urgente.. Gracias de antemano
ResponderEliminar@Marlon Rjs
ResponderEliminarHola Marlon;
Struts 2 tie un plugin para trabajar direct con jasperreports, solo debes indicarle donde está tu archivo .jasper. Con Struts 1 el procedimiento es exactamente igual que el mostrado aqui, obtienes el response, el ServletOutputStream y envias por ahi el reporte generado.
Saludos
Hola Alex, tengo que hacer esto pero usando portlets de liferay, sabes como podría ser tengo que crear un servlet o puedo hacerlo en el action? =(
ResponderEliminarGracias
por que se sale una excepcion en la el siguiente codigo:
ResponderEliminarJasperReport reporte = (JasperReport) JRLoader.loadObject(getServletContext().getRealPath("WEB-INF/reporte2.jasper"));
Por que me sale esta excepcion por favor ayuda:
ResponderEliminarINFO: Use of the properties initialization parameter 'properties' has been deprecated by 'org.apache.velocity.properties'
17-ene-2012 8:48:57 org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Servlet.service() para servlet AdmAlmacen.Reporte lanzó excepción
java.lang.ClassNotFoundException: net.sf.jasperreports.engine.JasperCompileManager
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1358)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1204)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
at AdmAlmacen.Reporte.Reporte_1(Reporte.java:50)
at AdmAlmacen.Reporte.handleRequest(Reporte.java:61)
at org.apache.velocity.servlet.VelocityServlet.doRequest(VelocityServlet.java:358)
at org.apache.velocity.servlet.VelocityServlet.doGet(VelocityServlet.java:317)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Unknown Source)
Muy buen tutorial, muchas gracias, me ha servido de mucho, lo pude adaptar perfectamente a mis consultas SQL y mi aplicacion Web con salidas a Pdf y Excel.... Saludos!!
ResponderEliminarQue buen material!... Muchas gracias por estos artículos!
ResponderEliminarNecesito que me ayuden con algo, el reporte PDF no se genera dando este error por consola:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number
at net.sf.jasperreports.engine.fill.JRIntegerSumIncrementer.increment(JRIntegerIncrementerFactory.java:299)
at net.sf.jasperreports.engine.fill.JRAbstractExtendedIncrementer.increment(JRAbstractExtendedIncrementer.java:42)
at net.sf.jasperreports.engine.fill.JRCalculator.estimateVariables(JRCalculator.java:182)
at net.sf.jasperreports.engine.fill.JRFillDataset.next(JRFillDataset.java:889)
at net.sf.jasperreports.engine.fill.JRFillDataset.next(JRFillDataset.java:864)
at net.sf.jasperreports.engine.fill.JRBaseFiller.next(JRBaseFiller.java:1435)
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:126)
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:836)
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:765)
at net.sf.jasperreports.engine.fill.JRFiller.fillReport(JRFiller.java:84)
at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:624)
at pruebas.reportes.jasperreports.web.ServletReporte.processRequest(ServletReporte.java:73)
at pruebas.reportes.jasperreports.web.ServletReporte.doGet(ServletReporte.java:99)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
------------------------------------
La línea 73 es:
JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, null, new JRBeanCollectionDataSource(listaParticipantes));
Muchas gracias!
Que gran tutorial, he seguido todas las indicaciones y me funciona todo correctamente. Muchísimas gracias por el post!!!!
ResponderEliminarcómo puedo acceder al servlet desde una ruta relativa? ya que al llamarlo desde data="http://localhost:8080/ReporteWeb/ServletReporte", si la aplicación la monto en un servidor en red no me muestra el pdf final
ResponderEliminarHola Sara;
EliminarCuando tu servidor está en red, que es lo normal una vez que lo pones en producción, en vez de usar "localhost", debes usar la IP del servidor, por ejemplo:
data="http://192.168.0.10:8080/ReporteWeb/ServletReporte
Usando, claro está, la IP de tu servidor.
Saludos
Yo tuve un tema así, y en vez de marearte con direcciones puedes capturar la el pathcontext, el portlet es como un servlet más así que esto debería servir.
Eliminarhttp://www.exampledepot.com/egs/javax.servlet/GetReqUrl.html
Hola saludos, he seguido tus tutoriales y me han parecido excelentes, muchas gracias!!
ResponderEliminarEste comentario ha sido eliminado por el autor.
ResponderEliminarEstoy trabajando una aplicación web con tres capas, estoy colocando el servlet en la capa web pero al ejecutar lanza una exception de tipo:
ResponderEliminarjava.lang.NoClassDefFoundError: Could not initialize class net.sf.jasperreports.engine.util.JRLoader
y se relaciona con la siguiente linea
JasperReport reporte = (JasperReport)JRLoader.loadObject(getServletContext().getRealPath("WEB INF/ConsolidadosClientePedidos.jasper"));
Sospecho que es un problema de ruta ya que la aplicacion se tiene que desplegar apartir de la capa web y el servlet solo es posible acceder a traves de la ruta del enterprise application
Si alguien tiene el truco para acomodar el path del servlet le agradeceria
Tengo una consulta, pero primero dejame felicitarte por tus excelentes tutoriales.
ResponderEliminarEsty trabajando en un proyecto web con las tecnologias de JSF, PRIMEFACES E HIBERNATE...y queria saber si esta forma de generar reportes se puede adaptar a mi aplicacion o es necesario algunos cambios o que consejo me dan ??, ya que con primefaces las etiquetas cambian pero igual pudes hacer un action , algo asi: habria problemas al llamar a la clase creada por ti??
Muchas gracias de antemano.
Saludos cordiales :
ResponderEliminaresta muy bueno el tutorial.
Pero tengo una consulta, lo que pasa estoy haciendo un módulo y
uno de los requerimiento es que reporte solo se pueda visualizar(.pdf) mas no pueda guardar ni imprimir (deshabilitar las opciones de guardar e imprimir).
Agradezco su pronta respuesta.
Los libros electrónicos según se usen, son una gran fuente de ingresos o una forma muy buena de obtener suscriptores a mi negocio en internet, les dejo la página www.EscritoresDeArticulos.com donde hacen estos libros y así nos ahorrarnos este gran trabajo. Espero sirva mi aporte.
ResponderEliminar