PortableRemoteObject.narrow方法杂谈

来源:互联网 发布:金高考软件下载 编辑:程序博客网 时间:2024/05/19 19:14

PortableRemoteObject.narrow方法的目的就是CORBA协作,在EJB以前有类似的一个CORBA来进行操作的,虽然本身CORBA比较的强大,但是非常难于使用,在EJB中为了添加对CORBA的支持,所以在使用home接口以前需要用PortableRemoteObject.narrow方法处理一下


我来说说我的看法  
   
  远程lookup一个对象的时候,返回的对象的引用并不明确。我们只知道它是一个Object,而不清楚是否是我们所需要的特定的类的对象(这里就是EjbHome)。所以用narrow方法,把lookup到的对象和EjbHome.class作为参数传进去,检查是否匹配,然后再转换成我们需要的类型。  
   
  而本地lookup一个对象的时候就有所不同,因为本地的对象是已经在本地JVM中存在的,注册过的Class的对象,所以已经知道lookup到的对象是什么类的引用,因此,就不必用narrow方法检查,而可以直接转型。  
   
  这是我的个人想法,不保证正确,欢迎大家继续探讨。 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

本人刚学EJB不久,在学习中碰到一些问题向高手们请教。

1、为什么有时候要用
Properties p = new Properties ();
p.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
p.put (Context.PROVIDER_URL, "t3://localhost:7001");
Context ctx = new InitialContext (p);

来初始化,而有时候只要
Context ctx = new InitialContext ();就可以了

2、还有为什么有时候要用
Object ref = context.lookup("SbLocalHome");
SbLocalHome testHome = (SbLocalHome)
PortableRemoteObject.narrow( ref , SbLocalHome.class );

而有时候只要
SbLocalHome sbh=(SbLocalHome)ctx.lookup("java:/SbLocalHome");
就可以了呢?

还请高手们指点迷津。





RobertDeNiro

第一个问题的答案是,Context ctx = new InitialContext ();是在server的jvm中调用上下文,当然不用地址和端口还有初始化的一些参数,而在远程调用的时候(同一台机器的不同jvm)这一切都不知道就必须指定了,第二个问题和第一个类似,在和server在同一个jvm中的同一个应用中调用ejb可以用java:comp/...,而调用同一个虚拟机中的其它资源就要用java:比如调用数据库连接源,而远程调用(不在同一个虚拟机中)则直接调用其jndi名称,不知这样说你是否明白.
对于第二个问题是否可以这样来理解,在和server在同一个jvm中的同一个应用中调用ejb可以直接用lookup(java:comp/...),而调用同一个虚拟机中的其它资源就直接用
lookup(java:)比如调用数据库连接源,而远程调用(不在同一个虚拟机中)则用lookup()直接调用其jndi名称,再用PortableRemoteObject.narrow()。
这就是jndi的精髓,如果从原理上看,更容易理解,本地的话不走socket(已经做优化了)所以不需要地址端口和server初始化context的信息,ejb也是这样的道理

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

   

//get naming context
Context context = getInitialContext();
//look up jndi name
Object ref = context.lookup("Enterprise1");

//look up jndi name and cast to Home interface
enterprise1Home = (Enterprise1Home) PortableRemoteObject.narrow(ref,Enterprise1Home.class);       <---
一个简单的调用SESSION EJB的小例子,结果每次运行到箭头指向的这句就报下面的错误,跟不进去,实在想不通到底哪里不通。通过JNDI找Enterprise1已经OK,为什么不行呢?请高手指点~~~~~~~

今天碰到了这个问题,调试了好久,搜索发现大家好像都有类似的问题,最终解决了PortableRemoteObject.narrow无法窄化的问题,我的原因如下,希望能给大家一点启发:

我的原因在于无法找到JNDI路径的问题,EJB已经成功部署在weblogic里面,自己编写的客户端Client.java所调用的EJB接口层次必须物理上完全于部署的EJB里面的层次一样,比如说部署的EJB里面的层次如下:
meeting/interfaces/Meeting.class
meeting/interfaces/MeetingHome.class
meeting/interfaces/MeetingPK.class
所以在客户端命令行调试的时候必须完全按照上面的物理层次调试:
Client.class
meeting/interfaces/Meeting.class
meeting/interfaces/MeetingHome.class
meeting/interfaces/MeetingPK.class
这样,JNDI才能找到对象并进行窄化。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

我看的一本书上说:如果服务器和客户断都在一个主机上时可以直接转型,若不在一个机子上时需要用PortableRemoteObject.narrow()来转型。

本地调用是不需要用narrow()转型的,可以直接使用java的类型转换直接转型,本地调用和远程调用最大的区别的就是本地调用中,stub类对客户端内存是可见的,而远程调用stub类只存在于服务器端,也就是对客户端内存是不可见的,而Ed   Roman的《精通EJB》也是这样做解释的,又此可以推断在对象类型转换中是需要类来协助的,而今天我做了一个测试,就是在类型转换的时候把生成的class文件删除,照样可以转换成功,所以感觉又不需要类来协助,所以更加茫然,在narrow()这个方法里到底做了什么操作,和普通的转换到底有什么不同还是搞不明白,比较郁闷!希望继续讨论!

ejb是建立在rmi-iiop之上的,这一点在《精通ejb》上面也讲的很清楚,如果想实现跨平台,就必须用narrow,然后使之能通过iiop来传送,而不是直接发送本地的串行字块

首先得到初始化的Context上下文信息,   lookup方法查找JNDI名,返回的是一个对象引用  
  因为这个对象很原始,是Object类的,因为查找的基础RMI-IIOP协议不支持多接口,  
  (因为RMIIIOP适应的语言中有的不支持继承)  
  所以需要cast这个一般化的Object为更具体的类型,即把他narrow成CodeSHome类型
lookup()方法返回的是一个Object类型的远程主接口对象的残根,为此需要使用javax.rmi.PortableRemoteObject的narrow()方法来获取一个具体的对象引用,narrow()方法:第一个参数是lookup()方法返回的对象,第二个参数是要得到的引用类型。