XML-RPC (Extensible Markup Language Remote Procedure Calling) can be downloaded from http://xml.apache.org/xmlrpc/. Download the version for the JavaTM language. With XML-RPC you can mix different languages for server and client, however we will stick to a pure Java implementation.
They provide a Servlet that you can use as the server for the XML-RPC, however, a JSP page is better, because you can make changes more easily. The following is a JSP page you can use as a server for XML-RPC:
Note that the tags are placed stacked to each other like ><. This is so that no blank lines will be sent back before the XML document is sent back. The XML header must be the first line sent back. This XML page is derived from the execute method. You won't see any XML in this JSP page because it is all done under the covers.
This example uses the uk.co.wilson.xml.MinML, the default xml-rpc parser that comes in xmlrpc jar file. This parser, MinML is a bare bones parser only 15 KB in size that is scaled down to only do xml-rpc functionality. If you need a more robust parser you can use org.apache.xerces.parsers.SAXParser in the xerces.jar file as a XML Parser, however, the xerces.jar file is 1464 KB. Therefore, if you are just using the parser for xmlrpc and you need a small download, MinML is the way to go. Note that no empty lines must be present in the following code outside any tags or that line will be sent back to the browser before the XML Docuemnt is sent, invalidating the XML.
<%@ page import="java.io.*" %><%@ page import="java.util.*" %><%@ page import="org.apache.xmlrpc.*" %><%@ page import="javax.servlet.*" %><%@ page import="javax.servlet.http.*" %><%! //methods and declarations in this tag: public String NoNull(String N){ return N == null ? "" : N.trim() ; } private XmlRpcServer xmlrpcServ = null; public byte[] convertStringToBytes(String Str){ char[] NewChr = Str.toCharArray(); byte[] NewByt = new byte[NewChr.length]; for (int i=0; i < NewByt.length; i++){ int Ci = NewChr[i] & 255; NewByt[i] = (byte) Ci; } return NewByt; } public byte[] readBytes(InputStream IPut) throws Exception { Vector BytArrsV = new Vector(); int size=0; byte[] FinalVal = new byte[0]; int read=0; try{ int i=0; byte[] bbuf = new byte[1024]; while ((read = IPut.read(bbuf, 0, bbuf.length)) > -1){ byte[] bbuf2 = new byte[read]; for (i=0; i < bbuf2.length; i++){ bbuf2[i] = bbuf[i]; } BytArrsV.addElement(bbuf2); size += read; } FinalVal = new byte[size]; int j = 0; for (i = 0; i < BytArrsV.size(); i++){ byte[] byarr = (byte[]) BytArrsV.elementAt(i); for (int k = 0; k < byarr.length; k++){ FinalVal[j++] = byarr[k]; } } } catch(Exception ex){ throw ex; } finally{ IPut.close(); } return FinalVal; } public void setXmlRpc(){ xmlrpcServ = new XmlRpcServer (); try{ XmlRpc.setDriver("uk.co.wilson.xml.MinML"); xmlrpcServ.addHandler ("MyRCPHandle", new com.javaemerald.MyRPCClass()); } catch (Exception ex){ StringBuffer Messenger = new StringBuffer(); Messenger.append("Err: "+ex.toString()+"\n"); StringWriter SW = new StringWriter(); PrintWriter PW = new PrintWriter(SW); ex.printStackTrace(PW); Messenger.append("Method setXmlRpc() "+ "of xmlrpcserver.jsp: Stack Trace:\n"+SW.toString()); throw new RuntimeException (Messenger.toString()); } } //end of methods in Declaration tag. %><% //start of main Servlet method. response.setHeader("Cache-Control","no-store"); response.setHeader("Pragma","no-cache"); response.setDateHeader ("Expires", 0); ByteArrayInputStream IPut = null; try{ if (xmlrpcServ == null) setXmlRpc(); byte[] reqdata = readBytes(request.getInputStream()); IPut = new ByteArrayInputStream(reqdata); byte[] result = xmlrpcServ.execute (IPut); //XML Page in the form of byte[] retrieved. response.setContentType("text/xml"); response.setContentLength (result.length); OutputStream output = response.getOutputStream(); output.write (result); //XML page outputted. output.flush (); } catch(Exception ex){ out.println("JSP Err: "+ex+" IPut: "+IPut); } //no spaces or lines after the last tag. %>
The remote RPC Class (in the above example it is called com.javaemerald.MyRPCClass) must follow these rules:
example MyRPCClass:
package com.javaemerald; public class MyRPCClass{ public MyRPCClass(){ //initialize here. } public String showNums(double NumA, int NumB){ return "parameters sent are: double: "+NumA+" int: "+NumB; } }
If you call the above JSP page as "xmlrpcserver.jsp" then the following is a client class that can use this server. I assume you will supply your own JSP URL.
import java.io.*; import java.util.*; import org.apache.xmlrpc.*; public class RPC_Caller{ XmlRpcClient client = null; /** * Creates a XmlRpcClient. XmlRpc is a class in org.apache.xmlrpc * package and setDriver is its static method. * The XmlRpcClient takes a String URL as a parameter. This * URL must point to the xmlrpc server, which in this case is called * "xmlrpcserver.jsp". */ public RPC_Caller(){ try{ XmlRpc.setDriver("uk.co.wilson.xml.MinML"); client = new XmlRpcClient("http://www.javaemerald.com/foobar/xmlrpcserver.jsp"); } catch(Exception ex){ throw new RuntimeException("Err Constructing XmlRpc RPC_Caller."+ex); } } /** * @Param RPCHandle the name bound to the class in the Remote Server. * @Param MethodName The name of the method on the remote class to call. * @Param Params is a Vector of all the Parameters in the right order for * each method. The XML RPC server will find the matching method * and invoke it (Remote Procedure Calling). */ public Object execute(String RPCHandle, String MethodName, Vector Params){ try{ return client.execute(RPCHandle+"."+MethodName, Params); } catch(Exception ex){ throw new RuntimeException("Err executing XmlRpc in RPC_Caller. "+ex); } } }
and example using this class is as follows:
RPC_Caller Caller = new RPC_Caller(); Vector Params = new Vector(); Params.addElement(new Double(2.0)); Params.addELement(new Integer(3)); String ReturnS = (String) Caller.execute("MyRCPHandle", "showNums", Params); System.out.println(ReturnS);
This will print out:
parameters sent are: double: 2.0 int: 3
*OracleTM and JavaTM are registered trademarks of Oracle and or its affiliates. Other names may be trademarks of their respective owners.*