项目作者: windoze

项目描述 :
A minimalist RPC framework for Vertx, supports both Kotlin and Java.
高级语言: Kotlin
项目地址: git://github.com/windoze/vertx-kotlin-rpc.git
创建时间: 2019-01-26T20:23:36Z
项目社区:https://github.com/windoze/vertx-kotlin-rpc

开源协议:Do What The F*ck You Want To Public License

下载


Vertx Kotlin RPC over EventBus

CircleCI
Download

A minimalist RPC framework for Vertx/Kotlin.

Getting Start

The artifact is hosted on jCenter, follow the instruction
to configure your building tool.

Maven:

  1. <dependency>
  2. <groupId>codes.unwritten</groupId>
  3. <artifactId>vertx-kotlin-rpc</artifactId>
  4. <version>0.6</version>
  5. <type>pom</type>
  6. </dependency>

Gradle:

  1. compile 'codes.unwritten:vertx-kotlin-rpc:0.6'

To create a RPC service

  1. import codes.unwritten.vertx.kotlin.rpc.RpcServerVerticle
  2. //...
  3. // Needs not to implement the service interface as long as the method signature matches
  4. class HelloSvcImpl {
  5. // Method can be suspend or not
  6. fun hello(name: String): String = "Hello, $name!"
  7. }
  8. // ...
  9. vertx.deployVerticle(RpcServerVerticle("test-channel")
  10. .register("hello", HelloSvcImpl()))

To call a RPC service

  1. import codes.unwritten.vertx.kotlin.rpc.getServiceProxy
  2. // ...
  3. interface HelloSvc {
  4. // Must be suspend, otherwise exceptions will be thrown on invocation.
  5. suspend fun hello(world: String): String
  6. }
  7. // ...
  8. // Get the service proxy object
  9. val svc: HelloSvc = getServiceProxy(vertx, "test-channel", "hello")
  10. // Call the service
  11. assertEqual("Hello, world!", svc.hello("world"))

To create a HTTP RPC service

  1. import io.vertx.core.Vertx
  2. import io.vertx.ext.web.Router
  3. import io.vertx.ext.web.handler.BodyHandler
  4. import io.vertx.kotlin.coroutines.CoroutineVerticle
  5. import codes.unwritten.vertx.kotlin.rpc.HttpRpcHandler
  6. // ...
  7. class SomeVerticle: CoroutineVerticle() {
  8. override suspend fun start() {
  9. // ...
  10. val router = Router.router(vertx)
  11. // Make sure body handler is enabled
  12. router.route().handler(BodyHandler.create())
  13. // Only POST method is supported
  14. router.post("/some-path").handler(HttpRpcHandler().register("hello", object {
  15. fun hello(name: String): String = "Hello, $name!"
  16. }))
  17. // Start HTTP server, etc.
  18. // ...
  19. }
  20. }

To call a HTTP RPC service

  1. import codes.unwritten.vertx.kotlin.rpc.getHttpServiceProxy
  2. interface HelloSvc {
  3. // Must be suspend, otherwise exceptions will be thrown on invocation.
  4. suspend fun hello(name: String): String
  5. }
  6. // ...
  7. // Get the service proxy object from a URL
  8. val svc = getHttpServiceProxy<HelloSvc>(vertx, "http://127.0.0.1:8080/some-path", "hello")
  9. // Call the service
  10. assertEqual("Hello, world!", svc.hello("world"))

To call a JSON RPC service

  1. import codes.unwritten.vertx.kotlin.rpc.HttpRequest
  2. import codes.unwritten.vertx.kotlin.rpc.JsonRpcException
  3. import codes.unwritten.vertx.kotlin.rpc.QueryParam
  4. import codes.unwritten.vertx.kotlin.rpc.getHttpJsonRpcServiceProxy
  5. interface DemoSvc {
  6. // Must be suspend, otherwise exceptions will be thrown on invocation.
  7. // HttpRequest annotation is used to customize mapping
  8. // Default method is POST and default path is the method name
  9. @HttpRequest(method = HttpMethod.GET, path = "comments")
  10. suspend fun getComments(postId: Int): List<Comment>
  11. }
  12. // ...
  13. // Get the service proxy object from a URL
  14. val svc = getHttpJsonRpcServiceProxy<PostmanSvc>(vertx, "https://postman-echo.com/")
  15. // Call the service
  16. context.assertTrue(svc.getComments(1).isNotEmpty())

Another example:

  1. interface PostmanSvc {
  2. @HttpRequest(method = HttpMethod.GET)
  3. // QueryParam annotation indicates it is a query parameter instead of part of request body,
  4. // Also param name can be customized
  5. suspend fun get(@QueryParam foo1: String, @QueryParam("foo2") arg2: String): PostmanResponse
  6. }

To create a RPC service in Java

  1. import codes.unwritten.vertx.kotlin.rpc.RpcServerVerticle;
  2. // ...
  3. // Methods in the implementation class shall not return Future<T>, return T directly.
  4. public class HelloSvcImpl {
  5. public String hello(String name) {
  6. return "Hello, " + name + "!";
  7. }
  8. }
  9. // ...
  10. vertx.deployVerticle((new RpcServerVerticle("test-channel"))
  11. .register("hello", new HelloSvcImpl()));

To call a RPC service from Java

Java doesn’t have suspend functions, make sure every function in the service
interface returns Future<T> instead of T.

  1. import io.vertx.core.Future;
  2. import static codes.unwritten.vertx.kotlin.rpc.ServiceProxyFactory.getAsyncServiceProxy;
  3. // ...
  4. // Method must return Future<T> instead of T
  5. interface AsyncHelloSvc {
  6. Future<String> hello(String world);
  7. }
  8. // ...
  9. AsyncHelloSvc svc = getAsyncServiceProxy(vertx, "test-channel", "hello", AsyncHelloSvc.class);
  10. svc.hello("world").setHandler(ar -> {
  11. if (ar.succeeded()) {
  12. assertEquals("Hello, world!", ar.result());
  13. } else {
  14. // Error handling
  15. }
  16. });

To create a HTTP RPC service in Java

TODO:

To call a HTTP RPC service from Java

Java doesn’t have suspend functions, make sure every function in the service
interface returns Future<T> instead of T.

  1. import io.vertx.core.Future;
  2. import static codes.unwritten.vertx.kotlin.rpc.AsyncServiceProxyFactory.getAsyncHttpServiceProxy;
  3. // ...
  4. // Method must return Future<T> instead of T
  5. interface AsyncHelloSvc {
  6. Future<String> hello(String world);
  7. }
  8. // ...
  9. AsyncHelloSvc svc = getAsyncHttpServiceProxy(vertx, "http://127.0.0.1:8080/some-path", "hello", AsyncHelloSvc.class);
  10. svc.hello("world").setHandler(ar -> {
  11. if (ar.succeeded()) {
  12. assertEquals("Hello, world!", ar.result());
  13. } else {
  14. // Error handling
  15. }
  16. });

Notes

  • JSON RPC use Jackson for serialization/deserialization.
  • All other arguments and returned values are serialized/deserialized by Kryo,
    refer to its documentations for more details.
  • Java Reflection API cannot retrieve function parameter names, which is required to build JSON object, so Java version of JSON RPC is unavailable.
    Tell me if you have any ideas.

TODO

  • Function overloading support.
  • Call tracing and debugging.
  • JSON RPC needs to support path parameters, which is used by many REST API.