本文解释了如何从远程客户端通过调用ejb的JNDI API首先查找bean代理,然后调用代理。
部署环境为Jboss Eap 6.3,首先部署ejbs到jboss服务器中
客户端实现
创建一个java项目,引入jboss-client.jar,该包在jboss\bin\client位置获取,用于获取jbossEAP中的JNDI上下文。
然后在代码最外层(src下),添加配置属性文件jboss-ejb-client.properties,该文件用于致命如何简历服务端的远程配置
jboss-ejb-client.properties
endpoint.name=client-endpoint
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
remote.connection.default.username=appuser
remote.connection.default.password=apppassword
这里使用无状态bean进行测试,官方文档中有两种可选方式进行调用
方式1使用org.jboss.ejb.client.naming
https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI
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();
}
}
}
方式2使用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();
}
}
}
其中引用client包中的org.jboss.naming.remote.client.InitialContextFactory命名查询功能,同时可以在代码中配置remote的链接地址。需要注意的是,依然需要jboss-ejb-client.properties这个文件,配置方式与方法一中的一样。其中也指定了host和port,虽然是强制有default的配置,但是不影响代码中remote到另外的ip:port中,实际链接的远端地址可以在代码中配置。
JNDI如何写
J2EE6 对 EJB JNDI 规范改动比较大
新规定的几个命名空间
java:global/
java:module/
java:app/
除了标准的名称空间,AS7还提供了以下两个全局命名空间:
java:jboss/
java:/
规定任何以java:开头的相对名称必须是这五个命名空间中的一种
如:
For statelessbeans:
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>
For statefulbeans:
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>?stateful
说明:
<app-name> ear包名称
<module-name> jar包名称
<distinctName>别名
<bean-name> bean中指定的名称
[!<fully-quali?fied-interface-name>]业务接口的全称
?stateful:如果是有状态bean需要添加上?stateful字段
从前的EJBJNDI name可以完全由Bean来指定,但最新的JEE6中EJBJNDI名称由多个部分组成,Bean中配置的只是其中一项。举个实例
以前: FirstejbBean
新的: java:global/ejb_01/FirstejbBean!com.tgb.ejb.FirstEjb
小结:
在上面的例子中,我们看到了如何从一个远程客户端调用一个EJB
首先在服务器端部署ejb程序
其次客户端
添加jboss-ejb-client.properties文件
添加 jboss-client jar在classpath中
编写获取jndi的代码方式