JBoss AS 7.1.1下,从远程客户端使用JNDI调用EJB

来源:互联网 发布:淘宝交易关闭alin41288 编辑:程序博客网 时间:2024/04/30 00:30

刚开始学习EJB,网上很多视频教程都是使用JBoss7之前的版本的应用服务器。在此,记录一下完成这个EJB HelloWorld 程序的过程。


第一步:使用Eclipse或MyEclips创建一个EJB Project,在项目中编写EJBs,这个项目将被我们部署到JBoss AS 7.1.1服务器端。此处工程名为ejb_01

package com.chan.ejb;public interface FirstEjb {public String sayHello(String name);}

定义好了EJB接口,再编写其实现类:

package com.chan.ejb;import javax.ejb.Remote;import javax.ejb.Stateless;@Stateless@Remotepublic class FirstEjbBean implements FirstEjb {@Overridepublic String sayHello(String name) {return "你好," + name;}}

在编写这个企业Bean的时候,类名一般遵循Bean结尾的命名方式,并且要为该Bean配置注解。配置注解的时候要注意@Stateless和@Stateful只能2选1,但可以同时为其配置@Remote和@Local便可同时支持本地客户端和远程客户端的访问方式。编写好这个Bean之后,启动JBoss 7.1.1 ,然后就可以将该项目部署到服务器上了。这样,我们的EJB就写好了。


接下来,我们开始编写远程客户端的代码,新建一个Java Project,名为ejb_01_client。这里我们将用到我们刚才定义的接口FirstEjb,将其以jar包的形式打包导入到现在的客户端工程ejb_01_client中,并将其加到类加载路径下。对了,别忘了将E:\jboss-as-7.1.1.Final\bin\client\jboss-client.jar加到客户端工程类路径下。好了,新建FirstEjbClient.java,代码如下:

package com.chan.ejb;import java.util.Hashtable;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import com.chan.ejb.FirstEjb;/** 通过jndi远程调用ejbjboss7之前的做法java.naming.factory.initial=org.jnp.interfaces.NamingContextFactoryjava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfacesjava.naming.provider.url=localhost */public class FirstEjbClient {public static void main(String[] args) throws Exception {/*
这是JBoss7之前,远程客户端调用EJB的方式InitialContext context = new InitialContext(); // 类似于一个工厂,在类路径下创建jndi.propertiesFirstEjb firstEjb = (FirstEjb) context.lookup("FirstEjbBean/remote");String s = firstEjb.saySomething("张三");System.out.println(s);*/FirstEjb firstEjb = lookupRemoteStatelessEjbBean();System.out.println(firstEjb);String s = firstEjb.saySomething("张三");System.out.println(s);}     /**     * Looks up and returns the proxy to remote stateless calculator bean     *     * @return     * @throws NamingException     */    private static FirstEjb lookupRemoteStatelessEjbBean() throws NamingException {        final Hashtable jndiProperties = new Hashtable();        jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");        final Context context = new InitialContext(jndiProperties);                final String appName = "";                final String moduleName = "ejb_01";                final String distinctName = "";                final String beanName = "FirstEjbBean";                final String viewClassName = FirstEjb.class.getName();                final String namespace = "ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName;                System.out.println(namespace);                return (FirstEjb) context.lookup(namespace);                /*           return (RemoteCounter) context.lookup("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName + "?stateful");          */    } }


在这里解释解释客户端代码:

在JBoss7之前,JNDI是通过jnp那些东西来和服务器端进行连接并放回EJB代理对象的,没接触过,具体工作原理我也不太清楚。在这里说说JBoss7下的客户端代码,首先还是像以前的方式一样,通过在类路径下提供一个jndi.properties文件或直接在代码中向InitialContext中传入所需的JNDI属性和值,这里我们通过后者实现:

final Hashtable jndiProperties = new Hashtable();        jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");        final Context context = new InitialContext(jndiProperties);
有了InitialContext之后,我们便可以调用context.lookup()获得通过JNDI返回的EJB代理对象了,但这里和以前有所区别的是,我们不可以直接通过context.lookup("FirstEjbBean/remote")这种方式之前进行查找了,lookup()方法中的参数将需要[ejb:命名空间]这样一个JNDI 名字的字符串,具体语法如下:

ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>

有状态Bean则应为

ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>?stateful

大概说说名字空间的各部分的意思:

app-name:如果部署到服务器的是一个.ear包,那么app-name就为出去后缀.ear之后的包名。如果部署的是.war包或普通的.jar包,那么app-name留空即可,我自己这个工程是以.jar包部署的,所以app-name为空。

module-name:此处就是部署到服务器上.war包或.jar包的名字,注意,module-name不能为空。

distinct-name:这是一个可选的用于指定在JBoss AS7上具体的部署配置的一个参数名,不需要使用的话,留空即可,此处我们留空。

bean-name:这是我们要使用lookup查找获取的Bean,这个项目中为FirstEjbBean,即FirstEjb的实现Bean,无需全限定类名,bean-name不能为空。

fully-qualified-classname-of-the-remote-interface:这是我们写的EJB中暴露出来的接口FirstEjb的全限定类名,不能为空。

构造好了这个查找EJB使用的JNDI参数名后,调用lookup()方法便可以获得EJB代理对象并调用EJB了。


完成了上面的工作之后,还需要重要的一步,就是配置EJB客户端上下文属性,即在客户端项目类加载路径下,提供一个名为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=sa
remote.connection.default.password=sa


配置客户端上下文属性(set up ejb cilent context properties):(此处大概翻译文档中的解释)

ejb 客户端上下文是一个包含执行远程调用EJB的上下文信息的上下文。该客户端上下文可以和多个EJB receiver关联(原来没有加入该配置文件之前,我的程序一直出现异常:大概是:no ejb receiver handle the [namespace....]),每个EJB receiver可以处理不同的EJB调用,每个这样的EJB receiver知道它可以操作哪些EJB,并且知道哪个目标服务器用户处理对bean的调用。

注意,此处的端口要为4447,而不是8080,4447是JBoss本地地址中的端口。这样我们运行客户端代码,就可以调用EJB了。

文件中各项属性的具体说明,可以参见:https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI

0 0
原创粉丝点击