【问题标题】:EJB Factory ClassEJB 工厂类
【发布时间】:2010-11-17 08:51:39
【问题描述】:

我正在尝试创建一个 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,我没有使用任何其他应用服务器对其进行测试。

【问题讨论】:

  • 拥有实际 bean 本身的对象有什么用? - 您将始终通过界面进行交互,对吗?基本上像 InterfaceType ref = (InterfaceType) jndiLookup;之后,您在 ref 上调用方法。试图了解对此的需求。

标签: java jakarta-ee glassfish ejb-3.0 ejb


【解决方案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 类中 - 如果您想在不实际运行业务方法的情况下进行这种检查,您可以创建一个实例使用 Class.forName... 就像我上面提到的。当您创建这样的实例时,您只能调用不执行任何“Java EE”内容的方法。例如,您可以调用 EJB 类中的一个方法,如下所示

public String someMethod(){
       return "I am a POJO but I look like an EJB";
}

【讨论】:

  • > 我不确定您为什么需要访问实际 bean 的对象(因为 > 显然我不知道您的要求)。例如测试它。将 EJB 对象放入 JavaSE 应用程序后,就可以使用 junit。
【解决方案2】:

你可以试试这个吗?

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

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

@stateless
public class ExampleBean implements Example{

}

【讨论】:

  • 啊……出于某种原因,我想当您寻找遥控器时它不存在。会更多地考虑这个。
【解决方案3】:

我不认为你可以得到 EJB 对象。你只能得到接口。应该使用接口调用 createEJB 并返回接口。

【讨论】:

  • 好的,但是如果注解在实际的bean类中而不是在interace中,那你怎么得到呢?
  • 我在 bean 类上使用了以下注解:@Stateless(name="TestBean", mappedName="ejb/TestBean")
【解决方案4】:

尝试替换

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

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

【讨论】:

  • 我已经尝试过了,但是有一个转换异常:Testcase: testSayHello(SimpleEJBTest): 导致错误 _TestRemote_Wrapper 无法转换为 TestBean java.lang.ClassCastException: _TestRemote_Wrapper 不能转换为 SimpleEJBTest.setUp 的 TestBean (SimpleEJBTest.java:16)
  • 可能是testBean的测试声明错误。它应该是 TestBean 类型而不是 TestRemote 类型吗?
  • 是的,当然我也改变了这一点。然后我得到了一个演员例外。对不起,上面忘了提到。
  • 我认为您将永远获得 Remote 而永远不会获得 Bean。我的意思是您将始终获得界面(我猜在您的情况下是 TestRemote)。所以我想声明没问题,但是对 createEJB 的调用应该是 TestRemote.class
  • 对不起,我应该更好地阅读你的问题,我认为这不可能得到对象本身。您将始终获得界面。
猜你喜欢
  • 2015-09-06
  • 1970-01-01
  • 2011-04-08
  • 1970-01-01
  • 2013-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多