• 2004-05-28

    恶斗EJB(五)

    Tag:向上走

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/dreamhead-logs/195334.html

    从SUN工程师的回复中,我得到了另外一个有用的信息,在SUN ONE Application Server的安装目录下的samples\rmi-iiop\simple有一个完整的普通应用调用EJB的例子。
    赶紧操练起来,按照文档一步一步走来,很是轻松愉悦,除了EJB Stub,还要用到应用服务器安装目录的lib目录下appserv-ext.jar。
    走到“Local or remote RMI/IIOP-based client without ACC(Application Client Container)”的一节,同样的问题出现了,程序运行起来就僵死在那里,没有反应。
    怎么又是这样?在我确定了我确实是按照文档一步一步走下来的,我有了一种束手无策的感觉。
    穷极无聊之际,我扫了一眼Troubleshooting:
    如果运行应用出现了任何问题,看一下server的日志。
    嗯?是啊!我光顾着client端了,竟然根本没有想过server端。打开server的日志,一个异常让我眼前一亮:
    com.iplanet.ias.cis.connection.ConnectException: com.iplanet.ias.cis.channel.tcp.TCPNativeException: -5973:EndPoint.JNI_getValidAddressNative: PR_GetHostByAddr() Failed
            at com.iplanet.ias.cis.connection.Connection.<init>(Connection.java:205)
            at com.iplanet.ias.cis.connection.ServerConnection.accept(ServerConnection.java:251)
            at com.sun.corba.ee.internal.iiop.ListenerThread.run(ListenerThread.java:77)
    Caused by: com.iplanet.ias.cis.channel.tcp.TCPNativeException: -5973:EndPoint.JNI_getValidAddressNative: PR_GetHostByAddr() Failed
            at com.iplanet.ias.cis.connection.EndPoint.getValidAddressNative(NativeMethod)
            at com.iplanet.ias.cis.connection.EndPoint.getValidAddress(EndPoint.java:239)
            at com.iplanet.ias.cis.connection.EndPoint.<init>(EndPoint.java:101)
            at com.iplanet.ias.cis.connection.EndPoint.getEndPoint(EndPoint.java:73)
            at com.iplanet.ias.cis.connection.EndPoint.getEndPoint(EndPoint.java:78)
            at com.iplanet.ias.cis.channel.tcp.TCPChannel.getPeerEndPoint(TCPChannel.java:74)
            at com.iplanet.ias.cis.connection.Connection.<init>(Connection.java:201)
            ... 2 more
    虽然单凭这个异常,我无法得知问题所在,但这比漫无目的的搜寻显然好上许多。

    再次向SUN工程师请教。很快,我得到了回复。显然,这个问题对于SUN的工程师来说已经是轻车熟路了。
    RMI通信的时候,需要主机地址解析,只要在两台机器互相把主机名和IP放到hosts配置文件中就可以了。
    在WinXP上,这个文件是C:\WINDOWS\system32\drivers\etc的目录下hosts,在Solaris上,这个文件是/etc/hosts。
    在文件中加入IP和主机名的映射
        xxx.xxx.xxx.xxx hostname

    运行,bingo,成功!
    SUN工程师的答案果然见效。只是我想不通,我用的是IP直连,这和主机名有什么关系。显然,这让人不爽,因为将来部署的时候,这肯定需要写在安装手册里,增加复杂度,牵扯得不仅仅是应用本身的部署了。

    再来试试自己的例子。显然我前面的思路多少有些偏差,没有加入EJB Stub确实是个问题,但并不是根本原因,地址解析才是我的代码僵死的元凶。
    好了,加入EJB Stub和appserv-ext.jar,运行,我终于见到了期盼已久的问候。
    在这个调用中,我并没有使用ORB的那两个参数,这大概也算是J2EE RI和SUN ONE Application Server的差异之一吧!不过后来的事实证明,这并非一个不可逾越的鸿沟。
    原来的异常出现在server端,client端为什么也要加呢?于是,我去掉了client端IP和主机名的映射,使用IP调用没问题,使用主机名调用的时候,抛出了个无法连接ORB的异常。没问题,和我预想的一样。

    再接再厉,尝试在Servlet中调用。
    因为Servlet最终要运行在应用服务器上,所以我省去了appserv-ext.jar,只加入了EJB Stub。写程序,

    配参数,部署……
    又出问题了,它怎么提示我<ejb-link>的参数不对。这是一个用来在Servlet中指示欲使用的EJB名称的参数。难道它让我把EJB应用也加进去,那还是一个单纯的Web应用了吗?
    瞎猫总能碰到死耗子。当我糊涂的把EJB Stub作为一个Module加入到Web应用中,居然部署成功了。
    敲入URL,又是半天没响应,这次可有经验了,赶紧把那台机器的IP和主机名加到部署EJB的服务器上。
    OK,成功!

    终于搞定了在SUN ONE Application Server上远程调用EJB的问题,最初设置的一个参数又引起了我的兴趣。前面的设置有这样一句:
        env.put("java.naming.factory.initial", "com.sun.jndi.cosnaming.CNCtxFactory");
    这个com.sun.jndi.cosnaming.CNCtxFactory并不是J2EE包特有的,而是存在于rt.jar中,换句话说,它是J2SE中的。那它是否可以用在J2EE RI上呢?
    带着这个问题,我翻出之前的那个例子,改动了参数,去掉ORB的那两个参数。
    运行,Hello来了。
    原来可以这么调。早知如此,何必当初呢!

    总结一下,算是个经验和教训的集合吧!
    J2EE RI和SUN ONE Application Server通用的调用远程EJB的参数是:
        java.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
        java.naming.provider.url=iiop://host:port

    如果使用的是SUN ONE Application Server,调用远程EJB需要在部署EJB的机器上hosts配置文件中加入调用端IP和主机名的映射。
    如果调用端在IIOP参数中使用的是主机名,则需要在其hosts配置文件中加入部署EJB的机器的IP和主机名的映射。
    在WinXP上,hosts配置文件是C:\WINDOWS\system32\drivers\etc的目录下hosts;在Solaris上,这个文件是/etc/hosts。
    在文件中加入IP和主机名映射的方式是
        xxx.xxx.xxx.xxx hostname

    又是一场恶斗,虽然精疲力竭,却也心情愉悦!战斗后的胜利感觉,总是最美妙的。

    分享到:

    历史上的今天:

    引用地址:

    评论

  • 你可以试着抓一下包,看看客户端和服务器之间通信的报文,应该有可能分析到为什么要自己解析地址。
    回复mochow说:
    呵呵,是个不错的办法,因为问题解决了,所以也懒得研究了,多谢指教。
    2004-05-30 23:43:40