comparison apache-xmlrpc-3.1.3/docs/advanced.html @ 151:db5f735fd2b4

add xml-rpc.jar
author e085711
date Sat, 10 Sep 2011 04:13:50 +0900
parents
children
comparison
equal deleted inserted replaced
147:a2b5149bbbe6 151:db5f735fd2b4
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
3
4
5
6
7
8
9
10
11
12
13 <html xmlns="http://www.w3.org/1999/xhtml">
14 <head>
15 <title>ws-xmlrpc - Advanced Programming Topics</title>
16 <style type="text/css" media="all">
17 @import url("./css/maven-base.css");
18 @import url("./css/maven-theme.css");
19 @import url("./css/site.css");
20 </style>
21 <link rel="stylesheet" href="./css/print.css" type="text/css" media="print" />
22 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
23 </head>
24 <body class="composite">
25 <div id="banner">
26 <a href="" id="bannerLeft">
27
28 <img src="images/xmlrpc-logo.gif" alt="" />
29
30 </a>
31 <div class="clear">
32 <hr/>
33 </div>
34 </div>
35 <div id="breadcrumbs">
36
37
38
39
40
41
42
43
44 <div class="xleft">
45 Last Published: 2010-02-06
46 </div>
47 <div class="xright"> <a href="http://www.apache.org/" class="externalLink">Apache</a>
48 |
49 <a href="../">Webservices</a>
50 |
51 <a href="">XML-RPC</a>
52
53
54
55
56
57
58
59
60 </div>
61 <div class="clear">
62 <hr/>
63 </div>
64 </div>
65 <div id="leftColumn">
66 <div id="navcolumn">
67
68
69
70
71
72
73
74
75 <h5>XML-RPC</h5>
76 <ul>
77
78 <li class="none">
79 <a href="index.html">Overview</a>
80 </li>
81
82 <li class="none">
83 <a href="download.html">Download</a>
84 </li>
85
86 <li class="none">
87 <a href="changes-report.html">Changes</a>
88 </li>
89
90 <li class="none">
91 <a href="mail-lists.html">Mailing Lists</a>
92 </li>
93
94 <li class="none">
95 <a href="contributing.html">Contributing</a>
96 </li>
97
98 <li class="none">
99 <a href="xmlrpc2">XML-RPC 2</a>
100 </li>
101
102 <li class="none">
103 <a href="links.html">Links</a>
104 </li>
105 </ul>
106 <h5>Documentation</h5>
107 <ul>
108
109 <li class="none">
110 <a href="client.html">Client Classes</a>
111 </li>
112
113 <li class="none">
114 <a href="server.html">Server Side XML-RPC</a>
115 </li>
116
117 <li class="none">
118 <a href="extensions.html">Vendor Extensions</a>
119 </li>
120
121 <li class="none">
122 <a href="ssl.html">SSL</a>
123 </li>
124
125 <li class="none">
126 <a href="introspection.html">Introspection</a>
127 </li>
128
129 <li class="none">
130 <strong>Advanced Techniques</strong>
131 </li>
132
133 <li class="none">
134 <a href="types.html">XML-RPC Types</a>
135 </li>
136
137 <li class="none">
138 <a href="faq.html">FAQ</a>
139 </li>
140
141 <li class="none">
142 <a href="apidocs/index.html">Javadocs</a>
143 </li>
144 </ul>
145 <h5>Project Documentation</h5>
146 <ul>
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 <li class="collapsed">
175 <a href="project-info.html">Project Information</a>
176 </li>
177
178
179
180
181
182
183
184
185
186 <li class="collapsed">
187 <a href="project-reports.html">Project Reports</a>
188 </li>
189 </ul>
190 <a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
191 <img alt="Built by Maven" src="./images/logos/maven-feather.png"></img>
192 </a>
193
194
195
196
197
198
199
200
201 </div>
202 </div>
203 <div id="bodyColumn">
204 <div id="contentBox">
205 <p>This page describes some advanced topics.</p>
206 <div class="section"><h2>Dynamic proxies</h2>
207 <p>Dynamic proxies are an extremely comfortable way of Client programming. Basically, the idea is as follows: All request processors on the server side are splitted into interface and implementation. The interfaces are shared between client and server, typically within some common jar file. Now, rather than using the <a href="apidocs/org/apache/xmlrpc/client/XmlRpcClient.html">XmlRpcClient</a> directly, the programmer creates an instance of <a href="apidocs/org/apache/xmlrpc/client/util/ClientFactory.html">ClientFactory</a>, which is configured with an <a href="apidocs/org/apache/xmlrpc/client/XmlRpcClient.html">XmlRpcClient</a>.</p>
208 <p>The <a href="apidocs/org/apache/xmlrpc/client/util/ClientFactory.html">factory</a> can take an interface as input and returns an implementation, which internally calls the server by using the <a href="apidocs/org/apache/xmlrpc/client/XmlRpcClient.html">XmlRpcClient</a>.</p>
209 <p>Perhaps some code shows more than words. First of all, let's create a request processor interface.</p>
210 <div class="source"><pre> package com.foo;
211
212 public interface Adder {
213 public int add(int pNum1, int pNum2);
214 }
215 </pre>
216 </div>
217 <p>The server contains the request processors implementation:</p>
218 <div class="source"><pre> package com.foo;
219
220 public class AdderImpl implements Adder {
221 public int add(int pNum1, int pNum2) {
222 return pNum1 + pNum2;
223 }
224 }
225 </pre>
226 </div>
227 <p>And here is how the client would use this:</p>
228 <div class="source"><pre> import com.foo.Adder;
229 import java.net.URL;
230 import org.apache.xmlrpc.client.XmlRpcClient;
231 import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
232 import org.apache.xmlrpc.client.util.ClientFactory;
233
234 XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
235 config.setServerURL(new URL(&quot;http://127.0.0.1:8080/xmlrpc&quot;));
236 XmlRpcClient client = new XmlRpcClient();
237 client.setConfig(config);
238 ClientFactory factory = new ClientFactory(client);
239 Adder adder = (Adder) factory.newInstance(Adder.class);
240 int sum = adder.add(2, 4);
241 </pre>
242 </div>
243 <div class="section"><h3>Exception handling</h3>
244 <p>Currently, exceptions are a problem: If the server throws an exception (for example an IOException), then the client receives an XmlRpcException. Consequently, the generated implementation will attempt to throw the XmlRpcException.</p>
245 <p>Unfortunately, the method signature will of course contain an IOException, but rarely an XmlRpcException. As the XmlRpcException cannot be thrown, it is converted into an UndeclaredThrowableException.</p>
246 <p>This is no problem, if you are prepared for runtime exceptions by enclosing your code with proper exception handlers. (Of course, the exception handlers may be in a calling method.) Only if you want to catch the exception (for example, because you expect an error at a certain point), then you need to consider, which exception is being trapped: If the method exposes XmlRpcException, then you'll need to catch the XmlRpcException. Otherwise, it's UndeclaredThrowableException.</p>
247 <p>It is recommended to use the property enabledForExceptions. If this property is set, then the server will attempt to convert the exception into a byte array, which is transmitted to the client. The client will be able to convert the byte array back into an exception and throw that, as if it came right out of the client. Note, that this approach may cause security and privacy issues, because the serialized exception may, in theory, contain arbitrary objects.</p>
248 </div>
249 <div class="section"><h3>Cookie handling</h3>
250 <p>Cookie has not yet been generalized. In other words, it depends on the transport.</p>
251 <ul><li>The XmlRpcLiteHttpTransport doesn't have support for cookies. * The XmlRpcSunHttpTransport requires hand written code for setting and getting the cookies or using a cookie library. (The latter is recommended, of course.) In either way, you've got to use a custom transport and overwrite the methods newURLConnection(URL), initHttpHeaders(XmlRpcRequest), and close():<div class="source"><pre> import java.net.URLConnection;
252 import org.apache.xmlrpc.client.XmlRpcClient;
253 import org.apache.xmlrpc.client.XmlRpcSunHttpTransport;
254 import org.apache.xmlrpc.client.XmlRpcTransport;
255 import org.apache.xmlrpc.client.XmlRpcTransportFactory;
256
257 final XmlRpcClient client = new XmlRpcClient();
258 XmlRpcTransportFactory factory = new XmlRpcTransportFactory(){
259 public XmlRpcTransport getTransport(){
260 private URLConnection conn;
261 protected URLConnection newURLConnection(URL pURL) throws IOException {
262 conn = super.newURLConnection(pURL);
263 return conn;
264 }
265 protected void initHttpHeaders(XmlRpcRequest pRequest) {
266 super.initHttpHeaders(pRequest);
267 setCookies(conn);
268 }
269 protected void close() throws XmlRpcClientException {
270 getCookies(conn);
271 }
272 private void setCookies(URLConnection pConn) {
273 // Implement me ...
274 }
275 private void getCookies(URLConnection pConn) {
276 // Implement me ...
277 }
278 }
279 };
280 client.setTransportFactory(factory);
281 </pre>
282 </div>
283 </li>
284 <li>The XmlRpcCommonsHttpTransport requires that the HttpClient is being reused. (By default, a new HttpClient is created for any connection.) To reuse the HttpClient, set it on the transport factory:<div class="source"><pre> import org.apache.commons.httpclient.HttpClient;
285 import org.apache.commons.httpclient.HttpState;
286 import org.apache.xmlrpc.client.XmlRpcClient;
287 import org.apache.xmlrpc.client.XmlRpcCommonsTransport;
288 import org.apache.xmlrpc.client.XmlRpcCommonsTransportFactory;
289
290 final XmlRpcClient client = new XmlRpcClient();
291 final HttpClient httpClient = new HttpClient();
292 final XmlRpcCommonsTransportFactory factory = new XmlRpcCommonsTransportFactory(client);
293 factory.setHttpClient(httpClient);
294 client.setTransportFactory(factory);
295 final HttpState httpState = client.getState();
296 </pre>
297 </div>
298 <p>Cookies may now be read or set on the httpState object.</p>
299 <p>Note, that this means losing the XmlRpcClients multithreading abilities! The factory above is obviously bound to the HttpClient, which must be bound to a thread. If you need to set cookies initially, overwrite the transport method initHttpHeaders(XmlRpcRequest) as well.</p>
300 </li>
301 </ul>
302 </div>
303 <div class="section"><h3>Custom data types</h3>
304 <p>Apache XML-RPC was built with extensibility in mind. In particular, it was written to support custom data types.</p>
305 <p>The data type handling is completely left to the <a href="apidocs/org/apache/xmlrpc/common/TypeFactory.html">TypeFactory</a>. In other words, adding support for custom data types is as simple as providing your own type factory. This is typically done by subclassing <a href="apidocs/org/apache/xmlrpc/common/TypeFactoryImpl.html">TypeFactoryImpl</a>.</p>
306 <p>We'll illustrate the concept by creating a type factory, which uses a non-standard date format for transmitting date values. First of all, we've got to implement the subclass:</p>
307 <div class="source"><pre> import java.text.DateFormat;
308 import java.text.SimpleDateFormat;
309 import org.apache.xmlrpc.common.TypeFactoryImpl;
310 import org.apache.xmlrpc.common.XmlRpcController;
311 import org.apache.xmlrpc.parser.DateParser;
312 import org.apache.xmlrpc.parser.TypeParser;
313 import org.apache.xmlrpc.serializer.DateSerializer;
314 import org.apache.xmlrpc.serializer.TypeSerializer;
315 import org.apache.ws.commons.util.NamespaceContextImpl;
316
317 public class MyTypeFactory extends TypeFactoryImpl {
318 public MyTypeFactory(XmlRpcController pController) {
319 super(pController);
320 }
321
322 private DateFormat newFormat() {
323 return new SimpleDateFormat(&quot;yyyy-MM-dd HH:mm:ss.SSS&quot;);
324 }
325
326 public TypeParser getParser(XmlRpcStreamConfig pConfig, NamespaceContextImpl pContext, String pURI, String pLocalName) {
327 if (DateSerializer.DATE_TAG.equals(pLocalName)) {
328 return new DateParser(pFormat);
329 } else {
330 return super.getParser(pConfig, pContext, pURI, pLocalName);
331 }
332 }
333
334 public TypeSerializer getSerializer(XmlRpcStreamConfig pConfig, Object pObject) throws SAXException {
335 if (pObject instanceof Date) {
336 return new DateSerializer(newFormat());
337 } else {
338 return super.getSerializer(pConfig, pObject);
339 }
340 }
341 }
342 </pre>
343 </div>
344 <p>On the client side, we've got to tell the <a href="apidocs/org/apache/xmlrpc/client/XmlRpcClient.html">XmlRpcClient</a> to use the new factory. That's as simple as typing</p>
345 <div class="source"><pre> XmlRpcClient client = new XmlRpcClient();
346 client.setTypeFactory(new MyTypeFactory());
347 </pre>
348 </div>
349 <p>Things are a little bit more difficult on the server side. Basically all we need to do is setting the type factory on the <a href="apidocs/org/apache/xmlrpc/server/XmlRpcServer.html">XmlRpcServer</a>. The question is, how to obtain the server object. That depends on the environment. If you are using the XmlRpcServlet, then you've got to derive a subclass:</p>
350 <div class="source"><pre> import org.apache.xmlrpc.webserver.XmlRpcServletServer;
351 import org.apache.xmlrpc.webserver.XmlRpcServlet;
352
353 public class MyXmlRpcServlet extends XmlRpcServlet {
354 protected XmlRpcServletServer newXmlRpcServer(ServletConfig pConfig) {
355 XmlRpcServletServer server = super.newXmlRpcServer(pConfig);
356 server.setTypeFactory(new MyTypeFactory(server));
357 return server;
358 }
359 }
360 </pre>
361 </div>
362 <p>And, if you are using the <a href="apidocs/org/apache/xmlrpc/webserver/WebServer.html">WebServer</a>, you've got to override a similar method:</p>
363 <div class="source"><pre> import java.net.InetAddress;
364 import org.apache.xmlrpc.server.XmlRpcStreamServer;
365 import org.apache.xmlrpc.webserver.WebServer;
366
367 public class MyWebServer extends WebServer {
368 public MyWebServer(int pPort) {
369 super(pPort);
370 }
371
372 public MyWebServer(int pPort, InetAddress pAddr) {
373 super(pPort, pAddr);
374 }
375
376 protected XmlRpcStreamServer newXmlRpcStreamServer() {
377 XmlRpcStreamServer server = new ConnectionServer();
378 server.setTypeFactory(new MyTypeFactory());
379 return server;
380 }
381 }
382 </pre>
383 </div>
384 </div>
385 </div>
386
387 </div>
388 </div>
389 <div class="clear">
390 <hr/>
391 </div>
392 <div id="footer">
393 <div class="xright">&#169;
394 2001-2010
395
396 The Apache Software Foundation
397
398
399
400
401
402
403
404
405 </div>
406 <div class="clear">
407 <hr/>
408 </div>
409 </div>
410 </body>
411 </html>