EJB工厂类 [英] EJB Factory Class

查看:114
本文介绍了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 {
属性props = new Properties();
props.setProperty(org.omg.CORBA.ORBInitialHost,host);
props.setProperty(org.omg.CORBA.ORBInitialPort,port);
ctx = new InitialContext(props);
}

//改进:返回的对象应该是类型ejbClass
//,而不是远程接口,它实现
public< T> T createEJB(class ejbClass)throws NamingException
{
类remoteInterface = null;
for(Class interface_:ejbClass.getInterfaces()){
if(interface_.isAnnotationPresent(Remote.class))
remoteInterface = interface_;
}

if(remoteInterface == null)
throw new IllegalArgumentException(
EJB需要一个远程接口);

//获取无状态注释,然后获取jndiName
无状态无状态=
(无状态)ejbClass.getAnnotation(Stateless.class);
String jndiName = stateless.mappedName();
T ejbObj =(T)ctx.lookup(jndiName);
return ejbObj;
}

}



使用Factory的单元测试示例。

  import junit.framework.TestCase; 


public class SimpleEJBTest扩展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配合使用,

解决方案

EJB的客户端通过EJB实现的本地/远程接口与他们进行交互。客户端应用程序从不直接访问实际的会话bean类实例。这样做可以使实例池化,容器可以重用EJB实例来服务不同的请求。



我不知道为什么你需要访问实际的bean的对象(显然我不知道你的要求)。但是如果您仍然需要创建一个实例,可以使用反射 Class.forName(className).newInstance(); 再次创建一个您创建的实例这不是EJB。



编辑 - 关于junit测试的评论之后:当您从JavaSE访问业务方法时,如下所示,您实际上正在调用EJB中的方法 - 只是通过该界面进行交互。所以如果你想测试任何业务方法,你仍然可以通过Junit测试通过JNDI查找获得的对象。

  // MyGreatBean实现MyGreat。 MyGreat有@Remote,MyGreatBean有@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 我是一个POJO,但我看起来像一个EJB;
}


I'm trying to create an EJB factory class, which works like this: You have a method which takes as argument a class of an EJB, then it checks whether the EJB has a remote interface (if not throw an exception) and if it does, it returns the concerning EJB.

The code below does exactly this. However the object it returns is of the type of the remote interface of the concerning bean and not of the bean itself. How can I change this? Is there a way to tell Java that the generic type T is of the same type as the class passed to the methods.

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

}

Example of a unit test which uses the Factory.

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

Note: The example works with Glassfish, I didn't test it with any other app server.

解决方案

Clients of EJBs interact with them through the local/ remote interface that the EJBs implement. Client applications never have direct access to an actual session bean class instance. This is done to make instance pooling possible, where the container can reuse EJB instances to service different requests.

I'm not sure why you need to access the actual bean's object (since obviously I dont know your requirement). But if you still need to create an instance of that you can do it as follows using reflection Class.forName(className).newInstance(); Again the instance that you create like this is not an EJB. It is just a POJO thats all.

EDIT - after your comment regarding junit testing: When you access business methods from a JavaSE as follows, you are actually calling the methods in the EJB - just that you interact thru the interface. So if you want to test any business methods you can still do it from an object got thru a JNDI lookup in a Junit test.

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

From an earlier comment, I get a feeling you want to check what kind of annotations have been added to the actual EJB class - if you want to do that kind of checking without actually running the business methods, you can create an instance using Class.forName... like I mentioned above. When you create an instance like this you can only call methods that don't do any "Java EE" stuff. For example you can call a method in the EJB class that is as follows

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

这篇关于EJB工厂类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆