Today you’ll learn how to develop REST API with Spring Boot 2 and Kotlin. Kotlin is 100% interoperable with Java. Which means you can call Java code from Kotlin and Kotlin code can be used from Java seamlessly. If you want to learn more about Kotlin, refer to Kotlin reference doc.
In this tutorial we'll use an in-memory database (H2) with Spring Data to persist and retrieve data via rest API.
Creating a New Project
Visit Spring Initializr and select Kotlin language. In this tutorial we'll use Maven, select Maven project. But you can also use Gradle.
Add the following dependencies:
- Spring Data JPA
- Spring Web
- H2 Database
- Spring Boot DevTools
Click Generate
to downlaod .zip file and upack it into your working directory.
Understanding Application entry point
src/main/com/example/demo/DemoApplication.kt
package com.example.demo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
Main fun is the entry point for Springboot application. runApplication<DemoApplication>(*args)
is Kotlin idiomatic alternative to SpringApplication.run(DemoApplication::class.java, *args)
that you see mostly in Java.
Create Project structure
Create the following packages in src/main/com/example/demo
directory:
- config
- controller
- domain
- repository
- service
Create Entity Class
Create Product.kt
in domain
package.
package com.example.demo.domain
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Id
import javax.persistence.Table
@Entity
@Table(name = "product")
class Product(
@Id
@GeneratedValue(strategy = GenerationType.AUTO
var id: Long,
@Column
var name: String,
@Column
var price: Float) {
override fun toString(): String {
return "Product(name='$name', price=$price)"
}
}
Compared to Java, you can notice that we defined primary constructor as part of the class header. Kotlin will generate getter, setter, hashcode, and equals methods for us, which you can also override.
Create Repository Interface
Create ProductRepository.kt
in domain
package.
package com.example.demo.repository
import com.example.demo.domain.Product
import org.springframework.data.repository.CrudRepository
import org.springframework.stereotype.Repository
@Repository
interface ProductRepository: CrudRepository<Product, Long> {
fun findProductsByName(name: String): List<Product>
}
Compared to Java, you can notice the use of :
to implement CrudRepository
Service Interface and Implementation
Create ProductService.kt
and ProductServiceImpl.kt
in service
package.
package com.example.demo.service
import com.example.demo.domain.Product
interface ProductService {
fun createProduct(product: Product)
fun findProductsByName(name: String): List<Product>
}
package com.example.demo.service
import com.example.demo.domain.Product
import com.example.demo.repository.ProductRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
@Service
class ProductServiceImpl(@Autowired val productRepository: ProductRepository): ProductService {
override fun createProduct(product: Product) {
productRepository.save(product)
}
override fun findProductsByName(name: String): List<Product> {
return productRepository.findProductsByName(name)
}
}
Notice how we used constructor injection as part of class header to inject ProductRepository
.
Controller Class
Create ProductController.kt
in controller
package
package com.example.demo.controller
import com.example.demo.domain.Product
import com.example.demo.service.ProductService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.*
@RestController
@RequestMapping("api/v1/products")
class ProductController(@Autowired val productService: ProductService) {
@PostMapping
fun createProduct(@RequestBody product: Product) {
productService.createProduct(product)
}
@GetMapping("{name}")
fun getProductsByName(@PathVariable("name") name: String): List<Product> {
return productService.findProductsByName(name)
}
}
Config Swagger UI
To configure Swagger UI add the following dependencies to pom.xml
:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
Create SwaggerConfig.kt
in config
package.
package com.example.demo.config
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import springfox.documentation.builders.PathSelectors
import springfox.documentation.builders.RequestHandlerSelectors
import springfox.documentation.spi.DocumentationType
import springfox.documentation.spring.web.plugins.Docket
import springfox.documentation.swagger2.annotations.EnableSwagger2
@EnableSwagger2
@Configuration
class SwaggerConfig {
@Bean
fun api(): Docket = Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
}
@EnableSwagger2 annotation will enable Swagger UI for this applicaton.
Now if you run the application and visit http://localhost:8080/swagger-ui.html, you will be able to persist/retrieve product using swagger-ui.
Code available on github.
Thank you for reading. Please leave a comment or questing.
Top comments (0)