Skip to content

Commit 19e1faf

Browse files
committed
created demo app by https://bit.ly/3fPxGgN
1 parent 59bfb72 commit 19e1faf

24 files changed

+503
-42
lines changed

build.gradle.kts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,60 @@
1+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
2+
13
plugins {
24
java
35
kotlin("jvm") version "1.5.10"
4-
id("org.springframework.boot") version "2.4.4"
6+
id("org.springframework.boot") version "2.5.0"
57
id("io.spring.dependency-management") version "1.0.11.RELEASE"
68
id("org.flywaydb.flyway") version "7.9.1"
9+
kotlin("plugin.spring") version "1.5.10"
10+
kotlin("plugin.jpa") version "1.5.10"
11+
kotlin("plugin.allopen") version "1.5.10"
12+
kotlin("kapt") version "1.5.10"
713
}
814

15+
allOpen {
16+
annotation("javax.persistence.Entity")
17+
annotation("javax.persistence.Embeddable")
18+
annotation("javax.persistence.MappedSuperclass")
19+
}
920

1021
group = "org.example"
1122
version = "1.0-SNAPSHOT"
23+
java.sourceCompatibility = JavaVersion.VERSION_1_8
1224

13-
val javaVer = JavaVersion.VERSION_1_8
1425

1526
repositories {
16-
jcenter()
1727
mavenCentral()
1828
}
1929

2030
dependencies {
2131
implementation("org.springframework.boot:spring-boot-starter-web")
22-
testImplementation("org.springframework.boot:spring-boot-starter-test")
32+
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
33+
implementation("org.jetbrains.kotlin:kotlin-reflect")
34+
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
35+
developmentOnly("org.springframework.boot:spring-boot-devtools")
36+
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
37+
testImplementation("org.springframework.boot:spring-boot-starter-test") {
38+
exclude(module = "junit")
39+
exclude(module = "mockito-core")
40+
}
41+
testImplementation("org.junit.jupiter:junit-jupiter-api")
42+
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
43+
testImplementation("com.ninja-squad:springmockk:3.0.1")
44+
implementation("org.springframework.boot:spring-boot-starter-mustache")
2345
implementation("org.springframework.boot:spring-boot-starter-actuator")
24-
implementation("org.springframework.data:spring-data-jpa:2.4.2")
25-
46+
runtimeOnly("com.h2database:h2")
47+
kapt("org.springframework.boot:spring-boot-configuration-processor")
48+
// runtimeOnly("org.postgresql:postgresql")
2649
}
2750

28-
java {
29-
sourceCompatibility = javaVer
30-
targetCompatibility = javaVer
51+
tasks.withType<KotlinCompile> {
52+
kotlinOptions {
53+
freeCompilerArgs = listOf("-Xjsr305=strict")
54+
jvmTarget = "1.8"
55+
}
3156
}
3257

33-
tasks.getByName<Test>("test") {
58+
tasks.withType<Test> {
3459
useJUnitPlatform()
3560
}

src/main/java/org/example/FirstJavaKotlinGradleApp.java renamed to src/main/java/org/example/java_kotlin/FirstJavaKotlinGradleApp.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
package org.example;
1+
package org.example.java_kotlin;
22

3+
import org.example.java_kotlin.config.BlogProperties;
34
import org.springframework.boot.CommandLineRunner;
45
import org.springframework.boot.SpringApplication;
56
import org.springframework.boot.autoconfigure.SpringBootApplication;
7+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
68
import org.springframework.context.ApplicationContext;
79
import org.springframework.context.annotation.Bean;
810

911
import java.util.Arrays;
1012

1113
@SpringBootApplication
14+
@EnableConfigurationProperties(BlogProperties.class)
1215
public class FirstJavaKotlinGradleApp {
1316

1417
public static void main(String[] args) {

src/main/java/org/example/HelloController.java renamed to src/main/java/org/example/java_kotlin/HelloController.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
package org.example;
1+
package org.example.java_kotlin;
22

33
import org.springframework.web.bind.annotation.RestController;
44
import org.springframework.web.bind.annotation.RequestMapping;
55

66
@RestController
77
public class HelloController {
88

9-
@RequestMapping("/")
10-
public String index() {
11-
return "Greetings from Spring Boot!";
12-
}
9+
// @RequestMapping("/")
10+
// public String index() {
11+
// return "Greetings from Spring Boot!";
12+
// }
1313

1414

1515

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.example.java_kotlin.config
2+
3+
import org.example.java_kotlin.model.Article
4+
import org.example.java_kotlin.model.User
5+
import org.example.java_kotlin.repositories.ArticleRepository
6+
import org.example.java_kotlin.repositories.UserRepository
7+
import org.springframework.boot.ApplicationRunner
8+
import org.springframework.context.annotation.Bean
9+
import org.springframework.context.annotation.Configuration
10+
11+
@Configuration
12+
class BlogConfiguration {
13+
14+
@Bean
15+
fun databaseInitializer(userRepository: UserRepository, articleRepository: ArticleRepository) = ApplicationRunner {
16+
val smaldini = userRepository.save(
17+
User("smaldini", "Stéphane", "Maldini")
18+
)
19+
articleRepository.save(
20+
Article(
21+
title = "Reactor Bismuth is out",
22+
headline = "Lorem ipsum",
23+
content = "dolor sit amet",
24+
author = smaldini
25+
)
26+
)
27+
articleRepository.save(
28+
Article(
29+
title = "Reactor Aluminium has landed",
30+
headline = "Lorem ipsum",
31+
content = "dolor sit amet",
32+
author = smaldini
33+
)
34+
)
35+
36+
}
37+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.example.java_kotlin.config
2+
3+
import org.springframework.boot.Banner
4+
import org.springframework.boot.context.properties.ConfigurationProperties
5+
import org.springframework.boot.context.properties.ConstructorBinding
6+
7+
@ConstructorBinding
8+
@ConfigurationProperties("blog")
9+
data class BlogProperties(var title: String, val banner: Banner) {
10+
data class Banner(val title: String? = null, val content: String)
11+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.example.java_kotlin.controller
2+
3+
import org.example.java_kotlin.config.BlogProperties
4+
import org.example.java_kotlin.model.Article
5+
import org.example.java_kotlin.model.User
6+
import org.example.java_kotlin.repositories.ArticleRepository
7+
import org.example.java_kotlin.util.format
8+
import org.springframework.http.HttpStatus
9+
import org.springframework.stereotype.Controller
10+
import org.springframework.ui.Model
11+
import org.springframework.ui.set
12+
import org.springframework.web.bind.annotation.GetMapping
13+
import org.springframework.web.bind.annotation.PathVariable
14+
import org.springframework.web.server.ResponseStatusException
15+
16+
@Controller
17+
class HtmlController(
18+
private val articleRepository: ArticleRepository,
19+
private val properties: BlogProperties
20+
) {
21+
22+
@GetMapping("/")
23+
fun blog(model: Model): String {
24+
model["title"] = properties.title
25+
model["banner"] = properties.banner
26+
model["articles"] = articleRepository.findAllByOrderByAddedAtDesc().map { it.render() }
27+
return "blog"
28+
}
29+
30+
@GetMapping("/article/{slug}")
31+
fun article(@PathVariable slug: String, model: Model): String {
32+
val article = articleRepository.findBySlug(slug)
33+
?.render()
34+
?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "This article does not exist")
35+
model["title"] = article.title
36+
model["article"] = article
37+
return "article"
38+
}
39+
40+
fun Article.render() = RenderedArticle(
41+
slug,
42+
title,
43+
headline,
44+
content,
45+
author,
46+
addedAt.format()
47+
)
48+
49+
data class RenderedArticle(
50+
val slug: String,
51+
val title: String,
52+
val headline: String,
53+
val content: String,
54+
val author: User,
55+
val addedAt: String
56+
)
57+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.example.java_kotlin.controller
2+
3+
import org.example.java_kotlin.repositories.ArticleRepository
4+
import org.example.java_kotlin.repositories.UserRepository
5+
import org.springframework.http.HttpStatus
6+
import org.springframework.web.bind.annotation.GetMapping
7+
import org.springframework.web.bind.annotation.PathVariable
8+
import org.springframework.web.bind.annotation.RequestMapping
9+
import org.springframework.web.bind.annotation.RestController
10+
import org.springframework.web.server.ResponseStatusException
11+
12+
@RestController
13+
@RequestMapping("/api/article")
14+
class ArticleController(private val articleRepository: ArticleRepository) {
15+
16+
@GetMapping("/")
17+
fun findAll() = articleRepository.findAllByOrderByAddedAtDesc()
18+
19+
@GetMapping("/{slug}")
20+
fun findOne(@PathVariable slug: String) = articleRepository
21+
.findBySlug(slug) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "This article does not exist!")
22+
23+
}
24+
25+
@RestController
26+
@RequestMapping("/api/user")
27+
class UserController(private val userRepository: UserRepository) {
28+
29+
@GetMapping("/")
30+
fun findAll() = userRepository.findAll()
31+
32+
@GetMapping("/{login}")
33+
fun findOne(@PathVariable login: String) = userRepository
34+
.findByLogin(login) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "This user does not exist!")
35+
36+
}
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
package org.example.controller
1+
package org.example.java_kotlin.controller
22

3+
import org.example.java_kotlin.model.Todo
34
import org.springframework.web.bind.annotation.*
45

56
@RestController
67
@RequestMapping("/todos")
78
class TodoController {
89

910
@GetMapping("/{todoId}")
10-
fun getTodo(@PathVariable("todoId") todoId: Long) {
11+
fun getTodo(@PathVariable todoId: Long) {
1112
// TODO: implement `getTodo`
1213
}
1314

@@ -16,10 +17,9 @@ class TodoController {
1617
// TODO: implement `getAllTodos`
1718
}
1819

19-
// TODO: Research how to implement Model class in Kotlin!
20-
// @PostMapping
21-
// fun saveTodo(TodoClass) {
22-
//
23-
// }
20+
@PostMapping
21+
fun saveTodo(@RequestBody todo: Todo) {
22+
// TODO: implement `saveTodo`
23+
}
2424

2525
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.example.java_kotlin.model
2+
3+
import org.example.java_kotlin.util.toSlug
4+
import java.time.LocalDateTime
5+
import javax.persistence.Entity
6+
import javax.persistence.GeneratedValue
7+
import javax.persistence.Id
8+
import javax.persistence.ManyToOne
9+
10+
@Entity
11+
class User(
12+
var login: String,
13+
var firstname: String,
14+
var lastname: String,
15+
var description: String? = null,
16+
@Id @GeneratedValue var id: Long? = null)
17+
18+
@Entity
19+
class Article(
20+
var title: String,
21+
var headline: String,
22+
var content: String,
23+
@ManyToOne var author: User,
24+
var slug: String = title.toSlug(),
25+
var addedAt: LocalDateTime = LocalDateTime.now(),
26+
@Id @GeneratedValue var id: Long? = null)
27+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.example.java_kotlin.model
2+
3+
import javax.persistence.Entity
4+
import javax.persistence.GeneratedValue
5+
import javax.persistence.Id
6+
7+
/* TODO: Try LATER to place `data` modifier before `class`
8+
keyword to check behaviour when using it with Hibernate */
9+
@Entity
10+
class Todo(
11+
@Id @GeneratedValue var todoId: Long,
12+
var title: String,
13+
var description: String)

0 commit comments

Comments
 (0)