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 java.io.serializable; import java.util.date; import java.util.hashset; import java.util.set; import javax.persistence.cascadetype; import javax.persistence.column; import javax.persistence.entity; import javax.persistence.generatedvalue; import javax.persistence.id; import javax.persistence.joincolumn; import javax.persistence.manytomany; import javax.persistence.manytoone;
import javax.persistence.onetomany; import javax.persistence.table; import javax.persistence.temporal; import javax.persistence.temporaltype; import org.hibernate.annotations.genericgenerator; @Entity @Table(name="GELADEIRAS") public class Geladeira implements VO { private Integer id; private String marca; private String modelo; private String cor; private Double volume; private Integer voltagem; private 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 Integer id; private String marca; private String modelo; private String cor; private Double volume; private String volumestr; private Integer voltagem; private String voltagemstr; private Date datarevisao; private 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/WEB- INF/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> <td valign="top"> <html:errors/> <html:form action="/geladeira.do?metodo=salvar"> <table> <th colspan="2">geladeira</th> <td>marca <td><html:text property="marca"/> <td>modelo <td><html:text property="modelo"/>
<td>cor <td><html:text property="cor"/> <td>data revisao <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>categoria <td><smerp:select property="geladeiracategoriaid" entity="geladeiracategoria" valueproperty="id" labelproperty="descricao"/> <hr/> <table border="0"> <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> <table border="0"> <td> <html:submit property="btnsalvar" value="salvar"/> <html:reset property="btnlimpar" value="limpar"/> <html:button property="btnpesquisar" value="pesquisar" onclick="pesquisar('geladeira');"/> </html:form> <%@ 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"> <td> <fieldset> <legend><font color='red'>filtros de Pesquisa</font></legend> <table> <td>codigo:<br/> <html:text property="id" size="15"/> <td colspan="2" align="left"><html:submit value="buscar"/> </fieldset> </html:form> <form method="post" id="mainform"> <input type="hidden" name="id"> <table border="0" cellpadding="0" cellspacing="0"> <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> <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 align="left" nowrap="nowrap">${entity.modelo <td align="left" nowrap="nowrap">${entity.marca <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> </c:foreach> <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"/> Itens <b>${resultadopesquisageladeira_total</b> <hwp:pagedlink name="resultadopesquisageladeira" label="proximo" number="1"/> <hwp:pagedlink name="resultadopesquisageladeira" label="prox" number="10"/></th>
<table border="0" cellpadding="5" cellspacing="5"> <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> </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.