EJB Genérico

Já postei um tópico sobre a utilização de um único EJB para a aplicação toda.
Pensei e tive uma ideia e gostaria de ver a opinião de voces.
Não testei e o código tem vários erros, mas é apenas para exemplificar a ideia.
Gostaria de saber quais os problemas que posso ter.
Performance, se eu utilizo a transação do container, etc.

ex:


class GenericEJB implements SessionBean
{
  public Object callMethod(String className, String methodName, Object object)  
  {
     Class targetClass  = Class.forName(className);	
     Object target = targetClass.newInstance();
     return targetClass.getMethod(methodName,new Class[] { object.getClass }).invoke(target,new Object[] { object });
  }
}

class Delegate 
{
   protected Object callMethod(String className, String methodName, Object object)
   {
      GenericEJB  ejb = ... pega o ejb todo mundo sabe como;
      ejb.callMethod(className,  methodName, object);
   }
}

class FuncionarioDelegate extends Delegate
{
  public Funcionario consultarFuncionario(FuncionarioDTO funcionarioDTO)
  {
     return (Funcionario) callMethod("FuncionarioService",  "consultarFuncionario", funcionarioDTO);
  }
}

class FuncionarioService
{
  public Funcionario consultarFuncionario(FuncionarioDTO funcionarioDTO)
  {
     // consulta o funcionario
  }
}

class Cliente
{
 public void chama()
 {
    FuncionarioDTO fd = new FuncionarioDTO ();
    fd.setCodigo(1);
    fd.setNome("Maria");

    FuncionarioDelegate f = new FuncionarioDelegate();
    Funcionario func = f.consultarFuncionario(f);
 }
}

Como podem ver é um negócio louco, mas que pode ter fundamento…

Tem fundamento, sim, e a gente ja usou num projeto aqui - mas desse jeito que vc esta fazendo ta muuuuuuito fraquinho. Recomendo dar uma olhada em dynamic proxies :wink:

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/Proxy.html

Mas para ter esse proxy aí deve-se informar a classe em tempo de desenvolvimento.
Mas seria interessante informa-la em tempo de execução através de uma string.

Class.forName(classe);

Achei muito elaborado para apenas fazer uma chamada dinamica.
Não vi utilidade nesse código todo.
Não é mais fácil dar invoke no método.

Mas pela sua experiência isso ajudou com a manipulação de EJBs ?
Pois com essa solução teoricamente resolveria esse problema, pois teria um único EJB para toda aplicação.
O deploy seria bem mais fácil.

Você continua usando essa técnica ?

jprogrammer,

você anda trabalhando em algum projeto aqui no Rio?

No último projeto Java por onde eu passei, tinhamos uma GenericEJB MUITO similar ao que você propôs.

O deploy realmente era mais simples e quando queríamos adicionar um novo serviço, precisávamos apenas escrever POJOs e acertar a configuração no preferences (que poderia ser XML, .properties, whatever).

O GenericEJB sabia o que chamar a partir dessa configuração.

Acho que há uma certa perda de performance por conta de utilizar reflection. Mas não sei a que ponto essa perda chega a ser significativa.

Como no nosso caso o objetivo do EJB era apenas o de disponibilizar chamadas remotas aos serviços, não nos deixava muito amarrados. Mas acho que se para cada service você tiver requisitos transacionais diferentes, pode começar a complicar a história.

Outro ponto que você tem que prestar atenção é que se você tem apenas 1 GenericEJB deployado que pode atender a N services, você estará utilizando apenas 1 único pool de Sessions. Então a configuração/tuning tem que levar isso em consideração também.

Abraços,
Marco Campêlo

Sou de SP.
Mas isso gerou resultados satisfatórios ?

Explique melhor:

E bom saber disso.
legal.

Sim. Era produtivo deployar novos serviços porque o EJB estava pronto. Era apenas uma questão de escrever sua classe de negócios e fazer a configuração necessária.

Imagine que você usa 1 Session para 10 Services. Será apenas 1 EJB deployado que atende a 10 services.

Agora imagine que você recebe 15 requests/segundo em cada um desses services.

O seu pool de EJB tem que dar conta de atender 150 requests/segundo.

Se você tem services com características muito distintas que necessitam de configurações muito diferentes, ter tudo isso em um único pool vai ser um complicador.

Ex.:

Service precisa de transação? Sim ou não?
Qual timeout necessário para cada service?

[]'s
Marco Campêlo

Isso é uma das minhas dúvidas.
No caso de transação o método invocado pelo reflection participa.
Mas a maior parte das transações seriam controladas pelo banco.

O pool atende apenas uma requisição por vez ?
Eu pensei que o container criasse instancias do sessionbean sob demanda.

Cria sob demanda. Atende a tantas requisições quantos beans você tiver no pool.

O problema é que se cada service possui características diferentes, um trabalho de fine tuning fica muito mais difícil, não acha? Afinal, você possui um EJBGenérico que atende a 10 services com características distintas.

[]'s
Marco Campêlo

Nesse caso não seria apenas fazer o deploy do mesmo EJB usando um nome JNDI diferente? Isso permitiria configurações diferentes.

Exato, louds. Essa era a estratégia adotada. A vantagem é ficar livre para configurar a sua maneira. A desvantagem é que você volta a ter que fazer o deploy de N EJBs e manter N deployment descriptors.

Tem que colocar na balança e ver para o seu caso, o que é melhor.

[]'s
Marco Campêlo

Se precisa de N configurações diferentes não vejo como não usar N artefatos EJBs. Mas como você mesmo falou, isso é para o tunnig da aplicação, se só isso já for suficiente não é de se reclamar.

Mas já seria uma vantagem ou não ?
Vc teria que apenas que usar a mesma classe genericEJB com nomes JNDI diferentes, não criar várias classes identicas.
Isso pode ?

Agora outra dúvida.
O container pode administrar apenas uma instancia porque eu posso invocar um método de uma instancia simultaneamente por várias threads ?
Não é o que o Web container faz com os servlets ?
Não seria o mesmo com os EJB containers ?

[quote=jprogrammer]Mas já seria uma vantagem ou não ?
Vc teria que apenas que usar a mesma classe genericEJB com nomes JNDI diferentes, não criar várias classes identicas.
Isso pode ?[/quote]

Pode tudo. Depende do seu cenário! :slight_smile: Se houvesse uma resposta definitiva para tudo, nossa profissão seria moleza e nós não teríamos salários de milhões que temos! :smiley:

Não entendi nada da sua pergunta. Sorry! :frowning:

[]'s
Marco Campêlo

Tá mesmo embassada essa pergunta…
Vamos lá.

Um container Web como Tomcat tenta administrar no máximo uma instancia de um servlet.
Qualquer requisição para o servlet faz a invocação do método service.
Várias requisições simultaneas podem invocar o service sem problemas.

A mesma coisa não seria com o EJB container ?
Ele administraria as instancias ou a instancia e invocaria o método deste objeto para várias requisições simultaneamente.
Esse negócio de pool me parece mais apropriado com statefull sessions bean.

Não, EJBs são threadsafe, a idéia de um pool é exatamente para isso. Um EJB fica ativo em somente uma thread por vez.

Quer dizer que ele espera uma requisição acabar para atender outra para o mesmo EJB.

[quote=jprogrammer]Quer dizer que ele espera uma requisição acabar para atender outra para o mesmo EJB.
[/quote]

Aí que entra a configuração do seu pool de EJBs.

Se você configurar que o número de EJBs no pool no start será 1 e o máximo será 1, sim, isso irá acontecer.

Se você configurar que o inicial será 10 e o máximo é 30, você consegue atender até 30 requests simultâneos.

[]'s
Marco Campêlo

Não confunda o EJB com as instancias dele.

EJBs são feitos para processamento paralelo massivo, mas cada instancia de um EJB é usada em uma thread por vez.

Pelo que ouvi falar ele cria instancias sob demanda, ou seja, ele tem 10 instancias no pool, pelo que o louds disse , cada instancia atende uma requisição.
Se tiver 15 requisições ele cria mais 5 instancias.
O pool é só para ter uma chache.
É isso ?

No caso do EJB genérico que vcs fizeram (mcampelo) como ficou isso ?
Porque dá na mesma eu ter um EJB só que atende 100 e ter 10 EJB que atendem 10 cada um. Ou não ?

Se possível me exemplifique…

Se for o mesmo EJB com nomes diferentes, deve dar na mesma. A questão que o marco levanto é quando um dos comandos executados pelo seu EJB precisar de tunning diferente. Se ele for mais importante de repente merece um pool a parte do resto, ou então se tiver requisitos transacionais diferentes.