Kotlin has gained a lot of popularity in recent times due to its productivity features and a first class support in Android.
Owing to the increasing popularity of Kotlin, Spring framework 5 has also introduced a dedicated support for Kotlin in Spring applications.
In this article, You’ll learn how to build a Restful CRUD API with Kotlin and Spring Boot 2.x, which is based on Spring framework 5.
So Stay tuned!
In this blog post, we’ll build Restful APIs for a mini blog application. The blog has a list of Articles. We’ll write APIs for creating, retrieving, updating and deleting an Article. An Article has an id
, a title
and some content
.
We’ll use MySQL as our data source and JPA & Hibernate to access the data from the database.
All right, Let’s now create the application.
Creating the Application
We’ll use Spring initializr web tool to bootstrap our application. Follow the steps below to generate the application :
- Go to http://start.spring.io
- Select Kotlin in the language section.
- Enter Artifact as kotlin-demo
- Add Web, JPA, and MySQL dependencies.
- Click Generate to generate and download the project.
Once the project is generated, unzip it and import it into your favorite IDE. Here is the Project’s directory Structure for your reference.
Configure MySQL
We’ll need to configure MySQL database url, username, and password so that Spring Boot can create a Data source.
Open src/main/resources/application.properties
file and add the following properties to it :
## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url = jdbc:mysql://localhost:3306/kotlin_demo_app?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
spring.datasource.username = root
spring.datasource.password = root
## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
Please don’t forget to change spring.datasource.username
and spring.datasource.password
as per your MySQL installation.
Note that, I’ve set spring.jpa.hibernate.ddl-auto
property to update
. This property updates the database schema whenever you create or modify the domain models in your application.
Creating the Domain Model
Let’s now create the Article
domain entity. Create a new package called model
inside com.example.kotlindemo
package, and then create a new Kotlin file called Article.kt
with the following contents -
package com.example.kotlindemo.model
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.validation.constraints.NotBlank
@Entity
data class Article (
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = 0,
@get: NotBlank
val title: String = "",
@get: NotBlank
val content: String = ""
)
The Entity class is so small and concise, right? That’s because A Kotlin class doesn’t need getters and setters like Java. Moreover, I have used a data class here. A data class automatically generates equals()
, hashcode()
, toString()
and copy()
methods.
Note that, I’ve assigned a default value for all the fields in the Article
class. This is needed because Hibernate requires an entity to have a no-arg constructor.
Assigning default values to all the member fields will let hibernate instantiate an Article
without passing any argument. It Works because Kotlin supports Default Arguments :).
Creating the Repository
Let’s now create the repository for accessing the data from the database. First, create a package called repository
inside com.example.kotlindemo
package, and then create a Kotlin file named ArticleRepository.kt
with the following contents -
package com.example.kotlindemo.repository
import com.example.kotlindemo.model.Article
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
@Repository
interface ArticleRepository : JpaRepository<Article, Long>
That’s all we need to do here. Since we’ve extended ArticleRepository
from JpaRepository
interface, all the CRUD methods on Article
entity is readily available to us. Spring boot automatically plugs-in a default implementation of JpaRepository
called SimpleJpaRepository
at runtime.
Creating the controller End-points
Finally, Let’s create the controller end-points for all the CRUD operations on Article
entity.
First, create a new package called controller
inside com.example.kotlindemo
package and then create a new kotlin file called ArticleController.kt
inside controller
package with the following contents -
package com.example.kotlindemo.controller
import com.example.kotlindemo.model.Article
import com.example.kotlindemo.repository.ArticleRepository
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import java.util.*
import javax.validation.Valid
@RestController
@RequestMapping("/api")
class ArticleController(private val articleRepository: ArticleRepository) {
@GetMapping("/articles")
fun getAllArticles(): List<Article> =
articleRepository.findAll()
@PostMapping("/articles")
fun createNewArticle(@Valid @RequestBody article: Article): Article =
articleRepository.save(article)
@GetMapping("/articles/{id}")
fun getArticleById(@PathVariable(value = "id") articleId: Long): ResponseEntity<Article> {
return articleRepository.findById(articleId).map { article ->
ResponseEntity.ok(article)
}.orElse(ResponseEntity.notFound().build())
}
@PutMapping("/articles/{id}")
fun updateArticleById(@PathVariable(value = "id") articleId: Long,
@Valid @RequestBody newArticle: Article): ResponseEntity<Article> {
return articleRepository.findById(articleId).map { existingArticle ->
val updatedArticle: Article = existingArticle
.copy(title = newArticle.title, content = newArticle.content)
ResponseEntity.ok().body(articleRepository.save(updatedArticle))
}.orElse(ResponseEntity.notFound().build())
}
@DeleteMapping("/articles/{id}")
fun deleteArticleById(@PathVariable(value = "id") articleId: Long): ResponseEntity<Void> {
return articleRepository.findById(articleId).map { article ->
articleRepository.delete(article)
ResponseEntity<Void>(HttpStatus.OK)
}.orElse(ResponseEntity.notFound().build())
}
}
The controller defines APIs for all the CRUD operations. I have used Kotlin’s functional style syntax in all the methods to make them short and concise.
Running the Application
You can run the application by typing the following command in the terminal -
mvn spring-boot:run
The application will start at Spring Boot’s default port 8080.
Exploring the Rest APIs
1. POST /api/articles - Create an Article
curl -i -H "Content-Type: application/json" -X POST \
-d '{"title": "How to learn Spring framework", "content": "Resources to learn Spring framework"}' \
http://localhost:8080/api/articles
# Output
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:25:59 GMT
{"id":1,"title":"How to learn Spring framework","content":"Resources to learn Spring framework"}
2. GET /api/articles - Get all Articles
curl -i -H 'Accept: application/json' http://localhost:8080/api/articles
# Output
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:25:29 GMT
[{"id":1,"title":"How to learn Spring framework","content":"Resources to learn Spring framework"}]
3. Get /api/articles/{id} - Get an Article by id
curl -i -H 'Accept: application/json' http://localhost:8080/api/articles/1
# Output
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:27:51 GMT
{"id":1,"title":"How to learn Spring framework","content":"Resources to learn Spring framework"}
4. PUT /api/articles/{id} - Update an Article
curl -i -H "Content-Type: application/json" -X PUT \
-d '{"title": "Learning Spring Boot", "content": "Some resources to learn Spring Boot"}' \
http://localhost:8080/api/articles/1
# Output
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:33:15 GMT
{"id":1,"title":"Learning Spring Boot","content":"Some resources to learn Spring Boot"}
5. DELETE /api/articles/{id} - Delete an Article
curl -i -X DELETE http://localhost:8080/api/articles/1
# Output
HTTP/1.1 200
Content-Length: 0
Date: Fri, 06 Oct 2017 03:34:22 GMT
Conclusion
That’s all folks! In this article, You learned how to use Kotlin with Spring Boot for building restful web services.
You can find the entire code for the application that we built in this article in my github repository. Consider giving a star on github if you find the project useful.
Thank you for reading folks! See you next time :)
Reference :
0 komentar: