Http Com Hessian Sim ou Nao?

10 respostas
jurunaloco

E ai pessoal blz ?

estou fazendo uma APP porem quero que:
seja acessada em diversos locais … cidades diferentes por exemplo…

porém… estou pensando em fazer uma interface usando Swing
com o servidor utilizando ServLets … a conexao seria feita via HTTP

alguem ja testou tal implementaçao ? estou usando a api do Hessian para tal comunicaçao…

sou bem leigo em web… e queria saber os prós… contras… e se é uma tecnologia usável em um sistema …

Obrigado a todos

10 Respostas

fantomas

E ai jurunaloco,

No spring tem o Hessian (vc está utilizando), Burlap e o HttpInvoker para comunicação HTTP.

 Se você estiver utilizando o spring aconselharia vc utilizar o HttpInvoker, segundo o tutorial ele é o mais rápido. Ele não utiliza xml, ao invés disso ele serializa o objeto com todos os tipos (int, double, as listas etc...) suportados pelo java.

 No projeto eu comecei com o Hessian mas mudei para o HttpInvoker, estava preocupado com a performance e os tipos de dados suportados pelo framework.

 O projeto atingiu as expectativas neste tocante, a diferença entre este projeto e o seu é que: Ele é executado em uma intranet nas unidades da empresa onde acredito que a rede seja mais estavel.

 O seu projeto vai funcionar com Hessian? Eu acredito fortemente que sim.

 A dúvida que tenho é em relação a arquitetura: Por que swing e não HTML+JavaScript que é considerado mais leve?

 P.S. Se vc não estiver utilizando o spring  uma boa olhada neste framework, no começo é meio complicado mas depois você terá um ganho enorme em produtividade e robustez no código.

[]'s

jurunaloco

fantomas:
E ai jurunaloco,

No spring tem o Hessian (vc está utilizando), Burlap e o HttpInvoker para comunicação HTTP.

 Se você estiver utilizando o spring aconselharia vc utilizar o HttpInvoker, segundo o tutorial ele é o mais rápido. Ele não utiliza xml, ao invés disso ele serializa o objeto com todos os tipos (int, double, as listas etc...) suportados pelo java.

 No projeto eu comecei com o Hessian mas mudei para o HttpInvoker, estava preocupado com a performance e os tipos de dados suportados pelo framework.

 O projeto atingiu as expectativas neste tocante, a diferença entre este projeto e o seu é que: Ele é executado em uma intranet nas unidades da empresa onde acredito que a rede seja mais estavel.

 O seu projeto vai funcionar com Hessian? Eu acredito fortemente que sim.

 A dúvida que tenho é em relação a arquitetura: Por que swing e não HTML+JavaScript que é considerado mais leve?

 P.S. Se vc não estiver utilizando o spring  uma boa olhada neste framework, no começo é meio complicado mas depois você terá um ganho enorme em produtividade e robustez no código.

[]'s

e ai td bem ?

eu estou utilizando essa biblioteca como teste http://hessian.caucho.com/ serializando objetos

o fato de utilizar swing no cliente… seria pela funcionalidade… troca de campos com enter… etc… um sistema mais pratico de usar , todo via teclado e mais simples para o usuario final
até pensei em implementar tais funcionalidades em web(via browser) mas creio que é inviável …

como esta sendo sua experiencia nessa forma de programaçao? que tecnologias usa para montar a interface ?

Obrigado e Abraços!

fantomas

No projeito que participei o swing foi utilizado pelos mesmos motivos. O client exigiu vários comportamentos na interface que julgamos difíceis de implementar em HTML, queriamos evitar ao máximo dizer que não dava pra fazer ou que éra muito difícil e não compensava fora outros requisitos malucos que haviam rsrsrs.

“Não eram usuários típicos de internet”, foi o que disseram. Até hoje não entendi essa frase direito mas blz.

A IDE utilizada foi o eclipse.

Para o módulo CLIENT:

.Spring - para acessar os serviços no server
.myEclipse - módulo Mantisse para desenhar as telas - não é free, custa menos de R$ 100,00. O matisse já vem com o NetBeans gratuitamente mas a maior parte da equipe votou em utilizar o eclipse (eu votei contra, apesar de gostar do eclipse).
.Genesis - Esse framework é brasileiro e É SHOW DE BOLA, ajuda a fazer binding dos objetos visuais com annotations e as dúvidas ou problemas são respondidos rapidamente.
.Glazed Lists - Api para grids. Muito bacana e simples de utilizar, acho que vai te ajudar muito.
.Em alguns casos utilizamos o swingx - ComboBox e digitação de data com calendario.

Para o módulo SERVER.

.Spring - disponibilizar os serviços, controle de transações, injeção de dependencia.
.JPA/Hibernate - persistencia. Foi utilizado annotations ao inves de xml, ainda acho que é uma questão de opção pois algumas vezes eu achava que as classes de modelo ficavam muito poluidas com as anotações talvez tenha sido a falta de constume estou refletindo sobre isso.

Para o módulo que faz o deploy no client.
.WebStart - site com o client envelopado.

Acho que é isso, espero não ter esquecido nada.

[]'s

jurunaloco

muito interessante fantomas
vou fazer uns testes aqui… hehe…

Muito obrigado por relatar sua experiencia aqui no forum…

abraços

sfidencio

fantomas:
No projeito que participei o swing foi utilizado pelos mesmos motivos. O client exigiu vários comportamentos na interface que julgamos difíceis de implementar em HTML, queriamos evitar ao máximo dizer que não dava pra fazer ou que éra muito difícil e não compensava fora outros requisitos malucos que haviam rsrsrs.

“Não eram usuários típicos de internet”, foi o que disseram. Até hoje não entendi essa frase direito mas blz.

A IDE utilizada foi o eclipse.

Para o módulo CLIENT:

.Spring - para acessar os serviços no server
.myEclipse - módulo Mantisse para desenhar as telas - não é free, custa menos de R$ 100,00. O matisse já vem com o NetBeans gratuitamente mas a maior parte da equipe votou em utilizar o eclipse (eu votei contra, apesar de gostar do eclipse).
.Genesis - Esse framework é brasileiro e É SHOW DE BOLA, ajuda a fazer binding dos objetos visuais com annotations e as dúvidas ou problemas são respondidos rapidamente.
.Glazed Lists - Api para grids. Muito bacana e simples de utilizar, acho que vai te ajudar muito.
.Em alguns casos utilizamos o swingx - ComboBox e digitação de data com calendario.

Para o módulo SERVER.

.Spring - disponibilizar os serviços, controle de transações, injeção de dependencia.
.JPA/Hibernate - persistencia. Foi utilizado annotations ao inves de xml, ainda acho que é uma questão de opção pois algumas vezes eu achava que as classes de modelo ficavam muito poluidas com as anotações talvez tenha sido a falta de constume estou refletindo sobre isso.

Para o módulo que faz o deploy no client.
.WebStart - site com o client envelopado.

Acho que é isso, espero não ter esquecido nada.

[]'s

fatomas, ei q ja faz tempo isso aqui mas pode me dar uma mão?

a um tempo atras você me deu umas ideias interessantes sobre Spring. Seguinte:

imagine um sistema de automação comercial em java, onde o sistema de gestao é WEB(jsf2+primefaces) (estou querendo usar Spring para injetar depencias, integrar com jsf, servico de email e etc, etc). Porem terei uma outra aplicação desktop semelhante a essa que você citou.

Olha só, essa aplicação destop terá seu proprio banco de dados entende, porem de tempos em tempos pretendo chamar um metodo na aplicação desktop que invoca o serviço remoto no appserver e faz uma select no sgbd local de todas as vendas, e vai inseririndo no sgbd da matriz. Você acha mais inteligente eu enviar esses registros local para o sgbd remoto atraves desse serviço ou conectar direto do sistema em Swing no SGBD da matriz?. Se eu usasse o serviço provido pelo spring, eu teria segurança igual eu usar a conexao direta com banco de dados da matriz? Imagina se o link cair?, eu nao posso ter inconsistencia, ou commit tudo ou nada certo?

Me ajude!

Fidencio

fantomas

Oi sfidencio,

Então…não sei se entendi o seu problema direito, mas mesmo assim vamos lá.

  1. O problema em transferir registros de uma base para outra é que se a informação for alterada na sua origem elas poderão ficar desincronizadas; a não ser que se pense em alguma solução para esta questão.

  2. Em relação a segurança na transferencia dos dados (caso opte por isto) em um primeiro momento você teria as transações anexadas aos servições, porem elas estariam separadas. Na primeira transação vc teria as leituras no servidor A e na segunda transação as inserções no servidor B. Porem existe o trafico dos dados após a primeira transação (leitura no servidor A), aqui existe o risco da conexão falhar. O que você poderia fazer seria primeiro ler os dados COMPLETOS referente a transação que você deseja executar, quando a leitura e a TRANSFERENCIA terminar sem problemas vc começa a atualização no servidor B.

  3. Existem casos que as pessoas tentam utilizar os serviços do próprio banco de dados para sincronização dos dados; acho que o Sql Server, Oracle e o postgre possuem este tipo de recurso.

  4. Tente utilizar bastante logs para vc ter o poder da rastreabilidade nas mãos. Se houver algum problema na origem ou no destino é sempre bom poder encontra-lo rápido.

Enfim, o seu problema geralmente não chega a ser trivial e depende muito do contexto do problema.

A principio eu optaria por não transferir os dados, a não ser que eu encontrasse uma justificativa bem clara para não fazer isto. Ex. conexões lentas ou instaveis durante o dia, sendo assim poderia executar as transferencias durante a noite.

A melhor solução para este tipo de problema depende bastante da analise e compreenção do dominio do seu problema.

Espero ter ajudado.

flws

sfidencio

fantomas:
Oi sfidencio,

Então…não sei se entendi o seu problema direito, mas mesmo assim vamos lá.

  1. O problema em transferir registros de uma base para outra é que se a informação for alterada na sua origem elas poderão ficar desincronizadas; a não ser que se pense em alguma solução para esta questão.

  2. Em relação a segurança na transferencia dos dados (caso opte por isto) em um primeiro momento você teria as transações anexadas aos servições, porem elas estariam separadas. Na primeira transação vc teria as leituras no servidor A e na segunda transação as inserções no servidor B. Porem existe o trafico dos dados após a primeira transação (leitura no servidor A), aqui existe o risco da conexão falhar. O que você poderia fazer seria primeiro ler os dados COMPLETOS referente a transação que você deseja executar, quando a leitura e a TRANSFERENCIA terminar sem problemas vc começa a atualização no servidor B.

  3. Existem casos que as pessoas tentam utilizar os serviços do próprio banco de dados para sincronização dos dados; acho que o Sql Server, Oracle e o postgre possuem este tipo de recurso.

  4. Tente utilizar bastante logs para vc ter o poder da rastreabilidade nas mãos. Se houver algum problema na origem ou no destino é sempre bom poder encontra-lo rápido.

Enfim, o seu problema geralmente não chega a ser trivial e depende muito do contexto do problema.

A principio eu optaria por não transferir os dados, a não ser que eu encontrasse uma justificativa bem clara para não fazer isto. Ex. conexões lentas ou instaveis durante o dia, sendo assim poderia executar as transferencias durante a noite.

A melhor solução para este tipo de problema depende bastante da analise e compreenção do dominio do seu problema.

Espero ter ajudado.

flws

Fatomas, é simples:

Eu tenho estação rodando uma aplicação em Swing entende? essa estação vai ter um banco de dados possivelmente o derby ou mysql, essa estação prover um sistema de vendas com emissão de cupom fiscal e transferencia de fundos eletronicos(TEF).

1.após a efetivação da venda, o sistema irá chamar um serviço para enviar todos registros do sgbd local cujo flag de enviando ou nao na tabela é ‘P’ DE pendente, se for ‘E’ é porque ja enviou. a chave primaria será o código da operação fornecido pela impressora, e ele de forma alguma se repete entende? , portanto a minha duvida e como chamar o webservice exposto pelos pela minhas classes de serviços com Spring, de tal forma que eu populo o sgbd do servidor com segurança, ou seja, se a conexao for abortada, então eu nao comito local e nem remoto só isso meu amigo.

att
fidencio

fantomas

sfidencio:
Eu tenho estação rodando uma aplicação em Swing entende? essa estação vai ter um banco de dados possivelmente o derby ou mysql, essa estação prover um sistema de vendas com emissão de cupom fiscal e transferencia de fundos eletronicos(TEF).

1.após a efetivação da venda, o sistema irá chamar um serviço para enviar todos registros do sgbd local cujo flag de enviando ou nao na tabela é ‘P’ DE pendente, se for ‘E’ é porque ja enviou. a chave primaria será o código da operação fornecido pela impressora, e ele de forma alguma se repete entende? , portanto a minha duvida e como chamar o webservice exposto pelos pela minhas classes de serviços com Spring, de tal forma que eu populo o sgbd do servidor com segurança, ou seja, se a conexao for abortada, então eu nao comito local e nem remoto só isso meu amigo.

Humm…acho que agora entendi.

  1. Para expor os serviços através do spring vc faz assim: http://static.springsource.org/spring/docs/2.0.x/reference/remoting.html

Perceba que quem vai expor os serviços é o spring através da configuração xml; ele irá criar um proxy baseado no objeto resultante da implementação do serviço (isto é transparente para nós). Significa que o serviço poderá ser utilizado pelo controller do módulo web e TAMBEM pelo client remoto sem problemas.

  1. Em relação as transações a idéia que me veio foi de disponibilizar um serviço para informar se dado grupo de registros foram atualizados ou não com base na chave que os identifica. Aí ficaria assim:

a) Obter o registro com flag de enviado igual a P.
b) Executar o serviço remoto e verificar (através da chave) se o registro já foi atualizado.
c) Se o registro não foi atualizado então atualizar senão ignorar.
d) Se a atualização foi bem sucedida alterar o flag para E

As transações dos dois lados não são dependentes uma da outra. Significa que, poderá haver um commit em uma extremidade da comunicação e ocorrer um problema na rede antes da resposta chegar no client provocando um rollback.

Minha dúvida: A sua dúvida reside mais no ponto 1 ou no ponto 2?

flws

sfidencio
fantomas:
sfidencio:
Eu tenho estação rodando uma aplicação em Swing entende? essa estação vai ter um banco de dados possivelmente o derby ou mysql, essa estação prover um sistema de vendas com emissão de cupom fiscal e transferencia de fundos eletronicos(TEF).

1.após a efetivação da venda, o sistema irá chamar um serviço para enviar todos registros do sgbd local cujo flag de enviando ou nao na tabela é 'P' DE pendente, se for 'E' é porque ja enviou. a chave primaria será o código da operação fornecido pela impressora, e ele de forma alguma se repete entende? , portanto a minha duvida e como chamar o webservice exposto pelos pela minhas classes de serviços com Spring, de tal forma que eu populo o sgbd do servidor com segurança, ou seja, se a conexao for abortada, então eu nao comito local e nem remoto só isso meu amigo.

Humm...acho que agora entendi.

1) Para expor os serviços através do spring vc faz assim: [url]http://static.springsource.org/spring/docs/2.0.x/reference/remoting.html[/url]

Perceba que quem vai expor os serviços é o spring através da configuração xml; ele irá criar um proxy baseado no objeto resultante da implementação do serviço (isto é transparente para nós). Significa que o serviço poderá ser utilizado pelo controller do módulo web e TAMBEM pelo client remoto sem problemas.

2) Em relação as transações a idéia que me veio foi de disponibilizar um serviço para informar se dado grupo de registros foram atualizados ou não com base na chave que os identifica. Aí ficaria assim:

a) Obter o registro com flag de enviado igual a P.
b) Executar o serviço remoto e verificar (através da chave) se o registro já foi atualizado.
c) Se o registro não foi atualizado então atualizar senão ignorar.
d) Se a atualização foi bem sucedida alterar o flag para E

As transações dos dois lados não são dependentes uma da outra. Significa que, poderá haver um commit em uma extremidade da comunicação e ocorrer um problema na rede antes da resposta chegar no client provocando um rollback.

Minha dúvida: A sua dúvida reside mais no ponto 1 ou no ponto 2?

flws

Fatomas, as transações estarão em contextos diferente como você disse, e pode haver que no servidor seja comitado e no cliente não em virtude do meio de comunicação ser interrompido, evidentemente, um roolback será chamado. Portanto, a minha dúvida está nos dois pontos, se ambos falhar? que tipo de algoritimo eu poderia fazer em ambos lados para verificar se existi algo Pendente em ambos os lados.? Imagina só: o Caixa 1 Vendeu 10.000,00 no dia, onde:

4000,00 Dinheiro
5000,00 Cartão de credito
1000,00 Cheque a prazo e a vista

Quando o usuario do sistema WEB for fazer o fechamento de caixa diario, para apurar a venda do caixa 1 irá perceber que está faltando 500,00 Reais, ou seja, existe um divergência de 500,00. Porque isso? Porque no Sistema de Caixa armazenamos dois tipos de movimento:

Movimento de Caixa (Leitura Z) - Esse movimento fica gravado na memoria Eprom da impressora fiscal (ECF)
Movimento de Produtos - Esse movimento fica gravado no banco de dados local

Esse dois tem que ser igual, imagina a falta dos 500,00 reais que teve. teremos uma diferença de 500,00. Isso não é outra coisa fatomas, o registro
que não foi sincronizado com a matriz.

Com base nisso, suponha que o commit do frente de caixa (swing app) não falhe, ou seja, ele alterou a FLAG, portanto não há possibilidade das rotinas automaticas (disparada via threads) tentar enviar tal registro novamente, visto que FLAG ja foi alterado, porém no servidor não foi alterada ainda. O que eu faço? Crio uma rotina no caixa para que o usuario forçe o enviou dos registros de determinada venda em um determinado periodo? Levando em conta que o registro não está no servidor e mesmo se tivesse ele ignoraria.

Veja só como ficaria a sequencia de implementação para enviou da venda do sistema PDV (swing) para o servidor (Web):

1. Seleciono as vendas pendentes na tabela Venda onde o status for igual a 'P', veja o schema da tabela venda:

Venda( coo(pk), data_mvto, status, enviado, usuario, Valor_Total)

Explicando:

coo = Codigo da operacao será a chave primaria
data_mvto = Data em que a venda foi realizada.
status = Se cumpom fiscal foi cancelado ou seja o cliente desistiu de comprar então gravo 'C' de cancelado ou 'N' de normal caso o cliente compre.
enviado = Se essa venda foi enviada ou não para o servidor a flag é 'P' de pendente, se foi enviada a FLAG é 'E' de enviado. (Ambos tem que confirmar o envio/recebimento)
Valor_Total = armazena o valor total da venda

Obs: Ao selecionar uma venda usando JPA/Hibernate posso trazer todos itens daquela venda caso o fech-join esteja habilitado, salvo erro, isso reduz pra mim quantidade de codigo se fosse fazer em SQL puro, logo eu tenho um objeto Venda que dentro dele como se trata de uma composição de objetos eu tenho varios obejtos que são os itens da Venda, resumindo eu farei a transferencia mais ou menos dessa forma me ajuda ai:

//Classe Implementação do Repositorio do Sistema de PDV Swing App.
public class VendaRepositoryJPAImpl implements VendaRepository {

  List<Venda> vendasPendentes = em.createQuery(
    "select cat from Cat as cat where cat.enviado:param1")
    .setParameter(1)
    .getResultList();
  return vendasPendentes;

} 


//Classe de serviço do Sistema PDV Swing App.
public void enviarVendaMatriz() {
  //Crio o serviço 
  ServicoWeb servicoWeb = new ServicoWeb();
  ServicoPorta servicoPorta = servicoWeb.getPorta();

  //Diz ao servidor se foi comitado no cliente.
  Boolean comitadoMatriz = false;
  
  //Resposta do Servidor Matriz.
  String respostaEnvioFilialMatriz;

  //Respostar Local para ser enviada para o servidor.
  String respostaEnvioMatrizFilial

  //Obtenho as vendas pendetes
  List<Venda> vendasPendentes =  vendaRepositoy.obterVendasPendentes();  
  
  //Mando o Objeto todo..(Esse objeto não é tao gordo não, vai depender se não possui muitas vendas pendentes, o ideal é sempre está sincronizando )
 //So vai devolver 'true' se foi realmente comitado..
  respostaEnvio = servicoPorta.enviarVenda(vendaPendentes,comitadoMatriz);

 //respostaEnvio pode receber: SUCESSO. FALHA  
 //Comito local caso ocorreu tudo certo no servidor.. 
if(repostaEnvio=="SUCESSO") {
    //Tento comitar Local.. ou seja alterar a FLAG de  P para E
    vendaRepository.confirmarEnvioVendaMatriz(vendasPendentes);
}

if(respostaEnvio=="FALHA") 
  System.out.println("Falhou");


if(respostaEnvio=="EXISTE")  //Comito localmente..
      vendaRepository.confirmarEnvioVendaMatriz(vendasPendentes);

Fatomas de qualquer forma vai ter uma lado que ficará teoricamente em risco, de nao ter enviado. no caso o cliente, porque o cliente nesse caso tem feedback do servidor, porem o servidor nao tem do cliente...
Não vejo problema quanto a isso caso o cliente nao consiga comitar porque olhar só posso fazer o seguinte, guardar em uma tabela em ambos os lados, informações de sicronização. ou seja, guardo o ultimo COO que foi enviado, e toda vez
que eu tentar enviar,..eu verifico antes,se o ultimo COO existe no servidor, porque o que importa mais pra mim é o servidor.. ou seja, se o cliente nao enviou..a proxima vez ele tenta enviar..e se ele tentar enviar algo que já existe eu so comito localmente

qc acha?

fantomas

Oi sfidencio!

sfidencio:
Fatomas, as transações estarão em contextos diferente como você disse, e pode haver que no servidor seja comitado e no cliente não em virtude do meio de comunicação ser interrompido, evidentemente, um roolback será chamado. Portanto, a minha dúvida está nos dois pontos, se ambos falhar? que tipo de algoritimo eu poderia fazer em ambos lados para verificar se existi algo Pendente em ambos os lados.? Imagina só: o Caixa 1 Vendeu 10.000,00 no dia, onde:

Se as transações dos dois lados falharem será como se "nada houvesse ocorrido" e na próxima atualização haverá uma nova tentativa.

sfidencio:
Fatomas de qualquer forma vai ter uma lado que ficará teoricamente em risco, de nao ter enviado. no caso o cliente, porque o cliente nesse caso tem feedback do servidor, porem o servidor nao tem do cliente... Não vejo problema quanto a isso caso o cliente nao consiga comitar porque olhar só posso fazer o seguinte, guardar em uma tabela em ambos os lados, informações de sicronização. ou seja, guardo o ultimo COO que foi enviado, e toda vez que eu tentar enviar,..eu verifico antes,se o ultimo COO existe no servidor, porque o que importa mais pra mim é o servidor.. ou seja, se o cliente nao enviou..a proxima vez ele tenta enviar..e se ele tentar enviar algo que já existe eu so comito localmente

qc acha?

Acho que este caminho já é um bom começo.

1) Por causa da dificuldade de fazer previsões este seu problema é mais um daqueles que começa e vai melhorando com o tempo durante os testes.

2) Um dos pontos chaves é a rastreabilidade. Se quem for fechar o caixa na matriz detectar um broblema (não bater os valores) você tem que ter condições de rastrear a falha. Por exemplo: Você poderia adicionar logs nestas transações (dos dois lados) registrando o ocorrido. Para as transações que NÃO terminarem com sucesso faça com que o sistema envie emails de notificação para algumas pessoas chaves para monitorar. Você poderia ainda registrar as transações que falharam em uma tabela (devidamente controlada) e permitir consultas via relatório e/ou formulario.

3) Tente conseguir duas máquinas para fazer testes. Você podera simular a situação retirando os cabos de conexão ou forçando exceptions para testar o seu código.

4) No seu código:

//Mando o Objeto todo..(Esse objeto não é tao gordo não, vai depender se não possui muitas vendas pendentes, o ideal é sempre está sincronizando )  
 //So vai devolver 'true' se foi realmente comitado..  
   respostaEnvio = servicoPorta.enviarVenda(vendaPendentes,comitadoMatriz);  // <---------------------------------------
   
 //respostaEnvio pode receber: SUCESSO. FALHA    
 //Comito local caso ocorreu tudo certo no servidor..   
 if(repostaEnvio=="SUCESSO") {  
     //Tento comitar Local.. ou seja alterar a FLAG de  P para E  
     vendaRepository.confirmarEnvioVendaMatriz(vendasPendentes);  // <---------------------------------------
 }

Só para alertar, onde coloquei as setas se houver uma exception (timeout por exemplo) todo o código abaixo será ignorado. Talvez seja melhor não depender muito das variáveis. Fique atento ao fluxo de controle das exceptions para você gerar os logs e tomar decisões.

flws

Criado 25 de julho de 2008
Ultima resposta 6 de out. de 2010
Respostas 10
Participantes 3