EJB工厂类

我正在尝试创建一个EJB工厂类,其工作原理如下:您有一个方法,它将EJB的一个类作为参数,然后检查EJB是否具有远程接口(如果不是抛出exception),如果它它会返回相关的EJB。

下面的代码就是这样做的。 但是它返回的对象是相关bean的远程接口的类型,而不是bean本身的类型。 我怎么能改变这个? 有没有办法告诉Javagenerics类型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 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; } 

}

使用Factory的unit testing示例。

 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,我没有使用任何其他应用服务器进行测试。

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

我不确定为什么你需要访问实际的bean的对象(因为显然我不知道你的要求)。 但是如果你仍然需要创建一个实例,你可以使用reflectionClass.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"; } 

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

尝试更换

 public  T createEJB(Class ejbClass) throws NamingException 

 public  T createEJB(Class ejbClass) throws NamingException 

你能试试吗?

创建一个界面。 让它有@Remote。 您使用@Stateless注释的ejb应该实现上面创建的接口。 现在尝试做你正在做的事情,我认为它应该给你想要的结果。 在这里输入它而不从ide复制,所以可以免除任何错误。 但你应该得到我想的漂移。

 @Remote public interface Example{ String some(); } @stateless public class ExampleBean implements Example{ }