[RESOLVIDO] ExtJS4 com Ireport. Não consigo renderizar o relatorio

Bom dia pessoal,

estou com um probleminha simples. Estou tentando gerar um relatorio e mostrar na tela. Bom, oq eu to tentando fazer? Criei um botão apenas para teste, e na tela existe campos de input text, que servirá como parametros para a busca. E então, quando se clica naquele botão, eu vou até uma classe controller, pego o parametro, gero uma lista daquele objeto, gero o relatorio e tento exibir. Bom, o relatorio já gera bonitinho do jeito que eu queria, porém não consigo jogar ele na tela. Aqui vai o meu método que eu fiz na classe java:

public void listarTdasEmpresas(final ServletContext context,HttpServletRequest request,HttpServletResponse response, Empresa element){
		
		//.out.println(element.getNomeFantasia());
		
		try {
		String caminhoRelatorio = context.getRealPath("/app/controller/administrativo/relatorio/empresa.jasper");
		 
		Map<String,Object> map = new HashMap<String, Object>();
			
		map.put("REPORT_CONNECTION", "");
			
		List<Empresa> listaEmpresas = empresaDao.listarEmpresasPorNomeFantasia(element.getNomeFantasia());
		
		JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(listaEmpresas);  
		
		JasperPrint print = JasperFillManager.fillReport(caminhoRelatorio,map,ds);
		
		JasperExportManager.exportReportToPdfFile(print,context.getRealPath("")+"/app/controller/administrativo/relatorio/Relatorio_Empresa.pdf");
		
		/*byte[] bytes = JasperExportManager.exportReportToPdf(print);  
		
		byte[] arquivo = bytes;  */
		
		response.setContentType("application/octet-stream");  
		  
	    response.setHeader("Content-Disposition","attachment; filename=relatorio.pdf"); 
	        
	   /* ServletOutputStream sos = response.getOutputStream();  
	     
	    response.setContentLength(arquivo.length);  
	  
	    sos.write(arquivo, 0, arquivo.length);  
	  
	    sos.flush();  
	  
	    sos.close();  */
		
		response.sendRedirect(context.getRealPath("")+"/app/controller/administrativo/relatorio/Relatorio_Empresa.pdf");

		result.use(Results.nothing());
		
		} catch (JRException e) {
			
			e.printStackTrace();
		} catch (IOException e) {
			
			e.printStackTrace();
		}
	
	}

E aqui vai uma parte do codigo js:

'pesquisarEmpresa button[action=gerar_relatorio]': {
    			click: function(){
    				Ext.getCmp('formPesquisarEmpresa').getForm().submit({
    					url: '/vianet/empresa/listarTdasEmpresas',
    					params: {
    						'element.nomeFantasia' : Ext.getCmp('empresaNomeFantasiaPesquisar').getValue()
    					},
    					
    					});
    			}
    		}

O bom é que, ele não me da erro… e então não sei porque não renderiza… Alguém poderá me ajudar ?

Euclides, se voce não tiver um viewer pdf como plugin no seu navegador ele pedirá pelo menos para fazer download. Isso não acontece?

Não acontece… porém eu olhando o fireBug do chrome, ele me mostra o seguinte erro:

You're trying to decode and invalid JSON String: %PDF-1.4
%����
3 0 obj
<</Length 297/Filter/FlateDecode>>stream
x����N�0E���Y�Eӱ����J<Z�� V*W�A�.���D@�D
R-K�d�̙;s�ȅ&><�1��(M�	������p���.�lN�"�29��!v����IE�|W�B~%�1ǐvE&���������Y�Pa�K���ݛ����!Ix�Ÿ��J+P��a��{��2dt��ȃ�ˀ
1CD:̇B�R(�dBJ���i�Y��a-lY��M՛��
��i�Μ�u�.����F.q�>�K�1=��kͻ��:����iC[uYk3S��7�����o�bS��6�$~���
endstream
endobj
1 0 obj
<</Group><</Type/Group/CS/DeviceRGB/S/Transparency>>/Parent 4 0 R/Contents 3 0 R/Type/Page/Resources<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]/ColorSpace><</CS/DeviceRGB>>/Font<</F1 2 0 R>>>>/MediaBox[0 0 595 842]>>
endobj
5 0 obj
[1 0 R/XYZ 0 852 0]
endobj
2 0 obj
<</BaseFont/Helvetica/Type/Font/Encoding/WinAnsiEncoding/Subtype/Type1>>
endobj
4 0 obj
<</ITXT(2.1.7)/Type/Pages/Count 1/Kids[1 0 R]>>
endobj
6 0 obj
<</Names[(JR_PAGE_ANCHOR_0_1) 5 0 R]>>
endobj
7 0 obj
<</Dests 6 0 R>>
endobj
8 0 obj
<</Names 7 0 R/Type/Catalog/ViewerPreferences><</PrintScaling/AppDefault>>/Pages 4 0 R>>
endobj
9 0 obj
<</Creator(JasperReports \(empresa\))/Producer(iText 2.1.7 by 1T3XT)/ModDate(D:20120319120526-03'00')/CreationDate(D:20120319120526-03'00')>>
endobj
xref
0 10
0000000000 65535 f 
0000000379 00000 n 
0000000648 00000 n 
0000000015 00000 n 
0000000736 00000 n 
0000000613 00000 n 
0000000799 00000 n 
0000000853 00000 n 
0000000885 00000 n 
0000000988 00000 n 
trailer
<</Root 8 0 R/ID [><09b601725f86519998013dd3f471210e><09fa7277dc1a2541aa796eaeceda9690>]/Info 9 0 R/Size 10>>
startxref
1145
%%EOF
Ext.apply.logext-debug.js:8967
Ext.Error.Ext.extend.statics.raiseext-debug.js:7893
(anonymous function)ext-debug.js:8203
Ext.Ajax.request.successEmpresa.js:110
Ext.apply.callbackext-debug.js:8404
Ext.define.onCompleteConnection.js:717
Ext.define.onStateChangeConnection.js:676
(anonymous function)

@Euclides, se tu olhar na documentação do ExtJS¹, vai ver que o submit do Ext.form.Panel que herda do Ext.form.Basic, nada mais é do que uma requisição ajax, portanto tu não vai poder baixar o PDF da forma que está fazendo, para isso tu teria que fazer um post/get normal nem que seja num iframe escondido, não trabalhei muito com ExtJS 4 ainda, mas nas versões 3.x havia uma opção ou plugin que você configurava pra fazer upload de arquivos, neste caso poderia ser utilizado também para obter o download também, creio eu.

¹ http://docs.sencha.com/ext-js/4-0/#!/api/Ext.form.Basic-method-submit

Eu vi uma solução, parecida com essa, porém não to vendo como usa-la

    Ext.Ajax.request({  
        method: 'POST',  
        scope: this,              
        url: 'meuAction/listaPdf',  
        success: function(response, options) {  
            console.log( Ext.decode(response.responseText).arquivo);  
            var j = new Ext.Window({  
                title : "iframe",  
                width : 300,  
                height: 300,  
                layout : 'fit',  
                items : [{  
                    xtype : "component",  
                    autoEl : {  
                        tag : "iframe",  
                        src : Ext.decode(response.responseText).arquivo  
                    }  
                }]  
            }).show();            
        },                    
        failure: function() {   
            Ext_example.msg('Erro:', 'Erro ao gerar o arquivo.', './images/cancel3.png');  
        },  
    });  

[quote=EuclidesFilizola]Eu vi uma solução, parecida com essa, porém não to vendo como usa-la

Ext.Ajax.request({ method: 'POST', scope: this, url: 'meuAction/listaPdf', success: function(response, options) { console.log( Ext.decode(response.responseText).arquivo); var j = new Ext.Window({ title : "iframe", width : 300, height: 300, layout : 'fit', items : [{ xtype : "component", autoEl : { tag : "iframe", src : Ext.decode(response.responseText).arquivo } }] }).show(); }, failure: function() { Ext_example.msg('Erro:', 'Erro ao gerar o arquivo.', './images/cancel3.png'); }, }); [/quote]

Eu faço algo parecido em um projeto aqui que usa jasper com rails, fica assim


            new Ext.Window({
                title:title, 
                resizable:false, 
                width:990, 
                heigth: 500,
                items: [
                    new Ext.Panel({
                    	autoWidth: true, 
                        autoHeigth: true,
                        html:"<iframe width=\"100%\" height=\"500\" src=\"/report.pdf\"></iframe>"
                    })
                ]
            }).show();

Basta trocar o src pelo caminho do seu relatorio com os parametros, isso vai garantir que ele vai carregar um iframe dentro da window, na pior das hipoteses vai pedir para fazer o down

vou colar o código completo aqui [extjs 3] de como faço:


//button que será adicionado no form

        var confirmar = new Ext.Button({
            tabIndex : 0,
            icon : Ext.Button.ICON_CONFIRMAR,
            tooltip : Ext.Button.TOOLTIP_CONFIRMAR,
            handler : function() {
                var form = formPanel.getForm();
                if (form.isValid()) {

                    var objeto = form.getValues();
                    var data_inicial = objeto.data_inicial.split("/")
                            .reverse().join("-");
                    var data_final = objeto.data_final.split("/")
                            .reverse().join("-");
                	
					var url = "/balanco" + ".file?data_inicial=" + data_inicial
							+ "&data_final=" + data_final;

					Pacioli.openReportInWindow(url, config.relatorio, config.titulo)
					
                }
            }
        });

a função que captura o resultado em um iframe, uso sempre jQuery com Extjs



Pacioli.openReportInWindow = function(url, reportName, title) {

	Ext.Msg.wait("Aguarde enquanto o relatório é processado.", "Processando...");
	
	$.ajax({
        error: function(objeto) {
            var errors = Ext.decode(objeto.responseText).errors;
            processarErrosValidacao(errors);
        },
        success: function(retorno){
            new Ext.Window({
                title:title, 
                resizable:false, 
                width:990, 
                heigth: 500,
                items: [
                    new Ext.Panel({
                    	autoWidth: true, 
                        autoHeigth: true,
                        html:"<iframe width=\"100%\" height=\"500\" src=\"" + window.location.href + "" +retorno+".pdf\"></iframe>"
                    })
                ]
            }).show();
            Ext.Msg.hide();
            reportLog(title + " [Processado no arquivo " + retorno + ".pdf] ");
        },
        type: 'GET', 
        url: url
    });
}

Esse código já tá meio antigo, mas é o mais novo que tenho com Extjs + jasper

Estou tentando fazer assim:

click: function(){
    				
    				Ext.Ajax.request({    
    				    method: 'POST',    
    				    scope: this,                
    				    url: '/vianet/empresa/listarTdasEmpresas',
    				    params: {
    						'element.nomeFantasia' : Ext.getCmp('empresaNomeFantasiaPesquisar').getValue()
    					},
    				    success: function(response, options) {    
    				           
    				        var j = new Ext.Window({    
    				            title : "iframe",    
    				            width : 400,    
    				            height: 400,    
    				            layout : 'fit',    
    				            items : [
    				                    new Ext.Panel({  
    				                    	 autoWidth: true,   
    				                    	 autoHeigth: true,  
    				                    	 html:"&lt;iframe width=\"100%\" height=\"400\" src=\"/relatorio.pdf\"&gt;&lt;/iframe&gt;"  
    				                    })  
    				          
							]    
    				        }).show();              
    				    },                      
    				    failure: function() {     
    				        Ext_example.msg('Erro:', 'Erro ao gerar o arquivo.', './images/cancel3.png');    
    				    },    
    				}); 

Bom, ele abre um iframe, porém com valores 404 not found… ou seja, faltam os parametros. como eu passo ?

[quote=EuclidesFilizola]Estou tentando fazer assim:

click: function(){
    				
    				Ext.Ajax.request({    
    				    method: 'POST',    
    				    scope: this,                
    				    url: '/vianet/empresa/listarTdasEmpresas',
    				    params: {
    						'element.nomeFantasia' : Ext.getCmp('empresaNomeFantasiaPesquisar').getValue()
    					},
    				    success: function(response, options) {    
    				           
    				        var j = new Ext.Window({    
    				            title : "iframe",    
    				            width : 400,    
    				            height: 400,    
    				            layout : 'fit',    
    				            items : [
    				                    new Ext.Panel({  
    				                    	 autoWidth: true,   
    				                    	 autoHeigth: true,  
    				                    	 html:"&lt;iframe width=\"100%\" height=\"400\" src=\"/relatorio.pdf\"&gt;&lt;/iframe&gt;"  
    				                    })  
    				          
							]    
    				        }).show();              
    				    },                      
    				    failure: function() {     
    				        Ext_example.msg('Erro:', 'Erro ao gerar o arquivo.', './images/cancel3.png');    
    				    },    
    				}); 

Bom, ele abre um iframe, porém com valores 404 not found… ou seja, faltam os parametros. como eu passo ?
[/quote]

Eu acho que confundi mais do que ajudei, via ajax não vai funcionar, o que faço via ajax é buscar o caminho do relatorio que é gerado em um processo assincrono eu já pego o pdf processado, meu caso é um pouco diferente do seu.

Voce tem que fazer algo mais ou menos assim [antes passe a responder via GET em vez de POST]:

click: function(){

    	                        var value = Ext.getCmp('empresaNomeFantasiaPesquisar').getValue();
			        var j = new Ext.Window({    
    				            title : "iframe",    
    				            width : 400,    
    				            height: 400,    
    				            layout : 'fit',    
    				            items : [
    				                    new Ext.Panel({  
    				                    	 autoWidth: true,   
    				                    	 autoHeigth: true,  
    				                    	 html:"&lt;iframe width=\"100%\" height=\"400\" src=\"/vianet/empresa/listarTdasEmpresas?element.nomeFantasia=\"+value+"&gt;&lt;/iframe&gt;"  
    				                    })  
    				          
							]    
    				        }).show();     

Dessa forma o seu relatorio será aberto dentro de um iframe que faz parte da window do Ext.

Isso, o que faço é assim também, via requisição ajax gero e salvo o relatório no servidor e retorno pro ajax uma flag de sucesso ou falha e o nome do relatório gerado, depois faço uma requisição get normal (não ajax) pra um iframe escondido que vai exibir o relatório para download.

No meu caso, tenho ainda uma opção visualizar em tela, ai é mais simples, só abrir uma requisição normal numa nova janela/aba que se o plugin do adobe tiver instalado já exibe o pdf.

Eu tentei fazer assim:

	Ext.Ajax.request({
    					method: 'POST', 
    					url: '/vianet/empresa/listarTdasEmpresas',
    					params: {
    						'element.nomeFantasia' : Ext.getCmp('empresaNomeFantasiaPesquisar').getValue()
    					},
    				    success: function(response, options) {    
    				           
    				           var value = Ext.getCmp('empresaNomeFantasiaPesquisar').getValue();  
    		                    var j = new Ext.Window({      
    		                                title : "iframe",      
    		                                width : 400,      
    		                                height: 400,      
    		                                layout : 'fit',      
    		                                items : [  
    		                                        new Ext.Panel({    
    		                                             autoWidth: true,     
    		                                             autoHeigth: true,    
    		                                             html:"&lt;iframe width=\"100%\" height=\"400\" src=\"/vianet/empresa/listarTdasEmpresas?element.nomeFantasia=\ "+value+"&gt;&lt;/iframe&gt;"    
    		                                        })    
    		                                
    		                            ]      
    		                            }).show();             
    				    },                      
    				    failure: function() {     
    				        Ext_example.msg('Erro:', 'Erro ao gerar o arquivo.', './images/cancel3.png');    
    				    },    
    				}); 

E oq acontece é:

abre o iframe vazio, não aparece nenhum erro no console do java e também não aparece erro algum no firebug …

[quote=EuclidesFilizola]Eu tentei fazer assim:

	Ext.Ajax.request({
    					method: 'POST', 
    					url: '/vianet/empresa/listarTdasEmpresas',
    					params: {
    						'element.nomeFantasia' : Ext.getCmp('empresaNomeFantasiaPesquisar').getValue()
    					},
    				    success: function(response, options) {    
    				           
    				           var value = Ext.getCmp('empresaNomeFantasiaPesquisar').getValue();  
    		                    var j = new Ext.Window({      
    		                                title : "iframe",      
    		                                width : 400,      
    		                                height: 400,      
    		                                layout : 'fit',      
    		                                items : [  
    		                                        new Ext.Panel({    
    		                                             autoWidth: true,     
    		                                             autoHeigth: true,    
    		                                             html:"&lt;iframe width=\"100%\" height=\"400\" src=\"/vianet/empresa/listarTdasEmpresas?element.nomeFantasia=\ "+value+"&gt;&lt;/iframe&gt;"    
    		                                        })    
    		                                
    		                            ]      
    		                            }).show();             
    				    },                      
    				    failure: function() {     
    				        Ext_example.msg('Erro:', 'Erro ao gerar o arquivo.', './images/cancel3.png');    
    				    },    
    				}); 

E oq acontece é:

abre o iframe vazio, não aparece nenhum erro no console do java e também não aparece erro algum no firebug …
[/quote]

Euclides, olha o código que postei antes, não tem mais essa chamada ajax, faça a resposta para GET em vez de POST e mande a url direta no src do iframe

Tentei fazer assim e continua vindo em branco.

'pesquisarEmpresa button[action=gerar_relatorio]': {
    			click: function(){
    				var value = Ext.getCmp('empresaNomeFantasiaPesquisar').getValue();  
    		        var j = new Ext.Window({      
    		        	method: 'GET',
    		        title : "iframe",      
    		        width : 400,      
    		        height: 400,      
    		        layout : 'fit',      
    		        items : [  
    		        new Ext.Panel({    
    		        autoWidth: true,     
    		        autoHeigth: true,    
    		        html:"&lt;iframe width=\"100%\" height=\"400\" src=\"/vianet/empresa/listarTdasEmpresas?element.nomeFantasia=\ "+value+"&gt;&lt;/iframe&gt;"    
    		        })    
    		        ]      
    		          
    		        }).show();
    				
    		        }
    		}

Quando você chiama a URL direttamente no browser o relatório em PDF é gerado?

Tentei :

http://localhost:8080/aplicacao/app/controller/administrativo/relatorio/relatorio.pdf

e realmente não acessa. Da erro 404. Porém o arquivo encontra-se em:

Webcontent/app/controller/administrativo/relatorio/relatorio.pdf. Porque não consigo acessa-lo ?

Então, eu não acho que a melhor maneira seja redirecionar para um PDF salvo em disco. Isso pode dar problema dependendo do volume de requisições.
Acho que o melhor é escrever o arquivo diretamente do response.
Da uma olhada nesse post:
http://www.avajava.com/tutorials/lessons/how-do-i-serve-up-a-pdf-from-a-servlet.html

Primeiro valide a geração do PDF, depois tente abrir com o ExtJS.

[]'s
Daniel

Beleza yorgan, vou verificar. Qualquer coisa que eu conseguir positivamente, eu posto. Agradeço a atenção… Vou ver como faço.

E aqui tem algumas dicas de como carregar o PDF com ExtJS:
http://www.sencha.com/forum/showthread.php?32504-PDF-file-in-Ext.Window

[]'s
Daniel

Precisando é só mandar DM =).
Coisa tá bem corrida, então estou com pouco tempo de acompanhar novos posts do Guj.

[]'s
Daniel

[quote=EuclidesFilizola]Tentei :

http://localhost:8080/aplicacao/app/controller/administrativo/relatorio/relatorio.pdf

e realmente não acessa. Da erro 404. Porém o arquivo encontra-se em:

Webcontent/app/controller/administrativo/relatorio/relatorio.pdf. Porque não consigo acessa-lo ?[/quote]

Euclides, a url do pdf tem que ser essa “/vianet/empresa/listarTdasEmpresas?”, acessando diretamente não funciona?