Jooby is a scalable, fast and modular micro web framework for Java and Kotlin. It is very easy to use and has a lot of different kind, ready to use modules.
Build configuration
The integration with Jooby is contained in the kvision-server-jooby module. It has to be added as the dependency in the common target. This module depends on the jooby-guice and jooby-jackson. Any other dependencies can be added to build.gradle.kts and then be used in your application.
Note: You can use other engines instead of Netty - see Jooby documentation. Remember to add the appropriate dependency.
Application configuration
The standard way to configure Jooby application is src/jvmMain/resources/application.conf file. It contains options needed for optional modules. It can be empty if no modules are used.
Implementation
Service class
The implementation of the service class comes down to implementing required interface methods.
@Suppress("ACTUAL_WITHOUT_EXPECT")
actual class AddressService : IAddressService {
override suspend fun getAddressList(search: String?, sort: Sort) {
return listOf()
}
override suspend fun addAddress(address: Address) {
return Address()
}
override suspend fun updateAddress(id: Int, address: Address) {
return Address()
}
override suspend fun deleteAddress(id: Int) {
return false
}
}
The integration module utilizes Guice and you can access external components and resources by injecting server objects into your class. KVision allows you to inject Kooby, Environment and Config instances, which give you access to the application configuration and also Context object, which allow you to access the current request and session information.
@Suppress("ACTUAL_WITHOUT_EXPECT")
actual class AddressService : IAddressService {
@Inject
lateinit var kooby: Kooby
@Inject
lateinit var env: Environment
@Inject
lateinit var config: Config
@Inject
lateinit var ctx: Context
override suspend fun getAddressList(search: String?, sort: Sort) {
println(config.getString("option1") ?: "default")
println(ctx.remoteAddress)
println(ctx.session().id)
return listOf()
}
// ...
}
You can also inject other Guice components, defined in your application and configured in custom Guice modules or with just-in-time bindings.
Note: The new instance of the service class will be created by Guice for every server request. Use session or request objects to store your state with appropriate scope.
Blocking code
Since Jooby execution model assumes suspending endpoints are non-blocking, you should never block a thread in your application code. If you have to use some blocking code (e.g. blocking I/O, JDBC) always use the dedicated coroutine dispatcher.
@Suppress("ACTUAL_WITHOUT_EXPECT")
actual class AddressService : IAddressService {
override suspend fun getAddressList(search: String?, sort: Sort) {
return withContext(Dispatchers.IO) {
retrieveAddressesFromDatabase(search, sort)
}
}
}
The main function
This function is the application starting point. It's used to initialize and configure the application. Minimal implementation for KVision integration contains kvisionInit and applyRoutes function calls.
Apart from the above KVision configuration you are free to use any other module of the Jooby framework.
Authentication with Pac4j
You can use Pac4j security module to configure authentication and authorization in your app. By calling applyRoutes function before or after Pac4j module declaration, you apply different security requirements to different services.