viernes, 5 de octubre de 2007

Comunicación Java / Python con XML-RPC

Estuve investigando cómo conectar Java y Python. Lo primero que se me ocurrió fue XMLRPC, y verdaderamente fue muy facil!
La info la saqué de:

El servidor Java:



1 package ar.com.hgdeoro.xmlrpc;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Random;
8
9 import org.apache.xmlrpc.server.PropertyHandlerMapping;
10 import org.apache.xmlrpc.server.XmlRpcServer;
11 import org.apache.xmlrpc.server.XmlRpcServerConfigImpl;
12 import org.apache.xmlrpc.webserver.WebServer;
13
14 public class Server {
15
16 private static final int port = 8000;
17
18 public static void main(String[] args) throws Exception {
19
20 final WebServer webServer = new WebServer(port);
21 final XmlRpcServer xmlRpcServer = webServer.getXmlRpcServer();
22 final PropertyHandlerMapping phm = new PropertyHandlerMapping();
23
24 phm.addHandler("Calculator", Calculator.class);
25
26 xmlRpcServer.setHandlerMapping(phm);
27 XmlRpcServerConfigImpl serverConfig = (XmlRpcServerConfigImpl) xmlRpcServer.getConfig();
28 serverConfig.setEnabledForExtensions(true);
29 serverConfig.setContentLengthOptional(false);
30 webServer.start();
31 }
32
33 public static class Calculator {
34
35 public int add(int i1, int i2) {
36 return i1 + i2;
37 }
38
39 public List<Integer> randomList(int num) {
40 if (num <= 0) {
41 throw new RuntimeException("num debe ser > 0");
42 }
43 final List<Integer> list = new ArrayList<Integer>();
44 for (int i = 0; i < num; i++) {
45 list.add(new Random().nextInt());
46 }
47 return list;
48 }
49
50 public Map<Integer, Integer> randomMap(int num) {
51 if (num <= 0) {
52 throw new RuntimeException("num debe ser > 0");
53 }
54 final Map<Integer, Integer> list = new HashMap<Integer, Integer>();
55 for (int i = 0; i < num; i++) {
56 list.put(Integer.valueOf(i), Integer.valueOf(new Random().nextInt()));
57 }
58 return list;
59 }
60
61 public Map<String, Integer> randomMap2(int num) {
62 if (num <= 0) {
63 throw new RuntimeException("num debe ser > 0");
64 }
65 final Map<String, Integer> list = new HashMap<String, Integer>();
66 for (int i = 0; i < num; i++) {
67 list.put(Integer.valueOf(i).toString(), Integer.valueOf(new Random().nextInt()));
68 }
69 return list;
70 }
71
72 }
73 }



El cliente Java:



1 package ar.com.hgdeoro.xmlrpc;
2
3 import java.net.MalformedURLException;
4 import java.net.URL;
5
6 import org.apache.xmlrpc.XmlRpcException;
7 import org.apache.xmlrpc.client.XmlRpcClient;
8 import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
9
10 public class Client {
11
12 public static void dump(Object obj) {
13 System.out.println("======================================================================");
14 System.out.println("Clase: " + obj.getClass());
15 System.out.println("toString(): " + obj.toString());
16
17 if (obj.getClass().isArray()) {
18 Object[] objs = (Object[]) obj;
19 System.out.println("---------- ARRAY ----------");
20 System.out.println("Tamanio: " + objs.length);
21 for (int i = 0; i < objs.length; i++) {
22 System.out.println("Object[" + i + "]: " + objs[i]);
23 }
24 }
25 }
26
27 public static void main(String args[]) throws MalformedURLException, XmlRpcException {
28 final XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
29 config.setServerURL(new URL("http://127.0.0.1:8000"));
30 final XmlRpcClient client = new XmlRpcClient();
31 client.setConfig(config);
32
33 Object obj = client.execute("add", new Object[] { new Integer(33), new Integer(9) });
34 dump(obj);
35
36 obj = client.execute("random_list", new Object[] { new Integer(14) });
37 dump(obj);
38
39 obj = client.execute("random_map", new Object[] { new Integer(9) });
40 dump(obj);
41
42 try {
43 obj = client.execute("random_map", new Object[] { new Integer(-1) });
44 throw new RuntimeException("La llamada remote deberia haber generado excepcion");
45 } catch (XmlRpcException e) {
46 e.printStackTrace();
47 }
48 }
49
50 }



El servidor Python:



1 from SimpleXMLRPCServer import SimpleXMLRPCServer
2 import random
3
4 def add(x,y):
5 return x + y
6
7 def random_list(num):
8 num = int(num)
9 if(num <= 0):
10 raise Exception("num debe ser mayor a 0")
11 list = []
12 for i in range(num):
13 list.append(random.randint(1, 999999))
14 return list
15
16 def random_map(num):
17 num = int(num)
18 if(num <= 0):
19 raise Exception("num debe ser mayor a 0")
20 map = {}
21 for i in range(num):
22 key = "elem_%d" % i
23 map[key] = random.randint(1, 999999)
24 return map
25
26 if __name__ == '__main__':
27 server = SimpleXMLRPCServer(("127.0.0.1", 8000))
28 server.register_function(add, 'add')
29 server.register_function(random_list, 'random_list')
30 server.register_function(random_map, 'random_map')
31 server.serve_forever()



El cliente Python:



1 import xmlrpclib
2 from pprint import pprint
3
4 if __name__ == '__main__':
5 proxy = xmlrpclib.Server('http://localhost:8000/xmlrpc')
6 pprint(proxy.Calculator.add(2,3))
7 pprint(proxy.Calculator.randomList(8))
8 pprint(proxy.Calculator.randomMap2(8))



Al ejecutar el cliente Python, obtengo:


5
[-816678161,
1435519307,
-648064553,
1198345419,
-332555131,
1349182312,
1286868314,
1756261972]
{'0': -1238582501,
'1': -711045786,
'2': 1242324380,
'3': 453035820,
'4': 727377110,
'5': 1443025388,
'6': -280665009,
'7': -1336015917}


y al ejecutar el cliente Java (esa excepcion que se muestra es un error producido adrede, para ejemplificar qué pasa cuando en el servidor se produce una excepción):


======================================================================
Clase: class java.lang.Integer
toString(): 42
======================================================================
Clase: class [Ljava.lang.Object;
toString(): [Ljava.lang.Object;@11a698a
---------- ARRAY ----------
Tamanio: 14
Object[0]: 140980
Object[1]: 917718
Object[2]: 951678
Object[3]: 405149
Object[4]: 758315
Object[5]: 412932
Object[6]: 488689
Object[7]: 721836
Object[8]: 658873
Object[9]: 590256
Object[10]: 667364
Object[11]: 552500
Object[12]: 784894
Object[13]: 865306
======================================================================
Clase: class java.util.HashMap
toString(): {elem_8=85992, elem_7=47193, elem_6=599464, elem_5=331449, elem_4=982397, elem_3=88299, elem_2=723048, elem_1=462681, elem_0=565753}
org.apache.xmlrpc.XmlRpcException: :num debe ser mayor a 0
at org.apache.xmlrpc.client.XmlRpcStreamTransport.readResponse(XmlRpcStreamTransport.java:186)
at org.apache.xmlrpc.client.XmlRpcStreamTransport.sendRequest(XmlRpcStreamTransport.java:145)
at org.apache.xmlrpc.client.XmlRpcHttpTransport.sendRequest(XmlRpcHttpTransport.java:94)
at org.apache.xmlrpc.client.XmlRpcSunHttpTransport.sendRequest(XmlRpcSunHttpTransport.java:44)
at org.apache.xmlrpc.client.XmlRpcClientWorker.execute(XmlRpcClientWorker.java:53)
at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:166)
at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:136)
at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:125)
at ar.com.hgdeoro.xmlrpc.Client.main(Client.java:43)