Compilar arquivo xml do iReport em um Servlet

Olá pessoal, estou usando o jasper reports para criar relatórios e tudo acontece normalmente quando eu faço a chamada dos métodos dentro de uma aplicação que é desktop, no entanto, o mesmo não acontece quando eu tento gerar o relatório a partir de um servlet, já no primeiro comando:
JasperDesign jasperDesign = JasperManager.loadXmlDesign(“relatorio.xml”);
onde eu compilo o meu arquivo xml, a aplicação para e o incrível é que ela pula direto para a clausula finnaly sem passar pelo catch e por isso não mostra nenhuma exceção.
Se alguem imaginar o que pode ser ficarei muito agradecido pois preciso arrumar isto bem rápido.
Valeu, Spranta

[quote=“spranta”]Olá pessoal, estou usando o jasper reports para criar relatórios e tudo acontece normalmente quando eu faço a chamada dos métodos dentro de uma aplicação que é desktop, no entanto, o mesmo não acontece quando eu tento gerar o relatório a partir de um servlet, já no primeiro comando:
JasperDesign jasperDesign = JasperManager.loadXmlDesign(“relatorio.xml”);
onde eu compilo o meu arquivo xml, a aplicação para e o incrível é que ela pula direto para a clausula finnaly sem passar pelo catch e por isso não mostra nenhuma exceção.
Se alguem imaginar o que pode ser ficarei muito agradecido pois preciso arrumar isto bem rápido.
Valeu, Spranta[/quote]

Amigao, vc nao precisa compilar o xml na sua aplicacao, o esquema eh vc compilar o relatorio e colocar em alguma pasta dentro do webapp e chamar uma funcao do jasper para gerar o relatorio em html ou pdf, fora que se vc compilar dentro da sua aplicacao fica muito lento.

Eu estou no trampo, mas quando eu chegar em minha casa eu posto aqui uma servlet e uma classe que eu fiz no meu projeto de conclusao de curso para gerar relatorio html/pdf de arquivos .jasper (xml do jasper compilado)

[]s

Segue as classes conforme post anterior : (não esqueça dos jars do jasperreports e do driver jdbc)

Essas classes foram modificadas, tentei deixar o mais simples, qualquer coisa posta aqui

/*
 * Created on 09/08/2003
 * $Revision: 1.4 $
 * $Source: C:/cvsrepo/cvspfc2/pfc/src/pfc/util/ReportManager.java,v $
 * $Log: ReportManager.java,v $
 * Revision 1.4  2003/11/29 13:35:35  douglas
 * Correções
 *
 * Revision 1.3  2003/11/02 19:00:11  douglas
 * Diversas atualizações
 *
 * Revision 1.2  2003/08/16 00:08:45  douglas
 * Diversos Refactorings
 *
 * Revision 1.1  2003/08/09 22:16:37  douglas
 * Códigos-fonte que será utilizado no último semestre
 *
 */
package pfc.util;

import java.io.OutputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;

import dori.jasper.engine.JRException;
import dori.jasper.engine.JRExporterParameter;
import dori.jasper.engine.JasperExportManager;
import dori.jasper.engine.JasperManager;
import dori.jasper.engine.JasperPrint;
import dori.jasper.engine.JasperReport;
import dori.jasper.engine.export.JRHtmlExporter;
import dori.jasper.engine.export.JRHtmlExporterParameter;
import dori.jasper.engine.util.JRLoader;

import pfc.exception.RelatorioNotFoundException;

/**
 * Classe utilitária que efetua o gerenciamento de relatórios baseado na
 * biblioteca JasperReports
 * @author <a href="mailto:douglasfsbr@yahoo.com.br">Douglas</a>
 * @url element://model:project::Projeto Final de Curso/design:node:::N9zn4d9dnl4bk2m-8zzkm0
 * @version $Id: ReportManager.java,v 1.4 2003/11/29 13:35:35 douglas Exp $
 */

public final class ReportManager {

    private ReportManager() {
    }

    public static ReportManager getInstance() {
        return new ReportManager();
    }

    /**
     * @param relatorio
     * @param parametros
     * @param saida
     * @throws SQLException
     * @throws JRException
     * @throws RelatorioNotFoundException
     */
    public final void processarRelatorioHTML(
        String relatorio,
        Map parametros,
        OutputStream saida)
        throws SQLException, JRException, RelatorioNotFoundException {
        JasperPrint jasperPrint = processarRelatorioBasico(relatorio, parametros);
        JRHtmlExporter exporter = new JRHtmlExporter();
        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, saida);
        exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, "images/");
        exporter.exportReport();
    }

    /**
     * @param relatorio
     * @param parametros
     * @param saida
     * @throws SQLException
     * @throws JRException
     * @throws RelatorioNotFoundException
     */
    public final void processarRelatorioPDF(
        String relatorio,
        Map parametros,
        OutputStream saida)
        throws SQLException, JRException, RelatorioNotFoundException {
        JasperPrint jasperPrint = processarRelatorioBasico(relatorio, parametros);
        JasperExportManager.exportReportToPdfStream(jasperPrint, saida);
    }

    /** Processa um relatório e o transforma num arquivo XML
     * @param relatorio
     * @param parametros
     * @param arquivoDestino
     * @throws SQLException
     * @throws JRException
     * @throws RelatorioNotFoundException
     */
    public final void processarRelatorioXML(
        String relatorio,
        Map parametros,
        String arquivoDestino)
        throws SQLException, JRException, RelatorioNotFoundException {
        JasperPrint jasperPrint = processarRelatorioBasico(relatorio, parametros);
        JasperExportManager.exportReportToXmlFile(jasperPrint, arquivoDestino, true);
    }

    /**
     * @param relatorio
     * @param parametros
     * @return
     * @throws SQLException
     * @throws JRException
     * @throws RelatorioNotFoundException
     */
    private final JasperPrint processarRelatorioBasico(
        String relatorio,
        Map parametros)
        throws SQLException, JRException, RelatorioNotFoundException {

        JasperPrint jp = null;
        Connection conexao = ... // escreva um código para retornar um conexao com o DB
        if (conexao == null) {
            throw new SQLException("Nao é possível efetuar conexão com o banco de dados");
        }

        try {
            // carrega o relatório
            JasperReport jr = (JasperReport) JRLoader.loadObject(relatorio);
            // preenche o relatório com o objeto JasperReport, parametros e o ponteiro para conexao com o BD        
            jp = JasperManager.fillReport(jr, parametros, conexao);
            if (jp.getPages().size() < 1) {
                //Pode chorar, pois o relatório está em branco                        
                throw new RelatorioNotFoundException();
            }
        }
        finally {
            try {
                conexao.close();
            }
            catch (SQLException sqle) {
                sqle.printStackTrace();
            }
        }
        return jp;
    }
}

Essa Servlet que dispara a classe do post acima

Também foi modificado pra ser o mais simples, qualquer coisa posta suas dúvidas

/*
 * Created on 09/08/2003
 * $Revision: 1.3 $
 * $Source: C:/cvsrepo/cvspfc2/pfc/src/pfc/util/servlets/ServletReportsServer.java,v $
 * $Log: ServletReportsServer.java,v $
 * Revision 1.3  2003/11/29 13:35:35  douglas
 * Correções
 *
 * Revision 1.2  2003/08/17 23:33:49  douglas
 * Agora redireciona para o controller, ao invés de enviar o sendRedirect
 *
 * Revision 1.1  2003/08/09 22:16:43  douglas
 * Códigos-fonte que será utilizado no último semestre
 *
 */
package pfc.util.servlets;

import java.io.IOException;
import java.sql.SQLException;
import java.util.logging.Logger;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import dori.jasper.engine.JRException;

import pfc.action.IRelatorio;
import pfc.exception.RelatorioNotFoundException;
import pfc.util.PFCLogger;
import pfc.util.ReportManager;
/**
 * Servlet para gerenciamento e exibicao de relatorios na WEB
 * @author <a href="mailto:douglasfsbr@yahoo.com.br">Douglas</a>
 * @url element://model:project::Projeto Final de Curso/design:node:::N9zn4d9dnl4bk2m-8zzkm0
 * @version $Id: ServletReportsServer.java,v 1.3 2003/11/29 13:35:35 douglas Exp $
 * @web.servlet name = "ServletReportsServer"
 * display-name = "ServletReportsServer"
 * description = "Servlet para Gerenciamento de Relatorios"
 * @web.servlet-mapping url-pattern = "/ReportsServer"
 */
public class ServletReportsServer extends HttpServlet {

    //O separador pode ser \ em Windows ou / em Unix/Linux
    private static final String SEPARADOR =
        System.getProperty("file.separator");

    /** Initializes the servlet.
    */
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    /** Destroys the servlet.
    */
    public void destroy() {

    }

    /**
    * @param request
    * @param response
    * @throws ServletException
    * @throws IOException
    */
    /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
    * @param request servlet request
    * @param response servlet response
    */
    private void processRequest(
        HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, IOException {
        // aqui eu estou assumindo que embaixo do WEB-INF do seu webapp tem uma pasta "reports" e embaixo do "reports" tem uma subpasta "jasper", que no caso essa última pasta contém seu relatórios compilados (de xml para .jasper)
        final String caminhoRelatorio =
            this.getServletContext().getRealPath("/WEB-INF/reports/jasper");
        response.setHeader("pragma", "no-cache");
        response.setHeader("cache-control", "no-cache");
        // recupera o fluxo de saida para que se possa exibir
        // conteúdo binário
        ServletOutputStream out = response.getOutputStream();
        // Recupera a sessao do usuario
       final String nomeRelatorio =
        montarNomeDoRelatorio(relatorio, caminhoRelatorio);
            final ReportManager reportManager = ReportManager.getInstance();

            try {
                switch (qualOtipodoRelatorio) { // qualOtipodoRelatorio nao esta declarado, pecisa declarar essa variável
                    case HTML : //defina um codigo para html
                        processarRelatorioHTML(
                            response,
                            reportManager,
                            nomeRelatorio,
                            relatorio,
                            out);
                        break;
                    case PDF : //defina um codigo para pdf
                        processarRelatorioPDF(
                            response,
                            reportManager,
                            nomeRelatorio,
                            out,
                            relatorio);
                        break;
                    default :
                        throw new UnsupportedOperationException("Operação não suportada !");
                }
            }
            catch (RelatorioNotFoundException rnfe) {
                response.sendRedirect("/meuwebapp/RelatorioNaoEncontrado.html");
            }
            catch (Exception e) {
                response.sendRedirect("/meuwebapp/RelatorioNaoProcessado.html");
            }
        }
        out.close();
    }

    /**
    * @param response
    * @param rep
    * @param relatorio
    * @param saida
    * @param iRelatorio
    * @throws RelatorioNotFoundException
    * @throws SQLException
    * @throws JRException
    */
    private void processarRelatorioPDF(
        HttpServletResponse response,
        ReportManager rep,
        String relatorio,
        ServletOutputStream saida,
        IRelatorio iRelatorio)
        throws RelatorioNotFoundException, SQLException, JRException {
        response.setHeader(
            "Content-disposition",
            "attachment;filename=" + iRelatorio.getNomeRelatorio() + ".pdf");
        response.setContentType("application/pdf");
        rep.processarRelatorioPDF(relatorio, // aqui passa os parametros, saida);
    }

    /**
    * @param response
    * @param rep
    * @param relatorio
    * @param iRelatorio
    * @param saida
    * @throws RelatorioNotFoundException
    * @throws SQLException
    * @throws JRException
    */
    private void processarRelatorioHTML(
        HttpServletResponse response,
        ReportManager rep,
        String relatorio,
        IRelatorio iRelatorio,
        ServletOutputStream saida)
        throws RelatorioNotFoundException, SQLException, JRException {
        response.setContentType("text/html");
        rep.processarRelatorioHTML(
            relatorio,
            // aqui passa os parametros,
            saida);
    }

    /**
    * @param relatorio
    * @param caminhoRelatorios
    * @return
    */
    private String montarNomeDoRelatorio(
        final IRelatorio relatorio,
        final String caminhoRelatorios) {
        StringBuffer buffer = new StringBuffer();
        buffer.append(caminhoRelatorios);
        buffer.append(SEPARADOR);
        buffer.append(relatorio.getNomeRelatorio());
        buffer.append(".jasper");
        return buffer.toString();
    }

    /** Handles the HTTP <code>GET</code> method.
    * @param request servlet request
    * @param response servlet response
    */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        processRequest(request, response);
    }

    /** Handles the HTTP <code>POST</code> method.
    * @param request servlet request
    * @param response servlet response
    */
    public void doPost(
        HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, IOException {
        processRequest(request, response);
    }

    /** Returns a short description of the servlet.
    */
    public String getServletInfo() {
        return "Servlet para Gerenciamento de Relatórios";
    }
}

Exceção …

/*
 * Created on 09/08/2003
 * $Revision: 1.2 $
 * $Source: C:/cvsrepo/cvspfc2/pfc/src/pfc/exception/RelatorioNotFoundException.java,v $
 * $Log: RelatorioNotFoundException.java,v $
 * Revision 1.2  2003/11/29 13:35:33  douglas
 * Correções
 *
 * Revision 1.1  2003/08/09 22:16:34  douglas
 * Códigos-fonte que será utilizado no último semestre
 *
 */
package pfc.exception;


import java.lang.Exception;
/**
 * Exceção que é disparada caso o relatório esteja em branco
 * @author <a href="mailto:douglasfsbr@yahoo.com.br">Douglas</a>
 * @url element://model:project::Projeto Final de Curso/design:node:::N9zn4d9dnl4bk2m-8zzkm0
 * @version $Id: RelatorioNotFoundException.java,v 1.2 2003/11/29 13:35:33 douglas Exp $
 */
public class RelatorioNotFoundException extends Exception{
    
    /**
     * 
     */
    public RelatorioNotFoundException() {
        super();
    }
}

Ai Douglas, muito obrigado pelas dicas, mas está acontecendo um problema estranho quando eu entro dentro do método processarRelatorioBasico() e mando carregar o relatorio pelo comando:
JasperReport jr = (JasperReport) JRLoader.loadObject(relatorio);
A seguinte exceção é lançada, vc sabe o que pode ser?

java.io.InvalidClassException: dori.jasper.engine.base.JRBaseReport; local class incompatible: stream classdesc serialVersionUID = 500, local class serialVersionUID = 501
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:454)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1511)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1425)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1511)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1425)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1616)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1264)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:322)
at dori.jasper.engine.util.JRLoader.loadObject(JRLoader.java:128)
at dori.jasper.engine.util.JRLoader.loadObject(JRLoader.java:105)

Mais uma vez obrigado, Spranta

Você está usando uma versão do Jasper para compilar e outra para executar o relatório.

Tem que ser exatamente a mesma versão do jasper e libs … o Jasper faz essa xaropisse para evitar problemas de compatibilidade das classes criadas.

[quote=“smota”]Você está usando uma versão do Jasper para compilar e outra para executar o relatório.

Tem que ser exatamente a mesma versão do jasper e libs … o Jasper faz essa xaropisse para evitar problemas de compatibilidade das classes criadas.[/quote]

Soh complementando a resposta do Samuel, isso pode estar acontecendo se vc esta usando o iReport. (se vc nao o usa, esquece o que eu estou escrevendo)

Motivo : o iReport tem um .jar do JasperReports, talvez vc esteje compilando essa classe pelo iReport e esta tentando executa-lo usando uma biblioteca com uma outra versao.

Pois é pessoal, era isso mesmo, o relatório saiu certinho aqui, só teve um problema. É que quando eu gero um relatório em pdf ele fica bem pequeno, cerca de uns 15k e já em html o relatório é absurdamente grande, mais de 500 mega, vcs sabem como posso fazer para minimizar este problema quando for gerado um relatório html?
Mais uma vez obrigado amigos.
Spranta

[quote=“spranta”]Pois é pessoal, era isso mesmo, o relatório saiu certinho aqui, só teve um problema. É que quando eu gero um relatório em pdf ele fica bem pequeno, cerca de uns 15k e já em html o relatório é absurdamente grande, mais de 500 mega, vcs sabem como posso fazer para minimizar este problema quando for gerado um relatório html?
Mais uma vez obrigado amigos.
Spranta[/quote]

:shock: 500 megas ???

Sera que vc nao errou na digitacao ??? Nao seria 500 k ?

Geralmente eu evitava utilizar relatorio html, soh uso .pdf, por ser um relatorio de melhor qualidade.

Pois é cara, parece brincadeira mesmo mas não é não, o arquivo gerado ficou em 500 mega, e eu tenho certeza disso, depois eu gerei outro e ficou ainda maior. muito estranho.

Uma pergunta que eu acho que não tem nada a ver ?

Sua máquina não está com vírus ?

não, não tem virus nenhum não, mas eu criei um outro relatório usando um xml modelo do proprio jasper reports e aí então o html foi mais coerente no tamanho, deu somente 30k. Acho que o problema era alguma configuração do xml que eu tinha criado antes.

Agora é o seguinte, estou usando o iReport mas não estou entendendo certas coisas como a diferença entre quando eu referencio os parametros com $F, $P, $V e outros, qual o significado de cada um, alguém sabe me falar? Também gostaria de saber como colocar código dentro do iReport, pois vou precisar colocar algumas condições, como por exemplo quando eu recebo um certo código do select eu quero verificar qual é o código e então imprimir uma certa string. Vocês sabem se tem como eu resolver isto no iReport, ou quem sabe até mesmo referenciar uma função de uma classe java diretamente no iReport que receberia um parametro e me retornaria o valor apropriado, acho que aí já seria demais né, mas como não sei vale a pena perguntar. Valeu pessoal. Um abraço
Spranta

$P :arrow: indica um parâmetro, será passado posteriormente pela aplicação usando a API do Jasper.
$V :arrow: indica uma variável, é criada e gerenciada internamente pelo Jasper.
$F :arrow: indica um campo (field), é extraído pelo Jasper do JRDataSource(alguma coisa assim) … são os campos vindos de uma query (o mais normal) ou de um bean ou seja lah o que for que você estiver usando como fonte dos dados.

Você pode sim criar métodos para utilizar internamente, vai ter que aprender um pouco sobre como funciona a instanciação dos objetos no Jasper já que vai ser obrigado a usar a chamada em uma só linha (você pode criar uma variável para aquele seu tipo).

Tem como tomar decisões, vai depender do problema. Os campos, grupos, etc. tem uma propriedade de Print when que dá conta do recado na maior parte dos problemas.

Lembre-se: o iReport é apenas um front-end para o JasperReports, então essas dúvidas dizem respeito ao Jasper, não ao iReport.
(Só pra facilitar a busca pelas soluções) :wink:

[quote=“spranta”] … quando eu recebo um certo código do select eu quero verificar qual é o código e então imprimir uma certa string. Vocês sabem se tem como eu resolver isto no iReport, ou quem sabe até mesmo referenciar uma função de uma classe java diretamente no iReport que receberia um parametro e me retornaria o valor apropriado, acho que aí já seria demais né, mas como não sei vale a pena perguntar. Valeu pessoal. Um abraço
Spranta[/quote]

Caso vc esteje usando um banco Oracle, vc pode verificar qual é o código no proprio select, no caso usando a funcao decode (que basicamente eh um if ou switch).

Exemplo :

select decode(codigo_departamento,1,'Vendas',2,'Informatica','Nao sei') from funcionario

Passando para um pseudocodigo o select acima ficaria assim :

se codigo_departamento == 1 entao
  imprima 'Vendas'
senao se codigo_departamento == 2 entao
  imprima 'Informatica'
senao
  imprima 'Nao sei'
fim se

Achei algo equivalente ao decode do Oracle para o MySQL no google, mas nao testei.

SELECT CASE 1 WHEN 1 THEN "one" WHEN 2 THEN "two" ELSE "more" END;

[quote]Você pode sim criar métodos para utilizar internamente, vai ter que aprender um pouco sobre como funciona a instanciação dos objetos no Jasper já que vai ser obrigado a usar a chamada em uma só linha (você pode criar uma variável para aquele seu tipo).

Tem como tomar decisões, vai depender do problema. Os campos, grupos, etc. tem uma propriedade de Print when que dá conta do recado na maior parte dos problemas.
[/quote]

smota, voce tem algum exemplo de xml que me mostre estas funcionalidade citadas por voce?

É isso aí, acho que esta deve ser minha ultima duvida sobre este tópico, mais uma vez obrigado a todos pela paciencia e boa vontade com que me ajudaram. A solidariedade e paciencia de todo o grupo acaba nos ajudando a ver o valor de uma ajuda sem interesses . Valeu e até a próxima
SPRANTA

Oba,

Os melhores exemplos estão realmente na página do Jasper: http://jasperreports.sourceforge.net/samples/index.html

Não tem muito segredo … com os exemplos e o Quick Reference você vai longe.

Depois poste suas dúvidas mais direcionadas que a gente tenta ajudar.

Please help

ejecuto esta linea de un programa:

try {
System.out.println(“AQUI VA 2”);
masterPrint = JasperFillManager.fillReport(masterReport, masterParams,
con);

                   System.out.println("AQUI VA 3");

y sale este error:

AQUI VA 1
AQUI VA 2
Exception in thread “main” java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at net.sf.jasperreports.engine.fill.JRBaseFiller.(JRBaseFiller.java:128)
at net.sf.jasperreports.engine.fill.JRFiller.fillReport(JRFiller.java:111)
at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:291)
at Reportes.SUBREPORTS.SubreportsSample.main(SubreportsSample.java:122)

Gracias por la ayuda que puedan proporcionarme!!!

Para usar o jasperReport nao basta vc colocar somente o jasperreportsx.x.jar no seu classpath, vc também precisa refenciar outras bibliotecas utilzadas pelo jasper como a commons-logging do projeto jakarta que contem a classe LogFactory que é o que tá gerando erro aí na sua aplicação e já adianto que provavelmente vc vai precisar adicionar outras libs mas daí eu nao me lembro de todas, entao a medida que que aparecer o erro NoClassDefFoundError vc procura a biblioteca a qual a classe nao encontrada pertence e adiciona ela ao classpath da aplicaçao