=default for generated implementation copy ctor
[ACE_TAO.git] / TAO / docs / tutorials / Quoter / On_Demand_Activation / index.html
blobca6ca9030782660c19ebec4eb5d8a4cecddc525c
2 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
3 <html>
4 <head>
5 <title>Servant Managers</title>
6 <!-- -->
7 </head>
9 <body text = "#000000"
10 link="#000fff"
11 vlink="#ff0f0f"
12 bgcolor="#ffffff">
14 <h1>Servant Managers</h1>
15 <P>In our <a href=../AMI/index.html>previous example</a>, we
16 extended our <a href=../Simple/Client/client.cpp>simple client</a>
17 using synchronous method invocation to handle asynchronous
18 requests: Asynchronous Method Invocation by using
19 the reply handlers.
20 </P>
21 <P>In applications which have many objects, activating
22 all of them all the time would be unnecessary
23 and also might require too much memory or too many database
24 lookups. For such applications, the POA provides an option
25 for the application to supply servant managers that can
26 dynamically supply servants on a per-request basis.
27 </P>
28 <p> A servant manager is a call-back object that the application
29 registers with a POA. When the POA attempts to determine the
30 servant associated with a particular request, it calls back the
31 application's servant manager to obtain the servant. To be able
32 to register a servant manager with the POA, the
33 <CODE>RequestProcessingPolicyValue</CODE>, which controls the
34 matching of requests to servants, is to be set to
35 <CODE>USE_SERVANT_MANAGER</CODE>.
36 </P>
37 <P>There are two types of servant managers depending on whether the POA
38 retains the associations of objects to servants in its Active
39 Object Map or not. This is determined by the value of the
40 <CODE>ServantRetentionPolicy</CODE> set when the
41 POA is created. If the value of this policy is set as RETAIN,
42 the POA retains the associations, and if the policy value is set
43 to be NON_RETAIN, the POA doesn't retain any associations between
44 the object and the servant.
45 </P>
46 <P>For a POA with the RETAIN value, the servant manager must
47 activate the servant associated with the object. This would need
48 the servant manager object to support the ServantActivator
49 interface. In the case of a POA with the NON_RETAIN value set,
50 our servant manager object should be able to locate the servant
51 for the requested object and then invoke it.
52 </P>
53 <P>In this example, let's use a servant locator to locate the
54 servant associated with our Stock_Factory object when a request
55 is invoked on this object.
56 </P>
57 <H3>The Stock Factory Locator Implementation</H3>
58 <P>Our implementation of the Stock_Factory_Locator_i will help
59 us find the Quoter_Stock_Factory servant.
60 </P>
61 <P>A servant Locator interface provides two operations: preinvoke
62 and postinvoke. The preinvoke operation is invoked to obtain the
63 servant to dispatch the request to. The servant returned by
64 the preinvoke is used only for a single request. The postinvoke
65 operation is later invoked to destroy the servant created by the
66 preinvoke operation.
67 </P>
68 <PRE>
69 #include "tao/corba.h"
71 class Quoter_Stock_Factory_Locator_i : public POA_PortableServer::ServantLocator
73 public:
74 Quoter_Stock_Factory_Locator_i (CORBA::ORB_ptr orb);
76 // Preinvoke function
77 virtual PortableServer::Servant preinvoke (const PortableServer::ObjectId &oid,
78 PortableServer::POA_ptr poa,
79 const char * operation,
80 void * & cookie);
82 // Postinvoke function
83 virtual void postinvoke (const PortableServer::ObjectId & oid,
84 PortableServer::POA_ptr poa,
85 const char * operation,
86 void * cookie,
87 PortableServer::Servant servant);
89 private:
90 CORBA::ORB_var orb_;
92 </PRE>
93 <P>In the implementation of the <CODE>preinvoke</CODE> operation, we check if
94 the object ID is valid and then check for the servant we want to
95 create and create and return the requested servant.
96 <PRE>
97 <PRE>
98 PortableServer::Servant
99 Quoter_Stock_Factory_Locator_i::preinvoke (const PortableServer::ObjectId &oid,
100 PortableServer::POA_ptr poa,
101 const char * operation,
102 void * & cookie)
105 try {
107 // Get the ObjectID in string format
108 CORBA::String_var oid_str =
109 PortableServer::ObjectId_to_string (oid);
111 // Check if the ObjectId is valid
112 if (strcmp (oid_str.in (), "Quoter/Stock_Factory") != 0) {
113 // Create the requested servant.
114 PortableServer::Servant servant =
115 new Quoter_Stock_Factory_i ();
117 cookie = servant;
119 return servant;
121 else {
122 throw CORBA::OBJECT_NOT_EXIST ();
125 }catch (const CORBA::BAD_PARAM &) {
126 throw CORBA::OBJECT_NOT_EXIST ();
128 </PRE>
129 <P>The implementation of the <CODE>postinvoke</CODE> operation is
130 simple. We just destroy the servant which we created by the
131 <CODE>preinvoke</CODE> operation. The <CODE>Cookie IDL
132 type</CODE> which is a parameter in both these operations
133 helps associate the invocation of <CODE>preinvoke</CODE> with
134 its <CODE>postinvoke</CODE> operation.
135 </P>
136 <PRE>
137 void
138 Quoter_Stock_Factory_Locator_i::postinvoke (const PortableServer::ObjectId &oid,
139 PortableServer::POA_ptr poa,
140 const char * operation,
141 void * cookie,
142 PortableServer::Servant servant)
145 // Delete the servant as it is no longer needed.
146 PortableServer::Servant my_servant = (PortableServer::Servant) cookie;
147 if (servant == my_servant)
148 delete servant;
150 </PRE>
151 <H3> Server Implementation </H3>
152 <P>Our first steps would be to create a new POA from the RootPOA
153 with the <CODE>USE_SERVANT_MANAGER</CODE> value for the
154 <CODE>RequestProcessingPolicy</CODE> and <CODE>NON_RETAIN</CODE>
155 for the <CODE>ServantRetentionPolicy</CODE>.
156 </P>
157 <PRE>
158 CORBA::PolicyList policies (3);
159 policies.length (3);
161 // Assign the polices
162 policies [0] =
163 poa->create_id_assignment_policy (PortableServer::USER_ID);
165 policies [1] =
166 poa->create_request_processing_policy
167 (PortableServer::USE_SERVANT_MANAGER);
169 policies [2] =
170 poa->create_servant_retention_policy (PortableServer::NON_RETAIN);
172 // Create the POA with these policies
173 PortableServer::POA_var child_poa =
174 poa->create_POA ("childPOA",
175 poa_manager.in (),
176 policies);
178 // Destroy the policy objects
179 for (CORBA::ULong i = 0; i != policies.length (); ++i) {
180 policies[i]->destroy ();
183 </PRE>
184 <P> The policy values are assigned, the <CODE>childPOA</CODE> is
185 created with these policies, and later these policy objects can be
186 deleted, as a copy of these objects is made by the
187 <CODE>create_POA</CODE> and we would not need these objects any more.
188 </P>
189 <P> Now that we have the POA which can support servant managers,
190 the next step would be to create a servant for the servant
191 locator object, activate it to obtain its reference, and set it as
192 the servant manager with the childPOA.
193 </P>
194 <PRE>
195 // Create a Stock_Factory_Locator servant
196 Quoter_Stock_Factory_Locator_i servant_locator_i(orb.in ());
198 // Need to activate a servant_manager object in the Root POA
199 PortableServer::ServantLocator_var servant_locator =
200 servant_locator_i._this ();
202 // Set the SM with the childPOA
203 child_poa->set_servant_manager (servant_locator.in ());
204 </PRE>
205 <P>Now that we have set the servant manager with the childPOA, the
206 next step would be to create a reference with the user-created
207 ID in the childPOA which uses the Quoter_Stock_Factory_Locator_i.
208 The <CODE>create_reference_with_id</CODE> operation lets us
209 create the required object without actually creating its servant.
210 The application supplies the ObjectId which signifies the
211 identity of the object in the application domain.
212 </P>
213 <PRE>
214 // Get the Object Id
215 PortableServer::ObjectId_var child_oid =
216 PortableServer::string_to_ObjectId ("childFoo");
218 //Create the Object without creating the servants
219 CORBA::Object_var stock_factory =
220 child_poa->create_reference_with_id (child_oid.in (),
221 "IDL:Quoter/Stock_Factory:1.0");
222 </PRE>
223 <P>After this, as before, let's put this object reference as an IOR
224 string and print it out.
225 </P>
226 <PRE>
227 // Put the object reference as an IOR string
228 CORBA::String_var ior = orb->object_to_string (stock_factory.in ());
230 // Print it out!
231 std::cout << ior.in () << std::endl;
232 </PRE>
233 <H3>Excercise</H3>
234 <P>Modify the <a href="../Simple/Server/server.cpp">server.cpp</a> in
235 the simple server to use servant managers and locators. Use
236 these files to help complete the implementation.
237 <a href="Stock_Factory_Locator_i.h">Stock_Factory_locator_i.h</a>
238 <a href="Stock_Factory_Locator_i.cpp">Stock_Factory_locator_i.cpp</a>
239 <a href="Makefile">Makefile</a>.
240 </P>
241 <H3>Solution</H3>
242 <P>Look at the <a href="server.cpp">server.cpp</a> file. It should not
243 be much different from yours.
244 </P>
245 <H3>Testing</H3>
246 <P>A client which uses request handlers is provided:
247 <a href="../AMI/client.cpp">client.cpp</a>. As before the
248 following files are provided.
249 <a href="../AMI/Quoter.idl">Quoter.idl</a>
250 <a href="../On_Demand_Activation/Stock_i.h">Stock_i.h</a>
251 <a href="../On_Demand_Activation/Stock_i.cpp">Stock_i.cpp</a>
252 <a href="Stock_Factory_i.h">Stock_Factory_i.h</a>
253 <a href="Stock_Factory_i.cpp">Stock_Factory_i.cpp</a>
254 <a href="../AMI/Handler_i.h">Handler_i.h</a> and
255 <a href="../AMI/Handler_i.cpp">Handler_i.cpp</a>.
256 </P>
257 <H3>More Reading</H3>
258 <P>The
259 <P>The <A HREF="http://www.triodia.com/staff/michi-henning.html">Henning</A> and
260 <A HREF="http://www.iona.com/hyplan/vinoski/">Vinoski</A>
261 <A HREF="http://www.iona.com/hyplan/vinoski/#book">CORBA book</A>
262 discusses POA policies in detail. Likewise, the Schmidt and Vinoski
263 <A HREF="http://www.cs.wustl.edu/~schmidt/report-doc.html">columns </A>
264 in C++ Report also include several articles about the POA. Finally,
265 the <A HREF="http://www.dre.vanderbilt.edu/~schmidt/TAO.html">TAO</a>
266 distribution includes
267 <A HREF="../../../../examples/POA">examples</A> that illustrate how to use the POA policies.
268 </P>
269 <hr>
270 <address><a href="mailto:pgontla@ece.uci.edu">Priyanka Gontla</a></address>
271 <!-- Created: Mon May 1 11:08:56 PDT 2000 -->
272 <!-- hhmts start -->
273 Last modified: Tue Apr 24 17:50:17 CDT 2001
274 <!-- hhmts end -->
275 </body>
276 </html>