/ktor-incontrol

MVC Style controllers for Ktor framewrok

Primary LanguageKotlinApache License 2.0Apache-2.0

INCONTROL - MVC style controllers for Ktor framework

Version Tests JitPack Kotlin GitHub License

Installation

Gradle

  1. Add JitPack repository:
repositories {
    ...
    maven { url 'https://jitpack.io' }
}
  1. Add dependency
// Core Module for controllers only
implementation 'com.github.SkoSC.k:ktor-incontrol:<latest version>'
// Kodein Integration + Auto Routing
implementation 'com.github.SkoSC.k:ktor-incontrol-kodein:<latest version>'

Advantages over default routing

  1. You can easily use dependency injection
  2. Simpler code without using complicated extensions
  3. Cleaner object-oriented code style

Getting Started

Define your controller

class MyController : Controller {
    
    override val route = "/{user}"
    
    // handler function is required to be only public function in class
    suspend fun handle(@Path user: String) = "Hello $user"
}

Add your controller to router

routing {
    get(MyController())
}

That's all, you are ready to go

Handler Functions

Parameters

There are 4 types of handler parameters supported at he monent

  1. Path - parameters are marked with @Path annotation
  2. Query - parameters are marked with @Path annotations
  3. Body - parameter is either named 'body' or marked with @Body
  4. Dependency (non request parameters) - parameters marked with @Dependency

Body and Dependency parameters can be any non-nullable and non-optional type, while Path and Query can be nullable and/or nullable but support only Int, Double, Boolean and String parameters.

Advanced Features

Type Adapters

You can add type adapters for a custom path and query parameter types

First, create your adapter class.

class UUIDTypeAdapter : PlainTypeAdapter<UUID> {
    
    override val type: KType = UUID::class.createType()

    override fun convert(value: String): UUID = UUID.fromString(value)
}

Then register it in feature builder

install(InControl) {
    registerTypeAdapters(
        listOf(UUIDTypeAdapter())
    )
}

After that, you can use adapted type in handler functions.

suspend fun handle(uuid: UUID) = "Hello, $uuid, with leastSignificantBits = ${uuid.leastSignificantBits}"

DI Container Integration

You can inject any object into handler method. To do this, implement DIContainerWrapper interface and set it in your installation.

install(InControl) {
    diContainer = MyContainer()
}

After that you can add @Dependency parameter to handler method, like so:

suspend fun handler(@Dependency myService: MyService) = myService.loadData() 

Kodein Integration

First, enable integration feature in your installation

install(InControl) {
    enableKodeinIntegration()
}

Then declare your kodein dependencies: Kodein Docs Don't forget to import jxInjectorModule to enable JSR330 support

di {
    import(jxInjectorModule)
}

After that declare your controller and dependencies

class SampleKodeinController @Inject constructor(private val classDependency: ClassDependency) : Controller {

    suspend fun handle(@Dependency parameterDependency: ParameterDependency, @Dependency call: ApplicationCall) = ...
}

Last step is to add your Controller to routing

routing {
    ...
    get<MySampleKodeinController>()
}

That's all you should be ready to go

Auto Routing

Enable auto routing

install(InControl) {
    enableKodeinIntegration()
    enableAutoRoutedControllers()
}

Then mark your controller with @AutoRouting annotation

@AutoRouting("GET")
class SampleAutoRoutingController @Inject constructor(private val dependency: SampleDependency): Controller {

    suspend fun handle() = "Hello world: $dependency"
}

Finally, add your auto routed controllers to your routing scheme

routing {
    autoRoute("<your root package>")
}

Roadmap To 1.0

✔️MVC Controllers
✔️Routing Integration
✔️Autowired Controllers Support
✔️Dependency Injection Support
✔️Optional Values Support
✔️MVC Controllers
✔️Extensive @Dependency Annotation Support
✔️Full Support For Non String Parameters
✔️Out Of Box Integration With Kodein
❌ Stable Architecture
❌ High Performance
❌ Test Coverage
❌ Documentation

Future

🚀 Ability To 'Hack' Library Internals
🚀 Extensive Feature Configuration