A Clojure library designed to provide hassle-free, ready to go gRPC experience without ton of preparations and Java code...
...or just a bunch of ~~macros~~ functions and macros.
netty
, what Java class to import where, etc.kebab-case
to camelCase
conversion in some places (weird identifiers might cause
problems here and there)spec
). But this is just a bunch of macros developed on real project, so I had no time to build
full testing workflow.clj-grpc
currently implements only system
(component
) behavior.lein-protoc
project.clj
add clj-grpc
to dependencies:[clj-grpc "0.1.0"]
lein-protoc
plugin. Please note, that until original protoc
is fixed, for Clojure 1.9 you have to use
awebneck
fork. For more details, see https://github.com/LiaisonTechnologies/lein-protoc/pull/16:plugins [...
[org.clojars.awebneck/lein-protoc "0.5.5"]
...
]
;; decide which version of protoc and grpc-java to use
:protoc-version "3.10.0"
:protoc-grpc {:version "1.25.0"}
:protoc-source-paths ["src/proto"] ;; where to look for `.proto` files
:proto-target-path "target/generated-sources/protobuf" ;; where should protoc put generated sources
:java-source-paths [... "target/generated-sources/protobuf"] ;; point java compiler to newly generated sources
example.proto
file in src/protoc
:syntax = "proto3";
option java_package = "example.grpc_api";
option java_outer_classname = "ExampleProto";
package example;
message GetAllExamplesParams {
}
message GetExampleParams {
string example_id = 1;
}
service Example {
rpc GetExample (GetExampleParams) returns (Example) {
}
rpc GetAllExamples (GetAllExamplesParams) returns (stream Example) {
}
}
message Example {
string example_id = 1;
string name = 2;
string description = 3;
}
grpc
service:(ns example.grpc-api.core
;; require macros from `clj-grpc.server` namespace
(:require [clj-grpc.server :refer [implement-grpc-service defrpc on-next]]))
;; describe service which will be implemented in this namespace.
;; `:java-package` and `:java-outer-classname` has to be consistent with `proto` file
;;
;; NOTE: it might be necessary to restart Clojure process after this is defined so all the classes will be compiled
(implement-grpc-service Client
:java-package "data_engine.grpc.client"
:java-outer-classname "ClientProto" )
;; define RPC method `getExample` returning only one example
(defrpc getExample [_this req res]
;;
;; do some code here
;;
;; Finally call `on-next` which builds message of type `Example`, initializes it with provided map
;; handling kebab-case to camelCase conversion and sends it through StreamObserver `res`
(on-next "Example" res
{:name "Name"
:description "Description"
:example-id (:example-id req)}))
;; Another example of method, this time `server-streaming`.
;; Implemenation has nothing specific about it, just call `on-next` multiple times
(defrpc getAllExamples [_this _req res]
(dotimes [x 10]
(on-next "Example" res
{:name (str "Name " x)
:description (str "Description" x)
:example-id (str "example-" x)})))
danielsz/system
, add GrpcServer
component to your system definition:;; Require `new-grpc-server`
(ns example.systems
"System definition"
(:require [com.stuartsierra.component :as component]
[system.core :refer [defsystem]]
[clj-grpc.server :refer [new-grpc-server]]
...
)
;; Add `GrpcServer` to system definition. Specify port on which to listen. It will automatically server
;; all services defined with `IMPLEMENT-GRPC-SERVICE`
(defsystem dev-system
[...
:my-grpc-server (new-grpc-server :port 5000)
...
]
(start-grpc (make-grpc-server :port <port-number>))
from clj-grpc.server
and you should be up and running.Start you system with system's (start)
and you should have your service running!
To avoid warnings and unexpected behaviour when using provided macros, configure their IDE resolution as follows:
implement-grpc-service
- resolve as def
defgrpc
- resolve as defn
Behavior won't be perfect, but good enough - for example warnings about unused functions might still occur.
See https://cursive-ide.com/userguide/macros.html#customising-symbol-resolution for more info.
Copyright © 2019 Slawomir Gonet slawek@otwiera.cz
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close