From 0e6689d53be640b58d5e768791933ffdadf6ad41 Mon Sep 17 00:00:00 2001 From: Qing Wang Date: Fri, 23 Oct 2020 16:39:10 +0800 Subject: [PATCH] Support Java pojo arguments and return value. --- examples/CMakeLists.txt | 16 ++-- java/pom.xml | 5 ++ .../main/java/org/restrpc/client/Codec.java | 20 +++-- .../examples/PassPojoAsArgumentExample.java | 81 +++++++++++++++++++ 4 files changed, 112 insertions(+), 10 deletions(-) create mode 100644 java/src/main/java/org/restrpc/examples/PassPojoAsArgumentExample.java diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 6f64c49..def60d2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.1) project(example) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -std=c++11") +set(ASIO_STANDALONE 1) SET(ENABLE_SSL OFF) @@ -10,12 +11,17 @@ if (ENABLE_SSL) message(STATUS "Use SSL") endif() -find_package(Boost COMPONENTS system filesystem REQUIRED) +find_package(JNI REQUIRED) +#find_package(Boost COMPONENTS system filesystem REQUIRED) include_directories( - "/usr/local/include" - "../../include" - "../../third/msgpack/include" -) + # "/usr/local/include" + "../include" + "../jni" + ${JNI_INCLUDE_DIRS} + # "/usr/local/opt/openjdk/include/" + "/Users/qingwang/workspace/opensource/rest_rpc/third/msgpack/include") +INCLUDE_DIRECTORIES(SYSTEM "/Users/qingwang/workspace/opensource/dousi/build/external/boost/src/boost_ep") +INCLUDE_DIRECTORIES(SYSTEM "/Users/qingwang/workspace/opensource/rest_rpc/third/msgpack/include") add_executable(basic_server server/main.cpp) add_executable(basic_client client/main.cpp) diff --git a/java/pom.xml b/java/pom.xml index 7a31d99..2b2e232 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -34,6 +34,11 @@ msgpack-core 0.8.21 + + org.msgpack + jackson-dataformat-msgpack + 0.8.21 + diff --git a/java/src/main/java/org/restrpc/client/Codec.java b/java/src/main/java/org/restrpc/client/Codec.java index 1935441..22f246e 100644 --- a/java/src/main/java/org/restrpc/client/Codec.java +++ b/java/src/main/java/org/restrpc/client/Codec.java @@ -1,11 +1,14 @@ package org.restrpc.client; +import com.fasterxml.jackson.databind.ObjectMapper; import org.msgpack.core.MessageBufferPacker; import org.msgpack.core.MessagePack; import org.msgpack.core.MessageUnpacker; - -import java.awt.print.PrinterGraphics; +import org.msgpack.jackson.dataformat.JsonArrayFormat; +import org.msgpack.jackson.dataformat.MessagePackFactory; import java.io.IOException; +import java.nio.Buffer; +import java.nio.ByteBuffer; public class Codec { @@ -39,13 +42,15 @@ public byte[] encode(String funcName, Object[] args) throws IOException { messagePacker.packString((String) arg); break; default: - throw new RuntimeException("Unknown type: " + argTypeName); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.setAnnotationIntrospector(new JsonArrayFormat()); + messagePacker.writePayload(objectMapper.writeValueAsBytes(arg)); } } return messagePacker.toByteArray(); } - public Object decodeReturnValue(Class returnClz, byte[] encodedBytes) throws IOException { + public Object decodeReturnValue(Class returnClz, byte[] encodedBytes) throws IOException { if (returnClz == null) { throw new RuntimeException("Internal bug."); } @@ -66,7 +71,12 @@ public Object decodeReturnValue(Class returnClz, byte[] encodedBytes) throws IOE return messageUnpacker.unpackLong(); } else if (String.class.equals(returnClz)) { return messageUnpacker.unpackString(); + } else { + final int remainder = (int) (encodedBytes.length - messageUnpacker.getTotalReadBytes()); + byte[] payload = messageUnpacker.readPayload(remainder); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.setAnnotationIntrospector(new JsonArrayFormat()); + return objectMapper.readValue(payload, returnClz); } - throw new RuntimeException("Unknown type: " + returnClz); } } diff --git a/java/src/main/java/org/restrpc/examples/PassPojoAsArgumentExample.java b/java/src/main/java/org/restrpc/examples/PassPojoAsArgumentExample.java new file mode 100644 index 0000000..eca5846 --- /dev/null +++ b/java/src/main/java/org/restrpc/examples/PassPojoAsArgumentExample.java @@ -0,0 +1,81 @@ +package org.restrpc.examples; + +import org.restrpc.client.NativeRpcClient; +import org.restrpc.client.RpcClient; + +import java.io.Serializable; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +class Person implements Serializable { + private static final long serialVersionUID = 5989656920203532884L; + private int id; + private String name; + private int age; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public String toString() { + return "Person {" + + "id=" + id + + ", name='" + name + '\'' + + ", age=" + age + + '}'; + } +} + +public class PassPojoAsArgumentExample { + + public static void main(String[] args) throws InterruptedException, ExecutionException { + /** + * An example shows how we use this Java client to connect to + * the C++ RPC server and invoke the C++ RPC methods. + * + * First of all, we should run a C++ rpc server. In this example, + * we first run the `basic_server` which is written here: + * https://github.com/qicosmos/rest_rpc/blob/master/examples/server/main.cpp + */ + RpcClient rpcClient = new NativeRpcClient(); + rpcClient.connect("127.0.0.1:9000"); + + { + Person p = new Person(); + p.setId(10001); + p.setName("Jack"); + p.setAge(22); + CompletableFuture future = rpcClient.asyncFunc("get_person_name").invoke(String.class, p); + System.out.println("The result of get_person_name() is " + future.get()); + } + + { + CompletableFuture future = rpcClient.asyncFunc("get_person").invoke(Person.class); + System.out.println("The result of get_person() is " + future.get()); + } + + rpcClient.close(); + } +}