O que fazer ao receber o Caso de Uso NOMEDAENTIDADE CRUD ?
Um caso de uso envolve uma regra de negocio com as telas e entidades associadas na operação. No
documento é descrito todas as validações de tela e o fluxo do processo. No caso de uso CRUD, as
funcionalidades são as Create, Retrieve, Update e Delete, ou seja, a criação de uma tela de pesquisa e uma
tela para alterar/inserir os registros. Normalmente estas atividades CRUD são desenvolvidas com
ferramentas de geração de código, no entanto para o nosso caso (didático) faremos nós mesmos as
estruturas para entender como funciona o fluxo das chamadas.
1 - Começe criando as entidades envolvidas.
Cliente, Produto, Fornecedor, Usuario, etc. Se as classes destas entidades ainda não existem começe
criando-as. As classes precisam seguir alguns padrões pois utilizam recursos de Annotations, para facilitar a
integração com o framework de persistência Hibernate. Estas classes recebem o nome de classes de
domínio pois estão diretamente relacionados com regras de negocio. No “caso de uso” você ira receber a
estrutura da classe em formato UML (diagrama de class). Se esta é uma tarefa de Laboratorio, você deve
utilizar a classe que voce modelou.
Diagrama de Classe
Modelo de Entidade-Relacionamento (MER)
Codigo Java
package br.com.twosolutions.simplemodularerp.domain;
import
import
import
import
java.io.Serializable;
java.util.Date;
java.util.HashSet;
java.util.Set;
import
import
import
import
import
import
import
import
javax.persistence.CascadeType;
javax.persistence.Column;
javax.persistence.Entity;
javax.persistence.GeneratedValue;
javax.persistence.Id;
javax.persistence.JoinColumn;
javax.persistence.ManyToMany;
javax.persistence.ManyToOne;
import
import
import
import
javax.persistence.OneToMany;
javax.persistence.Table;
javax.persistence.Temporal;
javax.persistence.TemporalType;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="GELADEIRAS")
public class Geladeira implements VO {
private
private
private
private
private
private
private
Integer id;
String marca;
String modelo;
String cor;
Double volume;
Integer voltagem;
Date dataRevisao;
// N - 1
private GeladeiraCategoria geladeiraCategoria;
// 1 - N
private Set<Alimento> alimentos;
@Id @GeneratedValue(generator="generator")
@GenericGenerator(name="generator", strategy = "increment")
@Column(name="ID_GELADEIRA")
public Integer getId() {
return id;
}
public void setId(Serializable id) {
this.id = (Integer)id;
}
@Column(name="COR")
public String getCor() {
return cor;
}
public void setCor(String cor) {
this.cor = cor;
}
@Column(name="MARCA")
public String getMarca() {
return marca;
}
public void setMarca(String marca) {
this.marca = marca;
}
@Column(name="MODELO")
public String getModelo() {
return modelo;
}
public void setModelo(String modelo) {
this.modelo = modelo;
}
@Column(name="DATA_REVISAO")
@Temporal(TemporalType.DATE)
public Date getDataRevisao() {
return dataRevisao;
}
public void setDataRevisao(Date dataRevisao) {
this.dataRevisao = dataRevisao;
}
@Column(name="VOLTAGEM")
public Integer getVoltagem() {
return voltagem;
}
public void setVoltagem(Integer voltagem) {
this.voltagem = voltagem;
}
@Column(name="VOLUME")
public Double getVolume() {
return volume;
}
public void setVolume(Double volume) {
this.volume = volume;
}
@ManyToOne
@JoinColumn(name="ID_GELADEIRA_CATEGORIA")
public GeladeiraCategoria getGeladeiraCategoria() {
return geladeiraCategoria;
}
public void setGeladeiraCategoria(GeladeiraCategoria geladeiraCategoria) {
this.geladeiraCategoria = geladeiraCategoria;
}
}
@ManyToMany(cascade={CascadeType.ALL})
@JoinColumn(name="ID_ALIMENTO")
public Set<Alimento> getAlimentos() {
return alimentos;
}
public void setAlimentos(Set<Alimento> alimentos) {
this.alimentos = alimentos;
}
public void addAlimento(Alimento alimento){
if(alimentos == null){
alimentos = new HashSet<Alimento>();
}
alimentos.add(alimento);
}
Como começar:
Utilizando o Eclipse, crie a classe dentro do pacote br.com.twosolutions.nomeprojeto.domain
Comece fazendo os atributos
Gere os Getters/Setter
Inclua as Annotations
Observações:
A classe de dominio criada deve implementar a interface VO. Esta interface é uma interface de infraestrutra, ou seja, serve de padrão para a aplicação de polimorfismo em algumas situações.
Todas os atributos da classes são declarados com private e utilizam as classes Wrappers como seus tipos
(Integer,Double,Character,etc)
Gerar os Getters/Setters, com detalhe para os atributos do tipo Collection que precisam do add
Colocar a Annotation @Entity e @Table indicando qual o nome da tabela que a classe esta associada.
Annotations é um recurso da versão 1.5, em que é possivel incluir informaçoes adicionais em algumas
estruturas.
Colocar as Annotations @Column indicando qual a coluna de cada atributo.
Para entender melhor para que serve as Annotations e Hibernate visite o site do projeto
http://www.hibernate.org
Atenção aos imports, pois nestes ficam descritos os respectivos pacotes das Annotations.
2 – Criar a Classe Form (específica do Struts)
O Framework Struts 1.2 exige que você crie uma classe que irá armazenar todos os valores que serão
utilizados nas telas. Essas classes recebem o nome de ActionForm. São classes simples que possuem os
mesmos atributos que a sua classe de domínio.
package br.com.twosolutions.simplemodularerp.form;
import java.io.Serializable;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import br.com.twosolutions.simplemodularerp.util.DateUtils;
import br.com.twosolutions.simplemodularerp.util.MonetaryUtils;
public class GeladeiraForm extends GenericForm {
private
private
private
private
private
private
private
private
private
private
Integer id;
String marca;
String modelo;
String cor;
Double volume;
String volumeStr;
Integer voltagem;
String voltagemStr;
Date dataRevisao;
String dataRevisaoStr;
// N - 1
private Integer geladeiraCategoriaId;
public void setId(Serializable id) {
if(id != null && !id.toString().equals("")){
if(id instanceof Integer){
this.id = (Integer)id;
}else{
this.id = new Integer(id.toString());
}
}
}
public Serializable getId() {
return id;
}
public String getCor() {
return cor;
}
public void setCor(String cor) {
this.cor = cor;
}
public String getMarca() {
return marca;
}
public void setMarca(String marca) {
this.marca = marca;
}
public String getModelo() {
return modelo;
}
public void setModelo(String modelo) {
this.modelo = modelo;
}
public Integer getVoltagem() {
return voltagem;
}
public void setVoltagem(Integer voltagem) {
this.voltagem = voltagem;
}
public Integer getGeladeiraCategoriaId() {
return geladeiraCategoriaId;
}
public void setGeladeiraCategoriaId(Integer geladeiraCategoriaId) {
this.geladeiraCategoriaId = geladeiraCategoriaId;
}
public Double getVolume() {
return volume;
}
public void setVolume(Double volume) {
this.volume = volume;
}
public String getVolumeStr() {
if(volume != null){
return MonetaryUtils.format(volume);
}
return "";
}
public void setVolumeStr(String volumeStr) {
this.volumeStr = volumeStr;
}
public String getVoltagemStr() {
if(voltagem != null){
return '' + voltagem;
}
return "";
}
public void setVoltagemStr(String voltagemStr) {
this.voltagemStr = voltagemStr;
}
public Date getDataRevisao() {
return dataRevisao;
}
public void setDataRevisao(Date dataRevisao) {
this.dataRevisao = dataRevisao;
}
public String getDataRevisaoStr() {
if(dataRevisao != null){
return DateUtils.format(dataRevisao);
}
return "";
}
public void setDataRevisaoStr(String dataRevisaoStr) {
this.dataRevisaoStr = dataRevisaoStr;
}
}
public ActionErrors validateSalvar(ActionMapping mapping, HttpServletRequest request){
ActionErrors errors = new ActionErrors();
try {
volume = MonetaryUtils.parse(volumeStr);
} catch (Exception e) {
ActionMessage message = new ActionMessage("geladeira.volume.invalido");
errors.add("volumeStr", message);
}
try {
dataRevisao = DateUtils.parse(dataRevisaoStr);
} catch (Exception e) {
ActionMessage message = new ActionMessage("geladeira.dataRevisao.invalido");
errors.add("dataRevisaoStr", message);
}
return errors;
}
Observações :
1 – A classe Form precisa extender de GenericForm. A classe GenericForm, assim como a interface VO, é
uma classe de infra-estrutura, específica do projeto.
2 – Adicionar todos os atributos da classe de domínio específica com os mesmos tipos
3 – Para os atributos que não são do tipo String criar um respectivo com o sufixo Str (Ex. para o atributo
volume é preciso ter o volumeStr também)
4 – Criar o metodo validateOperacao (Ex. ValidatePesquisar, validateSalvar, validateRemover) que deve
conter todas as regras de validação dos dados da tela.
5 – Para entender melhor as classes do Struts visite o site do projeto em http://jakarta.apache.org (Struts
1.2.9)
6 – No metodo de validação é preciso incluir todas as suas regras de validação que seriam realizadas na
tela, além de servir de binding para os Str. Toda variavel Str precisa ser convertida para o seu tipo.
try {
dataRevisao = DateUtils.parse(dataRevisaoStr);
} catch (Exception e) {
ActionMessage message = new ActionMessage("geladeira.dataRevisao.invalido");
errors.add("dataRevisaoStr", message);
}
Podem ocorrer situaçoes de validação de regra de negocio além da validação de parse.
if (volume < 0) {
ActionMessage message = new ActionMessage("geladeira.volume.negativo");
errors.add("volumeStr", message);
}
Se ocorrer uma exceção é preciso adicionar a descrição da exceção utilizando a classe ActionMessages do
Struts. Na sua definição a mensagem de erro na verdade é uma “chave de mensagem”. A verdadeira
mensagem de erro esta localizada no arquivo MessageResources.properties.
3 – Registrar suas mensagens no arquivo MessageResources.properties
Toda mensagem (ou texto) que utilizarmos no Struts deve ficar registrada neste arquivo de propriedades. O
benefício disto é que além de centralizarmos as mensagens, podemos utilizar o recurso de
internacionalização do Struts para suportar varias linguas na aplicação.
Cada nova propriedade segue o padrão
entidade.atributo.operacao=Mensagem
geladeira.volume.negativo=O volume nao pode ser negativo
4 – Registrar a classe de dominio no arquivo hibernate.cfg.xml
Para que o Hibernate consiga trabalhar com a classe de dominio que foi criada é preciso registra-la no
arquivo de configuração do Hibernate (/resources/hibernate.cfg.xml).
<mapping class="br.com.twosolutions.simplemodularerp.domain.Entidade" />
5 – Registrar a classe Form no arquivo struts-config.xml
Para poder utilizar a classe de Formulario e assim poder trabalhar com as validações e funcionalidades do
Struts é preciso registrar as classes Form no arquivo de configuração do Struts (/WebContent/WEBINF/struts-config.xml).
<form-bean name="EntidadeForm" type="br.com.twosolutions.simplemodularerp.form.EntidadeForm"/>
6 – Fazer o arquivo da tela com o nome Entidade.jsp
As telas são criadas utilizando tecnologia JSP. Esta é uma mistura de HTML, JAVA, TagLibs Struts e JSTL.
Muitos dos recursos utilizados na tela são padronizados para manter uma coerencia de funcionalidades
entre as diversas telas do sistema.
<%@ include file="/WEB-INF/common/Header.jsp"%>
<table>
<tr>
<td valign="top">
<html:errors/>
<html:form action="/Geladeira.do?metodo=salvar">
<table>
<tr>
<th colspan="2">Geladeira</th>
</tr>
<tr>
<td>Marca</td>
<td><html:text property="marca"/></td>
</tr>
<tr>
<td>Modelo</td>
<td><html:text property="modelo"/></td>
</tr>
<tr>
<td>Cor</td>
<td><html:text property="cor"/></td>
</tr>
<tr>
<td>Data revisao</td>
<td>
<html:text property="dataRevisaoStr" size="15"/>
<input type="image" name="anchorDataRevisaoStr"
id="anchorDataRevisaoStr" src="<%=request.getContextPath()%>/img/calendar.gif" onclick="new
CalendarPopup().select(this.form.dataRevisaoStr,'anchorDataRevisaoStr','dd/MM/yyyy'); return
false;"/>
</td>
</tr>
<tr>
<td>Categoria</td>
<td><smerp:select property="geladeiraCategoriaId"
entity="GeladeiraCategoria" valueProperty="id" labelProperty="descricao"/></td>
</tr>
</table>
<hr/>
<table border="0">
<tr>
<td colspan="2">
<jsp:include page="/associar/AssociarInclude.jsp">
<jsp:param name="label" value="Alimentos"/>
<jsp:param name="property" value="alimentos"/>
<jsp:param name="voAssociarType" value="Alimento"/>
<jsp:param name="voAssociarMethod" value="addAlimento"/>
<jsp:param name="voAssociarDescricao" value="descricao"/>
</jsp:include>
</td>
</tr>
</table>
<table border="0">
<tr>
<td>
<html:submit property="btnSalvar" value="Salvar"/>
<html:reset property="btnLimpar" value="Limpar"/>
<html:button property="btnPesquisar" value="Pesquisar" onclick="pesquisar('Geladeira');"/>
</td>
</tr>
</table>
</html:form>
</td>
</tr>
</table>
<%@ include file="/WEB-INF/common/Footer.jsp"%>
Observações :
1 – Utilizar as Tags do Struts no lugar das de HTML na parte de formularios
2 – Toda propriedade que for multivalorada (Collection, Set, List, etc) utilizar o componente preenchendo
com as respectivas propriedades
<jsp:include page="/associar/AssociarInclude.jsp">
<jsp:param name="label" value="Alimentos"/>
<jsp:param name="property" value="alimentos"/>
<jsp:param name="voAssociarType" value="Alimento"/>
<jsp:param name="voAssociarMethod" value="addAlimento"/>
<jsp:param name="voAssociarDescricao" value="descricao"/>
</jsp:include>
3 – Para as propriedades que são datas deve adicionar a parte de montagem do calendario
<input type="image" name="anchorDataRevisaoStr" id="anchorDataRevisaoStr" src="img/calendar.gif"
onclick="new CalendarPopup().select(this.form.dataRevisaoStr,'anchorDataRevisaoStr','dd/MM/yyyy');
return false;"/>
4 – Para as propriedades que são associações de outras classes utilizar um componente de montagem de
combo com dados específicos.
<smerp:select property="geladeiraCategoriaId" entity="GeladeiraCategoria" valueProperty="id"
labelProperty="descricao"/>
7 – Fazer o arquivo PesquisarEntidade.jsp
<%@ include file="/WEB-INF/common/Header.jsp"
%>
<br/>
<html:form action="/Geladeira.do?metodo=pesquisar">
<table border="0">
<tr>
<td>
<fieldset>
<legend><font color='red'>Filtros de Pesquisa</font></legend>
<table>
<tr>
<td>Codigo:<br/>
<html:text property="id" size="15"/>
</td>
</tr>
<tr>
<td colspan="2" align="left"><html:submit value="Buscar"/></td>
</tr>
</table>
</fieldset>
</td>
</tr>
</table>
</html:form>
<form method="POST" id="mainForm">
<input type="hidden" name="id">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<th width="1"><hwp:pagedtitle label="#" property="id"/></th>
<th width="200"><hwp:pagedtitle label="Marca" property="marca"/></th>
<th width="200"><hwp:pagedtitle label="Modelo" property="modelo"/></th>
<th width="1">Acao</th>
</tr>
<c:forEach var="entity" items="${resultadoPesquisaGeladeira}" varStatus="status">
<tr bgcolor="#FFFFFF" onmouseover="this.style.backgroundColor='#FFFF99'"
onmouseout="this.style.backgroundColor='#FFFFFF'">
<td align="left" nowrap="nowrap">${entity.id}</td>
<td align="left" nowrap="nowrap">${entity.modelo}</td>
<td align="left" nowrap="nowrap">${entity.marca}</td>
<td>
<c:if test="${param.popup != '1'}">
<input type="image" src="img/visualizar.png" onclick="visualizar(this,'Geladeira','${entity.id}');">
<input type="image" src="img/editar.png" onclick="editar(this,'Geladeira','${entity.id}');">
<input type="image" src="img/remover.png" onclick="remover(this,'Geladeira','${entity.id}');">
</c:if>
</td>
</tr>
</c:forEach>
<tr>
<th colspan="3" nowrap="nowrap"><hwp:pagedlink name="resultadoPesquisaGeladeira"
label="Ant" number="-10"/> <hwp:pagedlink name="resultadoPesquisaGeladeira" label="Anterior"
number="-1"/> <hwp:spn
name="resultadoPesquisaGeladeira"/>&nbsp;Itens&nbsp;<b>${resultadoPesquisaGeladeira_total}</b>
<hwp:pagedlink name="resultadoPesquisaGeladeira" label="Proximo" number="1"/> <hwp:pagedlink
name="resultadoPesquisaGeladeira" label="Prox" number="10"/></th>
</tr>
</table>
<table border="0" cellpadding="5" cellspacing="5">
<tr>
<td>
<c:if test="${param.popup != '1'}">
<input class="Btn2" type="button" value="Adicionar" onclick="adicionar(this,'Geladeira');" />
</c:if>
<c:if test="${param.popup == '1'}">
<input class="Btn2" type="button" value="Seleciona" onclick="selecionar(this);" />
</c:if>
</td>
</tr>
</table>
</form>
<%@include file="/WEB-INF/common/Footer.jsp" %>
Observaçoes :
1 – Para percorrer as pesquisas é so utilizar o nome “resultadoPesquisaEntidade”. Isso acontece pois
quando foi feito a pesquisa é colocado na sessao uma colecao com este nome.
2 – A parte do codigo que aparece <c:if test="${param.popup != '1'}"> serve para quando esta tela for
utilizada por um componente de associacao AJAX em que a mesma tela é apresentada em um popup.
8 – Incluir suas telas no menu
Para que seja possivel acessar as telas que foram desenvolvidas é preciso adicinar algumas linhas de
programação Javascript no arquivo /WebContent/js/menu/menu_data.jsp.
with(milonic=new menuname("Exemplo")){
style=windows98style;
aI("showmenu=Cargo;text=Cargo;");
aI("showmenu=TipoContato;text=Tipo de Contato;");
aI("showmenu=TipoContatoCategoria;text=Tipo de Contato Categoria;");
aI("showmenu=NOMEDAENTIDADE;text=NOMEDAENTIDADE;");
}
with(milonic=new menuname("NOMEDAENTIDADE")){
style=windows98style;
aI("text=Adicionar NOMEDAENTIDADE;url=NOMEDAENTIDADE .do?metodo=adicionar;");
aI("text=Pesquisar NOMEDAENTIDADEs;url=NOMEDAENTIDADE .do?metodo=pesquisar;");
}
Observaçoes :
Na fase de laboratorio suas entidades ficam descritas no menu “Exemplo”.
Download

O que fazer ao receber o Caso de Uso NOMEDAENTIDADE CRUD