本文介绍了JBOSS EAP 6.1 EJB 客户端的两种实现方式。由于客户端是通过JNDI的方式来唤起EJB,所以接下来深入的讨论了JBOSS EAP 6.1遵循的JEE6中EJB JNDI,对JNDI的变化以及这些变化所带来的利弊进行介绍。
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false remote.connections=default remote.connection.default.host=localhost remote.connection.default.port=4447 remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
public class HelloWorldClient { public static void main(String[] args) { Hashtable<String, String> jndiProperties = new Hashtable<String, String>(); jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); try{ Context context = new InitialContext(jndiProperties); String ejbPattern = "ejb:"; String appName = ""; String moduleName = "HelloWorld"; String distinctName = ""; String beanName = "HelloWorldBean"; String interfaceName = "com.xx.leo.HelloWorldBusiness"; String jndiName = ejbPattern + appName+"/"+ moduleName+"/" + distinctName+"/"+beanName+"!"+interfaceName; System.out.println(jndiName); //输出为:ejb:/HelloWorld//HelloWorldBean!com.hp.leo.HelloWorldBusiness HelloWorldBusiness hello = (HelloWorldBusiness)context.lookup(jndiName); System.out.println(hello.sayHello()); //输出为:Hello World. }catch(NamingException e){ e.printStackTrace(); } } }
public NamingEnumeration list(Name name) throws NamingException { throw Logs.MAIN.unsupportedNamingOperation(); } public NamingEnumeration list(String name) throws NamingException { throw Logs.MAIN.unsupportedNamingOperation(); }
方法二:org.jboss.naming.remote.client.InitialContextFactory
public class HelloWorldClient2 { public static void main(String[] args) { Properties jndiProps = new Properties(); jndiProps.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory"); jndiProps.put(Context.PROVIDER_URL,"remote://localhost:4447"); // create a context passing these properties Context ctx; try { ctx = new InitialContext(jndiProps); HelloWorldBusiness o1 = (HelloWorldBusiness) ctx.lookup( "HelloWorld/HelloWorldBean!com.xx.leo.HelloWorldBusiness"); System.out.println(o1.sayHello()); //输出为:Hello World. } catch (NamingException e) { e.printStackTrace(); } } }
同样最为关键的部分是还是ctx.lookup(“…”)中的部分,这写JNDI是怎么生成的?有什么规律将在下节中做介绍。
java:global[/<app-name>]/<module-name>/<bean-name>[!<fully-quali?fied-interface-name>]?stateful java:app/<module-name>/<bean-name>[!<fully-qualified-interface-name>]?stateful java:module/<bean-name>[!<fully-qualified-interface-name>]?stateful其中各部分解释如下:
ejb:/HelloWorld//HelloWorldBean!com.hp.leo.HelloWorldBusiness
这个名称来自JBOSS EAP 6.1规范。JBOSS 写了一套自己的客户端,使用ejb:开头。要调用的话需要实现以下类似于JEE6 中EJB JNDI的规范如下:
ejb:<appName>/<moduleName>/<distinctName>/<beanName>!<viewClassName>?stateful
String ejbPattern = "ejb:"; String appName = ""; String moduleName = "HelloWorld"; String distinctName = ""; String beanName = "HelloWorldBean"; String interfaceName = "com.xx.leo.HelloWorldBusiness"; String jndiName = ejbPattern + appName+"/"+ moduleName+"/" + distinctName+"/"+beanName+"!"+interfaceName;
【实例:产品中有很多个EJB,有些是同一类别的,但由不同的项目组来开发,在最终界面展示的时候需要列出所有现有的这一类EJB组件。】
这就用到了上文提及的list方法,它可以用来模糊查询容器中现有的EJB。但list有个限制就是JNDI名称按”/” 化分为多个级别,由左像右逐级查询。看看list在新旧JNDI中的表现:
旧JNDI名称自始至终都由代码直接限定,所以第一级可以统一规定一个名称。如:规定第一段为GroupA,不同的小组开发了不同的EJB Bean JNDI名称可规定为
使用list(“JarPack”)可以得到四个EJB,但问题是新的JNDI第一段(包含JarPack的一段)是包名,限制被放到了包的命名中,不能由代码来完全规定,而限定包名在很多情况下是一件很滑稽的事情。特别当这些包由客户来创建的时候,客户按照规范写他们自己的客户端,在代码中有一些限制是可以理解的。但是如果客户自己打个包都需要按照产品的限制来弄,无疑会让客户对产品的用户体验方面打上一个大问号。