blob: 728fa5dabb908d076c92af2baffd4dfeff06de6b [file] [log] [blame]
<!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">
<meta name="description" content="Demonstrates how the IDE can generate robust and easily maintainable code when generating JSF pages from entity classes.">
<meta name="keywords" content="NetBeans, IDE, integrated development environment,
Java, Java EE, open source, web technology, CRUD, JSF, tutorial, database">
<link rel="stylesheet" type="text/css" href="../../../netbeans.css">
<link rel="stylesheet" type="text/css" href="../../../lytebox.css" media="screen">
<script type="text/javascript" src="../../../images_www/js/lytebox-compressed.js"></script>
<script src="../../../images_www/js/listCollapse.js" type="text/javascript"></script>
<title>Gerando uma Aplicação CRUD do JavaServer Faces 2.x usando um Banco de Dados: Tutorial do NetBeans IDE</title>
</head>
<body>
<!-- Copyright (c) 2009, 2010, 2011, Oracle and/or its affiliates. All rights reserved. -->
<h1>Gerando uma Aplicação CRUD JavaServer Faces 2.x Usando um Banco de Dados</h1>
<p>Neste tutorial, você utilizará o NetBeans IDE para criar uma aplicação Web que interaja com um banco de dados de backend. A aplicação oferece a capacidade de exibir e modificar os dados contidos no banco de dados, conhecida como recurso <em>CRUD</em> (Create, Read, Update, Delete). A aplicação que você desenvolverá contará com as seguintes tecnologias.</p>
<ul>
<li><strong>JavaServer Faces (JSF) 2.x</strong> para páginas Web de frontend, manipulação de validação e gerenciamento do ciclo de solicitação-resposta.</li>
<li><strong>Java Persistence API (JPA) 2.0</strong> utilizando EclipseLink para gerar classes de entidade a partir do banco de dados e gerenciar transações. (EclipseLink é a implementação de referência para JPA e é o provedor de persistência default para o GlassFish Server.)</li>
<li><strong>Enterprise JavaBeans (EJB) 3.1</strong>, que oferece EJBs sem estado que acessam as classes de entidade e contém a lógica de negócios da aplicação.</li>
</ul>
<p>O IDE oferece dois assistentes que geram todos os códigos da aplicação. O primeiro é o <a href="#generateEntity">assistente para Classes de Entidade do Banco de Dados</a> que permite gerar as classes de entidade a partir do banco de dados fornecido. Após criar as classes de entidade, você utiliza o <a href="#jsfPagesEntityClasses">assistente de Páginas JSF de Classes de Entidade</a> para criar EJBs e beans gerenciados pelo JSF para as classes de entidade, bem como um conjunto de páginas de Facelets para manipular as views dos dados da classe de entidade. A seção final do tutorial, <a href="#explore">Explorando a Aplicação</a>, é opcional e oferece vários exercícios para ajudá-lo a entender melhor a aplicação e a se familiarizar mais com o IDE.</p>
<img alt="O conteúdo desta página se aplica ao NetBeans IDE 7.2, 7.3, 7.4 e 8.0" class="stamp" src="../../../images_www/articles/73/netbeans-stamp-80-74-73.png" title="O conteúdo desta página se aplica ao NetBeans IDE 7.2, 7.3, 7.4 e 8.0">
<h4>Conteúdo</h4>
<ul class="toc">
<li><a href="#createDB">Criando o Banco de Dados</a></li>
<li><a href="#examineDB">Examinando a Estrutura do Banco de Dados</a></li>
<li><a href="#createProject">Criando o Projeto de Aplicação Web</a></li>
<li><a href="#generateEntity">Gerando as Classes de Entidade do Banco de Dados</a></li>
<li><a href="#jsfPagesEntityClasses">Gerando páginas JSF de Classes de Entidade</a></li>
<li><a href="#explore">Explorando a Aplicação</a>
<ul>
<li><a href="#completedProject">Examinando o Projeto Concluído</a></li>
<li><a href="#populateDB">Preenchendo o Banco de Dados com um Script SQL</a></li>
<li><a href="#editorSupport">Explorando o Suporte do Editor em Páginas de Facelets</a></li>
<li><a href="#dbIntegrity">Explorando a Integridade do Banco de Dados com Validação de Campo</a></li>
<li><a href="#editEntity">Editando as Classes de Entidade</a></li>
</ul></li>
<li><a href="#troubleshooting">Solução de Problemas</a></li>
<li><a href="#seeAlso">Consulte Também</a></li>
</ul>
<p id="requiredSoftware">Para concluir este tutorial, você precisa dos seguintes recursos e softwares.</p>
<table>
<tbody>
<tr>
<th class="tblheader" scope="col">Software ou Recurso</th>
<th class="tblheader" scope="col">Versão Necessária</th>
</tr>
<tr>
<td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">NetBeans IDE</a></td>
<td class="tbltd1">Pacote Java EE 7.2, 7.3, 7.4, 8.0</td>
</tr>
<tr>
<td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">JDK (Java Development Kit)</a></td>
<td class="tbltd1">7 ou 8</td>
</tr>
<tr>
<td class="tbltd1"><a href="http://glassfish.dev.java.net/">GlassFish Server Open Source Edition</a></td>
<td class="tbltd1">3.x, 4.x</td>
</tr>
<tr>
<td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fmysql-consult.zip">mysql-consult.zip</a> (MySQL) <br><em class="margin-around" style="margin-left:6em">ou</em><br> <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fjavadb-consult.zip">javadb-consult.zip</a> (JavaDB)</td>
<td class="tbltd1">n/d</td>
</tr>
</tbody>
</table>
<p class="notes"><strong>Observações:</strong></p>
<div class="indent">
<ul>
<li>O pacote Java EE do NetBeans IDE também inclui o GlassFish Server, um servidor compatível com Java EE necessário para este tutorial.</li>
<li>Para o projeto de solução deste tutorial, faça o download de <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252FConsultingAgencyJSF20.zip">ConsultingAgencyJSF20.zip</a>.</li>
</ul>
</div>
<br>
<h2 id="createDB">Criando o Banco de Dados</h2>
<p>Este tutorial utiliza um banco de dados de agência de consultoria chamado <code>consult</code>. O banco de dados não é incluído quando você instala o IDE, portanto, é necessário criar primeiro o banco de dados para seguir este tutorial.</p>
<p>O banco de dados <code>consult</code> foi projetado para demonstrar o escopo do suporte do IDE para manipular uma variedade de estruturas de banco de dados. Portanto, o banco de dados não é um exemplo de melhores práticas ou design de banco de dados recomendado. Em vez disso, ele tenta incorporar muitas funcionalidades relevantes encontradas em um design de banco de dados. Por exemplo, o banco de dados <code>consult</code> contém todos os tipos de relacionamento possíveis, chaves primárias compostas e muitos tipos de dados diferentes. Consulte as tabelas abaixo para obter uma visão geral mais detalhada da estrutura do banco de dados.</p>
<p><strong class="notes">Observações:</strong></p>
<ul>
<li>Este tutorial utiliza o servidor de banco de dados MySQL, mas também é possível concluí-lo utilizando o servidor do banco de dados JavaDB. Para criar o banco de dados no JavaDB, faça download e extraia o arquivo compactado <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fjavadb-consult.zip">javadb-consult.zip</a>. O arquivo compactado contém scripts SQL para criar, eliminar e preencher o banco de dados de <code>consult</code>.</li>
<li>Para obter mais informações sobre a configuração do IDE para trabalhar com o MySQL, consulte o tutorial <a href="../ide/mysql.html">Estabelecendo Conexão com um Banco de Dados MySQL</a>.</li>
<li>Para obter mais informações sobre como configurar o IDE para trabalhar com JavaDB, consulte o tutorial <a href="../ide/java-db.html">Trabalhando com o Banco de Dados Java DB (Derby)</a>.</li>
</ul>
<div class="feedback-box float-left" style="width: 678px; margin: 0 0 10px 10px">
<p><strong class="alert">Combinação MySQL com GlassFish:</strong></p>
<p>Se você estiver usando o MySQL, e estiver usando o GlassFish v3 ou Open Source Edition 3.0.1, será preciso garantir que seu banco de dados esteja protegido por senha. (Para obter mais informações, consulte GlassFish <a href="https://java.net/jira/browse/GLASSFISH-12221" target="_blank">Edição 12221</a>.) Se você estiver utilizando a conta MySQL <code>root</code> sem senha, você poderá definir a senha usando um prompt de linha de comandos. <br><br> Por exemplo, para definir a senha para <code><em>nbuser</em></code>, digite os comandos a seguir no prompt de linha de comandos.</p>
<pre class="examplecode" style="width: 658px;">
shell> mysql -u root
mysql> UPDATE mysql.user SET Password = PASSWORD('<em>nbuser</em>') WHERE User = 'root';
mysql> FLUSH PRIVILEGES;</pre>
<p>Se você receber um erro '<code>mysql: command not found</code>', será porque o comando <code>mysql</code> não foi adicionado à sua variável de ambiente <code>PATH</code>. É possível chamar o comando inserindo o caminho completo para o diretório <code>bin</code> da instalação do MySQL. Por exemplo, se o comando <code>mysql</code> estiver localizado no seu computador em <code>/usr/local/mysql/bin</code>, digite o seguinte:</p>
<pre class="examplecode" style="width: 658px;">shell> /usr/local/mysql/bin/mysql -u root</pre>
<p>Para obter mais informações, consulte o Manual de Referência oficial do MySQL:</p>
<ul>
<li><a href="http://dev.mysql.com/doc/refman/5.1/en/default-privileges.html" target="_blank">Proteção das Contas MySQL Iniciais</a></li>
<li><a href="http://dev.mysql.com/doc/refman/5.1/en/invoking-programs.html" target="_blank">4.2.1. Chamando Programas MySQL</a></li>
<li><a href="http://dev.mysql.com/doc/refman/5.1/en/setting-environment-variables.html" target="_blank">4.2.4. Configurando Variáveis de Ambiente</a></li>
</ul>
</div>
<br style="clear: both;"/>
<br>
<p>Execute as etapas a seguir para criar um banco de dados e conecte-o a partir do IDE.</p>
<ol style="margin-top:0">
<li>Faça download de <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fmysql-consult.zip">mysql-consult.zip</a> e o extraia o arquivo compactado no seu sistema local. Quando você extrair o arquivo compactado, você verá os scripts SQL para criação e preenchimento do banco de dados. O arquivo compactado também tem scripts para eliminação de tabelas.</li>
<li>Na janela Serviços, expanda o nó Bancos de Dados, clique com o botão direito do mouse no nó MySQL e selecione Iniciar Servidor.</li>
<li>Clique com o botão direito do mouse no nó Servidor MySQL e escolha Criar Banco de Dados.</li>
<li>Digite <strong>consult</strong> como o Nome do Banco de Dados na caixa de diálogo Criar Banco de Dados MySQL. Clique em OK. Um novo nó aparecerá sob o nó Bancos de Dados (<code>jdbc:mysql://localhost:3306/consult [raiz no esquema Default]</code>).</li>
<li>Clique com o botão direito do mouse no novo nó e selecione Conectar.</li>
<li>Selecione Arquivo > Abrir Arquivo, no menu principal e vá até o arquivo extraído <code>mysql_create_consult.sql</code>. Clique em Abrir. O arquivo abre automaticamente no editor SQL.<br><img alt="Tela do editor de SQL" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/run-sql-script.png" title="Abrir arquivos SQL no editor do IDE"></li>
<li>Certifique-se de que o banco de dados <code>consult</code> esteja selecionado na lista drop-down Conexão da barra de ferramentas do editor SQL. Em seguida, clique no botão ( <img alt="Botão Executar SQL" src="../../../images_www/articles/72/web/jsf20-crud/run-sql-btn.png"> ) Executar SQL.
<p>Quando você clica em Executar SQL, a saída a seguir é exibida na janela de Saída.</p>
<img alt="Tela da janela de Saída" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/run-sql-output.png" title="A janela de Saída oferece informações sobre a execução SQL"></li>
</ol>
<br>
<h2 id="examineDB">Examinando a Estrutura do Banco de Dados</h2>
<p>Para confirmar se as tabelas foram criadas corretamente, expanda o nó Tabelas sob o nó da conexão do banco de dados. Você pode expandir um nó da tabela para ver suas colunas, índices e chaves estrangeiras. É possível clicar com o botão direito do mouse em uma coluna e selecionar Propriedades para exibir informações adicionais sobre a coluna.</p>
<div class="indent">
<img alt="Tela da janela Serviços" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/services-window-tables.png" title="A janela Serviços exibe conexões de bancos de dados, tabelas, colunas de tabelas, índices e chaves estrangeiras">
</div>
<p class="notes"><strong>Observação:</strong> Se você não vir nenhuma tabela sob o nó Tabelas, clique com o botão direito do mouse no nó Tabelas e selecione Atualizar.</p>
<p>Ao observar a estrutura do banco de dados <code>consult</code>, você pode ver que o banco de dados contém tabelas que possuem uma variedade de relacionamentos e vários tipos de campo. Quando você cria classes de entidade de um banco de dados, o IDE gera automaticamente o código apropriado para os vários tipos de campo.</p>
<img alt="Diagrama de relacionamento com entidades do banco de dados consult" class="margin-around b-all" id="er-diagram" src="../../../images_www/articles/72/web/jsf20-crud/diagram_consult.png" title="Diagrama de relacionamento com entidades do banco de dados consult">
<p>A tabela a seguir descreve as tabelas encontradas no banco de dados <code>consult</code>.</p>
<table class="indent" style="width: 744px">
<tr>
<th class="tblheader" scope="col">Tabela de Banco de Dados</th>
<th class="tblheader" scope="col">Descrição</th>
<th class="tblheader" scope="col">Funcionalidades de Design</th>
</tr>
<tr>
<td class="tbltd1">CLIENT</td>
<td class="tbltd0">Um cliente da agência de consultoria</td>
<td class="tbltd0">Chave primária composta, não gerada (cujos campos não constituem uma chave estrangeira)</td>
</tr>
<tr>
<td class="tbltd1">CONSULTANT</td>
<td class="tbltd0">Um funcionário da agência de consultoria que os clientes podem contratar</td>
<td class="tbltd0">Inclui um campo de retomada do tipo LONG VARCHAR</td>
</tr>
<tr>
<td class="tbltd1">CONSULTANT_STATUS</td>
<td class="tbltd0">O status de um consultor na agência de consultoria (por exemplo, Ativo e Inativo são status possíveis)</td>
<td class="tbltd0">Chave primária não gerada do tipo CHAR</td>
</tr>
<tr>
<td class="tbltd1">RECRUITER</td>
<td class="tbltd0">Um funcionário da agência de consultoria responsável por conectar clientes e consultores</td>
<td class="tbltd0">&nbsp;</td>
</tr>
<tr>
<td class="tbltd1">PROJECT</td>
<td class="tbltd0">Um projeto cuja equipe é formada pelos consultores da agência de consultoria</td>
<td class="tbltd0">Chave primária composta, não gerada que inclui dois campos que constituem uma chave estrangeira para a tabela CLIENT</td>
</tr>
<tr>
<td class="tbltd1">BILLABLE</td>
<td class="tbltd0">Um conjunto de horas trabalhadas por um consultor em um projeto, o qual a agência de consultoria cobra do cliente relevante</td>
<td class="tbltd0">Inclui um campo de artefato do tipo CLOB</td>
</tr>
<tr>
<td class="tbltd1">ADDRESS</td>
<td class="tbltd0">O endereço de cobrança de um cliente</td>
<td class="tbltd0">&nbsp;</td>
</tr>
<tr>
<td class="tbltd1">PROJECT_CONSULTANT</td>
<td class="tbltd0">Tabela com junção indicando a quais projetos os consultores estão designados no momento</td>
<td class="tbltd0">Faz referência cruzada entre PROJECT e CONSULTANT, a primeira possui uma chave primária composta</td>
</tr>
</table>
<br>
<p>O banco de dados <code>consult</code> inclui uma variedade de relacionamentos. Quando você cria classes de entidade de um banco de dados, o IDE gera automaticamente as propriedades do tipo Java apropriado com base no tipo SQL das colunas. A tabela a seguir descreve os relacionamentos de entidade do banco de dados <code>consult</code>. (os relacionamentos inversos não são mostrados.)</p>
<table id="relationships" class="indent" style="width: 744px">
<tr>
<th class="tblheader" scope="col">Entidade</th>
<th class="tblheader" scope="col">Entidade Relacionada</th>
<th class="tblheader" scope="col">Informações sobre Relacionamento</th>
<th class="tblheader" scope="col">Descrição</th>
</tr>
<tr>
<td class="tbltd1">CLIENT</td>
<td class="tbltd0">RECRUITER</td>
<td class="tbltd0">pode ser nulo, um para um com edição manual; pode ser nulo, um para muitos, caso não seja editado</td>
<td class="tbltd0">CLIENT possui muitos RECRUITERs e RECRUITER não possui nenhum ou um CLIENT (se não for manualmente editado)</td>
</tr>
<tr>
<td class="tbltd1">CLIENT</td>
<td class="tbltd0">ADDRESS</td>
<td class="tbltd0">não pode ser nulo, um para um</td>
<td class="tbltd0">CLIENT possui um ADDRESS e ADDRESS não possui nenhum ou um CLIENT</td>
</tr>
<tr>
<td class="tbltd1">CLIENT</td>
<td class="tbltd0">PROJECT</td>
<td class="tbltd0">não pode ser nulo, um para muitos; em uma entidade de Projeto, o valor do campo do cliente faz parte da chave primária do Projeto</td>
<td class="tbltd0">CLIENT tem muitos PROJECTS e PROJECT tem um CLIENT</td>
</tr>
<tr>
<td class="tbltd1">CONSULTANT</td>
<td class="tbltd0">PROJECT</td>
<td class="tbltd0">muitos para muitos</td>
<td class="tbltd0">CONSULTANT tem muitos PROJECTs e PROJECT tem muitos CONSULTANTs</td>
</tr>
<tr>
<td class="tbltd1">CONSULTANT</td>
<td class="tbltd0">BILLABLE</td>
<td class="tbltd0">não pode ser nulo, um para muitos</td>
<td class="tbltd0">CONSULTANT possui muitos BILLABLEs e BILLABLE possui um CONSULTANT</td>
</tr>
<tr>
<td class="tbltd1">CONSULTANT_STATUS</td>
<td class="tbltd0">CONSULTANT</td>
<td class="tbltd0">não pode ser nulo, um para muitos</td>
<td class="tbltd0">CONSULTANT_STATUS possui muitos CONSULTANTs e CONSULTANT possui um CONSULTANT_STATUS</td>
</tr>
<tr>
<td class="tbltd1">CONSULTANT</td>
<td class="tbltd0">RECRUITER</td>
<td class="tbltd0">pode ser nulo, um para muitos</td>
<td class="tbltd0">CONSULTANT não possui nenhum ou um RECRUITER e RECRUITER possui muitos CONSULTANTs</td>
</tr>
<tr>
<td class="tbltd1">BILLABLE</td>
<td class="tbltd0">PROJECT</td>
<td class="tbltd0">não pode ser nulo, um para muitos</td>
<td class="tbltd0">BILLABLE possui um PROJECT e PROJECT possui muitos BILLABLES</td>
</tr>
</table>
<p>Agora que o banco de dados está criado, você pode criar a aplicação Web e utilizar o assistente de Classes de Entidade do Banco de Dados para gerar bancos de dados com base nas tabelas do banco de dados.</p>
<h2 id="createProject">Criando o Projeto de Aplicação Web</h2>
<p>Neste exercício, você criará um projeto Web e adicionará o framework JavaServer Faces ao projeto. Ao criar o projeto, você irá selecionar JavaServer Faces no painel Frameworks do assistente de Novo Projeto.</p>
<ol>
<li>Escolha Arquivo > Novo Projeto (Ctrl-Shift-N; &amp;#8984-Shift-N no Mac) no menu principal.</li>
<li>Na categoria Java Web, selecione Aplicação Web. Clique em Próximo.</li>
<li>Digite <code>ConsultingAgency </code> para o nome do projeto e defina a localização do projeto. Clique em Próximo.</li>
<li>Defina o servidor como GlassFish Server e defina a versão do Java EE para Java EE 6 Web ou Java EE 7 Web. Clique em Próximo.</li>
<li>No painel Frameworks, selecione a opção JavaServer Faces. Clique em Finalizar.</li>
</ol>
<p>Quando você clicar em Finalizar, o IDE irá gerar o projeto de aplicação Web e abrir <code>index.xhtml</code> no editor.</p>
<h2 id="generateEntity">Gerando as Classes de Entidade do Banco de Dados</h2>
<p>Depois de se conectar a um banco de dados do IDE, você pode utilizar o assistente de Classes de Entidade do Banco de Dados para gerar rapidamente classes de entidade com base nas tabelas do banco de dados. O IDE pode gerar classes de entidade para cada tabela selecionada, e também pode gerar classes de entidade necessárias para tabelas relacionadas.</p>
<ol>
<li>Na janela Projetos, clique com o botão direito do mouse no nó do projeto <code> ConsultingAgency</code> e selecione Novo > Classes de Entidade do Banco de Dados. (Se esta opção não estiver na lista, escolha Outros. Em seguida, no assistente de Arquivo, selecione a categoria Persistência e, depois, Classes de Entidade do Banco de Dados.)</li>
<li>Selecione Nova Fonte de Dados na lista drop-down Fonte de Dados para abrir a caixa de diálogo Criar Fonte de Dados.</li>
<li>Digite <code>jdbc/consult</code> como o Nome da JNDI e selecione a conexão <code>jdbc:mysql://localhost:3306/consult</code> como a Conexão do Banco de Dados. <br> <img alt="Caixa de diálogo Criar Fonte de Dados" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/create-datasource.png" title="Especificar um nome e uma conexão de banco de dados JNDI para criar uma fonte de dados"></li>
<li>Clique em OK para fechar a caixa de diálogo e retornar ao assistente. As tabelas no banco de dados <code>consult</code> serão exibidas na lista de conteúdo Tabelas Disponíveis.</li>
<li>Clique no botão Adicionar Tudo para selecionar todas as tabelas contidas no banco de dados. Clique em Próximo. <br> <img alt="Assistente de Novas Entidades do Banco de Dados" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/new-entities-wizard.png"></li>
<li>Digite <code>jpa.entities</code> como o nome do Pacote. </li>
<li>Verifique se as caixas de seleção para gerar as consultas nomeadas e criar uma unidade persistente estão marcadas. Clique em Finalizar.</li>
</ol>
<p>Quando você clicar em Finalizar, o IDE gerará as classes de entidade no pacote <code>jpa.entities</code> do projeto.</p>
<p>Quando você utiliza o assistente para criar classes de entidade de um banco de dados, o IDE examina os relacionamentos entre as tabelas do banco de dados. Na janela Projetos, se você expandir o nó do pacote <code>jpa.entities</code>, você verá que o IDE gerou uma classe de entidade para cada tabela, exceto para a tabela <code>PROJECT_CONSULTANT</code>. O IDE não criou uma classe de entidade para <code>PROJECT_CONSULTANT</code> porque a tabela é uma tabela com junção.</p>
<div class="indent">
<img alt="tela da janela Projetos" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/projects-window-entities.png" title="Tela da janela Projetos mostrando as classes de entidades geradas">
</div>
<p>O IDE também gerou duas classes adicionais para as tabelas com chaves primárias compostas: <code>CLIENT</code> e <code>PROJECT</code>. As classes de chave primária dessas tabelas (<code>ClientPK.java</code> e <code>ProjectPK.java</code>) têm as letras <code>PK</code> acrescentadas ao nome.</p>
<p>Se você observar o código gerado para as classes de entidade, você verá que o assistente adicionou anotações <code>@GeneratedValue</code> aos campos ID gerados automaticamente e anotações <code>@Basic(optional = "false")</code> a alguns dos campos das classes de entidade. Com base nas anotações <code>@Basic(optional = "false")</code>, o assistente de Páginas JSF de Classes de Entidade pode gerar o código que inclui verificações para evitar violações de coluna que não podem ser nulas para esses campos.</p>
<br>
<h2 id="jsfPagesEntityClasses">Gerando Páginas JSF de Classes de Entidade</h2>
<p>Agora que as classes de entidade estão criadas, você pode criar a interface Web para exibir e modificar os dados. Você utilizará o assistente de Páginas JSF de Classes de Entidade para gerar páginas JavaServer Faces. O código gerado pelo assistente baseia-se nas anotações de persistência contidas nas classes de entidade.</p>
<p>Para cada classe de entidade o assistente gera os seguintes arquivos:</p>
<ul>
<li>um bean de sessão sem estado que estende <tt>AbstractFacade.java</tt></li>
<li>um bean gerenciado com escopo de sessão JSF</li>
<li>um diretório contendo quatro arquivos de Facelets para os recursos CRUD (<code>Create.xhtml</code>, <code>Edit.xhtml</code>, <code>List.xhtml</code> e <code>View.xhtml</code>)</li>
</ul>
<p>O assistente também gera os seguintes arquivos.</p>
<ul>
<li>a classe <tt>AbstractFacade.java</tt> que contém a lógica de negócio para criação, recuperação, modificação e remoção das instâncias da entidade</li>
<li>classes de utilitário utilizadas pelos beans gerenciados pelo JSF (<code>JsfUtil</code>, <code>PaginationHelper</code>)</li>
<li>um conjunto de propriedades para mensagens localizadas e uma entrada correspondente no arquivo de configuração Faces do projeto (será criado um arquivo <code>faces-config.xml</code>, caso já não exista um).</li>
<li>arquivos web auxiliares, incluindo uma folha de estilo default para componentes renderizados e um arquivo de modelo de Facelets</li>
</ul>
<p>Para gerar as páginas JSF:</p>
<ol>
<li>Na janela Projetos, clique com o botão direito do mouse no nó do projeto e selecione Novo > Páginas JSF de Classes de Entidade para abrir o assistente. (Se esta opção não estiver na lista, escolha Outros. Em seguida, no assistente de Arquivo, selecione a categoria JavaServer Faces e, depois, Páginas JSF de Classes de Entidade.)
<p>
A caixa Classes de Entidade Disponíveis lista as sete classes de entidade contidas no projeto. A caixa não lista as classes incorporadas (<code>ClientPK.java</code> e <code>ProjectPK.java</code>).</p></li>
<li>Clique em Adicionar Tudo para mover todas as classes para a caixa Classes de Entidade Selecionadas. <br> <img alt="Assistente de Novas Páginas JSF de Classes de Entidade" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/newjsf-wizard.png" title="O assistente de Novas Páginas JSF de Classes de Entidade exibe todas as classes de entidade contidas no projeto"> <br> Clique em Próximo.</li>
<li>Na etapa 3 do assistente, Gerar Classes e Páginas JSF, digite <code>jpa.session</code> no Pacote de Bean de Sessão JPA.</li>
<li>Digite <code>jsf</code> para o Pacote de Classes JSF.</li>
<li>Digite '<code>/resources/Bundle</code>' no campo Nome do Pacote de Localização. Isso gerará um pacote com o nome <code>resources</code> no qual o arquivo <code>Bundle.properties</code> residirá. (Se deixá-lo em branco, o conjunto de propriedades será criado no pacote default do projeto.)<br><img alt="Assistente de Novas Páginas JSF de Classes de Entidade. etapa 3" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/newjsf-wizard2.png" title="Especificar pacote e nomes de pastas para os arquivos gerados">
<p class="tips">Para que o IDE se ajuste melhor às convenções do projeto, você pode personalizar os arquivos gerados pelo assistente. Clique no link Personalizar Modelo para modificar os modelos de arquivo utilizados pelo assistente. <br> <img alt="Personalizar Lista drop-down Modelo" class="margin-around" src="../../../images_www/articles/72/web/jsf20-crud/customize-template.png" title="Personalizar modelos de arquivos gerados pelo assistente"> <br> Em geral, você pode acessar e fazer alterações em todos os modelos mantidos pelo IDE utilizando o Gerenciador de Modelos (Ferramentas > Modelos).</p></li>
<li>Clique em Finalizar. O IDE gera os beans de sessão sem estado no pacote <code>jpa.session</code>, e o escopo de sessão e beans gerenciados com JSF no pacote <code>jsf</code>. Cada bean de sessão sem estado manipula as operações da classe de entidade correspondente, incluindo a criação, edição e destruição de instâncias da classe de entidade por meio da API de Persistência Java. Cada Bean gerenciado pelo JSF implementa a interface <code>javax.faces.convert.Converter</code> e realiza as tarefas de conversão das instâncias da classe de entidade correspondente para objetos <code>String</code> e vice-versa.</li>
</ol>
<p>Se você expandir o nó Páginas Web, você poderá ver que o IDE gerou uma pasta para cada uma das classes de entidade. Cada pasta contém os arquivos <code>Create.xhtml</code>, <code>Edit.xhtml</code>, <code>List.xhtml</code> e <code>View.xhtml</code>. O IDE também modificou o arquivo <code>index.xhtml</code> inserindo links em cada uma das páginas <code>List.xhtml</code>.</p>
<div class="indent">
<img alt="Tela do diretório de Páginas Web na janela Projetos" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/projects-jsfpages.png" title="Páginas de Facelets para cada classe de entidade são geradas pelo assistente">
</div>
<p>Cada Bean gerenciado pelo JSF é específico dos quatro arquivos de Facelets correspondentes e inclui o código que chama os métodos no Bean de sessão apropriado.</p>
<p>Expanda o nó da pasta <code>resources</code> para localizar a folha de estilo <code>jsfcrud.css</code> default gerada pelo assistente. Se você abrir a página de boas-vindas da aplicação (<code>index.xhtml</code>) ou o arquivo de modelo de Facelets (<code>template.xhtml</code>) no editor, verá que eles contêm uma referência à folha de estilo.</p>
<div class="indent">
<pre class="examplecode">&lt;h:outputStylesheet name=&quot;css/jsfcrud.css&quot;/&gt;</pre>
</div>
<p>O arquivo de modelo de Facelets é utilizado por cada um dos quatro arquivos de Facelets para cada classe de entidade.</p>
<p>Se você expandir o nó Pacotes de Código-Fonte, você verá os Beans de sessão, os Beans gerenciados pelo JSF, as classes de utilitário e o conjunto de propriedades gerados pelo assistente.</p>
<div class="indent">
<img alt="Tela do diretório Pacotes de Código-Fonte na janela Projetos" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/projects-generated-classes70.png" title="Tela do diretório de Pacotes de Código-Fonte na janela Projetos mostrando as classes geradas pelo assistente">
</div>
<p>O assistente também gerou o arquivo de Configuração do Faces (<code>faces-config.xml</code>) a fim de registrar a localização do conjunto de propriedades. Se expandir o nó Arquivos de Configuração e abrir <code>faces-config.xml</code> no editor XML, você verá que a entrada a seguir está incluída.</p>
<div class="indent">
<pre class="examplecode">&lt;application&gt;
&lt;resource-bundle&gt;
&lt;base-name&gt;/resources/Bundle&lt;/base-name&gt;
&lt;var&gt;bundle&lt;/var&gt;
&lt;/resource-bundle&gt;
&lt;/application&gt;</pre>
</div>
<p>Além disso, se expandir o novo pacote <code>resources</code>, você encontrará o arquivo <code>Bundle.properties</code> que contém mensagens no idioma default do cliente. As mensagens são obtidas das propriedades da classe de entidade.</p>
<p class="tips">Para adicionar um novo conjunto de propriedades, clique com o botão direito do mouse no arquivo <code>Bundle.properties</code> e selecione Personalizar. A caixa de diálogo Personalizador permite adicionar novas configurações regionais à aplicação.</p>
<br>
<h2 id="explore">Explorando a Aplicação</h2>
<p>Agora que seu projeto contém classes de entidade, Beans de sessão EJB para controlar as classes de entidade e um frontend desenvolvido para JSF para exibir e modificar bancos de dados, tente executar o projeto para ver os resultados.</p>
<p>A seguir, encontra-se uma série opcional de exercícios rápidos que ajudará você a se familiarizar com a aplicação, bem como com os recursos e as funcionalidades que o IDE oferece.</p>
<ul>
<li><a href="#completedProject">Examinando o Projeto Concluído</a></li>
<li><a href="#populateDB">Preenchendo o Banco de Dados com um Script SQL</a></li>
<li><a href="#editorSupport">Explorando o Suporte do Editor em Páginas de Facelets</a></li>
<li><a href="#dbIntegrity">Explorando a Integridade do Banco de Dados com Validação de Campo</a></li>
<li><a href="#editEntity">Editando as Classes de Entidade</a></li>
</ul>
<div class="indent">
<h3 id="completedProject">Examinando o Projeto Concluído</h3>
<ol>
<li>Para executar o projeto, clique com o botão direito do mouse no nó do projeto, na janela Projetos, e selecione Executar ou clique no botão ( <img alt="Botão Executar Projeto" src="../../../images_www/articles/72/web/jsf20-crud/run-project-btn.png"> ) Executar Projeto na barra de ferramentas principal.
<p>
Quando a página de boas-vindas da aplicação é exibida, aparece uma lista de links que permite exibir as entradas contidas em cada uma das tabelas do banco de dados.
</p>
<img alt="Página de boas-vindas da ConsultingAgency no browser" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/welcome-page-links.png" title="Links para exibição do conteúdo do banco de dados para cada tabela">
<p>
Os links foram adicionados à página de boas-vindas (<code>index.xhtml</code>) ao concluir o assistente de Páginas JSF de Classes de Entidade. Esses links são fornecidos como pontos de entrada nas páginas de Facelets que oferecem a funcionalidade CRUD no banco de dados da Agência de Consultoria.</p>
<pre class="examplecode">
&lt;h:body&gt;
Hello from Facelets
&lt;h:form&gt;
&lt;h:commandLink action=&quot;/address/List&quot; value=&quot;Show All Address Items&quot;/&gt;
&lt;/h:form&gt;
&lt;h:form&gt;
&lt;h:commandLink action=&quot;/billable/List&quot; value=&quot;Show All Billable Items&quot;/&gt;
&lt;/h:form&gt;
&lt;h:form&gt;
&lt;h:commandLink action=&quot;/client/List&quot; value=&quot;Show All Client Items&quot;/&gt;
&lt;/h:form&gt;
&lt;h:form&gt;
&lt;h:commandLink action=&quot;/consultant/List&quot; value=&quot;Show All Consultant Items&quot;/&gt;
&lt;/h:form&gt;
&lt;h:form&gt;
&lt;h:commandLink action=&quot;/consultantStatus/List&quot; value=&quot;Show All ConsultantStatus Items&quot;/&gt;
&lt;/h:form&gt;
&lt;h:form&gt;
&lt;h:commandLink action=&quot;/project/List&quot; value=&quot;Show All Project Items&quot;/&gt;
&lt;/h:form&gt;
&lt;h:form&gt;
&lt;h:commandLink action=&quot;/recruiter/List&quot; value=&quot;Show All Recruiter Items&quot;/&gt;
&lt;/h:form&gt;
&lt;/h:body&gt;</pre></li>
<li>Clique no link '<code>Mostrar todos os Itens do Consultor</code>'. Ao observar o código acima, você pode ver que a página de destino é <code>/consultant/List.xhtml</code>. (No JSF 2.x, a extensão do arquivo é deduzida devido à navegação implícita.) <br> <img alt="Página Consultores" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/empty-consultants-list.png" title="A tabela Consultores está vazia no momento"> <br> Atualmente, o banco de dados não contém dados de amostra. É possível adicionar dados manualmente clicando no link '<code>Criar Novo Consultor</code>' e utilizando o Web form fornecido. A página <code>/consultant/Create.xhtml</code> é carregada para que seja exibida. Você também pode executar um script SQL no IDE para preencher as tabelas com os dados de amostra. As subseções a seguir exploram ambas as opções.</li>
</ol>
<p>Você pode clicar no link do índice para voltar à lista de links da página de boas-vindas. Os links oferecem uma view dos dados contidos em cada tabela do banco de dados e carrega o arquivo <code>List.xhtml</code> de cada pasta de entidade para que seja exibido. Conforme será demonstrado posteriormente, após adicionar os dados às tabelas, outros links serão exibidos em cada entrada permitindo que você exiba (<code>View.xhtml</code>), edite (<code>Edit.xhmtl</code>) e destrua os dados de um único registro da tabela.</p>
<p class="notes"><strong>Observação.</strong> Se a implantação da aplicação falhar, consulte a <a href="#troubleshooting">seção de solução de problemas</a> a seguir. (Consulte também a seção de solução de problemas de <a href="mysql-webapp.html#troubleshoot">Criando uma Aplicação Web Simples Usando um Banco de Dados MySQL</a>.)</p>
<h3 id="populateDB">Preenchendo o Banco de Dados com um Script SQL</h3>
<p>Execute o script fornecido, que gera dados de amostra para as tabelas do banco de dados. O script (<code>mysql_insert_data_consult.sql</code>) está incluído no arquivo ZIP Consultando o Banco de Dados da Agência que pode ser obtido por download da <a href="#requiredSoftware">tabela de software exigido</a>.</p>
<p>Dependendo do servidor de banco de dados com que estiver trabalhando (MySQL ou JavaDB), você poderá executar o script fornecido, que irá gerar dados de amostra para as tabelas de banco de dados. Para o MySQL, esse é o script <code>mysql_insert_data_consult.sql</code>. Para o JavaDB, esse é o script <code>javadb_insert_data_consult.sql</code>. Ambos os scripts são incluídos nos respectivos arquivos compactados, que podem ser obtidos por download na <a href="#requiredSoftware">tabela de software exigido</a>.</p>
<ol>
<li>Selecione Arquivo > Abrir Arquivo no menu principal e, em seguida, vá até o local do script no seu computador. Clique em Abrir. O arquivo é aberto automaticamente no editor SQL do IDE.</li>
<li>Certifique-se de que o banco de dados <code>consult</code> esteja selecionado na lista drop-down Conexão da barra de ferramentas do editor SQL.<br><img alt="Tela do editor SQL e o script de dados inserido" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/run-sql-insert.png" title="Abrir o script no editor SQL do IDE">
<p>
Clique com o botão direito do mouse no editor e selecione Executar Instrução ou clique no botão ( <img alt="Botão Executar SQL" src="../../../images_www/articles/72/web/jsf20-crud/run-sql-btn.png"> ) Executar SQL. É possível ver o resultado da execução do script na janela de Saída.</p></li>
<li>Reinicie o GlassFish Server. Essa é uma etapa necessária para ativar o servidor e recarregar e armazenar no cache os novos dados contidos no banco de dados <code>consult</code>. Para isso, clique na guia do GlassFish Server na janela de Saída (A guia do GlassFish Server exibirá o log do servidor.), em seguida, clique no botão ( <img alt="Botão Reiniciar Servidor" src="../../../images_www/articles/72/web/jsf20-crud/glassfish-restart.png"> ) Reiniciar Servidor na margem esquerda. O servidor para e, em seguida, reinicia.</li>
<li>Execute o projeto novamente e clique no link '<code>Mostrar Todos os Itens do Consultor</code>'. Você verá que a lista não está mais vazia.<br><a href="../../../images_www/articles/72/web/jsf20-crud/consultants-list.png" id="consultantsList" rel="lytebox" title="A página de Facelets exibe as entradas contidas na tabela Consultores"><img alt="Página de Consultores exibindo as entradas da tabela" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/consultants-list-small.png"></a>
<div class="feedback-box float-left" style="width: 683px;">
<h3>Suporte ao Banco de Dados NetBeans</h3>
<p>É possível utilizar o visualizador de tabelas do banco de dados do IDE para exibir e modificar os dados da tabela mantidos diretamente no banco de dados. Por exemplo, clique com o botão direito do mouse na tabela <code>consultant</code> na janela Serviços e selecione Exibir Dados.</p>
<img alt="Janela Serviços - menu contextual da tabela de banco de dados" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/view-data.png" title="Selecione Exibir Dados no menu contextual das tabelas de banco de dados">
<p>A consulta SQL utilizada para executar a ação é exibida na parte superior do editor e uma exibição gráfica da tabela é exibida abaixo.</p>
<a href="../../../images_www/articles/72/web/jsf20-crud/view-data-table.png" rel="lytebox" title="Utilizar a view gráfica das tabelas de banco de dados para exibir e modificar dados ta tabela"> <img alt="Editor SQL exibindo os dados do banco de dados" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/view-data-table-small.png"></a>
<p>Clique duas vezes nas células da tabela para efetuar modificações diretamente nos dados. Clique no ícone ( <img alt="Ícone Confirmar Registros" src="../../../images_www/articles/72/web/jsf20-crud/commit-records-icon.png"> ) Confirmar Registros para confirmar as alterações feitas no banco de dados.</p>
<p>
A view gráfica oferece mais funcionalidade. Consulte <a href="../../docs/ide/database-improvements-screencast.html">Suporte ao Banco de Dados no NetBeans IDE</a> para obter mais informações.</p>
</div>
<br style="clear: both;"/></li>
</ol>
<h3 id="editorSupport">Explorando o Suporte do Editor em Páginas de Facelets</h3>
<ol>
<li>Abra a página <code>/consultant/List.xhtml</code> no editor. A linha 8 indica que a página depende do arquivo de Facelets <code>template.xhtml</code> para que ser renderizada.
<pre class="examplecode">&lt;ui:composition template=&quot;/template.xhtml&quot;&gt;</pre>
<p class="tips">Para exibir os números das linhas, clique com o botão direito do mouse na margem esquerda do editor e selecione Mostrar Números de Linhas.</p></li>
<li>Utilize a caixa de diálogo Ir para Arquivo do IDE para abrir o arquivo <code>template.xhtml</code>. Pressione Alt-Shift-O (Ctrl-Shift-O no Mac) e, em seguida, digite <code>modelo</code>.<br><img alt="Caixa de diálogo Ir para Arquivo" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/go-to-file.png" title="Utilizar a caixa de diálogo Ir para Arquivo para abrir rapidamente arquivos do projeto">
<p>Clique em OK (ou pressione Enter).</p></li>
<li>O modelo aplica as tags <code>&lt;ui:insert></code> para inserir o conteúdo de outros arquivos no título e corpo. Coloque o cursor na tag <code>&lt;ui:insert></code> e pressione Ctrl-Espaço para chamar uma janela pop-up de documentação.<br><img alt="Pop-up de documentação exibida no Editor" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/doc-popup.png" title="Pressione Ctrl-Espaço para chamar um pop-up de documentação nas tags de Facelets">
<p>É possível pressionar Ctrl-Espaço nas tags JSF e seus atributos para chamar o pop-up da documentação. A documentação exibida é obtida das descrições fornecidas na <a href="http://javaserverfaces.java.net/nonav/docs/2.1/vdldocs/facelets/index.html">Documentação da Biblioteca de Tags JSF</a> Oficial.</p></li>
<li>Volte para o arquivo <code>List.xhtml</code> (pressione Ctrl-Tab). As tags <code>&lt;ui:define></code> são utilizadas para definir o conteúdo que será aplicado ao título e ao corpo do modelo. Esse padrão é utilizado nos quatro arquivos de Facelets (<code>Create.xhtml</code>, <code>Edit.xhtml</code>, <code>List.xhtml</code> e <code>View.xhtml</code>) gerados para cada classe de entidade.</li>
<li>Coloque seu cursor em qualquer uma das expressões EL utilizadas nas mensagens localizadas contidas no arquivo <code>Bundle.properties</code>. Pressione Ctrl-Espaço para exibir a mensagem localizada. <br> <a href="../../../images_www/articles/72/web/jsf20-crud/localized-messages.png" rel="lytebox" title="Exibir mensagens localizadas utilizando o suporte à funcionalidade autocompletar código do editor"><img alt="Mensagens pop-up da funcionalidade autocompletar código do conjunto de propriedades" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/localized-messages-small.png"></a>
<p>Na imagem acima, você pode ver que a expressão EL é determinada como '<code>List</code>', que é aplicada ao título do modelo e pode ser verificada na página renderizada no browser.</p></li>
<li>Navegue até a parte inferior do arquivo e localize o código do link <code>Criar novo consultor</code> (Linha 92). Trata-se do seguinte:
<pre class="examplecode">
&lt;h:commandLink action=&quot;#{consultantController.prepareCreate}&quot; value=&quot;#{bundle.ListConsultantCreateLink}&quot;/&gt;</pre></li>
<li>Pressione Ctrl-Espaço no atributo <code>action</code> do <code>commandLink</code> para chamar a janela pop-up da documentação. <br><br> O atributo <code>ação</code> indica o método que manipula a solicitação quando o link é clicado no browser. A documentação a seguir será fornecida: <br><br>
<div class="indent" style="width:680px">
<em>MethodExpression, que representa a ação da aplicação a qual será chamada quando este componente for ativado pelo usuário. A expressão deve ser interpretada como um método público que não toma nenhum parâmetro e retorna um Object (o toString() do qual é chamado para gerar o resultado lógico) que será passado para o NavigationHandler desta aplicação.</em></div>
<br> Em outras palavras, o valor de <code>action</code> se refere normalmente a um método em um bean gerenciado pelo JSF que é avaliado como uma <code>String</code>. Então, a string é utilizada pelo <code>NavigationHandler</code> do JSF para encaminhar a solicitação para a view apropriada. É possível verificar isso nas etapas a seguir.</li>
<li>Coloque o cursor no <code>consultantController</code> e pressione Ctrl-Espaço. A funcionalidade autocompletar código do editor indica que <code>consultantController</code> é um Bean gerenciado pelo JSF.<br><img alt="Funcionalidade autocompletar código chamada no editor" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/code-completion-managed-bean.png" title="A funcionalidade autocompletar código é fornecida para Beans gerenciados pelo JSF"></li>
<li>Mova o cursor para <code>prepareCreate</code> e pressione Ctrl-Espaço. A funcionalidade autocompletar código lista os métodos contidos no Bean gerenciado <code>ConsultantController</code>.<br><img alt="Funcionalidade autocompletar código chamada no editor" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/code-completion-properties.png" title="A funcionalidade autocompletar código é fornecida para métodos de classe"></li>
<li>Pressione Ctrl (&amp;#8984 no Mac) e, em seguida mova o mouse sobre <code>prepareCreate</code>. É formado um link, que permite ir diretamente para o método <code>prepareCreate()</code> no Bean gerenciado <code>ConsultantController</code>.<br><img alt="Link exibido no editor" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/editor-navigation.png" title="Utilizar a navegação do editor para ir rapidamente até o código-fonte"></li>
<li>Clique no link e exiba o método <code>prepareCreate()</code> (exibido a seguir).
<pre class="examplecode">
public String prepareCreate() {
current = new Consultant();
selectedItemIndex = -1;
return &quot;Create&quot;;
}</pre>
O método retornará <code>Create</code>. O <code>NavigationHandler</code> coleta informações em segundo plano e aplica a string <code>Create</code> ao caminho que indica a view enviada em resposta à solicitação: <code>/consultant/<strong>Create</strong>.xhtml</code>. (No JSF 2.x, a extensão do arquivo é deduzida devido à navegação implícita.)</li>
</ol>
<h3 id="dbIntegrity">Explorando a Integridade do Banco de Dados com Validação de Campo</h3>
<ol>
<li>Na <a href="#consultantsList">página Lista de Consultores</a> do browser, clique no link '<code>Criar Novo Consultor</code>'. Conforme demonstrado na subseção anterior, isso carrega a página <code>/consultant/Create.xhtml</code> para que seja renderizada.</li>
<li>Informe os detalhes a seguir no form: Temporariamente, deixe os campos <code>RecruiterId</code> e <code>StatusId</code> em branco.<br><br>
<table>
<tbody>
<tr>
<th class="tblheader" scope="col">Campo</th>
<th class="tblheader" scope="col">Valor</th>
</tr>
<tr>
<td class="tbltd1">ConsultantId</td>
<td class="tbltd1">2</td>
</tr>
<tr>
<td class="tbltd1">Email</td>
<td class="tbltd1">jack.smart@jsfcrudconsultants.com</td>
</tr>
<tr>
<td class="tbltd1">Password</td>
<td class="tbltd1">jack.smart</td>
</tr>
<tr>
<td class="tbltd1">HourlyRate</td>
<td class="tbltd1">75</td>
</tr>
<tr>
<td class="tbltd1">BillableHourlyRate</td>
<td class="tbltd1">110</td>
</tr>
<tr>
<td class="tbltd1">HireDate</td>
<td class="tbltd1">22/07/2008</td>
</tr>
<tr>
<td class="tbltd1">Retomar</td>
<td class="tbltd1">Sou um ótimo consultor. Contrate-me - Você não vai se arrepender!</td>
</tr>
<tr>
<td class="tbltd1">RecruiterId</td>
<td class="tbltd1">---</td>
</tr>
<tr>
<td class="tbltd1">StatusId</td>
<td class="tbltd1">---</td>
</tr>
</tbody>
</table></li>
<li>Clique em Salvar. Quando você fizer isso, um erro de validação será sinalizado no campo <code>StatusId</code>. <br> <img alt="Página Criar Novo Consultor contendo dados de amostra" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/create-new-consultant.png" title="Informar os dados de amostra no form"> <br> Por que aconteceu isso? Examine novamente o <a href="#er-diagram">diagrama de relacionamento com entidades do banco de dados da Agência de Consultoria</a>. Conforme apresentado na <a href="#relationships">tabela de relacionamentos</a> acima, as tabelas <code>CONSULTANT</code> e <code>CONSULTANT_STATUS</code> compartilham um relacionamento que não pode ser nulo, um para muitos. Portanto, cada entrada da tabela <code>CONSULTANT</code> deve conter uma referência a uma entrada na tabela <code>CONSULTANT_STATUS</code>. Isso é indicado pela chave estrangeira <code>consultant_fk_consultant_status</code> que vincula as duas tabelas.
<p class="tips">É possível exibir as chaves estrangeiras contidas nas tabelas expandindo o nó Chaves Estrangeiras da tabela na janela Serviços (Ctrl-5; &amp;#8984-5 no Mac).</p>
<img alt="Janela Serviços - chaves estrangeiras para a tabela de consultores" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/consultant-fk.png" title="Examinar os atributos da chave estrangeira na janela Serviços"></li>
<li>Para solucionar o erro de validação, selecione <code>entity.ConsultantStatus[statusId=A]</code> na lista drop-down <code>StatusId</code>. <br><br> <strong class="notes">Observação: </strong>Você pode deixar o campo <code>RecruiterId</code> em branco. Conforme indicado no <a href="#er-diagram">diagrama de relacionamento com as entidades do banco de dados</a>, há um relacionamento que pode ser nulo, um para muitos entre as tabelas <code>CONSULTANT</code> e <code>RECRUITER</code>, indicando que as entradas em <code>CONSULTANT</code> não precisam estar associadas a uma entrada de <code>RECRUITER</code>.</li>
<li>Clique em Salvar. Será exibida uma mensagem indicando que a entrada do consultor foi salva com êxito. Se você clicar em <code>Exibir Todos os Itens do Consultor</code>, você verá a nova entrada listada na tabela.</li>
</ol>
<p>Em geral, as páginas de Facelets geradas produzem erros para entradas do usuário que introduz:</p>
<ul>
<li>campos vazios em células de tabela que não podem ser nulas.</li>
<li>modificações em dados que não podem ser alterados (por exemplo, chaves primárias).</li>
<li>inserção de dados que não são do tipo correto.</li>
<li>modificações em dados quando uma view do usuário não estiver mais sincronizada com o banco de dados.</li>
</ul>
<h3 id="editEntity">Editando as Classes de Entidade</h3>
<p>Na subseção anterior, você viu como a lista drop-down <code>StatusId</code> forneceu a opção mais complexa <code>entity.ConsultantStatus[statusId=A]</code>. Você já deve ter notado que o texto exibido em cada item desta lista drop-down é a representação de uma string de cada entidade <code>ConsultantStatus</code> encontrada (por exemplo, o método <code>toString()</code> da classe de entidade é chamado).</p>
<p>Essa subseção demonstra como você pode utilizar a funcionalidade autocompletar código, a documentação e o suporte à navegação do editor para chegar a essa conclusão. Também oferece uma mensagem mais amigável para a lista drop-down.</p>
<ol>
<li id="markup">Abra o arquivo <code>/consultant/Create.xhtml</code> no editor. Trata-se do form Criar Novo Consultor que você acaba de exibir no browser. Role para baixo até o código da lista drop-down <code>StatusId</code> (ilustrado em <strong>negrito</strong> abaixo).
<pre class="examplecode">
&lt;h:outputLabel value=&quot;#{bundle.CreateConsultantLabel_resume}&quot; for=&quot;resume&quot; /&gt;
&lt;h:inputTextarea rows=&quot;4&quot; cols=&quot;30&quot; id=&quot;resume&quot; value=&quot;#{consultantController.selected.resume}&quot; title=&quot;#{bundle.CreateConsultantTitle_resume}&quot; /&gt;
<strong>&lt;h:outputLabel value=&quot;#{bundle.CreateConsultantLabel_statusId}&quot; for=&quot;statusId&quot; /&gt;
&lt;h:selectOneMenu id=&quot;statusId&quot; value=&quot;#{consultantController.selected.statusId}&quot; title=&quot;#{bundle.CreateConsultantTitle_statusId}&quot; required=&quot;true&quot; requiredMessage=&quot;#{bundle.CreateConsultantRequiredMessage_statusId}&quot;&gt;
&lt;f:selectItems value=&quot;#{consultantStatusController.itemsAvailableSelectOne}&quot;/&gt;
&lt;/h:selectOneMenu&gt;</strong>
&lt;h:outputLabel value=&quot;#{bundle.CreateConsultantLabel_recruiterId}&quot; for=&quot;recruiterId&quot; /&gt;
&lt;h:selectOneMenu id=&quot;recruiterId&quot; value=&quot;#{consultantController.selected.recruiterId}&quot; title=&quot;#{bundle.CreateConsultantTitle_recruiterId}&quot; &gt;
&lt;f:selectItems value=&quot;#{recruiterController.itemsAvailableSelectOne}&quot;/&gt;
&lt;/h:selectOneMenu&gt;
&lt;/h:panelGrid&gt;</pre></li>
<li>Examine o <code>value</code> aplicado à tag <code>&lt;f:selectItems></code>. O atributo <code>value</code> determina o texto exibido para cada item na lista drop-down. <br><br> Pressione Ctrl-Espaço em <code>itemsAvailableSelectOne</code>. A funcionalidade autocompletar código do editor indica que o método <code>getItemsAvailableSelectOne()</code> do <code>ConsultantStatusController</code> retorna um array de objetos <code>SelectItem</code>.<br><img alt="Funcionalidade autocompletar código chamada no editor" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/code-completion-returned-object.png" title="A funcionalidade autocompletar código exibe as classes retornadas para os métodos"></li>
<li>Pressione Ctrl (&amp;#8984 no Mac) e, em seguida, mova o mouse sobre <code>itemsAvailableSelectOne</code>. É formado um link que permite ir diretamente para o método <code>getItemsAvailableSelectOne()</code> no código-fonte da entidade <code>ConsultantStatus</code>. Clique neste link.</li>
<li>Coloque o cursor sobre o valor de retorno <code>SelectItem[]</code> na assinatura do método e pressione Ctrl-Espaço para chamar a janela pop-up da documentação.<br><img alt="Pop-up de documentação chamada na classe Java" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/documentation-select-item.png" title="Pressione Ctrl-Espaço para chamar o suporte à documentação">
<p class="tips">Clique no ícone ( <img alt="Ícone Web browser" src="../../../images_www/articles/72/web/jsf20-crud/web-browser-icon.png"> ) Web browser na janela da documentação para abrir o Javadoc em um Web browser externo.</p>
Como você pode ver, a classe <code>SelectItem</code> pertence ao framework JSF. O componente <code>UISelectOne</code>, conforme mencionado na documentação, é representado pela tag <code>&lt;h:selectOneMenu></code> da marcação que você examinou na <a href="#markup">Etapa 1</a> acima.</li>
<li>Pressione Ctrl (&amp;#8984 no Mac) e, em seguida, mova o mouse sobre <code>findAll()</code>. Uma janela pop-up será exibida com a assinatura do método. <br> <img alt="Pop-up da assinatura do método" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/method-signature.png" title="Exibir pop-ups das assinaturas do método no editor"> <br> É possível observar que aqui o <code>ejbFacade.findAll()</code> retorna uma <code>Lista</code> de objetos <code>ConsultantStatus</code>.</li>
<li>Vá para <code>JsfUtil.getSelectItems</code>. Coloque o mouse sobre <code>getSelectItems</code> e pressione Ctrl (&amp;#8984 no Mac), a seguir, clique no link exibido. <br><br> <strong class="notes">Observação: </strong>Lembre-se de que <code>JsfUtil</code> é uma das classes de utilitário geradas ao concluir o <a href="#jsfPagesEntityClasses">assistente de Páginas JSF de Classes de Entidade</a>. <br><br> O método cria o loop por meio da lista de entidades (por exemplo, a <code>List</code> de objetos <code>ConsultantStatus</code>), criando um <code>SelectItem</code> para cada entidade. Conforme indicado abaixo em <strong>negrito</strong>, cada <code>SelectItem</code> é criado utilizando o objeto da entidade e um <em>label</em> para o objeto.
<pre class="examplecode">
public static SelectItem[] getSelectItems(List&lt;?&gt; entities, boolean selectOne) {
int size = selectOne ? entities.size() + 1 : entities.size();
SelectItem[] items = new SelectItem[size];
int i = 0;
if (selectOne) {
items[0] = new SelectItem(&quot;&quot;, &quot;---&quot;);
i++;
}
<strong>for (Object x : entities) {
items[i++] = new SelectItem(x, x.toString());
}</strong>
return items;
}</pre>
<p>O label é criado utilizando o método <code>toString()</code> da entidade e corresponde à representação do objeto quando renderizado na resposta. (Consulte a definição do Javadoc para o construtor <code>SelectItem(java.lang.Object value, java.lang.String label)</code>.)</p>
<p>
Agora que você verificou que o método <code>toString()</code> da entidade é o método renderizado no browser ao exibir os itens em uma lista drop-down, modifique o método <code>toString()</code> do <code>ConsultantStatus</code>.</p>
</li>
<li>Abra a classe de entidade <code>ConsultantStatus</code> no editor. Modifique o método <code>toString</code> para retornar <code>statusId</code> e <code>description</code>. Trata-se das propriedades da entidade que correspondem às duas colunas da tabela <code>CONSULTANT_STATUS</code>.
<pre class="examplecode">public String toString() {
return <strong>statusId + ", " + description;</strong>
}</pre></li>
<li>Execute o projeto novamente. Quando o browser exibir a página de boas-vindas, clique no link <code>Mostrar Todos os Itens do Consultor</code> e, em seguida, em <code>Criar Novo Consultor</code>.
<p>
Inspecione a lista drop-down <code>StatusId</code>. Você verá que agora ela exibe o ID de status e a descrição do registro contido na tabela <code>CONSULTANT_STATUS</code> do banco de dados.</p>
<img alt="Exibição no browser da lista drop-down StatusId" class="margin-around b-all" src="../../../images_www/articles/72/web/jsf20-crud/drop-down.png" title="A lista drop-down StatusId exibe itens de acordo com o método toString() da entidade ConsultantStatus">
</li>
</ol>
</div>
<h2 id="troubleshooting">Solução de Problemas</h2>
<p>Dependendo da sua configuração, a implantação da aplicação no servidor poderá falhar e você talvez veja a seguinte mensagem na janela Saída.
</p>
<pre class="examplecode">GlassFish Server 4 is running.
In-place deployment at /MyDocuments/ConsultingAgency/build/web
GlassFish Server 4, deploy, null, false
/MyDocuments/ConsultingAgency/nbproject/build-impl.xml:1045: The module has not been deployed.
See the server log for details.</pre>
<p>A causa mais comum da falha é um problema ao gerar os recursos JDBC no servidor. Se esse for o caso, você provavelmente verá uma mensagem semelhante à seguinte na guia de log do servidor, na janela Saída.
</p>
<pre class="examplecode">Severe: Exception while preparing the app : Invalid resource : jdbc/consult__pm
com.sun.appserv.connectors.internal.api.ConnectorRuntimeException: Invalid resource : jdbc/consult__pm</pre>
<p class=tips>Se a guia de log do servidor não for aberta, será possível abri-la clicando com o botão direito do mouse no nó GlassFish Server, na janela Serviços, e escolhendo Exibir Log do Servidor de Domínio.</p>
<p>Essa aplicação exige dois recursos JDBC:</p>
<ul>
<li>Recurso ou Fonte de Dados JDBC. A aplicação usa a pesquisa JNDI para localizar o recurso JDBC. Se você examinar a unidade de persistência (<code>persistence.xml</code>), poderá ver que o nome da JNDI para a fonte de dados JTA dessa aplicação é <code>jdbc/consult</code>.
<p>O recurso JDBC identifica o pool de conexões atualmente utilizado pela aplicação.</p></li>
<li>Pool de Conexões JDBC. O pool de conexões especifica os detalhes da conexão do banco de dados, o que inclui local, nome do usuário e senha. O pool de conexões usado nessa aplicação é <code>consultPool</code>.</li>
</ul>
<p>O recurso JDBC e o pool de conexões são especificados no arquivo <code>glassfish-resources.xml</code>. Você pode abrir <code>glassfish-resources.xml</code> no editor expandindo o nó Recursos do Servidor na janela Projetos e clicando duas vezes no arquivo. O arquivo será semelhante ao seguinte:</p>
<pre class="examplecode">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd"&gt;
&lt;resources&gt;
&lt;jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="consultPool" non-transactional-connections="false" ping="false" pool-resize-quantity="2" pooling="true" res-type="javax.sql.DataSource" statement-cache-size="0" statement-leak-reclaim="false" statement-leak-timeout-in-seconds="0" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false"&gt;
&lt;property name="serverName" value="localhost"/&gt;
&lt;property name="portNumber" value="3306"/&gt;
&lt;property name="databaseName" value="consult"/&gt;
&lt;property name="User" value="root"/&gt;
&lt;property name="Password" value="nb"/&gt;
&lt;property name="URL" value="jdbc:mysql://localhost:3306/consult?zeroDateTimeBehavior=convertToNull"/&gt;
&lt;property name="driverClass" value="com.mysql.jdbc.Driver"/&gt;
/&lt;jdbc-connection-pool&gt;
&lt;jdbc-resource enabled="true" jndi-name="jdbc/consult" object-type="user" pool-name="consultPool"/&gt;
/&lt;resources&gt;</pre>
<p>Em <code>glassfish-resources.xml</code>, você poderá ver que o recurso JDBC <code>jdbc/consult</code> identifica <code>consultPool</code> como nome do pool de conexões. É possível também ver as propriedades de <code>consultPool</code>. Nessa aplicação, apenas uma fonte de dados e um pool de conexões são definidos em <code>glassfish-resources.xml</code>. Em alguns casos, convém especificar recursos adicionais, por exemplo, para identificar um armazenamento de dados temporário usado apenas para fins de desenvolvimento ou teste.</p>
<p>Se o recurso JDBC e o pool de conexões não tiverem sido gerados automaticamente no servidor quando você executou a aplicação, será possível realizar as etapas a seguir para criar manualmente os recursos na Console Admin do GlassFish.</p>
<ol>
<li>Abra <code>glassfish-resources.xml</code> no editor se não tiver feito isso ainda.
<p>Use os valores de propriedade especificados em <code>glassfish-resources.xml</code> ao criar o recurso JDBC e o pool de conexões.</p></li>
<li>Clique com o botão direito no nó GlassFish Server, na janela Serviços, e escolha Abrir Console Admin do Domínio no menu pop-up para abrir a Console do GlassFish no browser.</li>
<li>No painel de navegação Tarefas Comuns da Console do GlassFish, expanda o nó <strong>JDBC</strong> e os nós <strong>Recursos JDBC</strong> e <strong>Pool de Conexões JDBC</strong>. <br> <a href="../../../images_www/articles/80/web/jsf20-crud/gf-admin-console-lg.png"> <img alt="Exibição do browser da Console Admin do GlassFish" class="margin-around b-all" src="../../../images_www/articles/80/web/jsf20-crud/gf-admin-console-sm.png" title="Clique para ver a imagem em tamanho normal da Console Admin do GlassFish"></a>
<p>Você pode ver os recursos JDBC que estão registrados atualmente no servidor. Será necessário criar <code>jdbc/consult</code> e <code>consultPool</code> se não estiverem listados sob o nó JDBC no painel de navegação Tarefas Comuns. Alguns recursos JDBC foram criados por padrão quando você instalou o servidor e são exibidos como subnós. </p></li>
<li>Clique no nó <strong>Pools de Conexões JDBC</strong> e clique em Novo no painel Novo Pool de Conexões JDBC. <br> <img alt="Exibição do browser do painel Novo Pool de Conexões JDBC" class="margin-around b-all" src="../../../images_www/articles/80/web/jsf20-crud/gf-new-jdbc-pool1.png" title="Painel Novo Pool de Conexões JDBC na Console Admin do GlassFish"></li>
<li>Digite <strong>consultPool</strong> como Nome do Pool, selecione <strong>javax.sql.ConnectionPoolDataSource</strong> como Tipo de Recurso e selecione <strong>MySql</strong> como Fornecedor do Driver de Banco de Dados. Clique em Próximo.</li>
<li>Na Etapa 2, localize e especifique os valores das propriedades <strong>URL</strong>, <strong>nome do usuário</strong> e <strong>senha</strong>. Clique em Finalizar. <br> <img alt="Exibição do browser do segundo painel Novo Pool de Conexões JDBC" class="margin-around b-all" src="../../../images_www/articles/80/web/jsf20-crud/gf-new-jdbc-pool2.png" title="Painel Novo Pool de Conexões JDBC na Console Admin do GlassFish">
<p class="tips">Os valores das propriedades se encontram em <code>glassfish-resources.xml</code>.</p>
<p>O novo pool de conexões é criado no servidor quando você clica em Concluir e um nó do pool de conexões é exibido sob o nó Pools de Conexões JDBC.</p></li>
<li>Clique no nó <strong>Recursos JDBC</strong> no painel de navegação Tarefas Comuns e clique em Novo.</li>
<li>Digite <strong>jdbc/consult</strong> como Nome da JNDI e selecione <strong>consultPool</strong> na lista drop-down Nome do Pool. Clique em OK. <br> <img alt="Exibição do browser do painel Novo Recurso JDBC" class="margin-around b-all" src="../../../images_www/articles/80/web/jsf20-crud/gf-new-jdbc-resource.png" title="Painel Novo Recurso JDBC na Console Admin do GlassFish">
<p>O novo recurso JDBC é criado no servidor quando você clica em OK e um nó para o recurso é exibido sob o nó Recursos JDBC.</p>
<p>Na janela Serviço do IDE, você pode expandir o nó Recursos no GlassFish Server e ver se o IDE adicionou os novos recursos. Pode ser necessário atualizar a view (clique com o botão direito do mouse em Recursos e escolha Atualizar) para exibir as alterações.</p>
<img alt="captura de tela da janela Serviços no IDE" class="margin-around b-all" src="../../../images_www/articles/80/web/jsf20-crud/gf-services-jdbc-resources.png" title="Recursos JDBC exibidos na janela Serviços do IDE"></li>
</ol>
<p>Para obter mais dicas sobre solução de problemas ao usar o MySQL e o IDE, consulte os seguintes documentos:</p>
<ul>
<li>Tutorial <a href="../ide/mysql.html">Estabelecendo Conexão com um Banco de Dados MySQL</a>.</li>
<li>A seção de solução de problemas de <a href="mysql-webapp.html#troubleshoot">Criando uma Aplicação Web Simples Usando um Banco de Dados MySQL</a></li>
</ul>
<div class="feedback-box">
<a href="/about/contact_form.html?to=3&amp;subject=Feedback:%20Creating%20a%20JSF%202.0%20CRUD%20Application">Enviar Feedback neste Tutorial</a>
</div>
<br style="clear:both;" />
<h2 id="seealso">Consulte Também</h2>
<p>Para obter mais informações sobre o JSF 2.x, consulte os recursos a seguir:</p>
<div class="indent">
<h3>Tutoriais e Artigos NetBeans</h3>
<ul>
<li><a href="jsf20-intro.html">Introdução ao JavaServer Faces 2.x no NetBeans IDE</a></li>
<li><a href="jsf20-support.html">Suporte a JSF 2.x no NetBeans IDE</a></li>
<li><a href="../../samples/scrum-toys.html">Scrum Toys: A Aplicação de Amostra Completa do JSF 2.0</a></li>
<li><a href="../javaee/javaee-gettingstarted.html">Conceitos Básicos sobre Aplicações do Java EE</a></li>
<li><a href="../../trails/java-ee.html">Trilha do Aprendizado do Java EE e Java Web</a></li>
</ul>
<h3>Recursos Externos</h3>
<ul>
<li><a href="http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html">Tecnologia JavaServer Faces</a> (homepage Oficial)</li>
<li><a href="http://jcp.org/aboutJava/communityprocess/final/jsr314/index.html">Especificação do JSR 314 para o JavaServer Faces 2.0</a></li>
<li>Capítulo <a href="http://docs.oracle.com/javaee/7/tutorial/doc/jsf-intro.htm">Tecnologia do JavaServer Faces</a> no Tutorial Java EE 7</li>
<li><a href="http://javaserverfaces.dev.java.net/">Projeto Mojarra GlassFish</a> (Implementação oficial de referência do JSF 2.x)</li>
<li><a href="http://forums.oracle.com/forums/forum.jspa?forumID=982">Fóruns de Discussão OTN: JavaServer Faces</a></li>
<li><a href="http://www.jsfcentral.com/">Central do JSF</a></li>
</ul>
<h3>Blogs</h3>
<ul>
<li><a href="http://www.java.net/blogs/edburns/">Ed Burns</a></li>
<li><a href="http://www.java.net/blogs/driscoll/">Jim Driscoll</a></li>
</ul>
</div>
</body>
</html>