-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: protobuf java converters (#382)
- Loading branch information
Showing
30 changed files
with
8,384 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Helper modules help you to interact with Kompendium. | ||
|
||
Some functionality is not possible or difficult to do with Kompendium by default. Modules in this folder help you to get | ||
functionality that would otherwise be difficult. | ||
|
||
The first one of which is [Protobuf java converter](protobuf_java_converter.md) which translates java protobuf classes | ||
to `customTypes` entries. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
The `Protobuf java converter` functions allow you to generate documentation from your generated Java classes. | ||
Since Kompendium relies a lot on `KProperties` we have yet to find a way to connect this with our Java. | ||
For now the documentation is generated for the `customTypes` in `NotarizedApplication`. | ||
|
||
## Usage with Kotlinx | ||
|
||
setup: | ||
```kotlin | ||
install(ContentNegotiation) { | ||
json(Json { | ||
encodeDefaults = false | ||
// Combine the kompendium serializers with your custom java proto serializers | ||
serializersModule = | ||
KompendiumSerializersModule.module + SerializersModule { serializersModule = yourCustomProtoSerializers } | ||
}) | ||
} | ||
``` | ||
|
||
For one message and all its nested sub messages: | ||
```kotlin | ||
private fun Application.mainModule() { | ||
// ... | ||
install(NotarizedApplication()) { | ||
spec = baseSpec | ||
customTypes = MyJavaProto.getDefaultInstance().createCustomTypesForTypeAndSubTypes().toMap() | ||
} | ||
} | ||
``` | ||
|
||
For multiple messages and their submesages: | ||
```kotlin | ||
private fun Application.mainModule() { | ||
// ... | ||
install(NotarizedApplication()) { | ||
spec = baseSpec | ||
customTypes = MyJavaProto.getDefaultInstance().createCustomTypesForTypeAndSubTypes() | ||
.plus(AnotherJavaProto.getDefaultInstance().createCustomTypesForTypeAndSubTypes()).toMap() | ||
} | ||
} | ||
``` | ||
|
||
### Example User | ||
|
||
The protobuf that is used on our endpoint | ||
```proto | ||
message User { | ||
string id = 1; | ||
string email = 2; | ||
string mobile_phone = 3; | ||
string name = 4; | ||
} | ||
``` | ||
|
||
A custom serializer deserializer: | ||
```kotlin | ||
@OptIn(ExperimentalSerializationApi::class) | ||
object UserSerializer : KSerializer<User> { | ||
|
||
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("User") { | ||
element("id", serialDescriptor<String>()) | ||
element("email", serialDescriptor<String>()) | ||
element("mobile_phone", serialDescriptor<String>()) | ||
element("name", serialDescriptor<String>()) | ||
} | ||
|
||
override fun deserialize(decoder: Decoder): User { | ||
return decoder.decodeStructure(descriptor) { | ||
var id: String? = null | ||
var email: String? = null | ||
var mobilePhone: String? = null | ||
var name: String? = null | ||
|
||
loop@ while (true) { | ||
when (val index = decodeElementIndex(descriptor)) { | ||
CompositeDecoder.DECODE_DONE -> break@loop | ||
0 -> id = decodeStringElement(descriptor, index) | ||
1 -> email = decodeStringElement(descriptor, index) | ||
2 -> mobilePhone = decodeStringElement(descriptor, index) | ||
3 -> name = decodeStringElement(descriptor, index) | ||
else -> throw RuntimeException( | ||
"Unexpected index field ${descriptor.getElementName(index)}" | ||
) | ||
} | ||
} | ||
// building the protobuf object | ||
val user = User.newBuilder().apply { | ||
id?.let { v -> this.id = v } | ||
email?.let { v -> this.email = v } | ||
mobilePhone?.let { v -> this.mobilePhone = v } | ||
name?.let { v -> this.name = v } | ||
}.build() | ||
user | ||
} | ||
} | ||
|
||
override fun serialize(encoder: Encoder, value: User) { | ||
encoder.encodeStructure(descriptor) { | ||
encodeStringElement(descriptor, 0, value.id) | ||
encodeStringElement(descriptor, 1, value.email) | ||
encodeStringElement(descriptor, 2, value.mobilePhone) | ||
encodeStringElement(descriptor, 3, value.name) | ||
} | ||
} | ||
} | ||
``` | ||
Setting the content type: | ||
```kotlin | ||
install(ContentNegotiation) { | ||
json(Json { | ||
encodeDefaults = false | ||
// Combine the kompendium serializers with your custom java proto serializers | ||
serializersModule = | ||
KompendiumSerializersModule.module + SerializersModule { | ||
serializersModule = SerializersModule { | ||
contextual(UserSerializer) | ||
} | ||
} | ||
}) | ||
} | ||
``` | ||
The installation of the noterized application: | ||
```kotlin | ||
install(NotarizedApplication()) { | ||
spec = baseSpec | ||
customTypes = User.getDefaultInstance().createCustomTypesForTypeAndSubTypes().toMap() | ||
} | ||
``` | ||
Route configuration as you normally would with one exception which is `createType()` to create kotlin type from a javaClass. | ||
|
||
```kotlin | ||
private fun Route.userDocumentation() { | ||
install(NotarizedRoute()) { | ||
post = PostInfo.builder { | ||
summary("My User API") | ||
description("Create a user") | ||
request { | ||
requestType(User::class.createType()) | ||
description("My user creation object") | ||
} | ||
response { | ||
responseCode(HttpStatusCode.OK) | ||
responseType(CreateUserResponse::class.createType()) | ||
description("Returns simulation object") | ||
} | ||
canRespond { | ||
responseCode(HttpStatusCode.NotFound) | ||
responseType<String>() | ||
description("Indicates that the user could not be found") | ||
} | ||
} | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
plugins { | ||
kotlin("jvm") | ||
kotlin("plugin.serialization") | ||
id("io.bkbn.sourdough.library.jvm") | ||
id("io.gitlab.arturbosch.detekt") | ||
id("com.adarshr.test-logger") | ||
id("maven-publish") | ||
id("java-library") | ||
id("signing") | ||
id("org.jetbrains.kotlinx.kover") | ||
} | ||
|
||
sourdoughLibrary { | ||
libraryName.set("Kompendium Protobuf java converter") | ||
libraryDescription.set("Converts Java protobuf generated classes to custom type maps") | ||
compilerArgs.set(listOf("-opt-in=kotlin.RequiresOptIn")) | ||
} | ||
|
||
dependencies { | ||
// Versions | ||
val detektVersion: String by project | ||
|
||
|
||
implementation(projects.kompendiumJsonSchema) | ||
implementation("com.google.protobuf:protobuf-java:3.21.9") | ||
implementation("org.jetbrains.kotlin:kotlin-reflect:1.7.21") | ||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1") | ||
|
||
// Formatting | ||
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:$detektVersion") | ||
testImplementation(testFixtures(projects.kompendiumCore)) | ||
} | ||
|
||
|
||
testing { | ||
|
||
suites { | ||
named("test", JvmTestSuite::class) { | ||
useJUnitJupiter() | ||
} | ||
} | ||
} | ||
|
Oops, something went wrong.