📄 ch04.html
字号:
<PRE CLASS="CODE"><A NAME="pgfId-1087503"></A> <A NAME="marker-1087502"></A>orb.connect(rs);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087504"></A> org.omg.CORBA.Object nameServiceObj = orb.resolve_initial_references("NameService");</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087505"></A> NamingContext nctx = NamingContextHelper.narrow(nameServiceObj);</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087507"></A>//API Ref: <A NAME="26082"></A>NameComponent(String nameid, String kind)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087512"></A> <A NAME="marker-1087508"></A> <A NAME="org.omg.CosNaming.NameComponent class"></A><A NAME="NameComponent class"></A><A NAME="NameComponent constructor"></A>NameComponent[] fullname = new NameComponent[2]; </PRE><PRE CLASS="CODE"><A NAME="pgfId-1087513"></A> fullname[0] = new NameComponent("auction", "");</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087514"></A> fullname[1] = new NameComponent("RegistrationBean", "");</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087515"></A> NameComponent[] tempComponent = new NameComponent[1];</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087516"></A> for (int i=0; i < fullname.length-1; i++ ) { tempComponent[0]= fullname[i]; </PRE><PRE CLASS="CODE"><A NAME="pgfId-1087517"></A> try {</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087519"></A>//API Ref: <A NAME="45977"></A>NamingContext bind_new_context(NameComponent[] nc)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087524"></A> <A NAME="marker-1087520"></A><A NAME="org.omg.CosNaming.NamingContext interface"></A><A NAME="NamingContext interface"></A><A NAME="bind_new_context method"></A>nctx=nctx.bind_new_context(tempComponent);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087525"></A> } catch (org.omg.CosNaming.NamingContextPackage.AlreadyBound e){</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087526"></A> //If this part of the tree is already bound then ignore this exception</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087527"></A> }</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087528"></A> }</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087529"></A> tempComponent[0]=fullname[fullname.length-1];</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087530"></A> //Finally bind the object to the full context path</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087532"></A>//API Ref: <A NAME="58515"></A>static void rebind(String rminame, Remote obj)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087537"></A> <A NAME="marker-1087533"></A><A NAME="java.rmi.Naming class"></A><A NAME="Naming class"></A><A NAME="bind method"></A>nctx.rebind(tempComponent, rs);</PRE><P CLASS="Body"><A NAME="pgfId-1087538"></A>Once the <EM CLASS="CODE">RegistrationServer</EM> object is bound, it can be looked up with a JNDI lookup using a <EM CLASS="CODE">CosNaming</EM> service provider as described in Java Naming and Directory Interface (page 59) or using the CORBA name lookup service. Either way, the CORBA name server must be started before any lookups can take place. In the Java 2 platform, the <A NAME="marker-1087539"></A>CORBA <EM CLASS="CODE">name server</EM> is started as follows to start the CORBA <EM CLASS="CODE">RegistrationServer</EM> on the default TCP port 900: </P><PRE CLASS="CODE"><A NAME="pgfId-1087540"></A>tnameserv</PRE><P CLASS="Body"><A NAME="pgfId-1087541"></A>If you need to use a different port, you can start the server like this:</P><PRE CLASS="CODE"><A NAME="pgfId-1087542"></A>tnameserv -ORBInitialPort 1050</PRE><P CLASS="Body"><A NAME="pgfId-1087544"></A><EM CLASS="Bold">CORBA SellerBean. </EM><A NAME="marker-1087543"></A>On the client side, the CORBA lookup uses the <EM CLASS="CODE">NameComponent</EM> object to construct the name. Start the object server like this: </P><PRE CLASS="CODE"><A NAME="pgfId-1087545"></A>java registration.RegistrationServer</PRE><P CLASS="Body"><A NAME="pgfId-1087546"></A>The difference in the client is that the name is passed to the <EM CLASS="CODE">resolve</EM> method, which returns the CORBA object. The following code from the <EM CLASS="CODE">SellerBean</EM> object illustrates this point. </P><PRE CLASS="CODE"><A NAME="pgfId-1087547"></A>public static void main(String args[]) { java.util.Properties props=System.getProperties();</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087548"></A> props.put("org.omg.CORBA.ORBInitialPort", "1050");</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087549"></A> System.setProperties(props);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087550"></A> ORB orb = ORB.init(args, props);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087551"></A> </PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087552"></A>//API Ref: Object resolve_initial_references(String servicename)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087553"></A> <A NAME="marker-1087554"></A><A NAME="resolve_initial_references method"></A>org.omg.CORBA.Object nameServiceObj = orb.resolve_initial_references(</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087556"></A> "NameService") ;</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087557"></A> nctx= NamingContextHelper.narrow(nameServiceObj);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087558"></A> NameComponent[] fullname = new NameComponent[2];</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087559"></A> fullname[0] = new NameComponent("auction", "");</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087560"></A> fullname[1] = new NameComponent("RegistrationBean", "");</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087561"></A>//API Ref: Object resolve(NameComponent[] nc)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087564"></A> <A NAME="marker-1087562"></A><A NAME="resolve method"></A>org.omg.CORBA.Object cobject= nctx.resolve(fullname);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087565"></A>}</PRE><P CLASS="Body"><A NAME="pgfId-1087566"></A>The <EM CLASS="CODE">narrow</EM> method from the <EM CLASS="CODE">Helper</EM> class is generated by the IDL compiler, which provides a detailed mapping to translate each CORBA field into its respective Java programming language field. For example, the<A NAME="marker-1087567"></A> <EM CLASS="CODE">SellerBean.insertItem</EM> method looks up a registration CORBA object using the name <EM CLASS="CODE">RegistrationBean</EM>, and returns a <EM CLASS="CODE">RegistrationHome</EM> object. With the <EM CLASS="CODE">RegistrationHome</EM> object, you can return a <EM CLASS="CODE">Registration</EM> record by calling its <EM CLASS="CODE">findByPrimaryKey</EM> method.</P><PRE CLASS="CODE"><A NAME="pgfId-1087568"></A>public int insertItem(String seller, String password, String description, </PRE><PRE CLASS="CODE"><A NAME="pgfId-1087569"></A> int auctiondays, double startprice, String summary) </PRE><PRE CLASS="CODE"><A NAME="pgfId-1087570"></A> throws RemoteException {</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087571"></A>try{</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087572"></A> NameComponent[] fullname = new NameComponent[2];</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087573"></A> fullname[0] = new NameComponent("auction", "");</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087574"></A> fullname[1] = new NameComponent("RegistrationBean", "");</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087575"></A> org.omg.CORBA.Object cobject= nctx.resolve(fullname);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087576"></A> RegistrationHome regHome = RegistrationHomeHelper.narrow(cobject);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087577"></A> RegistrationHome regRef = </PRE><PRE CLASS="CODE"><A NAME="pgfId-1087578"></A> RegistrationHomeHelper.narrow(nctx.resolve(fullname));</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087579"></A> RegistrationPKImpl rpk = new RegistrationPKImpl();</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087580"></A> rpk.theuser(seller); </PRE><PRE CLASS="CODE"><A NAME="pgfId-1087581"></A> Registration newseller = </PRE><PRE CLASS="CODE"><A NAME="pgfId-1087582"></A> RegistrationHelper.narrow(regRef.findByPrimaryKey(rpk));</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087583"></A> if ((newseller == null) || (!newseller.verifyPassword(password))) {</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087584"></A> return(Auction.INVALID_USER);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087585"></A> }</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087586"></A> } catch(Exception e) {</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087587"></A> System.out.println("insert problem="+e);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087588"></A> return Auction.INVALID_ITEM;</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087589"></A> }</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087590"></A>}</PRE></DIV></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087591"></A>Interoperable Object References</H5><P CLASS="Body"><A NAME="pgfId-1087592"></A>Using a CORBA name service works for most CORBA applications especially when the object request brokers (ORBs) are supplied by one vendor. However, you might find the name service is not completely compatible among all ORBs, and you could get a frustrating <EM CLASS="CODE">COMM_FAILURE</EM><A NAME="marker-1087593"></A> message when the CORBA client tries to connect to the CORBA server. </P><P CLASS="Body"><A NAME="pgfId-1087595"></A>The solution is to use an <A NAME="marker-1087594"></A>Interoperable Object Reference (IOR) instead. An IOR is available in ORBs that support the <A NAME="marker-1087596"></A>Internet Inter-ORB protocol (IIOP). It contains the information a naming service keeps for each object such as the host and port where the object resides, a unique lookup key for the object on that host, and what version of IIOP is supported. </P><P CLASS="Body"><A NAME="pgfId-1087600"></A><EM CLASS="Bold">IOR Server. </EM><A NAME="marker-1087597"></A><A NAME="marker-1087598"></A>To create an IOR all you do is call the <EM CLASS="CODE">object_to_string</EM><A NAME="marker-1087599"></A> method from the ORB class and pass it an instance of the object. For example, to convert the <EM CLASS="CODE">RegistrationServer</EM><A NAME="marker-1087601"></A> object to an IOR, you need to add the line <EM CLASS="CODE">String ref = orb.object_to_string(rs);</EM> to the <EM CLASS="CODE">main</EM> program: </P><PRE CLASS="CODE"><A NAME="pgfId-1087602"></A>String[] orbargs= {"-ORBInitialPort 1050"};</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087603"></A>ORB orb = ORB.init(orbargs, null);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087604"></A>RegistrationServer rs = new RegistrationServer();</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087605"></A>//Add this line</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087607"></A>//API Ref: <A NAME="50593"></A>String object_to_String(Object object)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087610"></A><A NAME="marker-1087608"></A><A NAME="object_to_string method"></A>String ref = orb.object_to_string(rs);</PRE><P CLASS="Body"><A NAME="pgfId-1087611"></A>So, instead of retrieving this object information from a naming service, there is another way for the server to send information to the client. You can register the returned <EM CLASS="CODE">String</EM> with a substitute name server, which can be a simple HTTP Web server because the object is already in a transmittable format. </P><P CLASS="Body"><A NAME="pgfId-1087612"></A><EM CLASS="Bold">IOR Client. </EM>This example uses an HTTP connection to convert the IOR string back to an object. You call the <EM CLASS="CODE">string_to_object</EM><A NAME="marker-1087613"></A> method from the ORB class. This method requests the IOR from the <EM CLASS="CODE">RegistrationServer</EM> and returns the IOR string. The <EM CLASS="CODE">String</EM> is passed to the ORB using the <EM CLASS="CODE">ORB.string_to_object</EM> method, and the ORB returns the remote object reference: </P><PRE CLASS="CODE"><A NAME="pgfId-1087614"></A>URL iorserver = new URL("http://server.com/servlet?object=registration");</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087615"></A>URLConnection con = ioserver.openConnection();</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087616"></A>BufferedReader br = new BufferReader(new InputStreamReader( con.getInputStream));</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087617"></A>String ref = br.readLine();</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087619"></A>//API Ref: <A NAME="38030"></A>Object string_to_object(String stringvalue)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087622"></A><A NAME="marker-1087620"></A><A NAME="string_to_object method"></A>org.omg.CORBA.Object cobj = orb.string_to_object(ref);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087623"></A>RegistrationHome regHome = RegistrationHomeHelper.narrow(cobj);</PRE><P CLASS="Body"><A NAME="pgfId-1087624"></A>The substitute name server can keep persistent IOR records that can survive a restart if needed.</P></DIV></DIV><DIV><H4 CLASS="A"><A NAME="pgfId-1087626"></A><A NAME="86521"></A>RMI Lookup Service</H4><P CLASS="Body"><A NAME="pgfId-1087629"></A><A NAME="marker-1087627"></A>The RMI API originally used its own communication protocol called <A NAME="marker-1087628"></A>Java Remote Method Protocol (JRMP), which resulted in having its own lookup service. Newer releases of RMI can now use the more ubiquitous IIOP protocol, in addition to JRMP. </P><P CLASS="Body"><A NAME="pgfId-1087630"></A>The JRMP RMI naming service is similar to other lookup and naming services. The actual lookup is achieved by calling <A NAME="marker-1087631"></A><EM CLASS="CODE">Naming.lookup</EM><A NAME="marker-1087632"></A> and passing a URL parameter to that method. The URL specifies the machine name, an optional port where the RMI naming server that knows about the object is running (<EM CLASS="CODE">rmiregistry</EM>) and the remote object you want to reference and call methods on. For example: </P><PRE CLASS="CODE-caption"><A NAME="pgfId-1087634"></A>//API Ref: <A NAME="48818"></A>static Remote lookup(String rminame)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087637"></A><A NAME="marker-1087635"></A><A NAME="lookup method"></A>SellerHome shome = (SellerHome)Naming.lookuup("rmi://appserver:1090/seller");</PRE><P CLASS="Body"><A NAME="pgfId-1087639"></A>The above code returns the remote <EM CLASS="CODE">SellerHome reference _stub</EM><A NAME="marker-1087638"></A> from the object bound to the name seller on the machine called appserver. The <EM CLASS="CODE">rmi</EM> part of the URL is optional and you may have seen RMI URLs without it, but if you are using JNDI or <A NAME="marker-1087640"></A>RMI-IIOP, including <EM CLASS="CODE">rmi</EM> in the URL will save confusion later. Once you have a reference to <EM CLASS="CODE">SellerHome</EM>, you can call its methods. </P><P CLASS="Body"><A NAME="pgfId-1087641"></A>In contrast to the JNDI lookup performed by <EM CLASS="CODE">AuctionServlet</EM> (page 59), which requires a two-stage lookup to create a context and then the actual lookup, RMI initializes the connection to the RMI name server, <EM CLASS="CODE">rmiregistry</EM><A NAME="marker-1087642"></A>, and also gets the remote reference with one call. This remote reference is leased to the client from the <EM CLASS="CODE">rmiregistry</EM>. The lease means that unless the client informs the server it still needs a reference to the object, the lease expires and the memory is reclaimed. This leasing operation is automatic and transparent to the user, but can be tuned by setting the server property <EM CLASS="CODE">java.rmi.dgc.leaseValue</EM><A NAME="marker-1087643"></A> value in milliseconds when starting the server as follows: </P><PRE CLASS="CODE"><A NAME="pgfId-1087644"></A>java -Djava.rmi.dgc.leaseValue=120000 myAppServer</PRE><P CLASS="Body"><A NAME="pgfId-1087645"></A>You can find more information on leasing in Distributed Garbage Collection (page 75).</P><DIV><H5 CLASS="B"><A NAME="pgfId-1087646"></A>RMI over Internet Inter-ORB Protocol</H5><P CLASS="Body"><A NAME="pgfId-1087648"></A><A NAME="marker-1087647"></A>RMI over Internet Inter-ORB Protocol lets existing RMI code reference and look up an object using the CORBA <EM CLASS="CODE">CosNaming</EM> service. This gives you greater interoperability between architectures with little change to your existing RMI code. </P><UL><LI CLASS="NOTE"><A NAME="pgfId-1087651"></A>NOTE The <EM CLASS="CODE">rmic</EM><A NAME="marker-1087649"></A> compiler provides the<A NAME="marker-1087650"></A> <EM CLASS="CODE">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -