📄 ch11.htm
字号:
<LI>Invoke the <TT>create_request()</TT> method on the CORBA object. This method takes several parameters that populate the <TT>Request</TT> object before it is returned. The arguments used in the call to <TT>create_request()</TT> can be reused, possibly enhancing performance.</UL><H3><A NAME="Heading6"></A><FONT COLOR="#000077">Anys and TypeCodes: A Review</FONT></H3><P>You recall from Day 3 the discussion about the <TT>Any</TT> and <TT>TypeCode</TT>types. An object of type <TT>Any</TT> can contain any type of object; a <TT>TypeCode</TT>is an object that describes an object's type. An <TT>Any</TT> consists of a <TT>TypeCode</TT>(describing the type of the <TT>Any</TT>) and the value itself. Most likely, whenusing the DII, you'll obtain <TT>TypeCode</TT>s through the ORB methods <TT>create_struct_tc()</TT>and <TT>create_exception_tc()</TT>.</P><P>Another object you'll encounter when using DII is the <TT>NVList</TT> (<I>NV</I>stands for <I>Named</I> <I>Value</I>). An <TT>NVList</TT> is a list of correspondingnames, values, and flags that specify whether its value is an <TT>in</TT> or <TT>out</TT>parameter. The values stored in the <TT>NVList</TT> are <TT>Any</TT>s. When usingthe <TT>request()</TT> method of an object to generate a <TT>Request</TT>, you simplyadd the arguments one at a time using <TT>add_value()</TT>; however, when using the<TT>create_request()</TT> method, you use an <TT>NVList</TT> to specify the inputarguments to the method being called. In either case, the return value from the methodinvocation is always supplied in an <TT>NVList</TT>.<H3><A NAME="Heading7"></A><FONT COLOR="#000077">Request and Reply Options</FONT></H3><P>A variety of options exist for sending a <TT>Request</TT> to a CORBA object. Afterthe <TT>Request</TT> psuedo-object is created and the arguments for the method arespecified, you invoke the method in one of the following ways:<UL> <LI>Call the <TT>invoke()</TT> method on the <TT>Request</TT>. This method behaves in a way you're most likely accustomed to (with non-<TT>oneway</TT> calls), blocking until the reply is received.<BR> <BR> <LI>Call the <TT>send_deferred()</TT> method on the <TT>Request</TT>. This method invokes the request but returns immediately; you can then retrieve the reply using one of the following methods:<BR> <BR> <UL> <LI>Call the <TT>send_oneway()</TT>method on the <TT>Request</TT>. You should do this only if the method being invoked is declared as a <TT>oneway</TT> method in the IDL definition.<BR> <BR> <LI>You can also use <TT>send_multiple_requests_deferred()</TT> and <TT>send_multiple_requests_oneway()</TT> on the ORB to invoke a number of methods on different objects in parallel. </UL></UL><P>Depending on how a method is invoked, there are several possible ways to obtainthe results of the method invocation:<UL> <LI>First, call the <TT>env()</TT> method on the <TT>Request</TT> to determine whether an exception was raised. If there was no exception, call the <TT>result()</TT> method on the <TT>Request</TT> object to obtain the <TT>NVList</TT> that contains the results of the method invocation. Use this method if you invoked the method using the <TT>invoke()</TT> method on the <TT>Request</TT>.<BR> <BR> <LI>Call the <TT>poll_response()</TT>method on the <TT>Request</TT> to periodically check for a response from the method invocation. After <TT>poll_response()</TT> indicates that the result has been received or the client wants to block while waiting for the result, call the <TT>get_response()</TT> method on the <TT>Request</TT> object. Use this method if you invoked the method using the <TT>send_deferred()</TT> method.<BR> <BR> <LI>Of course, if you used the <TT>send_oneway()</TT> method, there is no return result, and thus you don't call any method to get it.</UL><P>Now that you're familiar with the process of invoking a method via DII, it's timefor an example.<H3><A NAME="Heading8"></A><FONT COLOR="#000077">DII Example</FONT></H3><P>Using DII in a simple example is more straightforward than it might sound. Youcan obtain an object reference in much the same way as you have in the past, usingthe ORB's <TT>bind()</TT> mechanism (keeping in mind that <TT>bind()</TT>, whilebeing nonstandard, is useful for developing simple examples). However, the objectreference you obtain will be a generic object reference, pointing to a generic <TT>CORBA::Object</TT>,rather than an instance of a specific object type. The following are some highlightsfrom a CORBA client that uses DII:</P><PRE><FONT COLOR="#0066FF"><TT>CORBA::ORB_ptr orb;</TT><TT>CORBA::Object_ptr helloWorld;</TT></FONT></PRE><P>Of course, first of all, you need a pointer to an ORB object. You also want apointer to the object to which you'll be connecting. In this case, the object isa fictitious "Hello World" object, featuring a single method <TT>helloWorld()</TT>that takes a <TT>CORBA::String</TT> as a parameter and returns a <TT>CORBA::Long</TT>.The method does not raise any exceptions (but remember that a CORBA System Exceptioncan be raised by any remote method). Note that the pointer to the <TT>HelloWorld</TT>object is a generic <TT>CORBA::Object</TT> pointer.</P><PRE><FONT COLOR="#0066FF"><TT>CORBA::NamedValue_ptr resultVal;</TT><TT>CORBA::Any_ptr resultValAny;</TT><TT>CORBA::Long returnValue = 0;</TT><TT>CORBA::Request_ptr request;</TT><TT>CORBA::Any string;</TT></FONT></PRE><P>Next, you need a few other pointers. One holds the <TT>NamedValue</TT> returnedby the DII method invocation. Another pointer holds the <TT>Any</TT> value containedin the <TT>NamedValue</TT>. A <TT>CORBA::Long</TT> variable is created to hold theactual return value. Also, a pointer is created to hold the <TT>Request</TT> objectreturned by the <TT>invoke()</TT> call. Finally, a pointer is created to hold theinput parameter (which is the string <TT>"Hello World"</TT>).</P><PRE><FONT COLOR="#0066FF"><TT>orb = CORBA::ORB_init(argc, argv);</TT></FONT></PRE><P>You should be familiar with this call by now; it simply initializes the ORB. Thismuch is the same in a DII application as in a static invocation application.</P><PRE><FONT COLOR="#0066FF"><TT>try {</TT><TT> helloWorld = orb->bind("IDL:HelloWorld:1.0");</TT><TT>} catch (const CORBA::Exception& ex) {</TT><TT> cout << "Could not bind to HelloWorld" << endl;</TT><TT> cout << ex << endl;</TT><TT> return 1;</TT><TT>}</TT></FONT></PRE><P>Now the client application attempts to bind to the desired <TT>HelloWorld</TT>object. Note that, because the application does not have a client stub for the <TT>HelloWorld</TT>object, rather than use the <TT>HelloWorld::_bind()</TT> method, it uses the <TT>ORB::bind()</TT>method with a slightly revised syntax to obtain a reference to a <TT>HelloWorld</TT>object.</P><PRE><FONT COLOR="#0066FF"><TT>try {</TT><TT> request = helloWorld->_request("helloWorld");</TT><TT> string <<= "Hello World";</TT><TT> CORBA::NVList_ptr arguments = request->arguments();</TT><TT> arguments->add_value("string", string, CORBA::ARG_IN );</TT></FONT></PRE><P>The client application asks the <TT>HelloWorld</TT> object to create a <TT>Request</TT>object by calling the <TT>request()</TT> method. The name of the method that theclient wants to invoke on the <TT>HelloWorld</TT> object is the <TT>helloWorld()</TT>method, which is used as the parameter to the <TT>request()</TT> method. Then theclient gets a parameter list (an <TT>NVList</TT>) from the <TT>Request</TT> objectthrough its <TT>arguments()</TT> method and proceeds to populate the <TT>NVList</TT>with the single argument to the <TT>helloWorld()</TT> method: a <TT>CORBA::String</TT>with the value <TT>"Hello World"</TT>. This argument is added as an inputparameter using the <TT>add_value()</TT> method on the <TT>NVList</TT>.</P><PRE><FONT COLOR="#0066FF"><TT> resultVal = request->result();</TT><TT> resultValAny = result->value();</TT><TT> resultAny->replace(CORBA::_tc_long, &resultVal);</TT><TT>} catch (const CORBA::Exception& ex) {</TT><TT> cout << "Could not create request" << endl;</TT><TT> cout << ex << endl;</TT><TT> return 1;</TT><TT>}</TT></FONT></PRE><P>Before submitting the <TT>Request</TT>, the client must do one more thing: Specifythe expected return type for the method. As the method is expected to return a <TT>CORBA::Long</TT>,the <TT>TypeCode</TT> for this type is pushed into the result. To do this, the clientcalls <TT>result()</TT> on the <TT>Request</TT> object, gets the <TT>value()</TT>(which is an <TT>Any</TT>) from the result, and sets the type and value of the <TT>Any</TT>returned to be <TT>CORBA::Long</TT>. The client is now ready to invoke the methodthrough DII.</P><PRE><FONT COLOR="#0066FF"><TT>try {</TT><TT> request->invoke();</TT><TT> CORBA::Environment_ptr env = request->env();</TT><TT> if (env->exception()) {</TT><TT> cout << "An exception occurred: " << *env->exception() <<</TT><TT> endl;</TT><TT> returnValue = 0;</TT><TT> } else {</TT><TT> returnValue = *(CORBA::Long*)resultValAny->value();</TT><TT> }</TT><TT>} catch (const CORBA::Exception& ex) {</TT><TT> cout << "Could not invoke request" << endl;</TT><TT> cout << ex << endl;</TT><TT> return 1;</TT><TT>}</TT><TT>cout << "The return value was " << returnValue << endl;</TT></FONT></PRE><P>Finally, the client invokes the <TT>helloWorld()</TT> method on the <TT>HelloWorld</TT>object through the <TT>invoke()</TT> method on the <TT>Request</TT>. The client thenchecks for any exceptions that were raised by calling <TT>env()</TT> on the <TT>Request</TT>object and checking the returned environment by calling <TT>exception()</TT>. Ifthis call returns a non-<TT>NULL</TT> result, then an exception was raised by themethod call, and the exception is reported. If there is no exception, the clientcan call <TT>value()</TT> on the <TT>Any</TT> that was previously returned by the<TT>result()</TT> method, casting the value of the <TT>Any</TT> (obtained by calling<TT>value()</TT>) to a <TT>CORBA::Long</TT>, which is what the type of the <TT>Any</TT>should be.</P><P>Compared to the equivalent static invocation, you can see that the Dynamic InvocationInterface is much more involved. It is for this reason that most CORBA developersavoid the DII; the added flexibility often does not justify the added programmingcomplexity. When the functionality offered by the DII is required, DII is necessary;otherwise, it is probably best left alone.</P><P>It is probably worth reiterating once more that most developers will never needto touch DII. Aside from the sort of examples provided earlier in this chapter, DIIis not useful for most applications, and would generally only add unnecessary complexityto most applications. If you're developing tools--such as development and systemmanagement tools--that need to work with unknown CORBA objects in a generic way,you might find DII useful; otherwise, you'll find that it provides little, if any,benefit.<H2><A NAME="Heading9"></A><FONT COLOR="#000077">Summary</FONT></H2><P>Today you learned a new way to invoke methods on remote CORBA objects--throughthe Dynamic Invocation Interface (DII). You also learned about the advantages anddisadvantages of the DII mechanism compared to the traditional method of static invocation,as well as some potential practical applications of the DII mechanism. You then learnedhow to employ the DII features in an application, witnessing firsthand its extremecomplexity compared to the static invocation to which you're accustomed.</P><P>On Day 12, "Exploring CORBAservices and CORBAfacilities," you'll explorethe next in the series of advanced CORBA topics--the use of CORBAservices and CORBAfacilities.Because a great number of features are offered by these services, there is spacein this book for only a short description of each. However, you will also returnto the sample <TT>Bank</TT> application and get the opportunity to integrate theuse of a CORBAservice--namely, the CORBA Naming Service--with the <TT>Bank</TT> application.<H2><A NAME="Heading10"></A><FONT COLOR="#000077">Q&A</FONT></H2><DL> <DD><B>Q I think I need to use DII.</B><BR> <B><BR> A</B> You don't. Actually, this answer is only partly tongue-in-cheek. DII invites many opportunities for confusion and difficult-to-trace errors in your application development efforts. Unless you're developing an application similar to those described in the examples in this chapter and absolutely need to take advantage of a feature offered by DII, it is almost certain that you don't want to even <I>think</I> about DII.<BR> <B><BR> Q If DII is so useless for most applications, why does the CORBA specification bother with it in the first place?<BR> <BR> A</B> In the early days of CORBA, there were two camps with opposing views regarding how methods should be invoked. From one camp's view evolved the static invocation mechanism, and from the other came the DII.</DL><H2><A NAME="Heading11"></A><FONT COLOR="#000077">Workshop</FONT></H2><P>The following section will help you test your comprehension of the material presentedtoday and put what you've learned into practice. You'll find the answers to the quizin Appendix A. On most days, a few exercises will accompany the quiz; today, becauseno real "working knowledge" material was presented, there are no exercises.<H3><A NAME="Heading12"></A><FONT COLOR="#000077">Quiz</FONT></H3><DL> <DD><B>1</B>. Would you expect DII to be useful to most CORBA application developers? Why or why not?<BR> <B><BR> 2</B>. What are the advantages of DII over static method invocation?<BR> <B><BR> 3</B>. What are the disadvantages of DII compared to static method invocation?<FONT COLOR="#000077"></FONT></DL><CENTER><P><HR><A HREF="../ch10/ch10.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../ch12/ch12.htm"><IMGSRC="../button/next.gif" WIDTH="128" HEIGHT="28" ALIGN="BOTTOM" ALT="Next chapter"BORDER="0"></A><A HREF="../index.htm"><IMG SRC="../button/contents.gif" WIDTH="128"HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A> <BR><BR><BR><IMG SRC="../button/corp.gif" WIDTH="284" HEIGHT="45" ALIGN="BOTTOM" ALT="Macmillan Computer Publishing USA"BORDER="0"></P><P>© <A HREF="../copy.htm">Copyright</A>, Macmillan Computer Publishing. Allrights reserved.</CENTER></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -