有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java EJB工厂类

我试图创建一个EJB工厂类,其工作原理如下:您有一个方法,该方法将EJB的一个类作为参数,然后它检查EJB是否有远程接口(如果没有抛出异常),如果有,则返回相关的EJB

下面的代码正是这样做的。然而,它返回的对象是相关bean的远程接口类型,而不是bean本身的类型。我怎样才能改变这个?有没有办法告诉Java泛型类型T与传递给方法的类的类型相同

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;
    }

}

使用工厂的单元测试示例

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());
    }
}

注意:该示例适用于Glassfish,我没有使用任何其他应用服务器进行测试


共 (4) 个答案

  1. # 1 楼答案

    EJB的客户端通过EJB实现的本地/远程接口与它们交互。客户端应用程序从来没有直接访问实际会话bean类实例的权限。这样做是为了使实例池成为可能,容器可以重用EJB实例来服务不同的请求

    我不确定您为什么需要访问实际bean的对象(因为我显然不知道您的需求)。但是,如果您仍然需要创建它的实例,那么您可以使用反射Class.forName(className).newInstance();按如下方式进行创建。同样,您这样创建的实例不是EJB。这只是一个POJO,仅此而已

    编辑-在您对junit测试的评论之后:当您从JavaSE访问如下业务方法时,实际上是在EJB中调用这些方法-只是通过接口进行交互。因此,如果您想测试任何业务方法,您仍然可以从Junit测试中通过JNDI查找获得的对象中进行测试

    //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);
    

    从前面的评论中,我感觉您想要检查实际的EJB类中添加了什么样的注释——如果您想要在不实际运行业务方法的情况下进行这种检查,可以使用类创建实例。forName。。。就像我上面提到的。当您创建这样一个实例时,您只能调用不做任何“JavaEE”工作的方法。例如,您可以调用EJB类中的一个方法,如下所示

    public String someMethod(){
           return "I am a POJO but I look like an EJB";
    }
    
  2. # 2 楼答案

    试着替换

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

    public <T> T createEJB(Class<T> ejbClass) throws NamingException
    
  3. # 3 楼答案

    你能试试这个吗

    创建一个接口。让它有@Remote。用@Stateless注释的ejb应该实现上面创建的接口。现在试着做你正在做的事情,我认为这会给你想要的结果。在这里输入它而不从ide复制,所以请原谅任何错误。但我想你应该明白我的意思

    @Remote
    public interface Example{
       String some();
    }
    
    @stateless
    public class ExampleBean implements Example{
    
    }
    
  4. # 4 楼答案

    我认为您无法获得EJB对象。您只能获取接口。createEJB应该与接口一起调用,并返回接口