Ladies and gents, once again I’m sharing some sample app, this time we are building sample Spring Boot app implemented in Kotlin, talking to http://data.nba.net/ API to help us get some interesting, NBA related data. In this case we’re just listing NBA teams, but you extend this sample even further.
Creating project skeleton
The easiest way to create project skeleton is to navigate directly to Spring Boot Initializer website and download pre-configured project. In case you like kotlin – you can choose it from drop down with supported languages. If you’re using Intellij or Spring Tools Suite, you can achieve the same from within your IDE.
Application entry point
KotlinNbaApplicaiton.kt is our application entry point, it’s just a standard kotlin class containing main method and
being annotated with @SpringBootApplication.
package rs.dodalovic.nba
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
@SpringBootApplication
class KotlinNbaApplication
fun main(args: Array<String>) {
SpringApplication.run(KotlinNbaApplication::class.java, *args)
}
Handling request with TeamController
Let’s start with application entry point, simple servlet named TeamController, which is in charge of handling
http GET /nba/teams requests. Owing to compact kotlin syntax – we’re simply autowiring TeamRepository (responsible
for fetching data from 3rd party API) dependency via primary constructor. Controller is annotated by @RestController
which makes him request handler, and @RequestMapping("/teams") is narrowing URL paths he handles. Furthermore,
we’re defining getAll() function that is just proxying call to TeamRepository to actually get some data. Kotlin
helps us here with expression functions so that we have one-liner to implement getAll().
package rs.dodalovic.nba.team
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/teams")
class TeamController(val teamRepository: TeamRepository) {
@RequestMapping
fun getAll() = teamRepository.getAll()
}
Fetching data from external API
In order to get data from NBA API, we’re using TeamRepository kotlin class:
package rs.dodalovic.nba.team
import org.springframework.stereotype.Repository
import org.springframework.web.client.RestTemplate
import rs.dodalovic.nba.model.Team
val oddTeams = listOf("World", "West", "USA Celebrities", "USA", "Shanghai", "Real Madrid", "Haifa", "East",
"Canada Celebrities", "Buenos Aires", "Barcelona")
val allTeamsEndpoint = "http://data.nba.net/data/10s/prod/v1/2016/teams.json"
@Repository
class TeamRepository(val template: RestTemplate) {
fun getAll() = template.getForObject(allTeamsEndpoint, Map::class.java).extractTeams().nbaOnly().map { it.toTeam() }
}
private fun Map<*, *>.extractTeams() = (this.get("league") as Map<String, *>).get("standard") as List<Map<String, String>>
private fun Map<String, String>.toTeam() = Team(get("teamId")!!, get("city")!!, get("nickname")!!)
private fun List<Map<String, String>>.nbaOnly() = filterNot { rs.dodalovic.nba.team.oddTeams.contains(it["city"]) }
TeamRepository itself is slightly more complex. It’s been given RestTemplate HTTP client coming from Spring
(RestTemplate @Bean is configured in Config @Configuration class). We need that one in order to fetch some
data from NBA API we’re talking to. NBA API for some reasons return non NBA teams, so we build oddTeams collection.
We’re also defining allTeamsEndpoint constant, which is our 3rd party data-source namespace.
Kotlin extension functions
Implementation of TeamRepository::getAll() illustrates kotlin’s extension functions power to help us express ourselves
in more readable, less cryptic manner. We’re first calling RestTemplate::getForObject API, which is first deserializing
JSON API response to regular Map, then extracting teams portion out of response, proceeding with filtering only
NBA teams, and finishing by converting each team (which is Map instance) to Team model.
extractTeam(), toTeam() and nbaOnly() extension methods are defined below TeamRepository implementation.
There’s nothing so special about them, they’re just dealing with Map transformations and Collection filtering.
Running application
The easiest way to run the app is going to project root and executing maven command:
$ ./mvnw spring-boot:run
This will start application on port 8080, and all application paths will be living under http://localhost:8080/nba
namespace.
Testing application
We’ll be using CURL client to talk to our API and get some NBA data:
$ curl -s localhost:8080/nba/teams | jq .
We’re piping response to jq JSON processor, just for sake of pretty printing response data.
Response will look something like:
[
{
"teamId": "1610612737",
"city": "Atlanta",
"nickname": "Hawks"
},
{
"teamId": "1610612738",
"city": "Boston",
"nickname": "Celtics"
},
{
"teamId": "1610612751",
"city": "Brooklyn",
"nickname": "Nets"
},
{
"teamId": "1610612766",
"city": "Charlotte",
"nickname": "Hornets"
},
{
"teamId": "1610612741",
"city": "Chicago",
"nickname": "Bulls"
},
{
"teamId": "1610612739",
"city": "Cleveland",
"nickname": "Cavaliers"
},
{
"teamId": "1610612742",
"city": "Dallas",
"nickname": "Mavericks"
}
]
Sources can be found at GitHub
That was all for today! Hope you liked it!
