JSTL + Hibernate, Problemas para exibir resultados (resolvido)

Oi gente, partindo de um post anterior meu feito aqui
http://www.guj.com.br/java/228724-listar-varios-registros-usando-hibernate-com-anotacoes

exibi meus resultados usando hibernate com anotações

consegui exibir corretamente os resultados, porém gostaria de exibi-los agora usando JSTL, ai vai o codigo que eu usava antes e funciona:

<%-- 
    Document   : listarAlunosWeb
    Created on : 29/12/2010, 11:49:37
    Author     : estinfo
--%>

<%@page import="br.com.salesianos.Pessoa_completo"%>
<%@page import="br.com.salesianos.Pessoa"%>
<%@page contentType="text/html" pageEncoding="UTF-8"
import="java.sql.*"
import="java.util.Date"
import="java.text.SimpleDateFormat"
import="java.util.ArrayList"
import="java.util.Iterator"
import="java.util.List"
import="java.util.Set"
import="javax.swing.*"
import="org.hibernate.*"
import="org.hibernate.cfg.*"

%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>

    </head>
    <body>
        
<%
            try
            {
            AnnotationConfiguration cfg = new AnnotationConfiguration();
            cfg.addAnnotatedClass(Pessoa.class);

            SessionFactory fabrica = cfg.buildSessionFactory();
            Session sessao = fabrica.openSession();


            List<Pessoa> lista_pessoa = new ArrayList();
            lista_pessoa = sessao.createCriteria(Pessoa.class).list();
            int tamanho_lista = lista_pessoa.size();
            

            out.println("<table border='1'>");
            for(int i=0;i<tamanho_lista;i++)
            {
                Pessoa pessoa = lista_pessoa.get(i);
                {%>            
                    <tr>
                        <td><% out.println(pessoa.getNome()); %></td>
                        <td><% out.println(pessoa.getCidade()); %></td>
                    </tr>            
                <%}
            }
            out.println("</table>");

            
            sessao.clear();
        }
        catch(Exception erro)
        {
            out.println("Erro na Lista: "+erro);
        }
%>
    </body>
</html>

este é o codigo que estou usando agora para exibir os resultados usando JSTL e hibernate com anotações

<%-- 
    Document   : listarAlunosWeb
    Created on : 29/12/2010, 11:49:37
    Author     : estinfo
--%>

<%@page import="br.com.salesianos.Pessoa_completo"%>
<%@page import="br.com.salesianos.Pessoa"%>
<%@page contentType="text/html" pageEncoding="UTF-8"
import="java.sql.*"
import="java.util.Date"
import="java.text.SimpleDateFormat"
import="java.util.ArrayList"
import="java.util.Iterator"
import="java.util.List"
import="java.util.Set"
import="javax.swing.*"
import="org.hibernate.*"
import="org.hibernate.cfg.*"

%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>

    </head>
    <body>
        
    <jsp:useBean id="pessoas" class="br.com.salesianos.Pessoa" />
    <c:forEach var="pessoas" items="${pessoas}">
        ${pessoas.nome}, ${pessoas.fone}, ${pessoas.cidade},
    </c:forEach>

</html>

e este codigo simplesmente nao lista os resultados, o que eu estou esquecendo,

nunca havia utilizado JSTL antes com hibernate

ai esta minha classe Pessoa.java que foi mapeada com anotações,

package br.com.salesianos;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;

import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.IndexColumn;
import org.hibernate.annotations.MapKey;

@Entity
@Table(name="pessoas")
public class Pessoa implements Serializable
{
    
    @Id
    @SequenceGenerator(name="generator_pessoa",sequenceName="sequencia_pessoa")
    @GeneratedValue(generator="generator_pessoa")
    @Column(name="idPessoa")
    private Integer id;
    @Column(name="nome_pessoa",length=40, nullable=false)
    private String nome;
    @Column
    private String fone;
    @Column
    private String cidade;
    @Column(name="valor_salario", precision=2)
    private double salario;
    @Temporal(TemporalType.DATE)
    private Date DataCadastro;
    @Temporal(TemporalType.DATE)
    private Date DataNascimento;

     
   
    public Integer getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
     * @return the nome
     */
    public String getNome() {
        return nome;
    }

    /**
     * @param nome the nome to set
     */
    public void setNome(String nome) {
        this.nome = nome;
    }

    /**
     * @return the fone
     */
    public String getFone() {
        return fone;
    }

    /**
     * @param fone the fone to set
     */
    public void setFone(String fone) {
        this.fone = fone;
    }

    /**
     * @return the cidade
     */
    public String getCidade() {
        return cidade;
    }

    /**
     * @param cidade the cidade to set
     */
    public void setCidade(String cidade) {
        this.cidade = cidade;
    }

    /**
     * @return the salario
     */
    public double getSalario() {
        return salario;
    }

    /**
     * @param salario the salario to set
     */
    public void setSalario(double salario) {
        this.salario = salario;
    }

    /**
     * @return the DataCadastro
     */
    public Date getDataCadastro() {
        return DataCadastro;
    }

    /**
     * @param DataCadastro the DataCadastro to set
     */
    public void setDataCadastro(Date DataCadastro) {
        this.DataCadastro = DataCadastro;
    }

    /**
     * @return the DataNascimento
     */
    public Date getDataNascimento() {
        return DataNascimento;
    }

    /**
     * @param DataNascimento the DataNascimento to set
     */
    public void setDataNascimento(Date DataNascimento) {
        this.DataNascimento = DataNascimento;
    }

    /**
     * @return the telefones_pessoa
     */    
}

Analisando seu codigo reparei que você esta passando uma instancia de pessoa para o forEach realizar a iteração, isso é errado pois ele espera uma coleção para navegar nos dados.

Você precisa buscar as informações no banco de dados e passar o resultado para o forEach, faça uma servlet que para recuperar a informação do banco de dados, jogue o resultado como um atributo do request e faça um dispatcher para a jsp.

Até mais.

O foreach é capaz de interagir APENAS com coleções? quais coleções ele aceita, pode-se usar List, Set, Map, Bag?
eu criei um servlet para buscar os resultados, mas ele mesmo ja está exibindo os resultados, eu devo retornar a variavel ‘lista_pessoa’ para que o foreach consiga buscar o resultado?

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.com.salesianos;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

/**
 *
 * @author estinfo
 */
public class BuscaResultado extends HttpServlet {
   
    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            
            AnnotationConfiguration cfg = new AnnotationConfiguration();
            cfg.addAnnotatedClass(Pessoa.class);

            SessionFactory fabrica = cfg.buildSessionFactory();
            Session sessao = fabrica.openSession();


            List<Pessoa> lista_pessoa = new ArrayList();
            lista_pessoa = sessao.createCriteria(Pessoa.class).list();
            int tamanho_lista = lista_pessoa.size();


            out.println("<table border='1'>");
            for(int i=0;i<tamanho_lista;i++)
            {
                Pessoa pessoa = lista_pessoa.get(i);
                {
                    out.println("<tr>");
                        out.println("<td>"+pessoa.getNome()+"</td>");
                        out.println("<td>"+pessoa.getCidade()+"</td>");
                        out.println("<td>"+pessoa.getFone()+"</td>");
                    out.println("<tr>");
                }
            }
            out.println("</table>");


            sessao.clear();
            
        } finally { 
            out.close();
        }
    } 

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected 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
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

}

Bom dia

Então fabio, ao invés de realizar a iteração na servlet faça o seguinte:

request.setAttribute("pessoas", lista_pessoa);

request.getRequestDispatcher("/sua_pagina.jsp").forward(request, response);

Isso significa o seguinte, a servlet recebe a requisição realiza a consulta no banco de dados, coloca o resultado como um atributo do request e encaminha o request atual para outro recurso, no caso a pagina jsp que contém a JSTL responsavel por realizar a iteração da lista de pessoas.

Na JSTL ficará assim:

<%@ taglib uri="http://java.sun.com/jsp/jstl" prefix="c">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
<html>  
  <head>  
	   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
	   <title>JSP Page</title>  
 
   </head>  
   <body>  
   <c:forEach var="pessoas" items="${pessoas}">  
	   ${pessoas.nome}, ${pessoas.fone}, ${pessoas.cidade},  
   </c:forEach>  
    </body>
</html>  

Ola cvinicius, agradeço bastante a sua ajuda, quanto ao JSTL eu entendi tranquilo, mas ainda estou com duvidas sobre o servlet, os codigos que vc passou

request.setAttribute("pessoas", lista_pessoa);  

request.getRequestDispatcher("/sua_pagina.jsp").forward(request, response);  

não sei exatamente onde coloca-los, eu fiz agora dessa maneira abaixo, mas ainda não esta exibindo os resultados

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.com.salesianos;

import br.com.salesianos.Pessoa;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

/**
 *
 * @author estinfo
 */
public class BuscaResultado extends HttpServlet {
   
    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {

            AnnotationConfiguration cfg = new AnnotationConfiguration();
            cfg.addAnnotatedClass(Pessoa.class);

            SessionFactory fabrica = cfg.buildSessionFactory();
            Session sessao = fabrica.openSession();


            List<Pessoa> lista_pessoa = new ArrayList();
            lista_pessoa = sessao.createCriteria(Pessoa.class).list();
            int tamanho_lista = lista_pessoa.size();

            request.setAttribute("pessoas", lista_pessoa);
            /*
            out.println("<table border='1'>");
            for(int i=0;i<tamanho_lista;i++)
            {
                Pessoa pessoa = lista_pessoa.get(i);
                {
                    out.println("<tr>");
                        out.println("<td>"+pessoa.getNome()+"</td>");
                        out.println("<td>"+pessoa.getCidade()+"</td>");
                        out.println("<td>"+pessoa.getFone()+"</td>");
                    out.println("<tr>");
                }
            }
            out.println("</table>");
            */

            sessao.clear();


            
        } finally { 
            out.close();
        }
        

        
    } 

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        request.getRequestDispatcher("/sua_pagina.jsp").forward(request, response);
    } 

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        request.getRequestDispatcher("/sua_pagina.jsp").forward(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

}

Então fabio dessa maneira não funcionaria mesmo, faça assim retire todos os metodos da sua servlet e coloque apenas esse:

protected void service(HttpServletRequest request, HttpServletResponse response)  
throws ServletException, IOException 
{  
	 response.setContentType("text/html;charset=UTF-8");  
	 PrintWriter out = response.getWriter();  
	 
	 try{  
		 AnnotationConfiguration cfg = new AnnotationConfiguration();  
		 cfg.addAnnotatedClass(Pessoa.class);  

		 SessionFactory fabrica = cfg.buildSessionFactory();  
		 Session sessao = fabrica.openSession();  

		 List<Pessoa> lista_pessoa = new ArrayList();  
		 lista_pessoa = sessao.createCriteria(Pessoa.class).list();  
		 int tamanho_lista = lista_pessoa.size();  

		 request.setAttribute("pessoas", lista_pessoa);  
		   
		 RequestDispatcher rd = request.getRequestDispatcher("/pagina.jsp");
		 
		 rd.forward(request, response);
		 
		 sessao.clear();  
  
	 } finally {   
		 out.close();  
	 }     
} 

Agora teste, provavelmente irá funcionar, lembrando que o nome da jsp no exemplo acima esta pagina.jsp, você deve colocar o nome da sua página.

vivaaaaaaaa, funcionou agora, valeu mesmo cvinicius, muito obrigado pela ajuda

vi no sua assinatura q vc é programador certificado pela oracle e pela sun, como vc conseguiu esses certificações?

vc recomenda a leitura de algum livro java para alguém como eu que trabalho como programador web

JSF vai fazer alguma diferença se eu aprender, ele é a continuação do JSTL?

Blz então agora é só dar uma melhorada no código, como por exemplo:

1º) Crie apenas a SessionFactory uma vez, e retire esse código da servlet cria uma classe com essa responsabilidade;

2º) A porte de acesso aos dados tmb não deve ficar na servlet, crie um camada DAO;

Bom agora falando das certificações tirei a associate e a de programador, a associate é bem mais tranquila como quando fiz já tinha uma boa experiência fiz alguns simulados e comprei este livro http://www.submarino.com.br/produto/1/21323904/certificacao+sun+java+associado±+scja:+exame+cx-310-019.

A prova de programador é um pouco mais complexa tem muita pegadinha, principalmente naquale negocio se o codigo compila, da erro de tempo de execução e etc, então é uma prova que exije um bom estudo, nessa usei algumas apostilas, comprei este livro SCJP 5 e fiz varios simulados na net.

Tenho alguns materias em pdf, caso queria me mande seu e-mail que te encaminho.

Falou.

Opa esqueci de responder sobre o JSF e JSTL, então o JSTL é uma biblioteca de tags desenvolvida para dar produtividade no desenvolvimento JSP, por exemplo isso que você fez ai acima, com JSP puro ficou uma coisa muito confusa e de dificil entendimento, com JSTL ficou bem mais simples de entender, e separado, oque para uma manutenção futura vai ajudar bastante, fora que a JSTL tem várias outras tags que ajudam bastante no desenvolvimento de paginas JSP

Agora o JSF é um framework web, muito poderoso baseado em componentes, nas páginas ele parece a JSTL, pois tem o mesma caracteristica de trabalhar com tags libs, mas o CORE dele é bem diferente, as tags se comunicam diretamente com os metodos das entidades, essas entidades são chamadas de Managed Beans.

Com relação a aprender JSF acho que é muito válido, ele atualmente esta sendo muito usado pelas empresas.

Flw.

Sobre os materiais que vc tem, se possivel me envie por favor, meu email é psxbrasil#gmail.com, so substitua o # pelo @,

se eu remover a sessionFactory da servlet e coloca-la em uma classe, qual seria uma boa maneira de chama-la? eu deveria chama-la na minha pagina JSP com JSTL?

com relação ao DAO, justamente eu passei a usar o Hibernate com anotações para criar a minha classe e com isso ja mapear diretamente, com isso eu nem precisei criar essa camada achando que assim que eu estava economizando tempo,

pois quando eu aprendi a usar DAO, eu criava uma interface, uma classe pra so depois chamar o metodo pra gravar ou listar no bando de dados, eu acho que este metodo parece dar mais trabalho, vc acha que vale a pena usa-lo ao inves de simplesmente mapear as classes com anotações?

Então fabio, respondendo:

Não, a jsp não deve ter esse responsabilidade de chamar os métodos da classe de persistência, a pagina JSP junto com a JSTL deve apenas montar a parte de front-end, ou seja, receber os dados e formatar a exibição.

A SessionFactory é a fabrica de sessões do hibernate, ela deve ser criada apenas uma vez, por vc imagina o seguinte, a cada request no servidor o hibernate ir no banco de dados e tentar criar as tabelas, alem de ficar lento isso é totalmente inviável.

Existem várias maneiras de gerenciar a SessionFactory e as Sessions, o mais comum quando se inicia com esse tipo de desenvolvimento, é criar uma classe irá carregar a factory uma unica vez, seja por meio de um bloco static ou singleton, tipo assim:

public final class ConnectionFactory {
	
	private static SessionFactory sessionFactory;
	
	static{
		AnnotationConfiguration configuration = new AnnotationConfiguration();
		
		configuration.configure();
		
		ConnectionFactory.sessionFactory = configuration.buildSessionFactory();
	}
	
	/**
	 * Abre uma session no hibernate
	 * 
	 * @return Session
	 */
	public static Session getSession()
	{
		return ConnectionFactory.sessionFactory.openSession();
	}
	
	/**
	 * Realiza o close da session do hibernate
	 * 
	 * @param session
	 */
	public static void close(Session session){
		session.close();
	}
}

Obs: Em aplicações web tem outras maneiras de carregar a SessionFactory e depois gerenciar as aberturas de Sessions, uma muito comum, é usar um listener para carregar a SessionFactory e recuperar as Sessions atraves dos Filters, assim podemos trabalhar com a sessions durante todo ciclo de vida do request.

Bom nesse ponto existe várias maneiras de proceder com as camadas do software, eu te aconselho a sempre separar a logica de negocio, a persistencia, os controllers, e as views, de uma pesquisada sobre os padrões MVC e DAO, a separação em camadas facilita o crescimento do sistema, se você mata a camada de persistencia, no caso o DAO, e fica colocando as consultas na servlet, quando o sistema sofrer alguma manutenção vai ser complicado, porque esta tudo misturado nas servlets.

Flw.

Eu entendi sua explicação sobre a sessionFactory, que ela não deve ser criada toda vez que eu precisar puxar informações do bando de dados, vou tentar usar o singleton do Spring framework para inicia-lo, pois nunca usei esse bloco static que vc fala, apesar do que pude pesquisar sobre ele não parece ser complicado e como vc ja montou ele, deve ser tranquilo

mas se eu somente criasse uma classe java com o exemplo que vc fez do bloco static, depois para usar a sessão que ja foi criada eu deveria apenas instacia-la para pode usa-la, certo? mas ela so será chamada, quando eu instanciar um objeto pela primeira vez diferentemente do singleton que chama assim que a aplicação começa a rodar, este meu conceito esta certo?

vc fala sobre listener e filters para controlar as sessions em aplicações web, mas nunca mexi com isso, não sei como usar, mas vou pesquisar depois

vou seguir seu conselho sobre as camadas de software, eu ja havia criado um pequeno programa java para desktop usando todos estes conceitos de MVC e DAO, como logica de negocio, a persistencia, os controllers, e as views, porém como era um projeto para desktop, não é tao simples usa-lo para web, apesar de que muita coisa é aproveitavel, vc acha q vale a pena eu usar este projeto desktop e tentar transforma-lo em um projeto web, ou seja, transformar aplicação JavaSE em JavaEE?

Melhor ainda se você usar o Spring, ele já vai gerenciar a SessionFactory e as Sessions, sem a necessidade de realizar o gerenciamento manual nas classes.

Este exemplo que falei é utilizando o bloco static, o bloco static é inicializado apenas uma vez, isso acontece quando a classe for chamada pela 1º vez no sistema ai acontece a inicialização do conteudo static, a JVM carrega o arquivo .class para memória e inicia tudo oque é static, incluido o bloco.

Bom depende de como você fez a app desktop, geralmente por se tratar de arquiteturas diferentes não dá para aproveitar muita coisa em uma migração de desktop para web, mas claro que isso depende muito de como a app desktop esta modelada, mas geralmente o reaproveitamento não é alto.

Flw.

Infelizmente o meu conhecimento de Spring é um pouco limitado, so conheço o singleton dele e a parte de internacionalização, eu não sei controlar as sessions através dele, sabe onde posso pesquisar sobre isso? ou vc pode explicar aqui se não for pedir demais…

o bloco static ta blz, consegui entende-lo

vou tentar transformar a app desktop em web e depois te falo se consegui, t+