Estrutura da aplicação - MVC

Gostaria de saber a opinião da galera sobre a estrutura das classes da aplicação.

-Cidade _ Bean apenas com os atributos com gets e sets
int codigo;
String descricao;

Vou dar um exemplo:
-Tela de cadastro de cidade.
Esta tem uma instância de CidadeControll.

  • CidadeControll _ Tem os metodos para inserir/alterar, apagar e recuperar uma cidade. Caso alguma operação cause exceção ela tem a função de disparar um JOptionPanel

A Tela de Cadastro instancia o Bean Cidade e passa como parâmetro para por exemplo o método inserir para gravar no banco.

A CidadeControll por sua vez tem uma instância de CidadeDAO que implementa uma interface com os metodos para inserir/alterar, apagar e recuperar.

-CidadeDAO _ Pega uma connection e o parâmetro, no caso o objeto Cidade e grava no banco.

[quote=“fabriciogiordani”]Gostaria de saber a opinião da galera sobre a estrutura das classes da aplicação.

-Cidade _ Bean apenas com os atributos com gets e sets
int codigo;
String descricao;

Vou dar um exemplo:
-Tela de cadastro de cidade.
Esta tem uma instância de CidadeControll.

  • CidadeControll _ Tem os metodos para inserir/alterar, apagar e recuperar uma cidade. Caso alguma operação cause exceção ela tem a função de disparar um JOptionPanel

A Tela de Cadastro instancia o Bean Cidade e passa como parâmetro para por exemplo o método inserir para gravar no banco.

A CidadeControll por sua vez tem uma instância de CidadeDAO que implementa uma interface com os metodos para inserir/alterar, apagar e recuperar.

-CidadeDAO _ Pega uma connection e o parâmetro, no caso o objeto Cidade e grava no banco.[/quote]

É isso ae…

E dali arquitetura de 3 camadas (MVC). Vc tem sua tela sua tela de apresentação, com a regra de negócio (CidadeControll) e a persistência no banco de dados (CidadeDAO). O mais legal de tudo isso é a utilização de padrões, como o pattern DAO (CidadeDAO) e VO (e sua Bean Cidade). Uma coisa legal de vc fazer (se já não está fazendo) é padronizar os nomes para as camadas. Por exemplo, para as telas de Apresentação, colocar o prefixo, DL_NomeDaTela (Dialog) FM_NomeDaTela (JInternalFrame), por exemplo. Para as regras de negócio, RN_NomeDaTela (com a tela que está relacionada).

Tem uma outra abordagem, que na minha opnião, é mais elegante e bem estruturada, que é a seguinte… geralmente em uma RN (regra de negócio), quando uma tela tem que instânciar várias DAOs, isto é feito neste RN. Imagine uma tela de venda, onde várias DAOs na RN relacionada são instânciadas e geralmente algumas das validações feitas nestas tabelas são feitas em outras RN. Então… o que é feito… é criado mais um RN para a DAO e uma RN de negócio para a tela, ou seja, uma DAO terá sempre e somente uma RN (onde está RN terá os método de inserção, deleção…etc e método de validação para tais operações) e na RN da tela irá não mais instânciar DAOs e sim as RNs das DAOs. Assim se uma tela (de venda por exemplo), tinha que instânciar várias DAOs, agora poderá instâncias várias RNs (as relacionadas com as DAOs).

Resumindo… como ficou a arquitetura… ela de apresentação, RN da tela de apresentão, RN da DAO e DAO.

Só mais uma dica: Em vez de exibir um JOptionPanel quanoo ocorre uma exeção, suba uma mensagem (String), que a fica independente do componente que ela será exibida…

Blz??

Olá,

só para dar uma outra visão do que o JavaTeco já escreveu:

A arquitetura que vc descreveu não é MVC, por um detalhe: a falta da camada model, ou a nomeclatura errada da camada Model.

No seu exemplo, sua camada Model é composta pelos (Data Access Objects)DAOs e eles são acessados diretamente pela camada Control.
Isto é errado, segundo a definição do Pattern DAO.
O correto seria acessar o DAO através de um Objeto de Negócio. O É comum o Objeto de Negócios ser chamado Business Object nos livros. Aqui no Brasil também é conhecido como Regra de Negócio(RN), como o Teco já disse.

Finalizando sua aplicação usando MVC e o Pattern DAO ficaria assim:

View -> Control -> Business Object -> DAO

Vamos ver se entendi. Exemplificando com uma venda eu teria:

:arrow: Tela de venda (FM_Venda)
-RN_Venda
Possui uma instância de RN_Cliente e de RN_NotaFisal

:arrow: RN_Cliente
Possui uma instância de DAO_Cliente com os métodos insert, update, …, sendo que estes apenas invocam os metodos da DAO

:arrow: DAO_Cliente
Peja uma connection de uma classe especializada e executa os métodos insert, update, …

:arrow: RN_NotaFiscal
Possui uma instância de DAO_NotaFiscal com os métodos insert, update, …, sendo que estes apenas invocam os metodos da DAO

:arrow: DAO_NotaFiscal
Peja uma connection de uma classe especializada e executa os métodos insert, update, …

Só pra ilustrar, será usado EJB e estamos estudando a persistência com algum framework como Hibernate.

só pra aproveita o tópico…

Onde encotro materiais sobre MVC…

escuto fala direto… com esse tópico consegui ter uma idéia melhor…

[quote=“fabriciogiordani”]Vamos ver se entendi. Exemplificando com uma venda eu teria:

:arrow: Tela de venda (FM_Venda)
-RN_Venda
Possui uma instância de RN_Cliente e de RN_NotaFisal

:arrow: RN_Cliente
Possui uma instância de DAO_Cliente com os métodos insert, update, …, sendo que estes apenas invocam os metodos da DAO

:arrow: DAO_Cliente
Peja uma connection de uma classe especializada e executa os métodos insert, update, …

:arrow: RN_NotaFiscal
Possui uma instância de DAO_NotaFiscal com os métodos insert, update, …, sendo que estes apenas invocam os metodos da DAO

:arrow: DAO_NotaFiscal
Peja uma connection de uma classe especializada e executa os métodos insert, update, …

Só pra ilustrar, será usado EJB e estamos estudando a persistência com algum framework como Hibernate.[/quote]

Está bem estruturado agora… é isso ae…

No exemplo anterior que citei era necessário várias RNs para uma tela.

No caso de uma tela de cadastro de cidade por exemplo.

Tela de Cidade (FM_Cidade)
Possui uma instância de RN_Cidade, de onde são invocadas as operações (insert, update, …).
-RN_Cidade
-DAO_Cidade

Vejam se estou certo. Neste caso não precisaria de uma classe de RN intermediária a RN_Cidade pois não trabalharei com mais de um tipo de DAO.


Gostaria de saber também a opinião de vcs sobre ter a Cidade (VO) instanciada na FM_Cidade (Tela), já que essa será passada por parâmetro para a RN_Cidade.

[quote=“fabriciogiordani”]No exemplo anterior que citei era necessário várias RNs para uma tela.

No caso de uma tela de cadastro de cidade por exemplo.

Tela de Cidade (FM_Cidade)
Possui uma instância de RN_Cidade, de onde são invocadas as operações (insert, update, …).
-RN_Cidade
-DAO_Cidade

Vejam se estou certo. Neste caso não precisaria de uma classe de RN intermediária a RN_Cidade pois não trabalharei com mais de um tipo de DAO.


Gostaria de saber também a opinião de vcs sobre ter a Cidade (VO) instanciada na FM_Cidade (Tela), já que essa será passada por parâmetro para a RN_Cidade.[/quote]

Vc quis dizer várias RNs na RN da Tela… certo? Porque uma tela terá somente uma RN associada a ela.

Mesmo que a tela fosse usar uma DAO (ou seja RN da DAO) só, é melhor vc criar a RN intermediária, pois na RN associada a DAO serão feitas validações referênte a persistência e na RN intermediária serão feitas validações da regra de negócio… cada uma com suas resposabilidades…

Blz???

Legal pessoal!
Acho que entendi o que quiseram dizer.

Só não entendi pq usar servlet e para que serve a camada CONTROL do cliente por exemplo.

Eu tenho feito assim:

JSP -> RN -> DAO

Mas neste caso, vocês citaram que usam várias DAOs para processar as RNs… um DAO para cada RN…

PQ não ter 1 DAO genérico, com métodos como insertReg, deleteReg, etc e nas RN são inseridas as SQLs?

Posso não estar entendendo algo… se estiver, me expliquem melhor

o servlet controlador é pra onde todas as requisições vão, ele só filtra elas, e determina qual ação executar, no caso, qual business object chamar, ou regra de negocio delegar… hehe, ficando jsp -> servlet controlador -> RN -> DAO, o lance de ter varias DAOs é assim, imagine q tu tem a tabela Aluno e Professor no banco, então tu teria a classe AlunoDAO e ProfessorDAO, cada uma com métodos do tipo insertAluno() … insertProfessor()… deleteAluno()… etc…

Entendi a função do servlet controlador! :grin:

Agora, com relação aos DAOs, entendo o seguinte:
Supondo que tanhamos essas mesmas tabelas no banco de dados… como eu faria hoje em dia:

JSP -> Servlet controlador -> RN -> DAO…

great!

Porém, na camada RN eu teria por exemplo insertProfessor() com toda a regra de negócio para inserir um professor.
Na camada Dao eu apenas receberia a solicitação de inserção no banco de dados e faria toda a lógica necessária para tratar o dado que estaria entrando.
Porém esse meu DAO não precisaria ser específico para cada RN (pelo menos imagino isso), pois teria métodos genéricos. Como assim?

Bom… supondo que eu faça um tratamento específico sempre que for inserir um dado, então esse tratamento serviria para TODA a aplicação e não apenas para a Regra de Negócio que trata a respeito da parte de professores.

Ah, mas eu poderia ter regras com relação a inserção de dados que se apliquem somente a parte de professores, certo? Bem, eu teria esse tratamento dentro dos métodos da RNprofessor… que por sua vez passaria a solicitação ao DAO (genérico) que trataria casos genéricos.

Qual a vantagem?
Reutilização da DAO praticamente em qualquer escopo de projeto, deixando a lógica específica de cada parte (professores por exemplo) dentro da RN.

Teria então algo como:
professor.jsp -> Controlprofessor.class -> RNprofessor.class -> Dao.class
no caso de aluno seria:
aluno.jsp -> Controlaluno.class -> RNaluno.class -> Dao.class

:arrow: Observe que usei a mesma Dao para ambos :!:

Não sei se estou deixando de lado alguma característica importante, mas em primeiro momento acredito que seria viável fazer algo desse tipo.

O que pensam a respeito?

Mais uma dúvida que tenho é com relação ao Servlet… não poderíamos usar um JSP no lugar do servlet?

Sim, mas normalmente é um servlet, em todos os livros e referencias q li, é um servlet direto, até já vi implementações em jsp…

E sobre o DAO, olha só, vou te colocar um exemplo de fábrica de DAOs, vai sair comprido, mas, espero q ajude… ehhehe

A Factory abstrata, no caso, esse DAO esta usando o padrão abstract factory, cujo usa um DAO pra cada tipo de banco… tb pode-se usar o factory method, q usa uma só implementação pra todos os bancos, usando SQL padrão (javateco q adora essa heheh), eu fiz em abstract factory (confesso, é muito maior, por ter uma implementação pra cada tipo de banco) pq se ficar td em SQL padrão, há instruções nativas do Oracle q são muito mais rapidas do q o SQL padrão, quero dizer, tem bancos q se saem mais rapidos usando os recursos q só os mesmos oferecem, então, pra ter acesso a isso, fiz em abstract factory

[code]
package com.portaljava.dao;

import com.portaljava.dao.postgres.PostgresDAOFactory;
import com.portaljava.dao.oracle.OracleDAOFactory;

// DAO Factory de classe abstrata
public abstract class DAOFactory {

// tipos de DAO suportados pela factory
public static final int POSTGRES = 1;	
public static final int ORACLE = 2;

// haverá um método para cada DAO que pode ser
// criado. As factories concretas terão de
// implementar esses métodos.
public abstract AlunoDAO getAlunoDAO();

public abstract ProfessorDAO getProfessorDAO();

public static DAOFactory getDAOFactory( int factory ) {
	
	switch( factory ) {
		
		case POSTGRES: return new PostgresDAOFactory();
		case ORACLE: return new OracleDAOFactory();
		default: return null;
	}
}

}[/code]

A Factory do Postgres

[code]
package com.portaljava.dao.postgres;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.portaljava.dao.*;
import com.portaljava.locator.ServiceLocator;
import com.portaljava.locator.ServiceLocatorException;

public class PostgresDAOFactory extends DAOFactory {

private static DataSource dataSource;

public static Connection createConnection() {
	
	Connection connection = null;

	if ( dataSource == null )			
		try {
		
			dataSource = 
				ServiceLocator.getInstance().getDataSource( "java:jdbc/PostgresDS" );				
			
		} catch ( ServiceLocatorException e ) {

			System.out.println( e.getMessage() );	
		}
		
	try {
		
		connection = dataSource.getConnection();
			
	} catch ( SQLException e ) {
			
		System.out.println( e );
	}
		
	return connection;		
}

public AlunoDAO getAlunoDAO() {

	return new PostgresAlunoDAO();
}

public ProfessorDAO getProfessorDAO() {

	return new PostgresProfessorDAO();
}

}[/code]

A interface AlunoDAO, essa é a interface cujo as implementações concretas de postgress e outros bancos devem usar, essas implementações são os SQLs (tb tem a interface do ProfessorDAO, q é praticamente igual, só muda o tipo de Aluno pra Professor nos métodos…)

[code]
package com.portaljava.dao;

import java.util.ArrayList;
import com.portaljava.valueobject.Aluno;

public interface AlunoDAO {

public void insertAluno( Aluno aluno );

public Aluno findAlunoById( int id );
public Aluno findAlunoById( Aluno aluno );

public Aluno findAlunoByMatricula( int matricula );
public Aluno findAlunoByMatricula( Aluno aluno );

public Aluno findAlunoByNome( String nome );
public Aluno findAlunoByNome( Aluno aluno );

public boolean updateAluno( Aluno aluno );

public boolean removeAluno( int id );
public boolean removeAluno( Aluno aluno );

public ArrayList findAll();

}[/code]

A classe concreta q implementa AlunoDAO, é ela q contém obtém a referencia de uma conexão no pool, e executa os SQLs específicos de Aluno…, só nunca se esqueça de fechar essas conexões, digo, de devolver as referencias pro pool!! se não, não vai ter sentido o pool… hehehe

[code]
package com.portaljava.dao.postgres;

import java.util.ArrayList;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.portaljava.valueobject.Aluno;
import com.portaljava.dao.AlunoDAO;

public class PostgresAlunoDAO implements AlunoDAO {

// os metodos seguintes usam
// PostgreDAOFactory.createConnection()
// para obter uma conexao conforme exigido	

public void insertAluno( Aluno aluno ) {
	
	Connection connection = PostgresDAOFactory.createConnection();
	PreparedStatement statement = null;
	
	try {
	
		statement = connection.prepareStatement( 
			"INSERT INTO tabela (id, login, senha, nome, sobrenome) " +
			"VALUES (\'" + aluno.getNome() + "\')" 			
		);
		
		statement.execute();
	
	} catch( SQLException e ) {
		
		System.out.println( e );

	} finally {
		
		close( statement, connection );
	}
}

public Aluno findAlunoById( int id ) {
	
	Connection connection = PostgresDAOFactory.createConnection();
	PreparedStatement statement = null;
	ResultSet resultSet = null;		
	Aluno aluno = null;

	try {

		statement = connection.prepareStatement( "SELECT * FROM aluno WHERE nome=" + id );			
		resultSet = statement.executeQuery();

		if ( !resultSet.next() )
			return null;
			
		aluno = new Aluno();

		aluno.setId( resultSet.getInt( "id" ) );
		aluno.setMatricula( resultSet.getInt( "login" ) );
		aluno.setSenha( resultSet.getString( "senha" ) );
		aluno.setNome( resultSet.getString( "nome" ) );
		aluno.setSobrenome( resultSet.getString( "sobrenome" ) );
		aluno.setFoto( resultSet.getString( "foto" ) );
		aluno.setEndereco( resultSet.getString( "endereco" ) );
		aluno.setCep( resultSet.getLong( "cep" ) );
		aluno.setCaixaPostal( resultSet.getInt( "caixaPostal" ) );
		aluno.setTelefoneResidencial( resultSet.getLong( "telefoneResidencial" ) );
		aluno.setTelefoneComercial( resultSet.getLong( "telefoneComercial" ) );
		aluno.setCelular( resultSet.getLong( "celular" ) );
		aluno.setDataDeIngresso( resultSet.getDate( "dataDeIngresso" ) );

	} catch( SQLException e ) {

		System.out.println( e );
	
	} finally {
		
		close( statement, connection );
	}
	
	return aluno;
}

public Aluno findAlunoById( Aluno aluno ) {

	return findAlunoById( aluno.getId() );
}

public Aluno findAlunoByMatricula( int matricula ) {
	
	Connection connection = PostgresDAOFactory.createConnection();
	PreparedStatement statement = null;
	ResultSet resultSet = null;		
	Aluno aluno = null;		

	try {

		statement = connection.prepareStatement( 	
			"SELECT * FROM aluno WHERE matricula=" + matricula 
		);			
		
		resultSet = statement.executeQuery();

		if ( !resultSet.next() )
			return null;
			
		aluno = new Aluno();
		
		aluno.setId( resultSet.getInt( "id" ) );
		aluno.setMatricula( resultSet.getInt( "login" ) );
		aluno.setSenha( resultSet.getString( "senha" ) );
		aluno.setNome( resultSet.getString( "nome" ) );
		aluno.setSobrenome( resultSet.getString( "sobrenome" ) );
		aluno.setFoto( resultSet.getString( "foto" ) );
		aluno.setEndereco( resultSet.getString( "endereco" ) );
		aluno.setCep( resultSet.getLong( "cep" ) );
		aluno.setCaixaPostal( resultSet.getInt( "caixaPostal" ) );
		aluno.setTelefoneResidencial( resultSet.getLong( "telefoneResidencial" ) );
		aluno.setTelefoneComercial( resultSet.getLong( "telefoneComercial" ) );
		aluno.setCelular( resultSet.getLong( "celular" ) );
		aluno.setDataDeIngresso( resultSet.getDate( "dataDeIngresso" ) );

	} catch( SQLException e ) {

		System.out.println( e );

	} finally {
		
		close( statement, connection );
	}
	
	return aluno;		
}

public Aluno findAlunoByMatricula( Aluno aluno ) {

	return findAlunoByMatricula( aluno.getMatricula() );	
}

public Aluno findAlunoByNome( String nome ) {
	
	Connection connection = PostgresDAOFactory.createConnection();
	PreparedStatement statement = null;
	ResultSet resultSet = null;		
	Aluno aluno = null;		

	try {

		statement = connection.prepareStatement( 	
			"SELECT * FROM aluno WHERE matricula=" + nome 
		);			
		
		resultSet = statement.executeQuery();

		if ( !resultSet.next() )
			return null;
			
		aluno = new Aluno();
		
		aluno.setId( resultSet.getInt( "id" ) );
		aluno.setMatricula( resultSet.getInt( "login" ) );
		aluno.setSenha( resultSet.getString( "senha" ) );
		aluno.setNome( resultSet.getString( "nome" ) );
		aluno.setSobrenome( resultSet.getString( "sobrenome" ) );
		aluno.setFoto( resultSet.getString( "foto" ) );
		aluno.setEndereco( resultSet.getString( "endereco" ) );
		aluno.setCep( resultSet.getLong( "cep" ) );
		aluno.setCaixaPostal( resultSet.getInt( "caixaPostal" ) );
		aluno.setTelefoneResidencial( resultSet.getLong( "telefoneResidencial" ) );
		aluno.setTelefoneComercial( resultSet.getLong( "telefoneComercial" ) );
		aluno.setCelular( resultSet.getLong( "celular" ) );
		aluno.setDataDeIngresso( resultSet.getDate( "dataDeIngresso" ) );

	} catch( SQLException e ) {

		System.out.println( e );
	
	} finally {
		
		close( statement, connection );		
	}

	return aluno;
}

public Aluno findAlunoByNome( Aluno aluno ) {
	
	return findAlunoByNome( aluno.getNome() );
}

public boolean updateAluno( Aluno aluno ) {
	
	Connection connection = PostgresDAOFactory.createConnection();
	PreparedStatement statement = null;
	
	try {
		
		statement = connection.prepareStatement( "UPDATE * FROM tabela WHERE id=" + aluno.getId() );
		statement.executeQuery();
		
	} catch ( SQLException e ) {
		
		System.out.println( e );
		
		return false;
	
	} finally {
		
		close( statement, connection );
	}
	
	return true;		
}

public boolean removeAluno( int id ) {
	
		Connection connection = PostgresDAOFactory.createConnection();
		PreparedStatement statement = null;
	
		try {
		
			statement = connection.prepareStatement( "DELETE * FROM tabela WHERE id=" + id );
			statement.executeQuery();
		
		} catch ( SQLException e ) {
		
			System.out.println( e );
		
			return false;
		
		} finally {
		
			close( statement, connection );
		}		
	
	return true;
}

public boolean removeAluno( Aluno aluno ) {

	return removeAluno( aluno.getId() );		
}

public ArrayList findAll() {
	
	Connection connection = PostgresDAOFactory.createConnection();
	PreparedStatement statement = null;
	ResultSet resultSet = null;		
	ArrayList list = null;		

	try {

		statement = connection.prepareStatement( "SELECT * FROM aluno" );						
		resultSet = statement.executeQuery();

		if ( !resultSet.next() )
			return null;			
		
		list = new ArrayList();
		
		do {
			
			list.add( 
				new Aluno(		
					resultSet.getInt( "id" ),
					resultSet.getInt( "matricula" ),
					resultSet.getString( "senha" ),
					resultSet.getString( "nome" ),
					resultSet.getString( "sobrenome" ),
					resultSet.getString( "foto" ),
					resultSet.getString( "endereco" ),
					resultSet.getLong( "cep" ),
					resultSet.getInt( "caixaPostal" ),
					resultSet.getLong( "telefoneResidencial" ),
					resultSet.getLong( "telefoneComercial" ),
					resultSet.getLong( "celular" ),
					resultSet.getDate( "dataDeIngresso" )
				) 
			);
		
		} while( !resultSet.next() );

	} catch( SQLException e ) {

		System.out.println( e );

	} finally {
		
	   close( statement, connection );
	}
	
	return list;
}

public void close( PreparedStatement statement, Connection connection ) {
	
	try {
		
		statement.close();
		connection.close();		
	
	} catch( SQLException e ) {
	
		e.printStackTrace();
	}
}

}[/code]

e um exemplo do q o cliente da aplicação faria pra digamos, inserir um aluno no banco:

DAOFactory factory =   
   DAOFactory.getDAOFactory( DAOFactory.POSTGRES );

AlunoDAO alunoDAO = 
   factory.getAlunoDAO();

alunoDAO.insertAluno( new Aluno( ... ) );

Coisa de louco! :grin:

Era exatamente isso que precisava saber! :grin:

Estou desenvolvendo um trabalho de conclusão de curso para a faculdade e estava inseguro quanto a arquitetura do sistema. Depois de muita pesquisa e muita dica de vocês, já consolidei muito bem meus conceitos. OBRIGADÃO A TODOS!!!

Agora me diz uma coisa…
O Struts é exclusivamente para J2EE? Ou roda com J2SE?
O que acham da estrutura dele? Fácil de entender?

Estou a alguns dias do início do desenvolvimento e apesar de já ter definido os RNs, os DAOs e a classe “factory” semelhante ao exemplo acima, estou com dúvida com relação ao CONTROLLER…

Preciso da opinião de vocês para não ficar girando em círculo nem perdendo muito tempo com isso… afinal… terei apenas 4 meses para desenvolver o projeto…
detalhe…
É um sistema de business-to-business meio grandinho e mexo de verdade com java há apenas 2 semanas (apesar de ter um conceito sólido de O.O. e de já ter tido algumas matérias com a linguagem java na faculdade)

:wink:

o Struts é um framework web cara… super simples, em 1 semana tu ja ta craque nele… ah, boa sorte com o projeto… :cool:

Blz!

Matheus, seria legal se pudesse colocar um exemplo de controller, da mesma forma que colocou no caso dos Beans, Daos e Factory… Só que dessa vez, mostrando o view chamando o controller e em seguida o controller chamando o Bean.

Acho que isso irá elucidar bem algumas dúvidas como “Onde fazer a validação de formulários”, “E-mails”, “Data”, etc…

Vlw!

aqui comigo eu não tenho nenhum exemplo disso cara… o bom mesmo é tu estudar um passo-a-passo de Struts, na sessão de Artigos e Tutoriais do Portal Java tem uns… o Struts simples :slight_smile: