Retornar vários objetos por um método [Resolvido]

53 respostas
Guevara

Olá!
Estou tentando retornar várias fotos por um método do componente Imagens:

public File mostra(Long idImovel) {
		List<String> fotos = fotoDAO.getFotos(idImovel);
		for(String foto: fotos) {
		File destino = new File(pastaImagens, foto);
		}
		return destino; //este return 
	}

Pego a lista de url das fotos e crio vários Files, mas tá dando zica no “return”. Como posso retornar essas fotos para que sejam mostradas na JSP?
Abraço!

53 Respostas

G

Guevara, sugiro você dar uma lida muito boa no Java Collections, pois notei que você não conhece nada sobre elas, e é muito importante para o desenvolvimento você ter uma noção mínima sobre elas.

Nesse caso você precisará retornar no seu método uma lista de fotos, algo como:

public List<File> mostra(Long idImovel) { List<File> destinos= new LinkedList<File>(); List<String> fotos = fotoDAO.getFotos(idImovel); for(String foto: fotos) { File destino = new File(pastaImagens, foto); destinos.add(destino); } return destinos; //este return }

P

vc retorna uma List (arrayList) do objeto mesmo…

ex1

public List mostra(Long idImovel) {  
        List<String> fotos = fotoDAO.getFotos(idImovel);  
        List files = new ArrayList( fotos.size() );
        for(String foto: fotos) {  
           files.add(  new File(pastaImagens, foto) );  
        }  
        return files; //este return   
}
Lucas_Cavalcanti

vc não vai conseguir mostrar as fotos usando o new File(…) pois ele retorna o caminho da foto no servidor, e isso não adianta pra mostrar na página…

se vc salvou as imagens dentro de uma pasta da sua aplicação (usou context.getRealPath, ou coisas do tipo), vc pode retornar esse caminho, e com ele vc consegue mostrar a imagem…

se vc salvou em uma pasta fora da aplicação, ou dentro da pasta WEB-INF vc vai ter que criar uma lógica pra mostrar cada imagens…

Guevara

Estou fazendo um teste aqui pra mostrar o nome e a url salva no banco, mas não está mostrando nada:

<fieldset>
<legend>Galeria</legend>        
<c:forEach var="foto" items="${foto}"> 
<p>${foto.nome }</p>
<p>${foto.urlFoto }</p>
</c:forEach> 
</fieldset>

Estou enviando o nome e url pelo Controller assim:

public void adiciona(Long idImovel) {
		 result.include("imovel", imovelDAO.carregaId(idImovel));
		 result.include("foto", fotoDAO.getGaleria(idImovel));
	 }

E na classe FotoDAO está assim:

@SuppressWarnings("unchecked")
	public List<Foto> getGaleria(Long idImovel) {
		return session.createCriteria(Foto.class, "f")
		.setProjection(Projections.projectionList()
				.add( Projections.property("f.nome").as("nome") )
				.add( Projections.property("f.urlFoto").as("urlFoto") )
				).setResultTransformer(new AliasToBeanResultTransformer(Foto.class))
				.add(Restrictions.idEq(idImovel)).list();
	}

Tinha que printar na tela esses dados não? O.o
Abraço!!!

Lucas_Cavalcanti

a busca tá retornando algum resultado? não tá imprimindo nada na tela?

Guevara

Oi Lucas!
Está fazendo a consulta mas não mostra nada na JSP:

01:07:21,458 DEBUG [OgnlParametersProvider] Applying idImovel with [42]
01:07:21,471 DEBUG [ParanamerNameProvider] Found parameter names with paranamer for FotoController.adiciona(Long) as [idImovel]
01:07:21,471 DEBUG [ParametersInstantiatorInterceptor] Parameter values for [DefaultResourceMethod: FotoController.adicionaFotoController.adiciona(Long)] are [42]
01:07:21,498 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor ExecuteMethodInterceptor
01:07:21,498 DEBUG [ExecuteMethodInterceptor] Invoking FotoController.adiciona(Long)
Hibernate: 
    select
        this_.id_imovel as y0_ 
    from
        Imovel this_
Hibernate: 
    select
        this_.nome as y0_,
        this_.url_foto as y1_ 
    from
        Foto this_ 
    where
        this_.id_foto = ?
01:07:21,515 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor OutjectResult
01:07:21,521 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor ForwardToDefaultViewInterceptor
01:07:21,521 DEBUG [ForwardToDefaultViewInterceptor] forwarding to the dafault page for this logic
01:07:21,530 DEBUG [DefaultPageResult   ] forwarding to /WEB-INF/jsp/foto/adiciona.jsp
01:07:21,531 DEBUG [DefaultStaticContentHandler] Deferring request to container: /imobiliaria/WEB-INF/jsp/foto/adiciona.jsp 
01:07:23,592 DEBUG [VRaptor             ] VRaptor ended the request
Lucas_Cavalcanti

tudo bem que esteja fazendo a consulta, mas está retornando resultados na consulta?

Guevara

Pois é Lucas, colocando o breakpoint no result.include e no return do método getGaleria() na DAO só me dá este resultado:

Navegando pela árvore não consigo achar nada do objeto Foto. =/

Guevara
Alterei a consulta:
@SuppressWarnings("unchecked")
	public List<Foto> getFoto(Long idImovel) {
		return session.createQuery("select f.urlFoto, f.nome from Foto f where f.imovel.id = :id")  
        .setParameter("id", idImovel).list();
	}
Hibernate: 
    select
        this_.id_imovel as y0_ 
    from
        Imovel this_
Hibernate: 
    select
        foto0_.url_foto as col_0_0_,
        foto0_.nome as col_1_0_ 
    from
        Foto foto0_ 
    where
        foto0_.imovel_id_imovel=?
Acho que agora está certo ----> foto0_.imovel_id_imovel=? Tá dando pau na JSP:
<fieldset>
	 <legend>Galeria</legend>        
<c:forEach var="foto" items="${foto}"> 
<li>${foto.nome }</li>
<li>${foto.urlFoto }</li>
</c:forEach> 
</fieldset>
O erro é:
root cause
java.lang.NumberFormatException: For input string: "nome"
java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
	java.lang.Integer.parseInt(Integer.java:449)
	java.lang.Integer.parseInt(Integer.java:499)
	javax.el.ArrayELResolver.coerce(ArrayELResolver.java:161)
	javax.el.ArrayELResolver.getValue(ArrayELResolver.java:45)
	javax.el.CompositeELResolver.getValue(CompositeELResolver.java:54)
	org.apache.el.parser.AstValue.getValue(AstValue.java:123)
	org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:186)
	org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:935)
	org.apache.jsp.WEB_002dINF.jsp.foto.adiciona_jsp._jspx_meth_c_005fforEach_005f1(adiciona_jsp.java:313)
	org.apache.jsp.WEB_002dINF.jsp.foto.adiciona_jsp._jspService(adiciona_jsp.java:147)
No Controller:
result.include("foto", fotoDAO.getFoto(idImovel));
G

Note isso aqui:

Seu erro é no JSP. Como está o seu forEach nesse JSP? Conforme a mensagem do erro note que ele tenta transformar a String nome em Integer.

Guevara

Oi Garcia!
Na jsp está assim:

<fieldset>
	 <legend>Galeria</legend>     
	 	<table>
    		<tr>    
    			<td>Nome</td>
    			<th>url</th>    
     		</tr>  
		<c:forEach var="foto" items="${foto}"> 
 			<tr>  
				<td>${foto.nome }</td>
				<td>${foto.urlFoto }</td>
			</tr>
		</c:forEach> 
		</table>
</fieldset>

Eu reparei que ele está querendo converter, mas isso é impossível, não têm nada pra converter, a coluna “nome” é varchar no banco.

Mesmo problema rodando esta consulta:

@SuppressWarnings("unchecked")
	public List<Foto> getGaleria(Long idImovel) {
		return session.createSQLQuery("select nome, url_foto from Foto where imovel_id_imovel = :id")
		.setParameter("id", idImovel).list();
G
Você itera em uma variável reassociando com ela mesma? Outra coisa, o retorno do Vraptor não seria fotoList quando o retorno do método é List<Foto>?

Você itera em uma variável reassociando com ela mesma? Outra coisa, o retorno do Vraptor não seria fotoList quando o retorno do método é List?

Guevara

Pois é Garcia, eu tô fazendo por analogia, se funciona em outra página têm que funcionar em outra, tenho outro método para Imóvel que funciona, e agora não. Exemplo:

<c:forEach var="imovel" items="${imovel}">
    <tr>    	 
        <td>${imovel.codImovel }</td>
        <td>${imovel.titulo }</td>        
        <td>${imovel.bairro }</td>
		<td>${imovel.valor }</td>  
    </tr>
</c:forEach>

Isto funciona.

Mas isto não funciona:

<fieldset>
  <table>
    	<tr>    
    		<td>Nome</td>
    		<td>url</td>
    	</tr>      
		<tr> 
	<c:forEach var="foto" items="${foto}">  
		<tr>
    		<td>${foto.nome}</td>  
    		<td>${foto.urlFoto}</td>  
	</c:forEach> 
	   </tr>
 </table>
</fieldset>

Não consigo entender essas frescuras, que não sei se é por causa da consulta ou se é por causa da jstl, no primeiro caso a consulta é na tabela imóvel, o segundo caso é na tabela filha Foto. Fazer consultas nessas tabelas está sendo um parto com Criteria e Query.

Guevara
@SuppressWarnings("unchecked")
	public List<Foto> getGaleria(Long idImovel) {
		
		return session.createSQLQuery("select nome, url_foto from Foto where imovel_id_imovel = :id")
		.setParameter("id", idImovel).list();
Hibernate: 
    select
        nome,
        url_foto 
    from
        Foto 
    where
        imovel_id_imovel = ?
public void adiciona(Long idImovel) {
		 result.include("imovel", imovelDAO.carregaId(idImovel));
		 result.include("fotos", fotoDAO.getGaleria(idImovel));
	 }
<c:forEach var="fotos" items="${fotoList}">  
		<tr>
    		<td>${fotos.nome}</td>  
    		<td>${fotos.urlFoto}</td>  
	</c:forEach>

Resultado:

G

Pois é, ontem eu estava lendo uns tópicos antigos e notei que você está tendo muitos problemas que eu ainda não tinha visto. Pense positivo: você é um “bugs-finder”, hahahahaha.

Brincadeiras a parte, embora eu não use os objetos como retorno dos métodos do controller posso jurar que quando você usa assim o vraptor retorna como nome-do-objeto + List (no seu caso seria fotoList). Talvez na sua outra tela você retorne via results.include, não?

E até por questão de legibilidade, quando você tem mais de uma foto é normal usar ou plural ou um sufixo List, assim você se organiza melhor e evita pequenos erros bobos.

G

Guevara, me permita te dar um puxão de orelha :oops: ? Vocẽ precisa ler um pouco as APIs antes de usá-la. Olhe bem seu exemplo:

No controller

E no JSP

Ou seja, você exporta as suas fotos como fotos, então você deve fazer algo como:

Ou seja, VAR é o nome que o objeto receberá a cada iteração, e fotos é sua coleção de objetos. Traduzindo em Java seria como isso aqui:

Guevara

:smiley: Tô penando aqui pra resolver esses “bugs”. Eu vejo o pessoal do RubyOnRails e Python desenvolvendo coisas como essas sem problemas, enquanto no Java td é mais burocrático, embora o VRaptor dê a agilidade a própria linguagem não dá. Se tiver dois casos iguais, um vai dar certo e outro não, e nessa brincadeira o tempo vai embora e não se produz nada.
Nesse meu último post coloquei como vc sugeriu, e veja que não mostra nada na JSP, detalhe, nem erros aparecem no console, é ai que na minha opinião o desenvolvimento em Java fica no chinelo em comparação com as outras linguagens que citei.
Se existem dois casos iguais, os dois obrigatóriamente devem dar o mesmo resultado. Nos dois retorna a lista de objetos, nos dois a lista é enviada via result.include, e óbviamente vou pegar na JSP da mesma forma, mas não, um funciona e o outro não. =/

Guevara

Pois é Garcia, eu estava fazendo certo, e como não funciona fui tentando adivinhar o que ele quer, se eu colocar desse jeito olha o resultado:

result.include("fotos", fotoDAO.getGaleria(idImovel));
<c:forEach var="foto" items="${fotos}">  
		<tr>
    		<td>${foto.nome}</td>  
    		<td>${foto.urlFoto}</td>  
	</c:forEach>
java.lang.NumberFormatException: For input string: "nome"
	java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
	java.lang.Integer.parseInt(Integer.java:449)
	java.lang.Integer.parseInt(Integer.java:499)

Voltamos ao mesmo problema de alguns posts atrás, ele tenta converter o que é uma String/Varchar para Integer.
Vê se isso têm explicação… =/

G

O problema é que muitas linguagens o programador pode ir na base do chutômetro, ou como eu digo, na base da tentativa e erro. No Java não é que tudo é mais complicado, só é necessário que o programador leia o mínimo que seja para aprender a usar a API. Boa parte dos erros que eu notei que você teve é por não conhecer a API. Então acho que é um pouco cedo para você dizer que Java é complicado, afinal você ainda não conhece Java o suficiente para ter uma produtividade.

Trabalho há ~13 anos com Java, e conheço muito pouco de RoR e Python, então não posso mesmo fazer uma comparação. Mas creio que, como eu te disse, quando você conhecer um pouco melhor a API vai ver como Java é bem simples.

Teus códigos me pareceram diferentes. Um deles usa o retorno no próprio método do controller, já o outro usa via results.include.

Altere esses seus forEachs para não dar conflito de variáveis conforme eu já escrevi acima e também verifique os retornos dos controllers, passe tudo via results.include. Além disso verifiquei se você está passando os tipos corretos e não há mais de uma variável com o mesmo nome.

Fora isso eu não sei mais com ajudar.

Lucas_Cavalcanti

isso:

<c:forEach var="imovel" items="${imovel}">

não é certo…

items tem que ser uma lista, e o var é a variável que vc chama cada elemento da lista…

o código está funcionando por coincidência…

se vc deu um result.include(“fotos”, …), vc tem que acessar no jsp via ${fotos}, e colocar isso na parte items:

<c:forEach var="foto" items="${fotos}">    
         <tr>  
             <td>${foto.nome}</td>    
             <td>${foto.urlFoto}</td>
        </tr>
     </c:forEach>
Guevara

Agradeço aos dois pela ajuda. :smiley:
Sabem me dizer como carrego um objeto pela FK neste exemplo?

public Foto carrega(Long idImovel) {
		    return (Foto) this.session.load(Foto.class, idImovel);
	 }

No exemplo o id é do imóvel que é a FK de foto e não a PK.
Tô dando ctrl+space pra descobrir qual seria o parâmetro pra isso mas não consegui descobrir.

Lucas_Cavalcanti
session.createQuery("from Foto f where f.idImovel = :id")
   .setParameter("id", idImovel)
   .uniqueResult();
Guevara

Obrigado Lucas. =)
Vou ver o que consigo aqui.

Guevara

Consegui pegar os endereços e jogar na JSP, mas aconteceu o que eu imaginava, tá pegando o caminho como se fosse dentro do contexto da aplicação, quando na verdade está fora:
Tá mostrando assim:

http://localhost:8080/imobiliaria/home/bruno/fotos/42.xx.252(1).jpg

O código na JSP que usei foi este:

<img src="${pageContext.request.contextPath}/home/bruno/fotos/${foto.urlFoto }"/>

Alguém conhece alguma EL ou taglib que consiga acessar o contexto externo?
Tõ pesquisando por “external context path”.
Abraço!

Lucas_Cavalcanti
<img src="<c:url value="/home/bruno/fotos/${foto.urlFoto }"/>" />
Guevara

Oi Lucas!
Não deu certo, ele continua pegando como se fosse dentro do contexto da aplicação:

http://localhost:8080/imobiliaria/home/bruno/fotos/42.xx.252(1).jpg

Será que rola criar um contexto apontando para a pasta dentro de algum xml? Algo como:

<Context path="/home/bruno/fotos" docBase="/home/bruno/fotos"
//alguma coisa aqui que não faço idéia.
</Context>
Lucas_Cavalcanti

vc quer que vá pra uma pasta física dentro do seu computador?

você não deveria fazer isso nunca na vida… imagina se eu chamar: http://localhost:8080/imobiliaria/etc/passwd
eu veria seus passwords!

se vc quiser fazer essa correspondência, crie uma lógica do tipo:

@Path("/imagens/{caminho*}")
public InputStream imagem(String caminho) {
    try {
        return new FileInputStream("/home/bruno/fotos/" + caminho);
    } catch (FileNotFoundException e) {
         result.notFound();
         return null;
    }
}

daí vc só acessa http://localhost:8080/imobiliaria/imagens/42.xx.252(1).jpg e ele mapeia para a pasta física

(claro que vc vai mudar o código que eu passei, pra ele ficar mais configurável e tal, isso eh soh um exemplo)

Guevara

Beleza Lucas!
Vou tentar aqui com essa lógica.
Eu tentei aqui com:

<img src="<c:url value="file:///home/bruno/fotos/${foto.urlFoto }"/>" />

Na JSP não mostra a imagem, mas se eu pegar o endereço file:///home/bruno/fotos/42.xx.252(1).jpg que aparece num pequeno retângulo onde deveria aparecer a imagem e jogar no browser a imagem aparece. Essa tática de usar o endereço físico file:/// tb é furada?
Abraço!

Guevara

Na JSP não mostra a imagem mas o caminho mostra corretamente:

http://localhost:8080/imobiliaria/imagem/42.xx.252(1).jpg

No Controller:

@Get
	 @Path("/imagem/")
	 public InputStream getPasta() {		 
	    return imagens.getPasta(); 
	 }

	 public void adiciona(Long idImovel) {
		 result.include("imovel", imovelDAO.carrega(idImovel));	
		 result.include("fotos", fotoDAO.getGaleria(idImovel));	// aqui eu mando o nome completo da foto
	 }

No Componente Imagens:

public InputStream getPasta() {		 
		 try {
	         return new FileInputStream(pastaImagens);
	     } catch (java.io.FileNotFoundException e) {
	          return null;
	     }	
	 }

Mas não está instanciando o método InputStream, coloquei um breakpoint nos retornos de cada método mas passa batido.
Se o método funcionar acredito que a imagem apareça na JSP. =)

Lucas_Cavalcanti

não use file://

faça o controller exatamente do jeito que eu coloquei na minha última mensagem…

Guevara

Então Lucas, o método está retornando null, colocando no componente ou no controller:

public InputStream getPasta() {		 
		 try {
	         return new FileInputStream(pastaImagens);
	     } catch (FileNotFoundException e) {
	          return null;
	     }	
	 }

Retorna null no debug.
Eu tô colocando no componente pq lá já tenho o caminho:

public Imagens() {			  		 
		String pastaImagens = "/home/bruno/fotos";
		this.pastaImagens = new File(pastaImagens);   
		File destino = new File(pastaImagens);
		destino.mkdir();
	}

No Controller:

@Get
	 @Path("/imagem/")
	 public InputStream imagem() {
			 return imagens.getPasta();
	 }

Mesmo colocando o código todo no controller retorna null, não está criando a pasta.

Lucas_Cavalcanti

a idéia da lógica do controller NÃO é retornar a pasta…

é retornar a imagem direto! vc não pode retornar uma pasta como inputStream!!! nem faz sentido…

o que vc tem que fazer no controller é o que eu falei pra vc fazer naquela mensagem:

@Get  
 @Path("/imagem/{caminho*}")  
 public InputStream imagem(String caminho) {  
    try {
       return new FileInputStream(new File(caminho, imagens.getPasta()));  
    } catch (FileNotFoundException e) {
        result.notFound();
        return null;
    }
 }

quanto a não criar a pasta, vc deu uma olhada no sistema pra ver se ela existe mesmo? vc tem permissão pra criar essa pasta, a partir da sua app?

Guevara

Oi Lucas!
A pasta está liberada para incluir e deletar fotos, eu segui a sua lógica, mas o problema é que preciso passar a ID do imóvel para que sejam carregadas as fotos daquele imóvel, não dá pra colocar apenas uma String caminho, preciso da ID do imóvel, então fiz assim:
No componente:

public InputStream getPasta(Long idImovel) {
		FileInputStream destino = null;
		FotoDAO fotoDAO = new FotoDAO();
		List<Foto> fotos = fotoDAO.getGaleria(idImovel);
		for (Foto foto : fotos) {
			try {
				destino = new FileInputStream(new File(pastaImagens, foto.getUrlFoto()));
			} catch (java.io.FileNotFoundException e) {
				e.printStackTrace();
			}

		}
		return destino;
	}

Coloquei um breakpoint pra saber se o return tá mandando alguma coisa:

E no controller eu envio esse InputStream via result.include quando a página adiciona.jsp é chamada:

public void adiciona(Long idImovel) {
		 result.include("imovel", imovelDAO.carrega(idImovel));	
		 result.include("fotos", imagens.getPasta(idImovel));		 
	 }

Agora o que eu não consegui achar é como mostrar isso na JSP.

Lucas_Cavalcanti

vc não vai conseguir mostrar o inputStream via variável… vc precisa criar uma lógica que retorna esse inputStream mesmo, e na jsp vc chama essa lógica dentro de uma tag img, por exemplo:

<img src="/imagem/${imovel.id}" alt="imovel.nome"/>

e a lógica que responde por /imagem/{imovel.id} vai retornar o InputStream…

Guevara

Fiz uns testes aqui e constatei que só o result.include consegue trazer os dados das fotos, se eu colocar o método no Controller vêm td null.

@Path("/imagem/{imovel.idImovel}/")
	public InputStream imagem(Long idImovel) {
FileInputStream destino = null;
		FotoDAO fotoDAO = new FotoDAO();
		List<Foto> fotos = fotoDAO.getGaleria(idImovel);
		for (Foto foto : fotos) {
			try {
				destino = new FileInputStream(new File("/home/bruno/fotos", foto.getUrlFoto()));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}

		}
		return destino;
	}

Lucas_Cavalcanti

se vc tem um parâmetro Long idImovel, o parâmetro no @Path tem que se chamar idImovel

@Path("/imagem/{idImovel}/")

e se vc tem várias imagens por imóvel, vc precisa pegar pelo id da Foto, não pelo id do imóvel…

@Path("/imagem/{idFoto}")
	public InputStream imagem(Long idFoto) {
		FotoDAO fotoDAO = new FotoDAO();// vc não deveria fazer isso aqui! receba no construtor!
		Foto foto = fotoDAO.carrega(idFoto);
		
		try {
			return new FileInputStream(new File("/home/bruno/fotos", foto.getUrlFoto()));
		} catch (FileNotFoundException e) {
			result.notFound(); // receba esse result no construtor tb
			return null;
		}
	}

e na listagem do imóvel vc vai criar as <img baseado no id de cada foto do imóvel

G

Não entendo uma coisa... você faz um loop em várias fotos mas retorna apenas o stream da última? Analise o seu loop e veja que você retorna o stream apenas da última. Além disso você não deveria retornar um stream para o JSP, e sim retornar um FileDownloadStream no seu método.

Outra coisa, não esconda as exceptions, isso é muito perigoso. Se algum erro acontecer você nunca saberá. Apenas faça um catch se você quer tratar a exception.

Segue um exemplo meu usando os componentes de download do vraptor. No meu caso esse código é de uma ferramenta de geoprocessamento que a partir de uma coordenada geografica traz o mapa do local.

@Path("/l10n/map/{coordX}/{coordY}/")
    public Download map(double coordX, double coordY)
        throws IOException {
        FilePNG png = gisRemote.find(coordX, coordY);

        return new InputStreamDownload(file.getStream(), "image/png", file.getName());
    }
Lucas_Cavalcanti

se vc retorna um InputStream o vraptor transforma em download automaticamente

G

Hmm, achei que era apenas <? implements Download> (nos docs não diz isso). Mas faz sentido já que o File também faz download.

Lucas_Cavalcanti

http://vraptor.caelum.com.br/documentacao/downloading/

na apostila tb fala isso, citando o InputStream, com mais detalhes…

G

Lucas Cavalcanti:
http://vraptor.caelum.com.br/documentacao/downloading/

na apostila tb fala isso, citando o InputStream, com mais detalhes…

No link do site tem apenas File e FileDownload :smiley:

Ps: nunca ví um PDF tão bonito como os da Caelum. Simplesmente fantástico.

Guevara

A dica do Lucas que eu não entendi. =/
Não posso pegar as fotos do Imovel pela id foto, só posso pegar pela id de imovel, por isso coloquei {imovel.idImovel}, se eu colocar {idImovel} não aparece nada na JSP.
Garcia, tentei com a classe Download (que eu não sabia que existia) e não deu certo, eu vi que vc manda as coordenadas por parâmetro, faz a busca e depois retorna os dados, estou seguindo a mesma lógica, mando o id do imóvel por parâmetro, itero essa listagem criando um FileInputStream e retorno esses files:

@Get
	@Path("/imagem/{idImovel}/") // idImovel nem aparece na JSP
	public Download imagem(Long idImovel) throws IOException {
		FileInputStream destino = null; // inicializo a variavel destino
		List<Foto> fotos = fotoDAO.getGaleria(idImovel); // Pego todas as fotos do DAO e aarmazeno na variavel "fotos". 
		List<FileInputStream> destinos = new LinkedList<FileInputStream>(); // crio uma variavel para armazenar a List de objetos
		for (Foto foto : fotos) {
			try {
				destino = new FileInputStream(new File("/home/bruno/fotos", foto.getUrlFoto())); // crio um file "destino"
				destinos.add(destino); // adiciono os "files" na lista
			} catch (FileNotFoundException e) {
				//result.notFound(); Aqui o Eclipse manda fazer Cast, ele coloca um (Object) antes de destinos e em seguida manda remover o Cast, o Result  está injetado no construtor.
				return null;
			}

		}
		return (Download) destinos; // retorno os objetos na lista, o Eclipse mandou fazer o cast para Download.	
	}

Resultado disso na JSP:

http://localhost:8080/imobiliaria/imagem//
G

Você quer devolver uma ou muitas fotos? O componente de Download é para apenas UM arquivo.

O que o Lucas quer dizer é se você tem muitas fotos para um imóvel, você precisa passar é o ID da foto, e não do imóvel. Olhe no meu post que eu comentei sobre você fazer esse loop nas fotos e retornaer sempre a ultima foto.

Guevara

Quero retornar várias fotos de um imóvel para mostrar na JSP, mas se eu envio apenas a id do imóvel como parâmetro, como iria buscar as fotos do imóvel pela id da Foto? Tenho duas tabelas, uma imóvel e outra Foto, é na tabela Foto que armazeno a id do imóvel como FK, estou usando a FK para pegar todas as fotos na classe FotoDAO.

@SuppressWarnings("unchecked")
	public List<Foto> getGaleria(Long idImovel) {		
	    return session.createQuery("from Foto f where f.imovel.id = :id")
		   .setParameter("id", idImovel)
		   .list();
}
G

Guevara, suas dúvidas vão além do Vraptor, na verdade isso é uma dúvida simples de HTML. Você NUNCA vai conseguir imprimir uma lista de imagens da forma que você quer fazer, em nenhuma linguagem, seja Java ou Ruby (isso é uma limitação do HTML mesmo).

Não existe como você mandar imprimir o stream direto no HTML da página. Você precisa criar uma imagem com a tag e no campo SRC (source) apontar para uma action do vraptor que irá montar a foto retornando para o browser um array de bytes com o cabeçalho image/(png ou gif ou jpg).

Como minhas aplicações todas usam cluster eu gravo todas as imagens no banco de dados. Então o que eu faço é quando monto a tela que tem as fotos eu retorno para a tela a lista de ids de fotos, entendeu? De posse desses IDs eu chamo as imagens via , onde 15 é o ID da foto. Simples até aqui.

Depois eu faço um método no vraptor que a partir do ID da foto ele retorne a foto em sí, conforme o exemplo que eu te passei há alguns posts atrás.

Não sei se fui bem claro. Mas o rumo é esse.

Lucas_Cavalcanti

vc tem o id do imóvel, certo?

com o id do imóvel vc consegue pegar várias fotos, certo?

cada foto dessa tem um id, certo?

vc consegue buscar uma foto pelo id e retornar o inputStream dela, certo? (o código que eu mandei)

basta no seu jsp, vc receber a lista de fotos do imóvel (result.include(“fotos”, fotosDoImovel)), e fazer um foreach nessas fotos, usando pra mostrar cada foto (dentro do c:forEach…)

mas vc vai precisar da lógica que eu te mandei

Guevara

Isso, pego assim:

@SuppressWarnings("unchecked")
	public List<Foto> getGaleria(Long idImovel) {		
	    return session.createQuery("from Foto f where f.imovel.id = :id")
		   .setParameter("id", idImovel)
		   .list();
}

Isso, mas só poderia pegar a foto por um id foto se eu mandasse por parâmetro um id foto, só que a unica id que é usada é a do imóvel, fiz aqui no componente Imagens:

public InputStream getPasta(Long idImovel) { //mandando id do imovel para pegar as fotos no metodo getGaleria()
FotoDAO fotoDAO = new FotoDAO(); // O método não funciona injetando o DAO no construtor, por isso instanciei aqui.
		List<Foto> fotos = fotoDAO.getGaleria(idImovel);
		for (Foto foto : fotos) {
		try {
			return new FileInputStream(new File("/home/bruno/fotos", foto.getUrlFoto()));
		} catch (FileNotFoundException e) {
			return null;
		}
		}
		return null;
	}

Fiz aqui:

public void adiciona(Long idImovel) {
		 result.include("imovel", imovelDAO.carrega(idImovel));	
		  result.include("fotos", fotoDAO.getGaleria(idImovel));	// mandando url das fotos	 
	 }
<c:forEach var="foto" items="${fotos}">
    <ul>
        <li>
           <a href="<c:url value="/imagem/${imovel.idImovel }/${foto.urlFoto}"/>"/>
             
                      
            <img src="<c:url value="/imagem/${imovel.idImovel }/${foto.urlFoto }"/>" />                     	                        	 
            
            </a>
        </li>
   </ul>
</c:forEach>

Resultado:

=/

Lucas_Cavalcanti

faça no jsp:

<ul>
   <c:forEach var="foto" items="${fotos}">

        <li>
           <img src="<c:url value="/imagem/${foto.id }"/>" />
        </li>

    </c:forEach>
   </ul>

no controller (outro método):

@Path("/imagem/{idFoto}")
public InputStream mostraFoto(Long idFoto) throws FileNotFoundException {
     FotoDAO fotoDAO = new FotoDAO(); // pra injetar no construtor é  anotar o dao com @Component
     Foto foto = fotoDAO.carrega(idFoto); 
     return new FileInputStream(new File("/home/bruno/fotos", foto.getUrlFoto()));
}

entendeu agora?

Guevara

Deu certo!!! \o/

Coloquei o LightBox junto. =)
A única coisa que precisei fazer foi um método “carrega” na DAO, isso eu não tinha.
Ainda não consegui entender como ele está instânciando um FileInputStream de um determinado imóvel sem ter a id do imóvel sendo passada por parâmetro. O.o
Será pelo motivo de já ter um objeto imóvel carregado na página?
Obrigado pelo ajuda Lucas e Garcia, principalmente pela paciência, sem a ajuda de vcs não teria conseguido.
Abraço!

Lucas_Cavalcanti

vc não tá carregando o FileInputStream do Imóvel, e sim da Foto do imóvel… e ele tá carregando pq vc tah passando o id da foto

dá uma lida na apostila do FJ-11 da caelum pra saber direito o que eh um InputStream…

G

Eu compro o mercedão!!! :twisted:

Guevara

Eu sei que é InputStream da Foto, o que eu não entendi é como ele sabe que aquelas fotos são do imóvel correto já que não é passada a id do imóvel.
Como essa parte de InputStream eu sou leigo ainda, vou dar uma lida na apostila pra entender como essa mágica aconteceu.

Garcia, esses ônibus rodam até hj no meu bairro, fica em Buenos Aires - Argentina. :lol:
Os motoristas cuidam desses ônibus como se fossem seus filhos.

Lucas_Cavalcanti

ele sabe que as fotos são do imóvel, pq vc iterou pelas fotos do imóvel, usando os ids delas…

Criado 7 de maio de 2010
Ultima resposta 20 de mai. de 2010
Respostas 53
Participantes 4