-
Notifications
You must be signed in to change notification settings - Fork 927
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide a way to encode and decode Protobuf in annotated services #3124
Conversation
Motivation: Protocol Buffers is an universal serialization protocol. The usage is not limit to gRPC. It could be used an HTTP payload for REST API. It is also useful when building an HTTP proxy server in front of a gRPC server. Modifications: - Add ProtobufRequestConverterFunction that decodes Protocol Buffers or JSON body into Protobuf Message type - Add ProtobufResponseConverterFunction that encodes Protobuf Message(s) into Protocol Buffers or JSON body - These converters are applied only when the content type is: - `application/protobuf` - `application/json; charset=utf-8` - Or subtype contains `protobuf` because there is no standard for protobuf content type. See https://stackoverflow.com/questions/30505408/what-is-the-correct-protobuf-content-type Result: - You can now encode and decode Protobuf Message using annotated service automatically. - Closes line#3088
/cc @dpsoft |
Codecov Report
@@ Coverage Diff @@
## master #3124 +/- ##
============================================
+ Coverage 73.92% 73.95% +0.02%
- Complexity 12417 12587 +170
============================================
Files 1080 1098 +18
Lines 47380 47955 +575
Branches 5999 6094 +95
============================================
+ Hits 35027 35463 +436
- Misses 9269 9365 +96
- Partials 3084 3127 +43
Continue to review full report at Codecov.
|
grpc/src/main/java/com/linecorp/armeria/server/grpc/ProtobufRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
324c2d6
to
07fca0c
Compare
core/src/main/java/com/linecorp/armeria/internal/server/annotation/AnnotatedValueResolver.java
Outdated
Show resolved
Hide resolved
* However a <a href="https://tools.ietf.org/html/rfc7159#section-5">JSON array</a> body | ||
* could be converted into a {@link Collection} type. e.g, {@code List<Message>} and {@code Set<Message>}. | ||
*/ | ||
public final class ProtobufRequestConverterFunction implements RequestConverterFunction { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we make a separate module so that the user doesn't have to bring gRPC dependencies to use this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought this feature would be interesting to some users who want to gRPC service and client already. Do we need armeria-protobuf
? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure. 🤣 @anuraaga Do you have any suggestions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for late reply - it does seem strange to have this in gRPC package since it seems to have nothing to do with gRPC. Perhaps core with compileOnly dependency on protobuf so it's next to the other annotated service functionality? not sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, the code is too small to create a seperate module. Let me move this code to core and add @UnstableApi
in case we need armeria-protobuf
later.
core/src/main/java/com/linecorp/armeria/internal/server/annotation/AnnotatedValueResolver.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/internal/server/annotation/AnnotatedValueResolver.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/server/annotation/JacksonRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/ProtobufRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/ProtobufRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
...rc/main/java/com/linecorp/armeria/server/grpc/ProtobufResponseConverterFunctionProvider.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/server/annotation/RequestConverterFunctionProvider.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just nits.
Great job, @ikhoon!
core/src/main/java/com/linecorp/armeria/internal/server/annotation/AnnotatedValueResolver.java
Outdated
Show resolved
Hide resolved
...buf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
...buf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
...buf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
...buf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
...buf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
...uf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufResponseConverterFunction.java
Outdated
Show resolved
Hide resolved
...uf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufResponseConverterFunction.java
Outdated
Show resolved
Hide resolved
...uf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufResponseConverterFunction.java
Outdated
Show resolved
Hide resolved
...buf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
...buf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
...buf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
...buf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufRequestConverterFunction.java
Outdated
Show resolved
Hide resolved
...buf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufRequestConverterFunction.java
Show resolved
Hide resolved
} | ||
|
||
private static boolean isProtobufMessage(Class<?> clazz) { | ||
return Message.class.isAssignableFrom(clazz); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Message
or MessageLite
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Message
class extends MessageLite
. When building(deserializing) a message from protobuf, Message
class is required to get Builder
class. However, when serializing a message to protobuf, MessageLite
is enough.
This inconsistency is able to confuse users. Let me just use Message
instead of MessageLite
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MessageLite
is very rare in servers btw (though I remember an issue filed by someone that was actually using it don't remember the reasoning)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remember an issue filed by someone that was actually using it don't remember the reasoning
Maybe #3085? He said it was caused by wrong dependencies.
...uf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufResponseConverterFunction.java
Outdated
Show resolved
Hide resolved
...uf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufResponseConverterFunction.java
Outdated
Show resolved
Hide resolved
...c/main/java/com/linecorp/armeria/internal/server/annotation/CompositeConverterFunctions.java
Outdated
Show resolved
Hide resolved
gradle.properties
Outdated
scalaVersions=2.13.3 | ||
defaultScalaVersions=2.13.2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: Why these properties have two different versions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops... it was cruft. Actually, I removed gradle-scala-multiversion-plugin and add scalapb_2.12
and scalapb_2.13
because it is difficult to integrate gradle-scala-multiversion-plugin with Armeria's gradle scripts.
And we need a lot of workarounds and some of them are flaky. 😅
...uf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufResponseConverterFunction.java
Outdated
Show resolved
Hide resolved
protobuf/src/main/java/com/linecorp/armeria/server/protobuf/package-info.java
Outdated
Show resolved
Hide resolved
.../src/test/java/com/linecorp/armeria/server/protobuf/ProtobufRequestAnnotatedServiceTest.java
Show resolved
Hide resolved
...apb/src/main/scala/com/linecorp/armeria/server/scalapb/ScalaPbRequestConverterFunction.scala
Outdated
Show resolved
Hide resolved
...apb/src/main/scala/com/linecorp/armeria/server/scalapb/ScalaPbRequestConverterFunction.scala
Outdated
Show resolved
Hide resolved
...src/test/scala/com/linecorp/armeria/server/scalapb/ScalaPbRequestConverterFunctionTest.scala
Outdated
Show resolved
Hide resolved
Finally, all builds are passed. 😆 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still LGTM 👍
(Do not know much about the Scala part 🤣 )
@@ -0,0 +1,46 @@ | |||
/* | |||
* Copyright 2018 LINE Corporation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😱
scalapb/scalapb_2.13/build.gradle
Outdated
implementation "com.thesamet.scalapb:scalapb-runtime-grpc_2.13" | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: two empty lines
|
||
// Run `scalafmt` to automatically format scala code from source sets | ||
// https://github.com/alenkacz/gradle-scalafmt#tasks | ||
project.ext.getLintTask().dependsOn tasks.checkScalafmt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will we have to expose Scaladoc in our web site by the way?
...uf/src/main/java/com/linecorp/armeria/server/protobuf/ProtobufResponseConverterFunction.java
Outdated
Show resolved
Hide resolved
....13/src/main/scala/com/linecorp/armeria/server/scalapb/ScalaPbRequestConverterFunction.scala
Outdated
Show resolved
Hide resolved
How about adding a dedicated documentation page for ScalaPB? The page could have a simple introduction and a Scaladoc link. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work, @ikhoon. ScalaPB users will love this.
@ikhoon Could you update the PR description? |
Sure! The PR description is updated. |
Motivation:
Protocol Buffers is a universal serialization protocol. The usage is not limit to gRPC.
It could be used an HTTP payload for REST API.
It is also useful when building an HTTP proxy server in front of a gRPC server.
Modifications:
RequestConverterFunctionProvider
that can load a customRequestConverterFunction
using SPI@ConsumesProtobuf
and@ProducesProtobuf
annotationsarmeria-protobuf
module to use Protobuf in annotated servicesProtobufRequestConverterFunction
that decodes Protocol Buffers or JSON body into Protobuf Message typeProtobufResponseConverterFunction
that encodes Protobuf Message(s) into Protocol Buffers or JSONProtobufRequestConverterFunctionProvider
andProtobufResponseConverterFunctionProvider
to support Protobuf converters automatically via SPIarmeria-scalapb_2.12
andarmeria-scalapb_2.13
module to use ScalaPB in annotated servicesScalaPbRequestConverterFunction
that decodes Protocol Buffers or JSON body into ScalaPBGenreatedMessage
typeScalaPbResponseConverterFunction
that encodes ScalaPBGenerratedMesage
(s) into Protocol Buffers or JSONScalaPbRequestConverterFunctionProvider
andScalaPbResponseConverterFunctionProvider
to support ScalaPB converters automatically via SPIapplication/protobuf
,application/x-protobuf
orapplication/octet-stream
application/json; charset=utf-8
or subtype ends with+json
Result:
Message
and ScalaPB'sGeneratedMessage
as a request/response object in annotated service.