Download

Summer

Lightweight Jetty/JDBC wrapper library inspired by SparkJava and MyBatis with DI and Testing support for Kotlin.

Sample project: summer-template.

Example

import summer.*

private val log = logger("cats")

data class CatId(override val id: Int) : Id

data class CatDetails(val name: String)

data class Cat(val id: CatId, @json val details: CatDetails)

interface CatStore {

    @query("""
        |CREATE TABLE IF NOT EXISTS cat (
        |  id SERIAL NOT NULL PRIMARY KEY,
        |  details TEXT NOT NULL
        |)
    """)
    fun prepare()

    @query("INSERT INTO cat (details) VALUES (#details) RETURNING id")
    fun saveCat(@json details: CatDetails): CatId

    @query("SELECT * FROM cat WHERE id = #id")
    fun findCatById(catId: CatId): Cat?

    @query("SELECT * FROM cat")
    fun listCats(): List<Cat>

    @query("DELETE FROM cat")
    fun clear()

}

fun Bind.catController(catStore: CatStore) {
    get("/add") {
        val name = requireParam<String>("name")
        val catId = catStore.saveCat(CatDetails(name))

        log.info("Cat created $catId")
        jsonResponse(catId)
    }

    get("/list") {
        val cats = catStore.listCats()
        jsonResponse(cats)
    }

    get("/find") {
        val id = requireParam<CatId>("id")
        val cat = catStore.findCatById(id)
        jsonResponse(cat)
    }

    get("/clear") {
        catStore.clear()
        jsonMap("status" to "ok")
    }
}

data class MeowCounter(val cntr: AtomicInteger = AtomicInteger(0))

fun Bind.meowController(counterProvider: () -> MeowCounter) {
    data class Meow(val say: String)

    handle("/sayMeow") {
        log.info("Counter ${counterProvider().cntr.incrementAndGet()}") //always 1

        when (method()) {
            HttpMethod.get -> jsonResponse(requireParam<String>("meow"))
            HttpMethod.post -> jsonResponse(requireParam<Meow>("meow"))
            else -> {
                sendError(400)
                return@handle
            }
        }
    }

    get("/sayFromPathParam/*") {
       getWriter().println(pathParams<String>(0))
    }

}

class App(val cats: Cats) : AbstractModule() {

    fun dbPool() = singleton {
        dbpoll(DBConnectionParams("jdbc:hsqldb:mem:testdb;sql.syntax_pgs=true", "sa", ""))
    }

    fun catStore() = singleton { store<CatStore>(dbPool()).apply { prepare() } }

    fun catControllerFn() = controller { catController(catStore()) }

    fun meowCounter() = prototype { MeowCounter() }

    fun meowControllerFn() = controller { meowController(::meowCounter) }

    fun scheduledTask() = schedule("* * * * *") {
        println("meow")
    }

    fun httpServer() = singleton {
        server(cats.httpPort) {
            controller("/cat", catControllerFn())
            controller("/meow", meowControllerFn())
        }
    }

}

@Help("Simple cat server")
data class Cats(val httpPort: Int = 8080)

fun main(args: Array<String>) {
    App(optionsParseOrDie(args)).apply {
        scheduledTask() //start scheduled task
        val httpServer = httpServer() //start server

        shutdownHook { close() }

        httpServer.join()
    }
}

class CatControllerTest {
    @Test
    fun list() {
        val testCat = Cat(CatId(1), CatDetails("test"))

        val testBind = TestBind()
        testBind.catController(object : CatStore {
            override fun prepare() {}
            override fun saveCat(details: CatDetails) = testCat.id
            override fun findCatById(catId: CatId) = testCat
            override fun listCats(): List<Cat> = listOf(testCat)
            override fun clear() {}
        })

        val listResponse = testBind.test("/list", HttpMethod.get)
        assertEquals(listOf(testCat), listResponse.responseObj)
    }
}

compile "summer:summer:0.4.11"

Related Libraries

summer

Last updated 3 mins ago

koin

Last updated 3 mins ago

koin-android

Last updated 3 mins ago