-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updates kotlin to 1.9.0, ktor to 2.3.2, adopts simple plugin to handl…
…e json status code and body wrapping (#5) * updates dependencies other than ktor * updates kotlin to 1.9.0, updates ktor to last 1.x version, fixes resulting compile errors in MeterReadingControllerTest * changes last junit anotation to kotlin test library one * upgrades ktor to 2.3.2, does not yet adopt tests * Adjusts the application tests to use the new ktor v2 framework and simplifies the controllers. In particular, removes the custom Response class for a more idiomatic approach, using nullability to signal NotFound and turns validation errors into IllegalArgumentExceptions and then into BadRequest rather than an InternalServerError for less surprising error code. * adds ktor plugin to build to simplify further, adjusts README to reflect different name of fatJar * Adds the detekt plugin with the standard rules and fixes all warnings to make the code more familiar in layout and look. In particular: * moves code to directories corresponding to package * avoids wildcard imports * pulls constants out and uses `const` keyword for them * fixes assorted formatting nags * removes magic numbers Additionally: * Simplifies the `ElectricityReadingsGenerator` * Fixes some table formatting niggles in README * Restores explicit http status block with optional body in output from ktor. This had been modelled as a pseudo domain class (`Response`) that wrapped header and body along with an extension function to the `ApplicationCall`. However, that approach conflated http concerns and the chosen approach of wrapping up the domain concerns in a sort of JSON "envelope" with "normal" code. As these concerns are all about how the domain logic is mapping into specific outputs, we now go for a simple Ktor plugin that takes responsibility for: * mapping `null` responses to 404 * wrapping simple status code responses so that they can be serialised to JSON without the `ContentNegotiation` plugin intervening * wrapping normal responses into a `statusCode` and `body` * turning `IllegalArgumentExceptions` into 400 with an additional error message `ApplicationTest` is extended to validate these cases.
- Loading branch information
1 parent
634e95f
commit 9e8da33
Showing
26 changed files
with
388 additions
and
318 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 |
---|---|---|
@@ -1,5 +1,6 @@ | ||
logback_version=1.2.1 | ||
ktor_version=1.3.0 | ||
kotlin_version=1.8.22 | ||
logback_version=1.4.8 | ||
ktor_version=2.3.2 | ||
kotlin_version=1.9.0 | ||
strikt_version=0.34.1 | ||
jackson_version=2.10.2 | ||
jackson_version=2.15.2 | ||
detekt_version=1.23.0 |
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 was deleted.
Oops, something went wrong.
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,98 @@ | ||
package de.tw.energy | ||
|
||
import de.tw.energy.controllers.MeterReadingController | ||
import de.tw.energy.controllers.PricePlanComparatorController | ||
import de.tw.energy.domain.MeterReadings | ||
import de.tw.energy.domain.PricePlan | ||
import de.tw.energy.ktor.BodyAdapterPlugin | ||
import de.tw.energy.services.AccountService | ||
import de.tw.energy.services.MeterReadingService | ||
import de.tw.energy.services.PricePlanService | ||
import io.ktor.http.HttpStatusCode | ||
import io.ktor.serialization.jackson.jackson | ||
import io.ktor.server.application.Application | ||
import io.ktor.server.application.call | ||
import io.ktor.server.application.install | ||
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation | ||
import io.ktor.server.request.receive | ||
import io.ktor.server.response.respond | ||
import io.ktor.server.response.respondNullable | ||
import io.ktor.server.routing.get | ||
import io.ktor.server.routing.post | ||
import io.ktor.server.routing.route | ||
import io.ktor.server.routing.routing | ||
import java.math.BigDecimal | ||
|
||
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args) | ||
|
||
@Suppress("unused") // Referenced in application.conf | ||
fun Application.module() { | ||
install(BodyAdapterPlugin) | ||
install(ContentNegotiation) { | ||
jackson { | ||
setup() | ||
} | ||
} | ||
|
||
val meterReadingsService = MeterReadingService(mutableMapOf()) | ||
val pricePlanService = initPricePlanService(meterReadingsService) | ||
val accountService = initAccountService() | ||
|
||
routing { | ||
route("/readings") { | ||
val controller = MeterReadingController(meterReadingsService) | ||
|
||
get("/read/{smartMeterId}") { | ||
val smartMeterId = call.parameters["smartMeterId"] ?: "" | ||
call.respondNullable(controller.readings(smartMeterId)) | ||
} | ||
|
||
post("/store") { | ||
val readings = call.receive<MeterReadings>() | ||
try { | ||
controller.storeReadings(readings) | ||
call.respond(HttpStatusCode.OK) | ||
} catch (e: IllegalArgumentException) { | ||
call.respond(HttpStatusCode.BadRequest, e) | ||
} | ||
} | ||
} | ||
|
||
route("/price-plans") { | ||
val controller = PricePlanComparatorController( | ||
pricePlanService, | ||
accountService | ||
) | ||
|
||
get("/compare-all/{smartMeterId}") { | ||
val smartMeterId = call.parameters["smartMeterId"] ?: "" | ||
call.respondNullable(controller.calculatedCostForEachPricePlan(smartMeterId)) | ||
} | ||
|
||
get("/recommend/{smartMeterId}") { | ||
val smartMeterId = call.parameters["smartMeterId"] ?: "" | ||
val limit = call.request.queryParameters["limit"] | ||
call.respondNullable(controller.recommendCheapestPricePlans(smartMeterId, limit?.toInt())) | ||
} | ||
} | ||
} | ||
} | ||
|
||
private fun initAccountService() = AccountService( | ||
mapOf( | ||
SARAHS_SMART_METER_ID to MOST_EVIL_PRICE_PLAN_ID, | ||
PETERS_SMART_METER_ID to RENEWABLES_PRICE_PLAN_ID, | ||
CHARLIES_SMART_METER_ID to MOST_EVIL_PRICE_PLAN_ID, | ||
ANDREAS_SMART_METER_ID to STANDARD_PRICE_PLAN_ID, | ||
ALEXS_SMART_METER_ID to RENEWABLES_PRICE_PLAN_ID | ||
) | ||
) | ||
|
||
private fun initPricePlanService(meterReadingsService: MeterReadingService) = PricePlanService( | ||
listOf( | ||
PricePlan(MOST_EVIL_PRICE_PLAN_ID, DR_EVILS_DARK_ENERGY_ENERGY_SUPPLIER, BigDecimal.TEN, listOf()), | ||
PricePlan(RENEWABLES_PRICE_PLAN_ID, THE_GREEN_ECO_ENERGY_SUPPLIER, BigDecimal(2), listOf()), | ||
PricePlan(STANDARD_PRICE_PLAN_ID, POWER_FOR_EVERYONE_ENERGY_SUPPLIER, BigDecimal.ONE, listOf()) | ||
), | ||
meterReadingsService | ||
) |
File renamed without changes.
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
Oops, something went wrong.