Web services are common in most applications today.
Web services provide synchroneous request-response style integration between applications in a convenient way:
Any developer need to have a basic understanding of web services.
Web services exist in two types:
This article will cover RPC style JSON-RPC web services.
For RPC style SOAP web services read here.
For RESTful style web services read here.
If asynchroneous integration is required then look at message queues. Read more here.
JSON-RPC is a RPC style web service standard.
It is very much inspired by XML-RPC, but as the name indicates then it uses JSON as format instead of XML.
Version 1.0 was first released in 2005, but it was first truly standardized with version 2.0 in 2009/2010.
JSON-RPC has never been widely used. RESTful web services (usually with JSON as format) is by far the most common.
But the standard still exists and there are good libraries for most languages. So if one need/prefer RPC style, then JSON-RPC is an interesting possibility.
We will look at an example with the following calls:
The focus will not on a realtsic example but more about showing how to get data and get data out. As this is the real issue in some libraries.
The servers will be embedded in application - not deployed on general web server. As I believe that is the most common scenario for JSON-RPC.
The most common client language is probbaly JavaScript, but due to my lack of JavaScript skills, then I will not show examples of JavaScript client.
Data.java:
package common;
public class Data {
private int ival;
private String sval;
public Data() {
this(0, "");
}
public Data(int ival, String sval) {
super();
this.ival = ival;
this.sval = sval;
}
public int getIval() {
return ival;
}
public void setIval(int ival) {
this.ival = ival;
}
public String getSval() {
return sval;
}
public void setSval(String sval) {
this.sval = sval;
}
@Override
public String toString() {
return String.format("(%d,%s)", ival, sval);
}
}
Test.java:
package server;
import java.util.ArrayList;
import java.util.List;
import common.Data;
public class Test {
public int getInt() {
return 123;
}
public String getString() {
return "ABC";
}
public Data getData() {
return new Data(123, "ABC");
}
public List<Integer> getListOfInts() {
ArrayList<Integer> res = new ArrayList<Integer>();
res.add(123);
res.add(456);
return res;
}
public List<String> getListOfStrings() {
ArrayList<String> res = new ArrayList<String>();
res.add("ABC");
res.add("DEF");
return res;
}
public List<Data> getListOfData() {
ArrayList<Data> res = new ArrayList<Data>();
res.add(new Data(123, "ABC"));
res.add(new Data(456, "DEF"));
return res;
}
public int add(int a, int b) {
return a + b;
}
public String concat(String a, String b) {
return a + b;
}
public Data modify(Data o) {
Data o2 = new Data(o.getIval() + 1, o.getSval() + "X");
return o2;
}
}
TestServlet.java:
package server;
import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.googlecode.jsonrpc4j.JsonRpcServer;
@WebServlet(urlPatterns={"/test"})
public class TestServlet extends HttpServlet {
private JsonRpcServer real = new JsonRpcServer(new Test());
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
real.handle(req, resp);
}
}
TestServer.java:
package server;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public class TestServer {
public static void main(String[] args) throws Exception {
Server server = new Server(8001);
ServletContextHandler ctx = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
ctx.setContextPath("/");
server.setHandler(ctx);
ServletHolder srvlet = ctx.addServlet(TestServlet.class, "/*");
server.start();
server.join();
}
}
Data.java:
package common;
public class Data {
private int ival;
private String sval;
public Data() {
this(0, "");
}
public Data(int ival, String sval) {
super();
this.ival = ival;
this.sval = sval;
}
public int getIval() {
return ival;
}
public void setIval(int ival) {
this.ival = ival;
}
public String getSval() {
return sval;
}
public void setSval(String sval) {
this.sval = sval;
}
@Override
public String toString() {
return String.format("(%d,%s)", ival, sval);
}
}
Test.java:
package server;
import java.util.ArrayList;
import java.util.List;
import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcMethod;
import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcParam;
import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcService;
import common.Data;
@JsonRpcService
public class Test {
@JsonRpcMethod
public int getInt() {
return 123;
}
@JsonRpcMethod
public String getString() {
return "ABC";
}
@JsonRpcMethod
public Data getData() {
return new Data(123, "ABC");
}
@JsonRpcMethod
public List<Integer> getListOfInts() {
ArrayList<Integer> res = new ArrayList<Integer>();
res.add(123);
res.add(456);
return res;
}
@JsonRpcMethod
public List<String> getListOfStrings() {
ArrayList<String> res = new ArrayList<String>();
res.add("ABC");
res.add("DEF");
return res;
}
@JsonRpcMethod
public List<Data> getListOfData() {
ArrayList<Data> res = new ArrayList<Data>();
res.add(new Data(123, "ABC"));
res.add(new Data(456, "DEF"));
return res;
}
@JsonRpcMethod
public int add(@JsonRpcParam("a")int a, @JsonRpcParam("b")int b) {
return a + b;
}
@JsonRpcMethod
public String concat(@JsonRpcParam("s1")String a, @JsonRpcParam("s2")String b) {
return a + b;
}
@JsonRpcMethod
public Data modify(@JsonRpcParam("o")Data o) {
Data o2 = new Data(o.getIval() + 1, o.getSval() + "X");
return o2;
}
}
TestServlet.java:
package server;
import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.github.arteam.simplejsonrpc.server.JsonRpcServer;
@WebServlet(urlPatterns={"/test"})
public class TestServlet extends HttpServlet {
private JsonRpcServer real = new JsonRpcServer();
private Test svc = new Test();
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
real.handle(req.getInputStream(), resp.getOutputStream(), svc);
}
}
TestServer.java:
package server;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public class TestServer {
public static void main(String[] args) throws Exception {
Server server = new Server(8002);
ServletContextHandler ctx = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
ctx.setContextPath("/");
server.setHandler(ctx);
ServletHolder srvlet = ctx.addServlet(TestServlet.class, "/*");
server.start();
server.join();
}
}
Data.groovy:
package common
class Data {
int ival
String sval
@Override
String toString() {
return String.format("(%d,%s)", ival, sval)
}
}
TestServer.groovy:
package server
import javax.servlet.annotation.*
import javax.servlet.http.*
import org.eclipse.jetty.server.*
import org.eclipse.jetty.servlet.*
import com.googlecode.jsonrpc4j.*
import common.*
class Test {
int getInt() {
return 123
}
String getString() {
return "ABC"
}
Data getData() {
return new Data(ival: 123, sval: "ABC")
}
List<Integer> getListOfInts() {
return [ 123, 456 ]
}
List<String> getListOfStrings() {
return [ "ABC", "DEF" ]
}
List<Data> getListOfData() {
return [ new Data(ival: 123, sval: "ABC"), new Data(ival: 456, sval: "DEF") ]
}
int add(int a, int b) {
return a + b
}
String concat(String a, String b) {
return a + b
}
Data modify(Data o) {
return new Data(ival: o.ival + 1, sval: o.sval + "X")
}
}
@WebServlet(urlPatterns=["/test"])
class TestServlet extends HttpServlet {
def real = new JsonRpcServer(new Test())
void doPost(HttpServletRequest req, HttpServletResponse resp) {
real.handle(req, resp)
}
}
server = new Server(8003)
ctx = new ServletContextHandler(ServletContextHandler.NO_SESSIONS)
ctx.setContextPath("/")
server.setHandler(ctx)
srvlet = ctx.addServlet(TestServlet.class, "/*")
server.start()
server.join()
Data.groovy:
package common
class Data {
int ival
String sval
@Override
String toString() {
return String.format("(%d,%s)", ival, sval)
}
}
TestServer.groovy:
package server
import javax.servlet.annotation.*
import javax.servlet.http.*
import org.eclipse.jetty.server.*
import org.eclipse.jetty.servlet.*
import com.github.arteam.simplejsonrpc.core.annotation.*;
import com.github.arteam.simplejsonrpc.server.*
import common.*
@JsonRpcService
class Test {
@JsonRpcMethod
int getInt() {
return 123
}
@JsonRpcMethod
String getString() {
return "ABC"
}
@JsonRpcMethod
Data getData() {
return new Data(ival: 123, sval: "ABC")
}
@JsonRpcMethod
List<Integer> getListOfInts() {
return [ 123, 456 ]
}
@JsonRpcMethod
List<String> getListOfStrings() {
return [ "ABC", "DEF" ]
}
@JsonRpcMethod
List<Data> getListOfData() {
return [ new Data(ival: 123, sval: "ABC"), new Data(ival: 456, sval: "DEF") ]
}
@JsonRpcMethod
int add(@JsonRpcParam("a")int a, @JsonRpcParam("b")int b) {
return a + b
}
@JsonRpcMethod
String concat(@JsonRpcParam("a")String a, @JsonRpcParam("b")String b) {
return a + b
}
@JsonRpcMethod
Data modify(@JsonRpcParam("o")Data o) {
return new Data(ival: o.ival + 1, sval: o.sval + "X")
}
}
@WebServlet(urlPatterns=["/test"])
public class TestServlet extends HttpServlet {
def real = new JsonRpcServer()
def svc = new Test()
void doPost(HttpServletRequest req, HttpServletResponse resp) {
real.handle(req.inputStream, resp.outputStream, svc)
}
}
server = new Server(8004)
ctx = new ServletContextHandler(ServletContextHandler.NO_SESSIONS)
ctx.setContextPath("/")
server.setHandler(ctx)
srvlet = ctx.addServlet(TestServlet.class, "/*")
server.start()
server.join()
server.py:
from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple
from jsonrpc import JSONRPCResponseManager, dispatcher
def getInt():
return 123
def getString():
return 'ABC'
def getData():
return { 'ival': 123, 'sval': 'ABC' }
def getListOfInts():
return [ 123, 456 ]
def getListOfStrings():
return [ 'ABC', 'DEF' ]
def getListOfData():
return [ { 'ival': 123, 'sval': 'ABC' }, { 'ival': 456, 'sval': 'DEF' } ]
def add(v1, v2):
return v1 + v2
def concat(s1, s2):
return s1 + s2
def modify(d):
return { 'ival': d['ival'] + 1, 'sval': d['sval'] + 'X' }
@Request.application
def application(request):
dispatcher['getInt'] = getInt
dispatcher['getString'] = getString
dispatcher['getData'] = getData
dispatcher['getListOfInts'] = getListOfInts
dispatcher['getListOfStrings'] = getListOfStrings
dispatcher['getListOfData'] = getListOfData
dispatcher['add'] = add
dispatcher['concat'] = concat
dispatcher['modify'] = modify
response = JSONRPCResponseManager.handle(request.data, dispatcher)
return Response(response.json, mimetype='application/json')
run_simple('localhost', 8005, application)
server.php:
<?php
require 'vendor/autoload.php';
class Test {
public function getInt() {
return 123;
}
public function getString() {
return 'ABC';
}
public function getData() {
return [ 'ival' => 123, 'sval' => 'ABC' ];
}
public function getListOfInts() {
return [ 123, 456 ];
}
public function getListOfStrings() {
return [ 'ABC', 'DEF' ];
}
public function getListOfData() {
return [ [ 'ival' => 123, 'sval' => 'ABC' ], [ 'ival' => 456, 'sval' => 'DEF' ] ];
}
public function add($v1, $v2) {
return $v1 + $v2;
}
public function concat($s1, $s2) {
return $s1 . $s2;
}
public function modify($d) {
return [ 'ival' => $d['ival'] + 1, 'sval' => $d['sval'] . 'X' ];
}
}
use JsonRPC\Server;
$server = new Server();
$server->getProcedureHandler()->withObject(new Test());
echo $server->execute();
?>
server.php:
<?php
require 'vendor/autoload.php';
class Test {
public function getInt() {
return 123;
}
public function getString() {
return 'ABC';
}
public function getData() {
return [ 'ival' => 123, 'sval' => 'ABC' ];
}
public function getListOfInts() {
return [ 123, 456 ];
}
public function getListOfStrings() {
return [ 'ABC', 'DEF' ];
}
public function getListOfData() {
return [ [ 'ival' => 123, 'sval' => 'ABC' ], [ 'ival' => 456, 'sval' => 'DEF' ] ];
}
public function add($v1, $v2) {
return $v1 + $v2;
}
public function concat($s1, $s2) {
return $s1 . $s2;
}
public function modify($d) {
return [ 'ival' => $d['ival'] + 1, 'sval' => $d['sval'] . 'X' ];
}
}
use PhpJsonRpc\Server\MapperInterface;
use PhpJsonRpc\Server;
class MyMapper implements MapperInterface {
public function getClassAndMethod(string $method): array {
return [ Test::class, $method ];
}
}
$server = new Server();
$server->setMapper(new MyMapper());
$server->addHandler(new Test());
echo $server->execute();
?>
Data.java:
package common;
public class Data {
private int ival;
private String sval;
public Data() {
this(0, "");
}
public Data(int ival, String sval) {
super();
this.ival = ival;
this.sval = sval;
}
public int getIval() {
return ival;
}
public void setIval(int ival) {
this.ival = ival;
}
public String getSval() {
return sval;
}
public void setSval(String sval) {
this.sval = sval;
}
@Override
public String toString() {
return String.format("(%d,%s)", ival, sval);
}
}
TestClient.java:
package client;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.List;
import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
import common.Data;
public class TestClient {
private static void test(String urlstr) throws Throwable {
System.out.println(urlstr);
JsonRpcHttpClient client = new JsonRpcHttpClient(new URL(urlstr));
int v = client.invoke("getInt", new Object[0], Integer.class);
System.out.println(v);
String s = client.invoke("getString", new Object[0], String.class);
System.out.println(s);
Data d = client.invoke("getData", new Object[0], Data.class);
System.out.println(d);
@SuppressWarnings("unchecked")
List<Integer> lstv = client.invoke("getListOfInts", new Object[0], List.class);
System.out.println(lstv);
@SuppressWarnings("unchecked")
List<String> lsts = client.invoke("getListOfStrings", new Object[0], List.class);
System.out.println(lsts);
Type lstdata = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[] { Data.class };
}
@Override
public Type getRawType() {
return List.class;
}
@Override
public Type getOwnerType() {
return null;
}
};
@SuppressWarnings("unchecked")
List<Data> lstd = (List<Data>)client.invoke("getListOfData", new Object[0], lstdata);
System.out.println(lstd);
int v1 = 123;
int v2 = 456;
int v3 = client.invoke("add", new Object[] { v1, v2 }, Integer.class);
System.out.println(v3);
String s1 = "ABC";
String s2 = "DEF";
String s3 = client.invoke("concat", new Object[] { s1, s2 }, String.class);
System.out.println(s3);
Data d1 = new Data(123, "ABC");
Data d2 = client.invoke("modify", new Object[] { d1 }, Data.class);
System.out.println(d2);
}
public static void main(String[] args) throws Throwable {
test("http://localhost:8001/test");
test("http://localhost:8002/test");
test("http://localhost:8003/test");
test("http://localhost:8004/test");
test("http://localhost:8005/test");
test("http://localhost:8006/server.php");
test("http://localhost:8007/server.php");
}
}
Data.java:
package common;
public class Data {
private int ival;
private String sval;
public Data() {
this(0, "");
}
public Data(int ival, String sval) {
super();
this.ival = ival;
this.sval = sval;
}
public int getIval() {
return ival;
}
public void setIval(int ival) {
this.ival = ival;
}
public String getSval() {
return sval;
}
public void setSval(String sval) {
this.sval = sval;
}
@Override
public String toString() {
return String.format("(%d,%s)", ival, sval);
}
}
TestClient.java:
package client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import com.github.arteam.simplejsonrpc.client.JsonRpcClient;
import com.github.arteam.simplejsonrpc.client.Transport;
import common.Data;
public class TestClient {
public static class MyTransport2 implements Transport {
private String urlstr;
public MyTransport2(String urlstr) {
this.urlstr = urlstr;
}
@Override
public String pass(String body) throws IOException {
HttpClient client = HttpClientBuilder.create().build();
HttpPost request = new HttpPost(urlstr);
request.setEntity(new StringEntity(body, ContentType.APPLICATION_JSON));
HttpResponse response = client.execute(request);
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line;
while((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
return sb.toString();
}
}
public static class MyTransport implements Transport {
private String urlstr;
public MyTransport(String urlstr) {
this.urlstr = urlstr;
}
@Override
public String pass(String body) throws IOException {
try {
HttpURLConnection con = (HttpURLConnection)(new URL(urlstr)).openConnection();
con.setRequestMethod("POST");
con.addRequestProperty("accept", "application/json-rpc");
con.addRequestProperty("content-type", "application/json-rpc");
con.setDoOutput(true);
con.getOutputStream().write(body.getBytes());
StringBuilder sb = new StringBuilder();
con.connect();
if(con.getResponseCode() / 100 == 2) {
InputStream is = con.getInputStream();
byte[] b = new byte[1000];
int n;
while((n = is.read(b)) >= 0) {
sb.append(new String(b, 0, n));
}
is.close();
} else {
System.out.printf("Error: %d %s\n", con.getResponseCode(), con.getResponseMessage());
}
con.disconnect();
return sb.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
private static void test(String urlstr) {
System.out.println(urlstr);
JsonRpcClient client = new JsonRpcClient(new MyTransport(urlstr));
int v = client.createRequest().method("getInt").id(1).returnAs(int.class).execute();
System.out.println(v);
String s = client.createRequest().method("getString").id(2).returnAs(String.class).execute();
System.out.println(s);
Data d = client.createRequest().method("getData").id(3).returnAs(Data.class).execute();
System.out.println(d);
@SuppressWarnings("unchecked")
List<Integer> lstv = client.createRequest().method("getListOfInts").id(4).returnAs(List.class).execute();
System.out.println(lstv);
@SuppressWarnings("unchecked")
List<String> lsts = client.createRequest().method("getListOfStrings").id(5).returnAs(List.class).execute();
System.out.println(lsts);
@SuppressWarnings("unchecked")
List<Data> lstd = client.createRequest().method("getListOfData").id(6).returnAs(List.class).execute();
System.out.println(lstd);
int v1 = 123;
int v2 = 456;
int v3 = client.createRequest().method("add").params(v1, v2).id(7).returnAs(int.class).execute();
System.out.println(v3);
String s1 = "ABC";
String s2 = "DEF";
String s3 = client.createRequest().method("concat").params(s1, s2).id(8).returnAs(String.class).execute();
System.out.println(s3);
Data d1 = new Data(123, "ABC");
Data d2 = client.createRequest().method("modify").params(d1).id(9).returnAs(Data.class).execute();
System.out.println(d2);
}
public static void main(String[] args) {
test("http://localhost:8001/test");
test("http://localhost:8002/test");
test("http://localhost:8003/test");
test("http://localhost:8004/test");
test("http://localhost:8005/test");
test("http://localhost:8006/server.php");
test("http://localhost:8007/server.php");
}
}
Data.groovy:
package common
class Data {
int ival
String sval
@Override
String toString() {
return String.format("(%d,%s)", ival, sval)
}
}
TestClient.groovy:
package client
import java.lang.reflect.*
import com.googlecode.jsonrpc4j.*
import common.*
def test(String urlstr) {
println(urlstr)
client = new JsonRpcHttpClient(new URL(urlstr))
v = client.invoke("getInt", new Object[0], Integer.class)
println(v)
s = client.invoke("getString", new Object[0], String.class)
println(s)
d = client.invoke("getData", new Object[0], Data.class)
println(d)
lstv = client.invoke("getListOfInts", new Object[0], List.class)
println(lstv)
lsts = client.invoke("getListOfStrings", new Object[0], List.class)
println(lsts)
lstdata = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return [ Data.class ]
}
@Override
public Type getRawType() {
return List.class
}
@Override
public Type getOwnerType() {
return null
}
}
lstd = (List<Data>)client.invoke("getListOfData", new Object[0], lstdata)
println(lstd)
v1 = 123
v2 = 456
v3 = client.invoke("add", [ v1, v2 ], Integer.class)
println(v3)
s1 = "ABC"
s2 = "DEF"
s3 = client.invoke("concat", [ s1, s2 ], String.class)
println(s3)
d1 = new Data(ival: 123, sval: "ABC")
d2 = client.invoke("modify", [ d1 ], Data.class)
println(d2)
}
test("http://localhost:8001/test")
test("http://localhost:8002/test")
test("http://localhost:8003/test")
test("http://localhost:8004/test")
test("http://localhost:8005/test")
test("http://localhost:8006/server.php")
test("http://localhost:8007/server.php")
Data.groovy:
package common
class Data {
int ival
String sval
@Override
String toString() {
return String.format("(%d,%s)", ival, sval)
}
}
TestClient.groovy:
package client
import java.lang.reflect.*
import org.apache.http.*
import org.apache.http.client.*
import org.apache.http.client.methods.*
import org.apache.http.entity.*
import org.apache.http.impl.client.*
import com.github.arteam.simplejsonrpc.client.*
import common.*
class MyTransport2 implements Transport {
String urlstr
@Override
String pass(String body) {
def client = HttpClientBuilder.create().build()
def request = new HttpPost(urlstr)
request.setEntity(new StringEntity(body, ContentType.APPLICATION_JSON))
def response = client.execute(request)
def sb = new StringBuilder()
def br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))
def line
while((line = br.readLine()) != null) {
sb.append(line)
}
br.close()
return sb.toString()
}
}
class MyTransport implements Transport {
String urlstr
@Override
String pass(String body) {
def con = (HttpURLConnection)(new URL(urlstr)).openConnection()
con.setRequestMethod("POST")
con.addRequestProperty("accept", "application/json-rpc")
con.addRequestProperty("content-type", "application/json-rpc")
con.setDoOutput(true)
con.getOutputStream().write(body.getBytes())
def sb = new StringBuilder()
con.connect()
if(con.getResponseCode() / 100 == 2) {
def is = con.getInputStream()
def b = new byte[1000]
def n
while((n = is.read(b)) >= 0) {
sb.append(new String(b, 0, n))
}
is.close()
} else {
printf("Error: %d %s\n", con.rResponseCode, con.responseMessage)
}
con.disconnect()
return sb.toString()
}
}
def test(String urlstr) {
println(urlstr)
client = new JsonRpcClient(new MyTransport(urlstr: urlstr))
v = client.createRequest().method("getInt").id(1).returnAs(int.class).execute()
println(v)
s = client.createRequest().method("getString").id(2).returnAs(String.class).execute()
println(s)
d = client.createRequest().method("getData").id(3).returnAs(Data.class).execute()
println(d)
lstv = client.createRequest().method("getListOfInts").id(4).returnAs(List.class).execute()
println(lstv)
lsts = client.createRequest().method("getListOfStrings").id(5).returnAs(List.class).execute()
println(lsts)
lstd = client.createRequest().method("getListOfData").id(6).returnAs(List.class).execute()
println(lstd)
v1 = 123
v2 = 456
v3 = client.createRequest().method("add").params(v1, v2).id(7).returnAs(int.class).execute()
println(v3)
s1 = "ABC"
s2 = "DEF"
s3 = client.createRequest().method("concat").params(s1, s2).id(8).returnAs(String.class).execute()
println(s3)
d1 = new Data(ival: 123, sval: "ABC")
d2 = client.createRequest().method("modify").params(d1).id(9).returnAs(Data.class).execute()
println(d2)
}
test("http://localhost:8001/test")
test("http://localhost:8002/test")
test("http://localhost:8003/test")
test("http://localhost:8004/test")
test("http://localhost:8005/test")
test("http://localhost:8006/server.php")
test("http://localhost:8007/server.php")
client.py:
import requests
import json
def invoke(urlstr, method, params):
req = { 'method': method, 'params': params, 'jsonrpc': '2.0', 'id': 0, }
return requests.post(urlstr, json=req).json()['result']
def test(urlstr):
print(urlstr)
v = invoke(urlstr, 'getInt', [])
print(v)
s = invoke(urlstr, 'getString', [])
print(s)
d = invoke(urlstr, 'getData', [])
print(d)
lstv = invoke(urlstr, 'getListOfInts', [])
print(lstv)
lsts = invoke(urlstr, 'getListOfStrings', [])
print(lsts)
lstd = invoke(urlstr, 'getListOfData', [])
print(lstd)
v1 = 123
v2 = 456
v3 = invoke(urlstr, 'add', [ v1, v2 ])
print(v3)
s1 = 'ABC'
s2 = 'DEF'
s3 = invoke(urlstr, 'concat', [ s1, s2 ])
print(s3)
d1 = { 'ival': 123, 'sval': 'ABC' }
d2 = invoke(urlstr, 'modify', [ d1 ])
print(d2)
test('http://localhost:8001/test')
test('http://localhost:8002/test')
test('http://localhost:8003/test')
test('http://localhost:8004/test')
test('http://localhost:8005/test')
test('http://localhost:8006/server.php')
test('http://localhost:8007/server.php')
client.php:
<?php
require 'vendor/autoload.php';
use JsonRPC\Client;
function data2string($d) {
return "({$d['ival']},{$d['sval']})";
}
function test($urlstr) {
echo "$urlstr\r\n";
$client = new Client($urlstr);
$v = $client->execute('getInt', []);
echo "$v\r\n";
$s = $client->execute('getString', []);
echo "$s\r\n";
$d = $client->execute('getData', []);
$temp = data2string($d);
echo "$temp\r\n";
$lstv = $client->execute('getListOfInts', []);
$temp = '[' . implode(',',$lstv) . ']';
echo "$temp\r\n";
$lsts = $client->execute('getListOfStrings', []);
$temp = '[' . implode(',',$lsts) . ']';
echo "$temp\r\n";
$lstd = $client->execute('getListOfData', []);
$temp = '[' . implode(',',array_map(function($d) { return data2string($d); }, $lstd)) . ']';
echo "$temp\r\n";
$v1 = 123;
$v2 = 456;
$v3 = $client->execute('add', [$v1, $v2]);
echo "$v3\r\n";
$s1 = 'ABC';
$s2 = 'DEF';
$s3 = $client->execute('concat', [$s1, $s2]);
echo "$s3\r\n";
$d1 = [ 'ival' => 123, 'sval' => 'ABC' ];
$d2 = $client->execute('modify', [ $d1 ]);
$temp = data2string($d2);
echo "$temp\r\n";
}
test('http://localhost:8001/test');
test('http://localhost:8002/test');
test('http://localhost:8003/test');
test('http://localhost:8004/test');
test('http://localhost:8005/test');
test('http://localhost:8006/server.php');
test('http://localhost:8007/server.php');
?>
client.php:
<?php
require 'vendor/autoload.php';
use PhpJsonRpc\Client;
function data2string($d) {
return "({$d['ival']},{$d['sval']})";
}
function test($urlstr) {
echo "$urlstr\r\n";
$client = new Client($urlstr);
$v = $client->call('getInt', []);
echo "$v\r\n";
$s = $client->call('getString', []);
echo "$s\r\n";
$d = $client->call('getData', []);
$temp = data2string($d);
echo "$temp\r\n";
$lstv = $client->call('getListOfInts', []);
$temp = '[' . implode(',',$lstv) . ']';
echo "$temp\r\n";
$lsts = $client->call('getListOfStrings', []);
$temp = '[' . implode(',',$lsts) . ']';
echo "$temp\r\n";
$lstd = $client->call('getListOfData', []);
$temp = '[' . implode(',',array_map(function($d) { return data2string($d); }, $lstd)) . ']';
echo "$temp\r\n";
$v1 = 123;
$v2 = 456;
$v3 = $client->call('add', [$v1, $v2]);
echo "$v3\r\n";
$s1 = 'ABC';
$s2 = 'DEF';
$s3 = $client->call('concat', [$s1, $s2]);
echo "$s3\r\n";
$d1 = [ 'ival' => 123, 'sval' => 'ABC' ];
$d2 = $client->call('modify', [ $d1 ]);
$temp = data2string($d2);
echo "$temp\r\n";
}
test('http://localhost:8001/test');
test('http://localhost:8002/test');
test('http://localhost:8003/test');
test('http://localhost:8004/test');
test('http://localhost:8005/test');
test('http://localhost:8006/server.php');
test('http://localhost:8007/server.php');
?>
It works and it has a very good level of compatibility.
Version | Date | Description |
---|---|---|
1.0 | May 8th 2024 | Initial version |
See list of all articles here
Please send comments to Arne Vajhøj