-
Notifications
You must be signed in to change notification settings - Fork 42
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
Alternate "syntax" for routing. #10
Comments
I am open to any useful contributions. |
I want to look into this. A quick look revealed that it will probably touch some of the same files as you are working on now for parameters. I'll see how far I can get without getting in too much of a merge conflict. Or maybe I'll just work off of your branch and keep up to date. Are you planning on merging that one soon? |
You should be able to do this without interfering with the current work. |
|
I'll see what you come up with. |
@sheepdreamofandroids import org.junit.Test
import kotlin.reflect.KFunction
import kotlin.reflect.jvm.reflect
class ReflectionSandbox {
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME)
annotation class TestParam
fun <R> handleReflect(kfun: KFunction<R>) {
println(kfun)
println(kfun.parameters.associateWith { it.type.annotations }.mapKeys { it.key.type })
println(kfun.returnType)
}
inline fun <reified R> hanldleWithReflect(noinline test: () -> R) {
handleReflect(test.reflect()!!)
}
inline fun <reified R, reified A> hanldleWithReflect(noinline test: (a: A) -> R) {
handleReflect(test.reflect()!!)
}
inline fun <reified R, reified A, reified B> hanldleWithReflect(noinline test: (a: A, b: B) -> R) {
handleReflect(test.reflect()!!)
}
inline fun <reified R, reified A, reified B, reified C> hanldleWithReflect(noinline test: (a: A, b: B, c: C) -> R) {
handleReflect(test.reflect()!!)
}
inline fun <reified R, reified A, reified B, reified C, reified D> hanldleWithReflect(noinline test: (a: A, b: B, c: C, d: D) -> R) {
handleReflect(test.reflect()!!)
}
// etc...
data class BodyResponse<T>(val payload: T)
@Test
fun testNoInlineParameterReflection() {
hanldleWithReflect { a: @TestParam String ->
BodyResponse(a)
}
}
} So it is possible to annotate properties directly in the lambda. Theoretical syntax could be: get ("{id}/pagedResources") { id: @PathParam("ID of resources") UUID, paged: PagedParameters ->
ResourceService.getPaged(id, paged)
} this would use:
(please note that default parameters are not yet supported, and if they work it is by pure coincidence) post ("resource") { body: @RequestBody SomeObject ->
ResourceService.createSomeObject(body)
} Is this to your liking ? To me it even seems preferable to the current system as it is a lot clearer, flexible, and reusable |
I have pondered further on the question. I think it would be beneficial to completely change the system to this. It would drastically change the structure of the library and won't be backwards compatible. The benefits would be huge, as an injection based system will allow for greater modularity and flexibility as compared to the current system. I estimate the workload to be about two office weeks, or as i like to call it: 4 caffeine fuelled all-nighters. I will also try to reduce the usage of the reflections library. it is slow as hell. |
I love it. Much easier on the eye than the current way that forces you to create a data class for each parameter list. I think you would even be able to directly use a method reference. Like
This way all the info about the syntax of the endpoint is in the routing and all the reusable meaning in the method. |
alright, let's do this. |
Yeah, I see how putting that info in the path string is suboptimal. |
It would also be interesting to have a way to pass in the KClass instances for typed Parameters, Response and Body into a generic @AutoDiscover
class ManageUsersController(directDI: DirectDI) : AnnotationController(directDI) {
override val path = "$PATH_UI/auth/manage/users"
override val permissionPath = "auth/manage/users"
@Route(HttpMethod.Post, "list")
suspend fun routeList(
uiCtx: UiRequestContext,
params: ListParams
): ListResponse? {
// ...
}
// ...
} A method like this would allow for flexible implementation of "custom" route detection with reflection: @ContextDsl
inline fun <P : Any, R : Any, B : Any> NormalOpenAPIRoute.handle(
classParams: KClass<P>,
classResponse: KClass<R>,
classBody: KClass<B>
exampleResponse: R? = null,
exampleRequest: B? = null,
crossinline body: suspend OpenAPIPipelineResponseContext<R>.(P, B) -> Unit
) {
preHandle<P, R, B, NormalOpenAPIRoute>(classParams, classResponse, classBody, exampleResponse, exampleRequest) {
handle(body)
}
} |
Hi everyone, I love the suggested syntax, but it doesn't look like it's implemented. Wondering what's the status and if I can do anything to help out |
I haven't gotten around to start beyond the initial proof of feasibility. I am currently on other projects. If you think you can get something clean on the rails feel free to contribute. |
Just a wild idea. How about allowing routing like
get("path", ::someMethod)
and the parameters of that method are annotated the same way the fields of parameter classes are now annotated.That way you don't have to declare a class for just one or two simple parameters and you get a very natural looking routing style.
Also this would be quite familiar to users of springfox.
The text was updated successfully, but these errors were encountered: