Desenv. Projeto Web

Pessoal,

Sou novo nesse mundo de aplicações web, andei estudando Servlet’s e JSP (Use a cabeça, Servlets e JSP) e estou implementando um sisteminha.
Só que tenho um duvida para começar a implementar de vez o sistema. Estou querendo criar (um exemplo de cadastrar Cliente), uma JSP com um formulario e seja preenchido os dados do novo cliente, depois, o formulario é passado pra um servlet que faz todos os procedimento necessarios, e chama um classe bean(simples classe java), atribui todos os dados do cliente na classe, que tb tem função de conectar-se ao BD, só assim sendo armazenado lá.
Estou aplicando MVC.
Essa aplicação seria implementada corretamente? Se não, uma sugestão!

[]'s

Estou fazendo a mesma coisa Emanuell.
Para ser mais específico estou montando um framework com
Eclipse 3.2 com alguns plugins legais como SYSDEO pro Tomcat.
[list]Tomcat 5.5[/list]
[list]MySQL 5.0.27[/list]
[list]Struts 1.3.5[/list]

E pra variar já estou com vários problemas para fazer tudo isso se funcionar perfeitamente em conjunto. Já terminei praticamente toda a codificação do sistema, mas o diabo num roda e aposto que é por problemas de configuração!

Da uma olhada nesses tutoriais aqui que são bem interessantes. Ensinam muita coisa sobre aplicações web e o MVC.

http://javaboutique.internet.com/tutorials/Struts/
http://javaboutique.internet.com/tutorials/ApacheDAOs/

Aqui no GUJ tbm tem muita coisa boa, da uma olhada na parte de tutoriais e para os problemas já tem muita coisa boa no fórum.

até!

naum sei se eu entendi errado mas…
mas acho que não seria uma boa prática colocar uma função dentro de sua classe bean…
Separa isso também… cria outra classe só para mexer com o banco…

Dá uma olhada em DAO

:slight_smile:

[quote=albiere]naum sei se eu entendi errado mas…
mas acho que não seria uma boa prática colocar uma função dentro de sua classe bean…
Separa isso também… cria outra classe só para mexer com o banco…

Dá uma olhada em DAO

:)[/quote]

Então… criando uma classe DAO so pra interagir com o BD, qual seria a finalidade da classe bean?

Somente ser o POJO… O controlador tem o papel de recuperar os dados da sua View e fazer a jogada pra seus beans… O controlador não sabe de nada, ele simplesmente faz a chamada aos DAOs e para armazenar os dados de sua View existe a sua classe bean

Emanuell, sua classe bean vai ser responsavel por fazer os get e set’s da sua classe de negocio, nela deve ou devera existir um metodo que recupere o que vc digitou no formulario e salve no banco !

Um exemplo de um Bean

public class DadosProdutoTerminalBean {

private String cliente;
    public String getCliente() {
        return cliente;
    }
    public void setCliente(String cliente) {
        this.cliente = cliente;
    }
}

Entendeu ?

Qq duvida posta ai

Ahh, acho q entendi.

Meu servlet vai pegar os valores dos formulários e armazenar numa classe bean, depois, chamo a classe DAO passando o bean pra ser armazenado no BD. Estou certo?

Assim,

Seu servelet vai ter um metodo, execute, nele vc vai criar um objeto para armazenar as informações que vc vai salvar no banco, vou te passar um exemplo usando um dados salvo no banco usando um Bean


while (resultSet.next()) {

AcceSolicitacaoBean acceSolicBean = new AcceSolicitacaoBean();

acceSolicBean.setCodSol(resultSet.getString("COD_SOL"));
acceSolicBean.setCodServico(resultSet.getString("COD_SERVICO"));
acceSolicBean.setNrf(resultSet.getString("NRF"));

acceSolicitacoes.add(acceSolicBean);

O que ela faz ?
Quando houver um resultado na pesquisa ele vai setar um determinado valor no CodSol, se vc puder ver, ele seta e recupera do banco.

Entendeu ??

Um outra perguntinha…
Em um caso de cadastro, exclusao… (CRUD), de clientes, eu irei ter um servlet para cada funcionalidade dessa? Ex: CadastraClienteServlet, ExcluiClienteServlet e etc… isso eh uma boa pratica de programacao?

Emanuell,

Eu encaro como uma boa pratica a orientação a objeto vc criar uma unica classe e dentro dela existir um metodo para cadastrar, excluir, salvar, alterar e assim por diante, na hora da manutenção do sistema é mais facil de ser feito !

Voce entendeu o esquema do uso do Bean ?? Pq deve ser criado ? Quando deve ser usado ?? Eu expliquei por cima, so para voce ter uma ideia do que ele faz ! Mas qq coisa, posta ai sua duvida que eu ou qq outro pode te ajudar.

Abs

[quote=emanuell]Um outra perguntinha…
Em um caso de cadastro, exclusao… (CRUD), de clientes, eu irei ter um servlet para cada funcionalidade dessa? Ex: CadastraClienteServlet, ExcluiClienteServlet e etc… isso eh uma boa pratica de programacao?[/quote]

Pesquisando a minha dúvida aqui pelo GUJ achei esse tópico. Entretanto, o amigo que respondeu em seguida não respondeu à pergunta de emanuel. =)

Dúvida, boas práticas em Servlets (para variar).

Eu devo ter um servlet para cada “Módulo de cadastramento” do meu sistema? Por exemplo: ServletAgente, ServletOs, ServletEquipamento?

Devo dividir as operações de CRUD em servlets diferentes? Divido Cadastra, Altera, Atualiza e Exclui de cada módulo?

Como devo decidir qual método de um DAO chamar (Cadastra, Altera, Atualiza e Exclui). Faço um request.getAttribute(""), jogo este valor numa variável, e faço um if nesta variável?

Obrigado!

Bem, pelo pouco que pude pesquisar até agora, me parece que com relação aos servlets, a coisa corre um pouco mais frouxa. Não podendo sair do limite do bom-senso.

Resolvi adotar a abordagem de um servlet para cada módulo de cadastramento. Cada módulo desses seria um modelo de domínio? Agente, Equipamento e OS?

Bem, finalmente, segue uma abordagem que estou utilizando para o processo de login do usuário no sistema. Essa forma de fazer está correta?

No momento estou acometido por uma forte dor no estômago. O raciocínio está fraco. Devo ir para o hospital agora, por isso só devo ver as respostas logo mais, as 22h30.

Obrigado a todos que puderem ajudar e desculpe tantas dúvidas muito rasteiras.

package br.com.trimbase.os.servlets;

import java.io.IOException;
import java.sql.SQLException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import br.com.trimbase.agente.Usuario;
import br.com.trimbase.agente.dao.UsuarioDAO;

@SuppressWarnings("serial")
public class LoginServlet extends HttpServlet {
	
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
	}
	
	protected void service(HttpServletRequest req, 
			HttpServletResponse res) throws ServletException, IOException{
		
		String login = req.getParameter("login");
		String senha = req.getParameter("senha");
		
		RequestDispatcher rd;
		
		UsuarioDAO dao = new UsuarioDAO();
		try {
			Usuario usuario = dao.fazLogin(login, senha);
			if (usuario.getResultadoLogin() == 0) {
				// Usuário inexistente --- com AJAX ?
			}else if (usuario.getResultadoLogin() == 1) {
				// Senha não existe --- com AJAX ?
			}else {
				// Login OK
				HttpSession sessao = req.getSession();
				sessao.setAttribute("usuario", usuario);
				if (usuario.getNivel() == 0) {
					rd = getServletContext().getRequestDispatcher("/master.jsp");
				}else if (usuario.getNivel() == 1) {
					rd = getServletContext().getRequestDispatcher("/gerente.jsp");
				}else if (usuario.getNivel() == 2) {
					rd = getServletContext().getRequestDispatcher("/tecnico.jsp");
				}else if (usuario.getNivel() == 3) {
					rd = getServletContext().getRequestDispatcher("/operador.jsp");
				}else {
					rd = getServletContext().getRequestDispatcher("/cliente.jsp");
				}
	 
				rd.forward(req, res);
			}
		}catch (SQLException e) {
			rd = getServletContext().getRequestDispatcher("/erroBD.jsp");
		}
	}
}

Você poderia utilizar uma classe de negócio para acessar a sua classe de dados, assim simplificando o servlet e fazendo com que ele faça somente o que ele deve. Preparar a renderização do jsp.
Deixa o BO cuidar do negócio e o DAO somente para acesso aos dados. Use o VO para trafegar a informação entres as classes.

Classe BO

package br.com.exemplo.bo;

import br.com.exemplo.dao.LoginDAO;
import br.com.exemplo.vo.UsuarioVO;

public class LoginBO {
	
	private static final LoginBO INSTANCE = new LoginBO();
	
	private LoginDAO loginDAO;
	
	/**
	 * @return uma instância da classe
	 */
	public static LoginBO getInstance() {
		return INSTANCE;
	}
	
	
	private LoginBO() {
		loginDAO = new LoginDAO();
	}

	public boolean validaLogin(UsuarioVO usuario){
		return loginDAO.validaLogin(usuario);
	}
	
}

Chamada no Servlet

// Declarando no Servler
LoginBO loginBO = LoginBO.getInstance();

//Utilizando a classe
UsuarioVO usuario = new UsuarioVO();
usuario.getLogin(req.getParameter("login"));  
usuario.getSenha(req.getParameter("senha")); 

if(loginBO.validaLogin(usuario)){
   // Usuário Logado
} else {
  // Usuário não logado
}

Consegui ajudar em algo galera?!

Abraços a todos

Oi amigo, obrigado pela sua resposta.

Na verdade, pela sua explicação, já uso o tal do BO. Só não chamo assim por não ter certeza se devo chama-lo assim, por ainda ter dúvidas básicas com relação a essas denominações e padronizações. Esta classe é a classe Usuario. O padrão DAO já uso há algum tempo. Este é mais fácil definir, IMHO, pois se faz acesso a dados, pra mim é DAO. Essa é a classe UsuarioDAO. Por ter que fazer acesso ao banco e retornar um objeto do tipo Usuario, resolvi colocar o método fazLogin() na classe DAO.

Um amigo aqui do GUJ me disse que não seria uma má prática acessar um DAO diretamente (sem passar pela classe a que ela se refere: creio ser o tal do BO). Refleti esse conceito para os servlets e passei a acessar o DAO a partir deles. Isso eliminou uma péssima prática minha (eu tinha essa sensação e o pessoal aqui confirmou esta sensação): eu usava algo do tipo usuario.getUsuario(). Dentro deste método eu populava os atributos do próprio objeto e continuava a usar esta instância. Agora meu DAO retorna o objeto necessário, como sempre fiz, mas o acesso de fora da classe Usuario e, simplesmente, faço isso que você viu, isto é, Usuario usuario = dao.getUsuario(), por exemplo.

Meu problema é o seguinte:

Tenho, simplificando, 3 tipos de cadastro: Agente, Equipamento e OS. Cada um desses 3 se desdobra em Incluir, Alterar e Excluir. Bem, para trabalhar com JSP e Servlet, de uma forma um pouco mais elegante, me vieram a cabeça essas soluções:

[list]Usar um servlet para cada operação e classe. Neste caso eu teria 3 x 3 = 9 Servlets para CRUD. Isto é, IncluiAgenteServlet, AlteraAgenteServlet, ExcluiAgenteServlet, etc. [/list]
[list]Usar um Servlet para cada classe, isto é, AgenteServlet, EquipamentoServlet e OSServlet. [/list]
[list]Usar um Servlet para cada operação, isto é, CadastraServlet, AlteraServlet e ExcluiServlet.[/list]

A primeira abordagem é fácil, só tenho minhas dúvidas se é uma boa prática.

Caso não seja, caímos nas opções 2 e 3.

Maravilha, na opção 2 e 3 pensei em mais uma listinha para escolher a melhor forma, a melhor prática. Pensando sempre que o cara que vai manter meu código é um serial killer que sabe onde moro <>.

[list]Criar um hidden na JSP e perguntar quem é quem nessa joça[/list]
[list]Para a última opção da lista anterior, além da solução acima, pensei em fazer o objeto “dizer” o que precisa ser feito com ele. Criar um atributo que diga se ele “quer” se cadastrado, alterado ou excluído. Não me agradou esta solução.[/list]

Vamos às minhas considerações sobre o assunto, lembrando que sou muito fraco ainda em boas práticas:

Na solução 1 da primeira lista, vou povoar meu projeto de servlets, o que pode tornar difícil a manutenção do meu código.

Isto me faz cair nas duas outras soluções. Para isso precisaria criar esse atributo na JSP, para que o Servlet saiba o que fazer ou com quem fazer.

Pois bem, de que tipo seria essa variável?

Se inteira, não sei onde e como manteria a tabela de relacionamento, ou seja, 1 é cadastro, 2 é alteração, 3 é exclusão, por exemplo. Uso inteiros para controlar alguns tipos dentro das classes, mas posso documentar facilmente no javadoc.

Se String como evitar erros bobos e, inclusive no desenvolvimento, saber o que foi colocado ao certo. Exemplo: cadastro/cadastrar/cadastra. Esse é um dos motivos porque nunca gostei de usar String como variável de controle de nada.

Nos livros que pesquisei sobre o assunto e nos documentos da Web os exemplos são sempre muito simples e não abordam esta questão.

Bem o outro problema, colocado nesta mensagem é o seguinte. Criei um atributo resultadoLogin na classe usuário que me informa se o problema no login foi devido ao nome do usuário ou a senha. Como preciso devolver uma instância de Usuario para a minha sessão, nas JSPs, não poderia retornar apenas o inteiro (devidamente documentado no javadoc), precisava retornar uma instância da classe Usuario com as informações do cabra que fez o login. Queria saber, também, se isso é uma boa prática.

Bem, essas são as minhas questões do momento.

Obrigado!

Rapaz, eu faria da segunda forma.
Um Servlet responsável por cada módulo (Negócio).

Assim, você estaria definindo a responsabilidade do Servlet por negócio, assim como os JSP’s separados também.

Uma pergunta, porque você não utiliza o Struts? Teria algum problema?
Com ele você poderia usar o tiles para montar as telas. Facilitaria bastante o seu trabalho.

Qualquer dúvida ou contradição, estamos aí para nos ajudarmos.

Abraços

[quote=celso.martins][list]Usar um servlet para cada operação e classe. Neste caso eu teria 3 x 3 = 9 Servlets para CRUD. Isto é, IncluiAgenteServlet, AlteraAgenteServlet, ExcluiAgenteServlet, etc. [/list]
[list]Usar um Servlet para cada classe, isto é, AgenteServlet, EquipamentoServlet e OSServlet. [/list]
[list]Usar um Servlet para cada operação, isto é, CadastraServlet, AlteraServlet e ExcluiServlet.[/list][/quote]

A primeira opção é fácil, mas pelo aumento significativo de classes é muito fácil de se perder.

Entre a segunda e a terceira, é preferível a segunda opção, pois objetos são ortogonais às ações.

O que você pode fazer pra implementar isso é dizer no web-xml que as urls agente/insere, agente/altera e agente/exclui serão mapeadas para um único servlet AgenteServlet.

No servlet, você obtém a url fornecida pelo usuário, faz um if-else da vida pra descobrir qual url foi chamada e chame a ação apropriada.

Repare duas coisas, 1) nesse esquema é melhor criar um objeto independente de Servlet que faça as ações apropriadas, o Servlet apenas chamaria esse objeto; 2) isso é o que frameworks, como Struts 2, faz. Você poderia usá-la ao invés do esquema força bruta.

Outra coisa que outras pessoas falaram nesse tópico são coisas como BOs, VOs, DAOs…
Quanto aos dois primeiros, esqueçam que existem. Força um artificialismo e uma complexidade desnecessária na aplicação, além de não haver nenhuma bíblia que diga que os objetos devam ser pelados sem nenhum negócio.
Quanto ao DAO, existem alternativas. Tem gente que cria um repositório de acesso à base e injeta esse repositório nos objetos de negócio. Mas como é complexo para muita gente iniciante, o DAO é aceitável.

Amigo, obrigado pela explicação. Possivelmente é a chave que eu precisava para abrir esse cofre. Vou começar os testes agora mesmo e verificar como o servlet “sabe” quem o chamou.

Como eu sempre digo: E as nuvens começam a dissipar.

Tenho uma noção bem básica de Struts, assim como do Hibernate. Pretendo refatorar este projeto, quando o mesmo estiver em produção. A empresa pediu o projeto para ontem, e para ontem farei. Dentro das minhas limitações, farei da melhor forma possível. Só vou conseguir isso devido ao pessoal daqui do GUJ que está me dando verdadeiras aulas de boas práticas.

Nesta refatoração, usarei o Struts e o Hibernate.

Abraços e muito obrigado aos dois.

Do jeito que você descreveu a arquitetura do seu projeto, vejo da seguinte forma:

Os seus servlets vão receber as requisições da tela, certo? Então eles farão o papel de controlador do MVC. Modele os objetos do domínio para terem estado e comportamento, ou seja, atributos e métodos. Desta forma, os seu objetos de domínio terão dependências com os seus reposítórios. Então neste momento, escreva os DAOs para implementarem os seus repositórios.

M - Seus objetos de domínio e repositórios, com estado e comportamento.
V - Suas páginas
C - Seus servlets

Mas eu tenho uma sugestão que pode te ajudar: porque ao invés de fazer tudo na mão utilizando servlets você não usa um framework MVC (desde que não seja o struts 1.x)? Procure informações sobre o Vraptor, Spring ou Mentawai.
Caso se interesse em entender melhor tudo o que eu disse, baixe a apostila de desenvolvimento WEB da Caelum e comece por lá. É a melhor referência que eu conheço pra quem está iniciando e já quer ir praticando.

Rodrigo,
Essa arquitetura de BO, VO (cujo nome correto é DTO), etc só fazia sentido quando se utilizava EJB 2.x. O objetivo era eliminar tráfego excessivo na rede. Hoje em dia, com as técnicas para modelagem do domínio da aplicação, a separação dos objetos em estado e comportamento (DTO e BO, respectivamente) perdeu sentido. Se nos dias de hoje ainda precisar usar EJB 2.x, escreva DTOs e use assemblers para transformá-los nos seus objetos de domínio. Desta forma, você pode se aproveitar dos benefícios da orientação a objetos. Do jeito antigo estávamos programando de forma estruturada.

Oi Adolfo, obrigado pelas considerações.

Eu tenho essa apostila da Caelum. Impressa e encadernada. =)

Já fiz essa tralha funcionar outras vezes. Já dei uma olhada no Struts e fiz um sisteminha de teste para treinar. Da mesma forma fiz com o Hibernate.

COM JSP/Servlet já fiz algumas coisas. E pelo que vejo, da maneira errada. Mas já dei minhas cacetadas.

Ainda não me sinto confortável para usar esses frameworks em algo “para ser entregue”, como nesse sistema que estou fazendo. O prazo que dei para a chefia é de 45 dias, mas o meu prazo é menor. Minha intenção é deixa-lo em produção o mais rápido possível, com JSP/Servlets pro pessoal ir testando e, enquanto isso, vou metendo Struts e Hibernate na criança.

Minha experiência com esses frameworks é muito pequena. Assim, se acontecer algum problema, provavelmente vou me enrolar para resolver e meu prazo vai para as cucuias.

O prazo de 45 dias empurrei pela goela deles, pois, a princípio me pediram para ontem mesmo. Pediram inclusive que terceirizasse o desenvolvimento e eu ficasse coordenando (sic!). Mas como estou querendo ganhar experiência no desenvolvimento Java para WEB, convenci que o ideal era o projeto não sair da empresa.

Se eu der uma bobeada vão falar: - Não te disse, era melhor terceirizar.
Prefiro não correr esse risco. E melhor, entregar bem antes.

O mesmo aconteceu com a XP. Ainda não acabei de ler o livro do Beck e já queria aplicar. Acho que a ansiosidade é até explicável. Mas não deu. =)

Abraços!

Celso,
O meu post foi direcionado ao autor do tópico. No caso dele, o objetivo é aprender e aplicar conceitos que ele estudou. Continuo achando que, pra ele, as minhas dicas são válidas.

No seu caso, você está tocando um sistema. E é obrigatório pensar em prazo, esforço, custo, etc. São casos diferentes e a única pessoa capaz de determinar o que é melhor ou pior é você. Boa sorte!!