Swing para Servidor Tomcat, está correto assim?

24 respostas
jopss

Olá… antes de iniciar gostaria de dizer que pesquisei bem no forum e no google antes de postar, mas mesmo assim nao encontrei respostas.

Estou estudando e fazendo uma aplicacao desta forma:

CLIENTE DESKTOP --> SERVIDOR TOMCAT --> HIBERNATE --> FIREBIRD

Sendo que meu os clientes são vários (umas 8 maquinas), e mais adiante terá tambem web.
Uso no cliente o Genesis, faço pelo URLConnection para mandar para o servidor, recebo pelo Servlet e gravo com o DAO pelo hibernate.
Tudo ok e funfando…

Mas estou com dúvidas sobre a arquitetura e a forma como estou realizando. Na verdade “sinto” que tem algo errado, apesar de funcionar. Ou pelo menos incoerente. Para efetuar um cadastro de um cliente, por exemplo, faço da seguinte maneira:

A tela Swing faz o binding dos dados para um bean (POJO). Este bean é encapsulado em um List, junto com uma String indicando a operacao com ele: “gravar”, “alterar” e “excluir”. Entao na List terá sempre uma String operacao e um Object bean. Jogo entao a List para o stream do URLConnection.

No servidor, o servlet recebe esta List e separa a String operacao com o Object bean passado. Conforme a operação, ele “grava”, “altera” ou “exclui” do Firebird pelo DAO com Hibernate. Criei classes “genéricas” (mas nao com generics do java 5) com o DAO recebendo Objects.

Como disse isso funciona. Mas a passagem dessa List do cliente para o Tomcat é trivial?? Existe algo mais simples ou correto para isso?? Falo isso para tecnologias atuais utilizadas e detrimento de outras “antigas”, como EJB3.0, que ao meu ver aparenta ser mais complicado do que estou fazendo. Lembrando que o cliente é Swing. O que acham melhor para esta solução? Qual implementacao seria o ideal para passagem cliente/servidor?? Enviar objetos e/ou listas pela rede é legal?? Porque se eu enviasse os dados ao invés do objeto Cliente pronto, é pior não?

Gostaria de um cliente “magro” e tudo no servidor, mas de forma simples e atual, sem 150325487 milhoes de linhas configurações e usando Java, de forma leve. Dessa forma como faço, me aparenta mais transparência, mas está correto? Sinto “perigoso” essa forma, mas nao sei onde está o erro!!

jopss

24 Respostas

jopss

duplicado… :lol:

Luca

Olá

Se o banco de dados está no servidor e o cliente funciona apenas como uma camada de apresentação mais poderosa, então está como eu sempre achei que deveriam ser os sistemas desktop (sistemas que são chamados a partir do desktop como o Firefox, azureus, etc. sem misturar esta expressão com sistemas isolados como os burros da Sun fazem).

[]s
Luca

jopss

Sim o bd está no servidor e o cliente somente serve para apresentar. Mas a forma de enviar uma List com a operacao e o objeto pelo URLConnection estaria “nos conformes” ou tem algo melhor a fazer??

jopss

Luca

Olá

A forma de enviar e o protocolo das mensagens depende do sistema. Quando a gente tem muitos cliente como no caso do Banco Postal por exemplo com mais de 10 mil clientes swing, as mensagens precisam ser as mais simples possíveis. Mas com poucos clientes serialização dá certo. Quanto a sugestão de melhoria só posso lembrar do pacote HttpClient que faz poucas coisa a mais do que o UrlConnection mas vale a pena usar porque resolve algumas limitações da classe UrlConnection.

[]s
Luca

jopss

opa… vlw pela resposta… mas oq seria:

Nao vejo uma implementacao mais simples e rápida do que trafegar “objetos prontos” pela rede…

jopss :stuck_out_tongue:

Luca

Olá

Objetos prontos às vezes carregam informações demais. Imagine a diferença entre trafegar nome/senha recebendo resposta SIM/NÃO e trafegar classes inteiras. Se usar SSL então a demora será maior ainda.

[]s
Luca

jopss

Mas dae, por exemplo, em caso de Clientes, Funcionarios, Produtos, etc… que possuem mais dados, trafegar as informacoes em separado não causaria aumento na rede??? (falo isso num projeto como esse meu, mas para uns 10mil usuarios, como vc mencionou)…

e pra finalizar:
E sobre o HTTPCliente, é o da apache nao? o 4.0alpha será que tem mt bug ou uso o 3.1 mesmo?

jopss :stuck_out_tongue:

Luca

Olá

jopss:
Mas dae, por exemplo, em caso de Clientes, Funcionarios, Produtos, etc… que possuem mais dados, trafegar as informacoes em separado não causaria aumento na rede??? (falo isso num projeto como esse meu, mas para uns 10mil usuarios, como vc mencionou)…

e pra finalizar:
E sobre o HTTPCliente, é o da apache nao? o 4.0alpha será que tem mt bug ou uso o 3.1 mesmo?

jopss :stuck_out_tongue:

As informações não trafegam separado em caso nenhum. Elas poderiam ir como CSV, XML ou outro formato qualquer. Serialização é vantagem para o programador (bom) mas tem umas pequenas armadilhas no caso em que se necessita de alto throughput.

Use a versão estável do HttpClient.

[]s
Luca

Matheus_Tardivo

No projeto que trabalho atualmente usamos uma arquitetura parecida: cliente em Swing - também usamos Genesis; acessando uma aplicação web - usamos JPA/Hibernate.

A grande diferença fica no fato que não temos servlets no nosso projeto. Usamos o Spring, tanto no cliente quanto no servidor, e disponibilizamos serviços usando o Spring Remoting. Veja: [url]http://static.springframework.org/spring/docs/2.5.x/reference/remoting.html#remoting-httpinvoker[/url].

Dessa forma, a arquitetura fica bem parecida com o que seria usado com EJB 3. Seria algo como RMI/RPC via http.
No servidor temos o modelo com a lógica de negócio, os DAOs e os serviços - que recebem os DAOs por injeção de dependências. Os serviços apenas delegam as chamadas para o modelo e os DAOs.

Só pra ter uma idéia, vou colocar alguns trechos de código para ilustrar melhor como fazemos:

:arrow: No servidor:
package modelo;

public class Usuario implements Serializable {

	private String login;

	private String senha;

	// lógica de negócio ...
}
package persistencia;

public interface UsuarioDao {

	List<Usuario> list();
}
package servico;

// Este serviço é disponibilizado para o cliente usando o Spring Remoting.
public class UsuarioServicoImpl implements UsuarioServico {

	private UsuarioDao usuarioDao;

	@Autowired
	public void setUsuarioDao(UsuarioDao usuarioDao) {
		this.usuarioDao = usuarioDao; // injetado pelo Spring
	}

	public List<Usuario> buscarTodos() {
		// pode realizar outras operações, como enviar mensagens JMS ...
		return usuarioDao.list();
	}
}
:arrow: No cliente:
package form;

@Form
public class UsuarioForm {

	private UsuarioServico usuarioServico = // Recupera do contexto do Spring - ApplicationContext

	private String login;

	private String senha;

	private Usuario usuario;

	// outros atributos

	@DataProvider(objectField = "usuario")
	public List<Usuario> popularUsuarios() {
		// popula um combo, por exemplo ...
		return usuarioServico.buscarTodos(); // chamada remota
	}
}
Lembrando que os códigos são apenas de exemplo por isso não coloquei a implementação da interface.

Também não sei se é a melhor opção, mas tem funcionado bem para o nosso projeto. :D

[edit]
Esqueci de comentar: o Spring no servidor também nos dá outras vantagens como controle de transações declarativo e suporte para JMS.
[/edit]

Luca

Olá

Me considero experiente neste tipo de arquitetura e também com boas noções de rede e de integração de sistemas. Feito este preâmbulo, quero dizer que só em condiçoes muito especiais esta arquitetura pode ser melhor do que usar servlets ou outra solução mais desacoplada ainda como JMS.

Só de passagem gostaria que estudassem um pouco de história e verificassem sob quais circunstâncias e para quais aplicações RMI foi desenvolvido. Sei que aqui tem muitos fãs de RMI mas eu, que sou mais velho, não vejo porque adotar uma solução antiga quando hoje em dia temos muitas outras coisas melhores. Fora o fato de que RPC deve ser evitado ao máximo em qualquer sisteminha que a gente faça.

[]s
Luca (gosto do Spring mas Spring Remoting não foi feito para usar na camda de apresentação)

jopss

É… assim… por que?? (não conheço Spring Remoting)
Matheus Tardivo, tenho umas duvidas sobre o Genesis… poderia me dah um help?? Se puder add meu email que é meu msn…

jopss :stuck_out_tongue:

Luca

Olá

Para mim a camada de apresentação deve ser a mais leve possível e eu só admitiria usar RPC quando não tivesse outra alternativa e mesmo assim só se for um sistema muito pequeno que não vai crescer nunca tanto em número de usuários como em termos de serem incluídas novas facilidades no futuro.

Este papo só está acontecendo porque o Genesis induz o usuário a adotar esta arquitetura engrunvinhada, acoplada, pesada, enxuriçada, etc. e tal que para mim não faz sentido. Já comentei isto com o Michael e ele respondeu que esta não é a única arquitetura do Genesis e que só usa quem quer. Para mim seria melhor que o Genesis não admitisse esta arquitetura com EJBs/RMI/etc. no cliente.

[]s
Luca

Matheus_Tardivo

:lol:
Olá Luca.

Só pra entender melhor: qual problema você vê no cliente usando RPC? Estou perguntando isso pra entender melhor mesmo, não estou defendendo o meu ponto de vista.

Por que o cliente usar HttpClient enviando e recebendo objetos serializados é melhor?

Usando RPC, no caso do Spring Remoting, você executa um método remoto, através de um proxy via http, que pode enviar e receber objetos serializados. Qual seria a diferença do HttpClient? O proxy no cliente?

Desculpe a quantidade de perguntas (ainda tinha outras), mas realmente quero entender melhor o seu ponto.

Luca

Olá

Matheus Tardivo:
Só pra entender melhor: qual problema você vê no cliente usando RPC? Estou perguntando isso pra entender melhor mesmo, não estou defendendo o meu ponto de vista.

Por que o cliente usar HttpClient enviando e recebendo objetos serializados é melhor?

Usando RPC, no caso do Spring Remoting, você executa um método remoto, através de um proxy via http, que pode enviar e receber objetos serializados. Qual seria a diferença do HttpClient? O proxy no cliente?.

Executar um método remoto é exatamente o problema do RPC. Acopla os 2 sistemas. O ideal é que as partes do sistema troquem mensagens e de preferência de forma assíncrona sem que nenhum dos lados exponha sua API. Sem expor a API, a gente no futuro pode alterar a classe, o método e trocar tudo, inclusive a API.

Quero deixar claro que ainda acho que RMI e RPC podem ser usados em um sistema. Quer saber onde? Com JMX por exemplo porque JMX é acessado por pouca gente aom mesmo tempo e porque o RMI é apenas um conector fácil de usar. Mas na arquitetura de negócio do sistema só se for um programinha muito simples do tipo bacalhau para quebrar um galho isolado.

[]s
Luca

jopss

Muito boa a discução…

Sobre, gostaria do seu parecer sobre qual método usar para a ligação, no sentido que de um lado eu tenho um objeto Cliente, por ex, e no servidor tenho que ter este tal objeto e gravar no banco de dados… bem como para Fornecedor, Funcionario, Venda, Produto, Comissao, etc… no mesmo código. Ou seja nao posso denifir um padrão de colunas, pois cada um tem quantidades diferentes de dados.

Você tinha falado sobre XML e CSV… pesquisei sobre os dois e achei o CSV mais agradável… qual seria seu palpite? Pelo menos CVS saí o padrão Java, o que seria legal para “desacoplar mesmo” as coisas nao?

jopss :stuck_out_tongue:

Luca

Olá

Se você for passar mensagens sem serializar classes, crie suas classes de separadas no cliente e no servidor de modo que as classe no cliente sejam as ideiais para apresentar e no servidor as ideais para persistir.

Se enviar serializado, crie métodos usando reflection que serialize/deserialize de forma genérica. Você terá que replicar no servidor as classes do cliente e pode ser que ainda tenha que usar outras classes para fazer a persistência e construir as respostas das consultas.

Estas respostas só podem ser dadas analisando o sistema de perto e verificando o que é mais fácil de fazer de acordo com os conhecimentos técnicos da equipe. De acordo com o grau de conhecimentos da equipe, a solução adotada pelo Matheus pode ter preferência. A gente nunca deve esquecer de que a melhor solução é a que funciona e que o ótimo é inimigo do bom.

[]s
Luca

Matheus_Tardivo

Perfeito. Nesse caso seriam dois sistemas completamente independentes, com classes independentes, trocando mensagens por algum protocolo específico - XML, CSV, JSON, etc. O responsável por manter o protocolo seria o servidor e, para acessar seus serviços, basta seguir o protocolo. Qualquer alteração na aplicação servidora, desde que não altere esse protocolo, não causa impacto algum no cliente.

Agora, neste caso, mesmo não havendo RPC, depender das mesmas classes tanto no cliente quanto no servidor não acaba deixando o sistema tão acoplado quanto? O ponto é qualquer alteração nas classes do servidor afeta diretamente o cliente - não necessariamente nessa mesma ordem :roll: . E acho que é exatamente isso que você sugeriu evitar, certo?

Ter as mesmas classes no cliente e servidor, apenas usando servlets e serialização via XML, etc, ao invés de um proxy fazendo as chamadas aos métodos remotos, ainda deixa os dois sistemas acoplados. A conclusão que chego é que o ideal seria usar a primeira alternativa, onde não há dependência entre o cliente e servidor.

Na verdade, quando iniciamos esse projeto eu sugeri uma arquitetura REST. Mas como já havia um projeto feito em uma arquitetura muito semelhante, optamos por usá-la. Também acredito que não seja a melhor escolha, mas neste caso, fui voto vencido. :smiley:

jopss

É dois… estou vendo sobre CSV… a ideia seria criar um arq com os dados e cabeçalho e mandar pro server… lah ele abre e faz o objeto… seria isso??

jopss :stuck_out_tongue:

Luca

Olá

Certo. Na verdade seria ao contrário o mais provável de acontecer: alteração no cliente implica em alteração no servidor. Nos dias de hoje, fraco acomplamento deve ser um objetivo e tudo que dificultar deve ser pesado, medido, avaliado e só adotado se não houver outra solução igualmente fácil de fazer.

Fiz questão de lembrar desta possibilidade por que às vezes a gente critica determinada arquitetura sem saber exatamente o motivo pelo qual ela foi adotada. Por tudo que a gente fala hoje em dia de desenvolvimento ágil, de priorizar coisas que o cliente pode usar logo, de evitar desperdícios (Lean), etc. e tal, não adianta a gente ficar buscando algo que a equipe não domina e corre riscos demasiados. Apesar de REST ser algo bem mais promissor, neste caso a opção adotada parece ter sido a melhor possível.

[]s
Luca

Matheus_Tardivo

Só uma observação quanto a isso: usamos o Genesis apenas para binding e outras pequenas coisas no cliente. Neste caso, não usamos o esquema de chamadas remotas do Genesis - tanto que implementamos algo diferente usando o Spring. Aliás, como falei na resposta anterior, já havia um outro projeto usando uma arquitetura parecida, por isso não podemos nem falar que o Genesis nos influenciou a usar RPC.

Nada que acrescente muito a discussão, mas gostaria de deixar claro esse ponto. :slight_smile:

jopss

Opa…

Gostaria de discutir sobre a quantidade de lógica existente na aplicacao cliente.

No meu caso, eu estou fazendo assim:

NO CLIENTE.
Os dados da tela (swing) vai parar em um objeto bean… faço as validações nestes objetos, e replico na tela para ser mais efetivo… então este objeto bean é convertido em XML, e send pela rede!

NO SERVER.
Um servlet recebe o xml, reconverte em objeto bean (este anotado para hibernate) e efetua a gravação no banco de dados, retornando o necessário.


Mas me parece estranho. O cliente parece mais enxuto do que o necessário e não possui muita lógica no server, somente receber e gravar no banco. Por outro lado, nao tem muito mais o que fazer, só se eu colocasse as validações lá no server ao inves no cliente, mas ao meu ver isso geraria maior tráfego na rede.
Está correto isso? O que seria uma forma ideal?

jopss :stuck_out_tongue:

Luca

Olá

Como venho insistindo desde o início, é sempre preciso fazer as validações também no servidor por motivos de segurança (prevenir contra cliente fake)

[]s
Luca

jopss

… ae seria validação no bean cliente, no server e na tela !!!

no caso eu estou duplicando as classes bean no cliente e server para efetuar da forma que falei… eh “estranho” isso? :roll:

teria mais oq para colocar no server? Nao vejo oq mais…

por favor, tbm precisaria de um coment qualquer neste post:
http://www.guj.com.br/posts/list/86894.java#464781

vlw novamente! :thumbup:

jopss

Luca

Olá

Pouco importa se você vai usar Bean, Clipper ou assembler, tem que validar TAMBÉMno servidor.

Atente que na mensagem anterior coloquei também em negrito.

[]s
Luca

Criado 28 de março de 2008
Ultima resposta 11 de abr. de 2008
Respostas 24
Participantes 3