# vertx-kotlin-rpc
**Repository Path**: windoze/vertx-kotlin-rpc
## Basic Information
- **Project Name**: vertx-kotlin-rpc
- **Description**: 用Kotlin实现的极简的Vertx RPC框架,同时支持Java和Kotlin。
- **Primary Language**: Kotlin
- **License**: WTFPL
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 30
- **Forks**: 7
- **Created**: 2019-01-27
- **Last Updated**: 2024-02-22
## Categories & Tags
**Categories**: rpc
**Tags**: None
## README
Vertx Kotlin RPC over EventBus
==============================
[](https://circleci.com/gh/windoze/vertx-kotlin-rpc)
[ ](https://bintray.com/windoze/maven/vertx-kotlin-rpc/_latestVersion)
A minimalist RPC framework for Vertx/Kotlin.
Getting Start
-------------
The artifact is hosted on jCenter, follow the [instruction](https://bintray.com/beta/#/bintray/jcenter)
to configure your building tool.
Maven:
```xml
codes.unwritten
vertx-kotlin-rpc
0.6
pom
```
Gradle:
```Groovy
compile 'codes.unwritten:vertx-kotlin-rpc:0.6'
```
To create a RPC service
-----------------------
```kotlin
import codes.unwritten.vertx.kotlin.rpc.RpcServerVerticle
//...
// Needs not to implement the service interface as long as the method signature matches
class HelloSvcImpl {
// Method can be suspend or not
fun hello(name: String): String = "Hello, $name!"
}
// ...
vertx.deployVerticle(RpcServerVerticle("test-channel")
.register("hello", HelloSvcImpl()))
```
To call a RPC service
---------------------
```kotlin
import codes.unwritten.vertx.kotlin.rpc.getServiceProxy
// ...
interface HelloSvc {
// Must be suspend, otherwise exceptions will be thrown on invocation.
suspend fun hello(world: String): String
}
// ...
// Get the service proxy object
val svc: HelloSvc = getServiceProxy(vertx, "test-channel", "hello")
// Call the service
assertEqual("Hello, world!", svc.hello("world"))
```
To create a HTTP RPC service
----------------------------
```kotlin
import io.vertx.core.Vertx
import io.vertx.ext.web.Router
import io.vertx.ext.web.handler.BodyHandler
import io.vertx.kotlin.coroutines.CoroutineVerticle
import codes.unwritten.vertx.kotlin.rpc.HttpRpcHandler
// ...
class SomeVerticle: CoroutineVerticle() {
override suspend fun start() {
// ...
val router = Router.router(vertx)
// Make sure body handler is enabled
router.route().handler(BodyHandler.create())
// Only POST method is supported
router.post("/some-path").handler(HttpRpcHandler().register("hello", object {
fun hello(name: String): String = "Hello, $name!"
}))
// Start HTTP server, etc.
// ...
}
}
```
To call a HTTP RPC service
--------------------------
```kotlin
import codes.unwritten.vertx.kotlin.rpc.getHttpServiceProxy
interface HelloSvc {
// Must be suspend, otherwise exceptions will be thrown on invocation.
suspend fun hello(name: String): String
}
// ...
// Get the service proxy object from a URL
val svc = getHttpServiceProxy(vertx, "http://127.0.0.1:8080/some-path", "hello")
// Call the service
assertEqual("Hello, world!", svc.hello("world"))
```
To call a JSON RPC service
--------------------------
```kotlin
import codes.unwritten.vertx.kotlin.rpc.HttpRequest
import codes.unwritten.vertx.kotlin.rpc.JsonRpcException
import codes.unwritten.vertx.kotlin.rpc.QueryParam
import codes.unwritten.vertx.kotlin.rpc.getHttpJsonRpcServiceProxy
interface DemoSvc {
// Must be suspend, otherwise exceptions will be thrown on invocation.
// HttpRequest annotation is used to customize mapping
// Default method is POST and default path is the method name
@HttpRequest(method = HttpMethod.GET, path = "comments")
suspend fun getComments(postId: Int): List
}
// ...
// Get the service proxy object from a URL
val svc = getHttpJsonRpcServiceProxy(vertx, "https://postman-echo.com/")
// Call the service
context.assertTrue(svc.getComments(1).isNotEmpty())
```
Another example:
```
interface PostmanSvc {
@HttpRequest(method = HttpMethod.GET)
// QueryParam annotation indicates it is a query parameter instead of part of request body,
// Also param name can be customized
suspend fun get(@QueryParam foo1: String, @QueryParam("foo2") arg2: String): PostmanResponse
}
```
To create a RPC service in Java
-------------------------------
```java
import codes.unwritten.vertx.kotlin.rpc.RpcServerVerticle;
// ...
// Methods in the implementation class shall not return Future, return T directly.
public class HelloSvcImpl {
public String hello(String name) {
return "Hello, " + name + "!";
}
}
// ...
vertx.deployVerticle((new RpcServerVerticle("test-channel"))
.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` instead of `T`.
```Java
import io.vertx.core.Future;
import static codes.unwritten.vertx.kotlin.rpc.ServiceProxyFactory.getAsyncServiceProxy;
// ...
// Method must return Future instead of T
interface AsyncHelloSvc {
Future hello(String world);
}
// ...
AsyncHelloSvc svc = getAsyncServiceProxy(vertx, "test-channel", "hello", AsyncHelloSvc.class);
svc.hello("world").setHandler(ar -> {
if (ar.succeeded()) {
assertEquals("Hello, world!", ar.result());
} else {
// Error handling
}
});
```
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` instead of `T`.
```Java
import io.vertx.core.Future;
import static codes.unwritten.vertx.kotlin.rpc.AsyncServiceProxyFactory.getAsyncHttpServiceProxy;
// ...
// Method must return Future instead of T
interface AsyncHelloSvc {
Future hello(String world);
}
// ...
AsyncHelloSvc svc = getAsyncHttpServiceProxy(vertx, "http://127.0.0.1:8080/some-path", "hello", AsyncHelloSvc.class);
svc.hello("world").setHandler(ar -> {
if (ar.succeeded()) {
assertEquals("Hello, world!", ar.result());
} else {
// Error handling
}
});
```
Notes
-----
* JSON RPC use [Jackson](https://github.com/FasterXML/jackson) for serialization/deserialization.
* All other arguments and returned values are serialized/deserialized by [Kryo](https://github.com/EsotericSoftware/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.