Thanks a lot for your help Kevin. I got my library working.
In case anyone else has a similar interest, here is what I did:
my test:
*** Settings ***
Library Remote http://server:port/myRobot/xmlrpc
*** Test Cases ***
Ping Test
${pong} = ping bob
Should Be Equal as Strings ${pong} pong bob
The web.xml for the web app:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="
http://java.sun.com/xml/ns/javaee"
xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" >
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>XmlRpcServlet</servlet-name>
<servlet-class>com.mark.MyXmlRpcServlet</servlet-class>
<init-param>
<param-name>enabledForExtensions</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>XmlRpcServlet</servlet-name>
<url-pattern>/xmlrpc</url-pattern>
</servlet-mapping>
</web-app>
My remote library class:
package com.mark;
import java.util.Map;
import java.util.HashMap;
public class Robot {
public String ping(String input) {
System.out.println("[MARK] Robot.ping()");
return "pong " + input;
}
//
// methods required by the robotframework remote library protocol follow
//
public String[] get_keyword_names() {
//System.out.println("[MARK] Robot.get_keyword_names()");
return new String[] { "ping" };
}
public Map<String, Object> run_keyword(String keyword, Object[] args) {
//System.out.println("[MARK] Robot.run_keyword()");
HashMap<String, Object> kr = new HashMap<String, Object>();
try {
kr.put("status", "PASS");
kr.put("error", "");
kr.put("traceback", "");
Object retObj = "";
// run the right method
if (keyword.equalsIgnoreCase("ping")) {
retObj = ping((String)args[0]);
} else {
kr.put("status", "FAIL");
kr.put("return", "");
kr.put("error", "");
kr.put("traceback", "");
}
kr.put("return", retObj);
} catch (Throwable e) {
e.printStackTrace(System.out);
}
return kr;
}
}
my custom handler:
/*
* Adapted from
https://github.com/ombre42/jrobotremoteserver/blob/master/src/main/java/org/robotframework/remoteserver/xmlrpc/ReflectiveHandlerMapping.java *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0 *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mark;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.server.AbstractReflectiveHandlerMapping;
public class HandlerMapping extends AbstractReflectiveHandlerMapping {
/**
* Removes the prefixes from all keys in this handler mapping assuming a
* String was used as the key and period was
* used as a separator. Example: Robot.getInvoice -> getInvoice
*/
@SuppressWarnings("unchecked")
public void removePrefixes() {
//System.out.println("[MARK] entering HandlerMapping.removePrefixes()");
Map<String, Object> newHandlerMap = new HashMap<String, Object>();
for (Entry<String, Object> entry : (Set<Entry<String, Object>>) this.handlerMap.entrySet()) {
String newKey = (String) entry.getKey();
if (entry.getKey() instanceof String) {
String key = (String) entry.getKey();
if (key.contains(".")) {
newKey = key.substring(key.lastIndexOf(".") + 1);
}
}
newHandlerMap.put(newKey, entry.getValue());
}
this.handlerMap = newHandlerMap;
}
my custom servlet:
/**
* Adds handlers for the given object to the mapping. The handlers are build by invoking
* {@link #registerPublicMethods(String, Class)}.
*
* @param pKey
* The class key, which is passed to {@link #registerPublicMethods(String, Class)}.
* @param pClass
* Class, which is responsible for handling the request.
*/
public void addHandler(String pKey, Class<?> pClass) throws XmlRpcException {
//System.out.println("[MARK] entering HandlerMapping.addHandler()");
registerPublicMethods(pKey, pClass);
}
}
package com.mark;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.server.XmlRpcHandlerMapping;
import org.apache.xmlrpc.webserver.XmlRpcServlet;
public class MyXmlRpcServlet extends XmlRpcServlet {
@Override
protected XmlRpcHandlerMapping newXmlRpcHandlerMapping() throws XmlRpcException {
//System.out.println("[MARK] entering MyXmlRpcServlet.newXmlRpcHandlerMapping()");
HandlerMapping mapping = new HandlerMapping();
mapping.addHandler(com.mark.Robot.class.getName(), com.mark.Robot.class);
mapping.removePrefixes();
return mapping;
}
}
Out of interest, I did not want to run the server and fire up a new listener/thread on another port. I wanted to have the servlet run just in the normal container. This way, i can take advantage of the container/app server's tuning, thread and workload management, which I need to do in this particular exercise.
Thanks again for your help.
Best Regards,
Mark Nelson