EJB Classe de fábrica

votos
2

Eu estou tentando criar uma classe EJB fábrica, que funciona assim: Você tem um método que usa como argumento uma classe de um EJB, em seguida, ele verifica se o EJB tem uma interface remota (se não lançar uma exceção) e se faz, ele retorna o respeito EJB.

O código a seguir faz exatamente isso. No entanto, o objeto que ele retorna é do tipo da interface remota do respeito feijão e não do próprio feijão. Como eu posso mudar isso? Existe uma maneira de dizer Java que o tipo genérico T é do mesmo tipo que a classe passado para os métodos.

import java.util.Properties;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.naming.*;


public class EJBFactory
{

    private InitialContext ctx;

    public EJBFactory() throws NamingException {
        ctx = new InitialContext();
    }

    public EJBFactory(String host, String port) throws NamingException {
        Properties props = new Properties();
        props.setProperty(org.omg.CORBA.ORBInitialHost, host);
        props.setProperty(org.omg.CORBA.ORBInitialPort, port);
        ctx = new InitialContext(props);
    }
.
    // To improve: The object returned should be of the type ejbClass
    // instead of the remote interface, which it implements
    public <T> T createEJB(Class ejbClass) throws NamingException
    {
        Class remoteInterface = null;
        for(Class interface_: ejbClass.getInterfaces()) {
            if(interface_.isAnnotationPresent(Remote.class))
                remoteInterface = interface_;
        }

        if(remoteInterface == null)
            throw new  IllegalArgumentException(
                EJB Requires a remote interface);

        // Get the stateless annotation, then get the jndiName
        Stateless stateless =
            (Stateless)ejbClass.getAnnotation(Stateless.class);
        String jndiName = stateless.mappedName();
        T ejbObj = (T) ctx.lookup(jndiName);
        return ejbObj;
    }

}

Exemplo de uma unidade de teste que usa a fábrica.

import junit.framework.TestCase;


public class SimpleEJBTest extends TestCase
{
    TestRemote testBean;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        EJBFactory ejbFactory = new EJBFactory();
        testBean = ejbFactory.createEJB(TestBean.class);
    }

    public void testSayHello() {
        assertEquals(Hello, testBean.sayHello());
    }
}

Nota: O exemplo funciona com o Glassfish, eu não testá-lo com qualquer outro servidor de aplicações.

Publicado 06/08/2009 em 15:07
fonte usuário
Em outras línguas...                            


4 respostas

votos
3

Clientes de EJBs interagir com eles através da interface local / remoto que o EJBs implementar. As aplicações cliente nunca tem acesso directo a uma instância real da classe bean de sessão. Isto é feito para tornar instância pooling possível, onde o recipiente pode reutilizar instâncias EJB para atender a diferentes solicitações.

Eu não sei por que você precisa acessar o objeto do bean real (uma vez que, obviamente, eu não sei sua exigência). Mas se você ainda precisa criar uma instância de que você pode fazê-lo da seguinte forma usando a reflexão Class.forName(className).newInstance();Mais uma vez a instância que você cria como este não é um EJB. É apenas um POJO isso é tudo.

EDIT - após o seu comentário em relação ao teste junit: Quando você acessa os métodos de negócio a partir de uma JavaSE como segue, na verdade você está chamando os métodos do EJB - só que você interagir através da interface. Então, se você quiser testar quaisquer métodos de negócio você ainda pode fazê-lo a partir de um objeto tem através de uma consulta JNDI em um teste JUnit.

//MyGreatBean implements MyGreat. MyGreat has @Remote, MyGreatBean has @Stateless
ref = jndiContext.lookup("MyGreatBean/remote");
MyGreat bean = (MyGreat) ref; 
String retValue = bean.businessMethod();
assertEquals("Success", retValue);

A partir de um comentário anterior, eu recebo um sentimento você deseja verificar que tipo de anotações foram adicionados à classe EJB real - se você quiser fazer esse tipo de verificação sem realmente executar os métodos de negócio, você pode criar uma instância usando Class. forName ... como eu mencionei acima. Quando você cria uma instância como essa você só pode chamar métodos que não fazem qualquer coisa "Java EE". Por exemplo, você pode chamar um método na classe EJB que é a seguinte

public String someMethod(){
       return "I am a POJO but I look like an EJB";
}
Respondeu 17/08/2009 em 19:10
fonte usuário

votos
1

Eu não acho que você pode obter o objeto EJB. Você só pode obter a interface. O createEJB deve ser chamado com a interface e retorna a interface.

Respondeu 06/08/2009 em 15:51
fonte usuário

votos
0

você pode tentar isso?

Criar uma interface. Fazê-lo ter @Remote. Seu EJB que é anotado com @Stateless deve implementar a interface acima criado. Agora tente fazer a mesma coisa que você está fazendo eu acho que deveria lhe dar o resultado desejado. Digitando-o aqui sem copiar a partir de uma ide assim justificar eventuais erros. Mas você deve começar a deriva eu ​​acho.

@Remote
public interface Example{
   String some();
}

@stateless
public class ExampleBean implements Example{

}
Respondeu 14/08/2009 em 01:11
fonte usuário

votos
0

tente substituir

public <T> T createEJB(Class ejbClass) throws NamingException

com

public <T> T createEJB(Class<T> ejbClass) throws NamingException
Respondeu 06/08/2009 em 15:23
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more