From 0e4a4db8764785ca6ac37aff5d1e8eef80e42790 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Fri, 21 Aug 2020 17:24:10 +0900 Subject: [PATCH 01/19] =?UTF-8?q?CRUD=20=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/controller/PostController.kt | 31 +++++++++++++ .../kotlinweb/board/model/AbstractDatabase.kt | 26 +++++++++++ .../com/example/kotlinweb/board/model/Post.kt | 10 ++++ .../board/repository/PostCrudRepository.kt | 25 ++++++++++ .../board/repository/PostRepository.kt | 8 ++++ .../kotlinweb/board/service/BoardService.kt | 10 ++++ .../board/service/BoardServiceImpl.kt | 32 +++++++++++++ .../kotlinweb/controller/HealthController.kt | 2 +- .../board/service/BoardServiceImplTest.kt | 46 +++++++++++++++++++ 9 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/com/example/kotlinweb/board/controller/PostController.kt create mode 100644 src/main/kotlin/com/example/kotlinweb/board/model/AbstractDatabase.kt create mode 100644 src/main/kotlin/com/example/kotlinweb/board/model/Post.kt create mode 100644 src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt create mode 100644 src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt create mode 100644 src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt create mode 100644 src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt create mode 100644 src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt diff --git a/src/main/kotlin/com/example/kotlinweb/board/controller/PostController.kt b/src/main/kotlin/com/example/kotlinweb/board/controller/PostController.kt new file mode 100644 index 0000000..befdc16 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/controller/PostController.kt @@ -0,0 +1,31 @@ +package com.example.kotlinweb.board.controller +import com.example.kotlinweb.board.model.Post +import com.example.kotlinweb.board.service.BoardService +import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* + +@RestController +class BoardController(private val boardService: BoardService) { + + @GetMapping(value = ["/board"]) + fun findAllPosts(): ResponseEntity {; + return ResponseEntity(boardService.findPosts(), HttpStatus.OK); + } + + @PostMapping(value = ["/board"]) + fun savePost(@RequestBody post: Post): ResponseEntity { + return ResponseEntity(boardService.savePost(post), HttpStatus.CREATED); + } + + @PutMapping(value = ["/board/{id}"]) + fun updatePost(@RequestBody post: Post, @PathVariable id: String): ResponseEntity { + return ResponseEntity(boardService.updatePost(post), HttpStatus.OK); + } + + @DeleteMapping(value = ["/board"]) + fun deletePost(@RequestBody post: Post): ResponseEntity { + return ResponseEntity(boardService.deletePost(post), HttpStatus.OK); + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/model/AbstractDatabase.kt b/src/main/kotlin/com/example/kotlinweb/board/model/AbstractDatabase.kt new file mode 100644 index 0000000..b84136b --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/model/AbstractDatabase.kt @@ -0,0 +1,26 @@ +package com.example.kotlinweb.board.model + +class AbstractDatabase( + +) { + companion object { + var posts: MutableList = mutableListOf() + + fun create(obj: Any?) { + obj?.let { + posts.add(obj) + } + } + + fun delete(obj: Any?) { + obj?.let { + obj as Post + posts.removeAt(obj.id.toInt() - 1) + } + } + + fun read(): MutableList { + return posts; + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt b/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt new file mode 100644 index 0000000..922cd33 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt @@ -0,0 +1,10 @@ +package com.example.kotlinweb.board.model + +import java.time.LocalDateTime + +class Post( + val id: Long, val title: String, val writer: String, val text: String +) { + val createDate: LocalDateTime = LocalDateTime.now() + var updateDate: LocalDateTime = LocalDateTime.now() +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt b/src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt new file mode 100644 index 0000000..aa4f501 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt @@ -0,0 +1,25 @@ +package com.example.kotlinweb.board.repository + +import com.example.kotlinweb.board.model.AbstractDatabase +import com.example.kotlinweb.board.model.Post +import org.springframework.stereotype.Repository + +@Repository +class PostCrudRepository : PostRepository { + + override fun save(post: Post) { + AbstractDatabase.create(post); + } + + override fun find(): MutableList { + return AbstractDatabase.read() + } + + override fun findById(postId: Long): Post { + return find().map { any -> any as Post }.first { post -> post.id == postId } + } + + override fun delete(post: Post) { + return AbstractDatabase.delete(post) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt b/src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt new file mode 100644 index 0000000..0c983db --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt @@ -0,0 +1,8 @@ +package com.example.kotlinweb.board.repository + +interface PostRepository { + fun save(t: T) + fun find(): Any + fun findById(t: Long): Any + fun delete(t: T) +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt b/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt new file mode 100644 index 0000000..0632ce3 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt @@ -0,0 +1,10 @@ +package com.example.kotlinweb.board.service + +import com.example.kotlinweb.board.model.Post + +interface BoardService { + fun savePost(post: Post) + fun findPosts(): Any + fun updatePost(post: Post) + fun deletePost(post: Post) +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt b/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt new file mode 100644 index 0000000..859e8a7 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt @@ -0,0 +1,32 @@ +package com.example.kotlinweb.board.service + +import com.example.kotlinweb.board.model.Post +import com.example.kotlinweb.board.repository.PostRepository +import org.springframework.stereotype.Service + +@Service +class BoardServiceImpl(private val postRepository: PostRepository) : BoardService { + + override fun savePost(post: Post) { + postRepository.save(post) + } + + override fun findPosts(): Any { + return postRepository.find() + } + + override fun updatePost(post: Post) { + var foundPost: Post = postRepository.findById(post.id) as Post + foundPost?.let { + postRepository.delete(post) + postRepository.save(post) + } + } + + override fun deletePost(post: Post) { + var foundPost: Post = postRepository.findById(post.id) as Post + foundPost?.let { + postRepository.delete(post) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/controller/HealthController.kt b/src/main/kotlin/com/example/kotlinweb/controller/HealthController.kt index fed3266..c232c49 100644 --- a/src/main/kotlin/com/example/kotlinweb/controller/HealthController.kt +++ b/src/main/kotlin/com/example/kotlinweb/controller/HealthController.kt @@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.ResponseBody @Controller -class HealthController{ +class HealthController { @get:ResponseBody @get:GetMapping(value = ["/health_check.html"]) diff --git a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt new file mode 100644 index 0000000..5f414c9 --- /dev/null +++ b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt @@ -0,0 +1,46 @@ +package com.example.kotlinweb.board.service + +import com.example.kotlinweb.board.model.AbstractDatabase +import com.example.kotlinweb.board.model.Post +import com.example.kotlinweb.board.repository.PostCrudRepository +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertAll +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.junit.jupiter.SpringExtension + +@ExtendWith(SpringExtension::class) +@SpringBootTest +internal class BoardServiceImplTest( + @Autowired val repository: PostCrudRepository +) { + + @Test + fun savePostTest() { + val post: Post = Post(1L, "Test Title", "KDH", "memo") + val boardService: BoardService = BoardServiceImpl(repository) + boardService.savePost(post) + verify(AbstractDatabase, times(1)).create(Any()) + } + + @Test + fun readPostsTest() { + val post1: Post = Post(1L, "Test Title", "KDH", "memo1") + val post2: Post = Post(2L, "Test Title2", "KDH2", "memo2") + val boardService: BoardService = BoardServiceImpl(repository) + boardService.savePost(post1) + boardService.savePost(post2) + var posts: MutableList = AbstractDatabase.read() + val savedPost1: Post = posts[0] as Post + val savedPost2: Post = posts[1] as Post + assertAll( + "posts", + { Assertions.assertEquals(post1.title, savedPost1.title) }, + { Assertions.assertEquals(post2.writer, savedPost2.writer) } + ) + } +} \ No newline at end of file From 66b2bf3c4052ec750cae4f688e44206ce0b40bf7 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Mon, 5 Oct 2020 23:46:25 +0900 Subject: [PATCH 02/19] =?UTF-8?q?JPA=EB=A1=9C=20=EC=A0=84=ED=99=98?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 11 ++++++++ kotlinweb/test.mv.db | Bin 0 -> 20480 bytes .../board/controller/PostController.kt | 2 +- .../com/example/kotlinweb/board/model/Post.kt | 16 ++++++++++- .../board/repository/PostCrudRepository.kt | 20 +++----------- .../board/service/BoardServiceImpl.kt | 19 ++++++------- .../kotlinweb/config/H2ServerConfiguration.kt | 25 ++++++++++++++++++ src/main/resources/application.properties | 1 - src/main/resources/application.yml | 17 ++++++++++++ .../board/service/BoardServiceImplTest.kt | 1 - 10 files changed, 83 insertions(+), 29 deletions(-) create mode 100644 kotlinweb/test.mv.db create mode 100644 src/main/kotlin/com/example/kotlinweb/config/H2ServerConfiguration.kt delete mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/application.yml diff --git a/build.gradle.kts b/build.gradle.kts index 9a7cabb..0bf6658 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,6 +3,9 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.springframework.boot") version "2.3.2.RELEASE" id("io.spring.dependency-management") version "1.0.9.RELEASE" + id("org.jetbrains.kotlin.plugin.allopen") version "1.3.61" + id("org.jetbrains.kotlin.plugin.jpa") version "1.3.61" + id( "org.jetbrains.kotlin.plugin.noarg") version "1.3.61" kotlin("jvm") version "1.3.72" kotlin("plugin.spring") version "1.3.72" } @@ -16,7 +19,9 @@ repositories { } dependencies { + implementation("com.h2database:h2") implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") @@ -25,6 +30,12 @@ dependencies { } } +allOpen { + annotation("javax.persistence.Entity") + annotation("javax.persistence.MappedSuperclass") + annotation("javax.persistence.Embeddable") +} + tasks.withType { useJUnitPlatform() } diff --git a/kotlinweb/test.mv.db b/kotlinweb/test.mv.db new file mode 100644 index 0000000000000000000000000000000000000000..84fa75b437bf62d2f46759c74d98a820fec5b67c GIT binary patch literal 20480 zcmeI4&1=*^7>ASk1yw5^yhl~!7n?ke77l1y}Qn=HFo5zk%(FM{I# z;U6eYCdp=>eFCvebXfr=chJ??NjkW+vVhp<_<@D>0YL1hYJs6@S?wAUB5x%q+&ovSomC zTdcGJOvl-Se32C)F*?}Fo`Ub%)`bm?GVSKYJI1{i!@OQ z+%tCEz=`E`Vkd$JoLWI@v&ix+Ur>t>;X7#(xq*BG^W>Q=qLjFfO;StvUK;rFbNai7 z`;RqkLrUT$q({ZJ$ku}WzYJmS833+f>>si29xny zaVV33nC0lHia$}w;i}|dO>)@3CWl|=1|?N)FyfkvY%wpJM^u_rC;j4i-8Et@6Ni~? z;(V*8Wz`)j_LM|XdF!#98c2!H?xfB*=900@8p2&@n|>EEqGFQ20i zO8@se_5YI<*3$p~rk2{wezjQI)e69dxACd1rqiaXu3UPp)%1VRt3RGm;Fop$w!&Yv zf1H2$=VVczom$jiL+u>OzjDLD5ClK~1V8`;KmY_l00cl_Z3HU+Z~eP9=%xS5|Do4i G{r@Kt&08D* literal 0 HcmV?d00001 diff --git a/src/main/kotlin/com/example/kotlinweb/board/controller/PostController.kt b/src/main/kotlin/com/example/kotlinweb/board/controller/PostController.kt index befdc16..ab0bd76 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/controller/PostController.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/controller/PostController.kt @@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.* class BoardController(private val boardService: BoardService) { @GetMapping(value = ["/board"]) - fun findAllPosts(): ResponseEntity {; + fun findAllPosts(): ResponseEntity { return ResponseEntity(boardService.findPosts(), HttpStatus.OK); } diff --git a/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt b/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt index 922cd33..cc1a5f2 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt @@ -1,10 +1,24 @@ package com.example.kotlinweb.board.model import java.time.LocalDateTime +import javax.persistence.* + +@Entity class Post( - val id: Long, val title: String, val writer: String, val text: String + + @Id + @GeneratedValue(starategy = GenerationType.AUTO) + val id: Long, + @Column + val title: String, + @Column + val writer: String, + @Column + val text: String ) { + @Column val createDate: LocalDateTime = LocalDateTime.now() + @Column var updateDate: LocalDateTime = LocalDateTime.now() } \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt b/src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt index aa4f501..23bcd94 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt @@ -2,24 +2,12 @@ package com.example.kotlinweb.board.repository import com.example.kotlinweb.board.model.AbstractDatabase import com.example.kotlinweb.board.model.Post +import org.springframework.data.domain.Example +import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository +import javax.persistence.Id @Repository -class PostCrudRepository : PostRepository { +interface PostCrudRepository : JpaRepository { - override fun save(post: Post) { - AbstractDatabase.create(post); - } - - override fun find(): MutableList { - return AbstractDatabase.read() - } - - override fun findById(postId: Long): Post { - return find().map { any -> any as Post }.first { post -> post.id == postId } - } - - override fun delete(post: Post) { - return AbstractDatabase.delete(post) - } } \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt b/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt index 859e8a7..1a0672e 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt @@ -1,32 +1,33 @@ package com.example.kotlinweb.board.service import com.example.kotlinweb.board.model.Post +import com.example.kotlinweb.board.repository.PostCrudRepository import com.example.kotlinweb.board.repository.PostRepository +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service @Service -class BoardServiceImpl(private val postRepository: PostRepository) : BoardService { +class BoardServiceImpl(private val postCrudRepository: PostCrudRepository) : BoardService { override fun savePost(post: Post) { - postRepository.save(post) + postCrudRepository.save(post) } override fun findPosts(): Any { - return postRepository.find() + return postCrudRepository.findAll() } override fun updatePost(post: Post) { - var foundPost: Post = postRepository.findById(post.id) as Post - foundPost?.let { - postRepository.delete(post) - postRepository.save(post) + var foundPost: Post = postCrudRepository.findByIdOrNull(post.id) as Post + if(foundPost != null) { + foundPost = post } } override fun deletePost(post: Post) { - var foundPost: Post = postRepository.findById(post.id) as Post + var foundPost: Post = postCrudRepository.findById(post.id) as Post foundPost?.let { - postRepository.delete(post) + postCrudRepository.delete(post) } } } \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/config/H2ServerConfiguration.kt b/src/main/kotlin/com/example/kotlinweb/config/H2ServerConfiguration.kt new file mode 100644 index 0000000..6b225cd --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/config/H2ServerConfiguration.kt @@ -0,0 +1,25 @@ +package com.example.kotlinweb.config + +import com.zaxxer.hikari.HikariDataSource +import org.h2.tools.Server +import org.springframework.boot.context.properties.ConfigurationProperties +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class H2ServerConfiguration { + + @Bean + @ConfigurationProperties("spring.datasource.hikari") + fun dataSource(): HikariDataSource = run { + val server: Server = h2TcpServer() + return HikariDataSource() + } + + fun h2TcpServer(): Server = Server.createTcpServer( + "-tcp", + "-tcpAllowOthers", + "-ifNotExists", + "-tcpPort", "9092" + "").start() + +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 8b13789..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..813f792 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,17 @@ +spring: + h2: + console: + enabled: true + profiles: + active: local + datasource: + hikari: + jdbc-url: jdbc:h2:mem:test + driver-class-name: org.h2.Driver + username: sa + password: + jpa: + database-platform: H2 + show-sql: true + hibernate: + ddl-auto: create diff --git a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt index 5f414c9..a85a1f1 100644 --- a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt +++ b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt @@ -13,7 +13,6 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.junit.jupiter.SpringExtension -@ExtendWith(SpringExtension::class) @SpringBootTest internal class BoardServiceImplTest( @Autowired val repository: PostCrudRepository From 1d084ca5fc1e19e45ce80561bedf419b39c328b7 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 6 Oct 2020 17:29:53 +0900 Subject: [PATCH 03/19] =?UTF-8?q?JPA=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlinweb/board/model/AbstractDatabase.kt | 26 ------------------- .../com/example/kotlinweb/board/model/Post.kt | 16 +++++++----- .../board/repository/PostCrudRepository.kt | 3 --- .../board/repository/PostRepository.kt | 8 ------ .../kotlinweb/board/service/BoardService.kt | 3 ++- .../board/service/BoardServiceImpl.kt | 17 ++++++++---- .../board/service/BoardServiceImplTest.kt | 13 +++++----- 7 files changed, 30 insertions(+), 56 deletions(-) delete mode 100644 src/main/kotlin/com/example/kotlinweb/board/model/AbstractDatabase.kt delete mode 100644 src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt diff --git a/src/main/kotlin/com/example/kotlinweb/board/model/AbstractDatabase.kt b/src/main/kotlin/com/example/kotlinweb/board/model/AbstractDatabase.kt deleted file mode 100644 index b84136b..0000000 --- a/src/main/kotlin/com/example/kotlinweb/board/model/AbstractDatabase.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.example.kotlinweb.board.model - -class AbstractDatabase( - -) { - companion object { - var posts: MutableList = mutableListOf() - - fun create(obj: Any?) { - obj?.let { - posts.add(obj) - } - } - - fun delete(obj: Any?) { - obj?.let { - obj as Post - posts.removeAt(obj.id.toInt() - 1) - } - } - - fun read(): MutableList { - return posts; - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt b/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt index cc1a5f2..467d941 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt @@ -1,24 +1,28 @@ package com.example.kotlinweb.board.model +import org.hibernate.annotations.CreationTimestamp +import org.hibernate.annotations.UpdateTimestamp import java.time.LocalDateTime import javax.persistence.* - @Entity class Post( @Id - @GeneratedValue(starategy = GenerationType.AUTO) + @GeneratedValue(strategy = GenerationType.AUTO) val id: Long, @Column - val title: String, + var title: String, @Column val writer: String, @Column - val text: String + var text: String ) { @Column - val createDate: LocalDateTime = LocalDateTime.now() + @CreationTimestamp + lateinit var createDate: LocalDateTime + @Column - var updateDate: LocalDateTime = LocalDateTime.now() + @UpdateTimestamp + lateinit var updateDate: LocalDateTime } \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt b/src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt index 23bcd94..fe84a51 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt @@ -1,11 +1,8 @@ package com.example.kotlinweb.board.repository -import com.example.kotlinweb.board.model.AbstractDatabase import com.example.kotlinweb.board.model.Post -import org.springframework.data.domain.Example import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository -import javax.persistence.Id @Repository interface PostCrudRepository : JpaRepository { diff --git a/src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt b/src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt deleted file mode 100644 index 0c983db..0000000 --- a/src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.kotlinweb.board.repository - -interface PostRepository { - fun save(t: T) - fun find(): Any - fun findById(t: Long): Any - fun delete(t: T) -} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt b/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt index 0632ce3..ece68e5 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt @@ -4,7 +4,8 @@ import com.example.kotlinweb.board.model.Post interface BoardService { fun savePost(post: Post) - fun findPosts(): Any + fun findPostbyId(id: Long): Post? + fun findPosts(): MutableList fun updatePost(post: Post) fun deletePost(post: Post) } \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt b/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt index 1a0672e..08e8cec 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt @@ -2,9 +2,10 @@ package com.example.kotlinweb.board.service import com.example.kotlinweb.board.model.Post import com.example.kotlinweb.board.repository.PostCrudRepository -import com.example.kotlinweb.board.repository.PostRepository import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service +import java.time.LocalDateTime +import javax.transaction.Transactional @Service class BoardServiceImpl(private val postCrudRepository: PostCrudRepository) : BoardService { @@ -13,15 +14,21 @@ class BoardServiceImpl(private val postCrudRepository: PostCrudRepository) : Boa postCrudRepository.save(post) } - override fun findPosts(): Any { + override fun findPostbyId(id: Long): Post? { + return postCrudRepository.findByIdOrNull(id) + } + + override fun findPosts(): MutableList { return postCrudRepository.findAll() } + @Transactional override fun updatePost(post: Post) { + print(post.toString()) var foundPost: Post = postCrudRepository.findByIdOrNull(post.id) as Post - if(foundPost != null) { - foundPost = post - } + foundPost.text = post.text + foundPost.title = post.title + foundPost.updateDate = LocalDateTime.now() } override fun deletePost(post: Post) { diff --git a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt index a85a1f1..dd05310 100644 --- a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt +++ b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt @@ -1,17 +1,12 @@ package com.example.kotlinweb.board.service -import com.example.kotlinweb.board.model.AbstractDatabase import com.example.kotlinweb.board.model.Post import com.example.kotlinweb.board.repository.PostCrudRepository import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertAll -import org.junit.jupiter.api.extension.ExtendWith -import org.mockito.Mockito.times -import org.mockito.Mockito.verify import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest -import org.springframework.test.context.junit.jupiter.SpringExtension @SpringBootTest internal class BoardServiceImplTest( @@ -23,7 +18,10 @@ internal class BoardServiceImplTest( val post: Post = Post(1L, "Test Title", "KDH", "memo") val boardService: BoardService = BoardServiceImpl(repository) boardService.savePost(post) - verify(AbstractDatabase, times(1)).create(Any()) + val savedPost: Post? = boardService.findPostbyId(1L) + if (savedPost != null) { + Assertions.assertEquals(post.title, savedPost.title) + } } @Test @@ -33,7 +31,8 @@ internal class BoardServiceImplTest( val boardService: BoardService = BoardServiceImpl(repository) boardService.savePost(post1) boardService.savePost(post2) - var posts: MutableList = AbstractDatabase.read() + + val posts: MutableList = boardService.findPosts() val savedPost1: Post = posts[0] as Post val savedPost2: Post = posts[1] as Post assertAll( From 5b3b4b4ec8d71d67dd2e3439208b93156eac87e7 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 6 Oct 2020 17:40:29 +0900 Subject: [PATCH 04/19] =?UTF-8?q?HIT=20COUNT=20=EA=B0=9C=EB=B0=9C=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/example/kotlinweb/board/model/Post.kt | 6 ++++++ .../kotlinweb/board/service/BoardServiceImplTest.kt | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt b/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt index 467d941..20fceb0 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt @@ -17,7 +17,11 @@ class Post( val writer: String, @Column var text: String + ) { + @Column + var hitCount: Int = 0 + @Column @CreationTimestamp lateinit var createDate: LocalDateTime @@ -25,4 +29,6 @@ class Post( @Column @UpdateTimestamp lateinit var updateDate: LocalDateTime + + fun increaseHitCount() = hitCount++ } \ No newline at end of file diff --git a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt index dd05310..bdba86d 100644 --- a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt +++ b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt @@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertAll import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest +import javax.transaction.Transactional @SpringBootTest internal class BoardServiceImplTest( @@ -14,6 +15,7 @@ internal class BoardServiceImplTest( ) { @Test + @Transactional fun savePostTest() { val post: Post = Post(1L, "Test Title", "KDH", "memo") val boardService: BoardService = BoardServiceImpl(repository) @@ -25,6 +27,7 @@ internal class BoardServiceImplTest( } @Test + @Transactional fun readPostsTest() { val post1: Post = Post(1L, "Test Title", "KDH", "memo1") val post2: Post = Post(2L, "Test Title2", "KDH2", "memo2") @@ -41,4 +44,12 @@ internal class BoardServiceImplTest( { Assertions.assertEquals(post2.writer, savedPost2.writer) } ) } + + @Test + @Transactional + fun increaseHitCount() { + val post1: Post = Post(1L, "Test Title", "KDH", "memo1") + post1.increaseHitCount() + Assertions.assertEquals(post1.hitCount, 1) + } } \ No newline at end of file From 96c155d319f61f119f9bd1a78bdf17ef26204b65 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 6 Oct 2020 17:54:34 +0900 Subject: [PATCH 05/19] =?UTF-8?q?AssertJ=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 + .../kotlinweb/board/service/BoardService.kt | 2 +- .../kotlinweb/board/service/BoardServiceImpl.kt | 2 +- .../board/service/BoardServiceImplTest.kt | 16 ++++++++++++++-- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0bf6658..744b0a4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { testImplementation("org.springframework.boot:spring-boot-starter-test") { exclude(group = "org.junit.vintage", module = "junit-vintage-engine") } + testImplementation("org.assertj:assertj-core:3.13.2") } allOpen { diff --git a/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt b/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt index ece68e5..39ef94b 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt @@ -4,7 +4,7 @@ import com.example.kotlinweb.board.model.Post interface BoardService { fun savePost(post: Post) - fun findPostbyId(id: Long): Post? + fun findPostById(id: Long): Post? fun findPosts(): MutableList fun updatePost(post: Post) fun deletePost(post: Post) diff --git a/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt b/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt index 08e8cec..3b31255 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt @@ -14,7 +14,7 @@ class BoardServiceImpl(private val postCrudRepository: PostCrudRepository) : Boa postCrudRepository.save(post) } - override fun findPostbyId(id: Long): Post? { + override fun findPostById(id: Long): Post? { return postCrudRepository.findByIdOrNull(id) } diff --git a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt index bdba86d..e9ccf08 100644 --- a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt +++ b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt @@ -2,6 +2,7 @@ package com.example.kotlinweb.board.service import com.example.kotlinweb.board.model.Post import com.example.kotlinweb.board.repository.PostCrudRepository +import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertAll @@ -20,9 +21,10 @@ internal class BoardServiceImplTest( val post: Post = Post(1L, "Test Title", "KDH", "memo") val boardService: BoardService = BoardServiceImpl(repository) boardService.savePost(post) - val savedPost: Post? = boardService.findPostbyId(1L) - if (savedPost != null) { + val savedPost: Post? = boardService.findPostById(1L) + savedPost.let { Assertions.assertEquals(post.title, savedPost.title) + assertThat(post.title).isEqualTo(savedPost.title) } } @@ -38,11 +40,17 @@ internal class BoardServiceImplTest( val posts: MutableList = boardService.findPosts() val savedPost1: Post = posts[0] as Post val savedPost2: Post = posts[1] as Post + //assertion assertAll( "posts", { Assertions.assertEquals(post1.title, savedPost1.title) }, { Assertions.assertEquals(post2.writer, savedPost2.writer) } ) + //assertJ + assertAll( + { assertThat(post1.title).isEqualTo(savedPost1.title) }, + { assertThat(post2.writer).isEqualTo(savedPost2.writer) } + ) } @Test @@ -50,6 +58,10 @@ internal class BoardServiceImplTest( fun increaseHitCount() { val post1: Post = Post(1L, "Test Title", "KDH", "memo1") post1.increaseHitCount() + //assertion Assertions.assertEquals(post1.hitCount, 1) + //assertJ + assertThat(post1.hitCount).isEqualTo(1) + } } \ No newline at end of file From 16aa5d637d3b9020e3f67df1db10576983d3a18e Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 6 Oct 2020 17:56:48 +0900 Subject: [PATCH 06/19] =?UTF-8?q?TestCode=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/service/BoardServiceImplTest.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt index e9ccf08..dea4254 100644 --- a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt +++ b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt @@ -18,11 +18,11 @@ internal class BoardServiceImplTest( @Test @Transactional fun savePostTest() { - val post: Post = Post(1L, "Test Title", "KDH", "memo") + val post = Post(1L, "Test Title", "KDH", "memo") val boardService: BoardService = BoardServiceImpl(repository) boardService.savePost(post) val savedPost: Post? = boardService.findPostById(1L) - savedPost.let { + savedPost?.let { Assertions.assertEquals(post.title, savedPost.title) assertThat(post.title).isEqualTo(savedPost.title) } @@ -31,15 +31,15 @@ internal class BoardServiceImplTest( @Test @Transactional fun readPostsTest() { - val post1: Post = Post(1L, "Test Title", "KDH", "memo1") - val post2: Post = Post(2L, "Test Title2", "KDH2", "memo2") + val post1 = Post(1L, "Test Title", "KDH", "memo1") + val post2 = Post(2L, "Test Title2", "KDH2", "memo2") val boardService: BoardService = BoardServiceImpl(repository) boardService.savePost(post1) boardService.savePost(post2) val posts: MutableList = boardService.findPosts() - val savedPost1: Post = posts[0] as Post - val savedPost2: Post = posts[1] as Post + val savedPost1: Post = posts[0] + val savedPost2: Post = posts[1] //assertion assertAll( "posts", @@ -56,7 +56,7 @@ internal class BoardServiceImplTest( @Test @Transactional fun increaseHitCount() { - val post1: Post = Post(1L, "Test Title", "KDH", "memo1") + val post1 = Post(1L, "Test Title", "KDH", "memo1") post1.increaseHitCount() //assertion Assertions.assertEquals(post1.hitCount, 1) From 37e1c3df2f6f7bc65626aadb527bbe8035322a70 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 17 Nov 2020 10:55:34 +0900 Subject: [PATCH 07/19] Event Listener --- ...ostCrudRepository.kt => PostRepository.kt} | 0 .../kotlinweb/board/service/BoardService.kt | 43 ++++++++++++++++--- .../board/service/BoardServiceImpl.kt | 40 ----------------- 3 files changed, 37 insertions(+), 46 deletions(-) rename src/main/kotlin/com/example/kotlinweb/board/repository/{PostCrudRepository.kt => PostRepository.kt} (100%) delete mode 100644 src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt diff --git a/src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt b/src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt similarity index 100% rename from src/main/kotlin/com/example/kotlinweb/board/repository/PostCrudRepository.kt rename to src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt diff --git a/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt b/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt index 39ef94b..24609ae 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt @@ -1,11 +1,42 @@ package com.example.kotlinweb.board.service import com.example.kotlinweb.board.model.Post +import com.example.kotlinweb.board.repository.PostCrudRepository +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional -interface BoardService { - fun savePost(post: Post) - fun findPostById(id: Long): Post? - fun findPosts(): MutableList - fun updatePost(post: Post) - fun deletePost(post: Post) + +@Service +class BoardService(private val postCrudRepository: PostCrudRepository) { + + fun savePost(post: Post) { + postCrudRepository.save(post) + } + + @Transactional(readOnly = true) + fun findPostById(id: Long): Post? { + return postCrudRepository.findByIdOrNull(id) + } + + @Transactional(readOnly = true) + fun findPosts(): MutableList { + return postCrudRepository.findAll() + } + + @Transactional + fun updatePost(post: Post) { + print(post.toString()) + var foundPost: Post = postCrudRepository.findByIdOrNull(post.id) as Post + foundPost.text = post.text + foundPost.title = post.title + } + + @Transactional + fun deletePost(post: Post) { + var foundPost: Post = postCrudRepository.findById(post.id) as Post + foundPost?.let { + postCrudRepository.delete(post) + } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt b/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt deleted file mode 100644 index 3b31255..0000000 --- a/src/main/kotlin/com/example/kotlinweb/board/service/BoardServiceImpl.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.example.kotlinweb.board.service - -import com.example.kotlinweb.board.model.Post -import com.example.kotlinweb.board.repository.PostCrudRepository -import org.springframework.data.repository.findByIdOrNull -import org.springframework.stereotype.Service -import java.time.LocalDateTime -import javax.transaction.Transactional - -@Service -class BoardServiceImpl(private val postCrudRepository: PostCrudRepository) : BoardService { - - override fun savePost(post: Post) { - postCrudRepository.save(post) - } - - override fun findPostById(id: Long): Post? { - return postCrudRepository.findByIdOrNull(id) - } - - override fun findPosts(): MutableList { - return postCrudRepository.findAll() - } - - @Transactional - override fun updatePost(post: Post) { - print(post.toString()) - var foundPost: Post = postCrudRepository.findByIdOrNull(post.id) as Post - foundPost.text = post.text - foundPost.title = post.title - foundPost.updateDate = LocalDateTime.now() - } - - override fun deletePost(post: Post) { - var foundPost: Post = postCrudRepository.findById(post.id) as Post - foundPost?.let { - postCrudRepository.delete(post) - } - } -} \ No newline at end of file From 19d786a0efd0e089de0b3f8e9eb49e558df04f2b Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 17 Nov 2020 14:39:00 +0900 Subject: [PATCH 08/19] Entity Listener --- build.gradle.kts | 5 ++- .../board/event/PostEntityListener.kt | 43 +++++++++++++++++++ .../kotlinweb/board/event/PostSaveEvent.kt | 14 ++++++ .../board/event/PostSaveEventHandler.kt | 22 ++++++++++ .../example/kotlinweb/board/model/Notify.kt | 37 ++++++++++++++++ .../com/example/kotlinweb/board/model/Post.kt | 2 + .../board/repository/NotifyRepository.kt | 10 +++++ .../board/repository/PostRepository.kt | 2 +- .../kotlinweb/board/service/BoardService.kt | 23 ++++++---- .../kotlinweb/board/service/NotifyService.kt | 32 ++++++++++++++ src/main/resources/application.yml | 2 +- ...ServiceImplTest.kt => BoardServiceTest.kt} | 16 ++++--- 12 files changed, 192 insertions(+), 16 deletions(-) create mode 100644 src/main/kotlin/com/example/kotlinweb/board/event/PostEntityListener.kt create mode 100644 src/main/kotlin/com/example/kotlinweb/board/event/PostSaveEvent.kt create mode 100644 src/main/kotlin/com/example/kotlinweb/board/event/PostSaveEventHandler.kt create mode 100644 src/main/kotlin/com/example/kotlinweb/board/model/Notify.kt create mode 100644 src/main/kotlin/com/example/kotlinweb/board/repository/NotifyRepository.kt create mode 100644 src/main/kotlin/com/example/kotlinweb/board/service/NotifyService.kt rename src/test/kotlin/com/example/kotlinweb/board/service/{BoardServiceImplTest.kt => BoardServiceTest.kt} (77%) diff --git a/build.gradle.kts b/build.gradle.kts index 744b0a4..f227dcf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -38,7 +38,9 @@ allOpen { } tasks.withType { - useJUnitPlatform() + useJUnitPlatform { + includeTags("fast") + } } tasks.withType { @@ -47,3 +49,4 @@ tasks.withType { jvmTarget = "11" } } + diff --git a/src/main/kotlin/com/example/kotlinweb/board/event/PostEntityListener.kt b/src/main/kotlin/com/example/kotlinweb/board/event/PostEntityListener.kt new file mode 100644 index 0000000..a065f5e --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/event/PostEntityListener.kt @@ -0,0 +1,43 @@ +package com.example.kotlinweb.board.event + +import com.example.kotlinweb.board.model.Post +import javax.persistence.* + + +class PostEntityListener { + + @PostLoad + fun postLoad(post: Post?) { + println("post load: $post") + } + + @PrePersist + fun prePersist(post: Post?) { + println("pre persist: $post") + } + + @PostPersist + fun postPersist(post: Post?) { + println("post persist: $post") + } + + @PreUpdate + fun preUpdate(post: Post?) { + println("pre update: $post") + } + + @PostUpdate + fun postUpdate(post: Post?) { + println("post update: $post") + } + + @PreRemove + fun preRemove(post: Post?) { + println("pre remove: $post") + } + + @PostRemove + fun postRemove(post: Post?) { + println("post remove: $post") + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/event/PostSaveEvent.kt b/src/main/kotlin/com/example/kotlinweb/board/event/PostSaveEvent.kt new file mode 100644 index 0000000..ad3b151 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/event/PostSaveEvent.kt @@ -0,0 +1,14 @@ +package com.example.kotlinweb.board.event + +data class PostSaveEvent( + private val postId: Long, + private val message: String +) { + fun getPostId(): Long { + return postId + } + + fun getMessage(): String { + return message + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/event/PostSaveEventHandler.kt b/src/main/kotlin/com/example/kotlinweb/board/event/PostSaveEventHandler.kt new file mode 100644 index 0000000..18bc3a7 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/event/PostSaveEventHandler.kt @@ -0,0 +1,22 @@ +package com.example.kotlinweb.board.event + +import com.example.kotlinweb.board.model.Notify +import com.example.kotlinweb.board.service.NotifyDTO +import com.example.kotlinweb.board.service.NotifyService +import org.springframework.context.event.EventListener +import org.springframework.stereotype.Component +import org.springframework.transaction.event.TransactionPhase +import org.springframework.transaction.event.TransactionalEventListener + +@Component +class PostSaveEventHandler( + private val notifyService: NotifyService +) { + // @EventListener + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + fun postSaveEventListener(event: PostSaveEvent) { + println("Event Listen") + notifyService.saveNotify(Notify.of(event.getPostId().toString(), event.getMessage())) + notifyService.sendNotify(NotifyDTO(event.getMessage(), "0")) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/model/Notify.kt b/src/main/kotlin/com/example/kotlinweb/board/model/Notify.kt new file mode 100644 index 0000000..f2bdc41 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/model/Notify.kt @@ -0,0 +1,37 @@ +package com.example.kotlinweb.board.model + +import org.hibernate.annotations.CreationTimestamp +import org.hibernate.annotations.UpdateTimestamp +import java.time.LocalDateTime +import javax.persistence.* + + +@Entity +class Notify( + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + val id: Long?, + + @Column + var postId: String, + + @Column + val message: String + +) { + companion object { + fun of(postId: String, message: String): Notify { + return Notify(null, postId, message) + } + } + + @Column + @CreationTimestamp + lateinit var createDate: LocalDateTime + + @Column + @UpdateTimestamp + lateinit var updateDate: LocalDateTime + +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt b/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt index 20fceb0..fa89d92 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/model/Post.kt @@ -1,11 +1,13 @@ package com.example.kotlinweb.board.model +import com.example.kotlinweb.board.event.PostEntityListener import org.hibernate.annotations.CreationTimestamp import org.hibernate.annotations.UpdateTimestamp import java.time.LocalDateTime import javax.persistence.* @Entity +@EntityListeners(PostEntityListener::class) class Post( @Id diff --git a/src/main/kotlin/com/example/kotlinweb/board/repository/NotifyRepository.kt b/src/main/kotlin/com/example/kotlinweb/board/repository/NotifyRepository.kt new file mode 100644 index 0000000..6eb4a1d --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/repository/NotifyRepository.kt @@ -0,0 +1,10 @@ +package com.example.kotlinweb.board.repository + +import com.example.kotlinweb.board.model.Notify +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface NotifyRepository : JpaRepository { + +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt b/src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt index fe84a51..633cbeb 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/repository/PostRepository.kt @@ -5,6 +5,6 @@ import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository @Repository -interface PostCrudRepository : JpaRepository { +interface PostRepository : JpaRepository { } \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt b/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt index 24609ae..0e0fe2a 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/service/BoardService.kt @@ -1,42 +1,49 @@ package com.example.kotlinweb.board.service +import com.example.kotlinweb.board.event.PostSaveEvent import com.example.kotlinweb.board.model.Post -import com.example.kotlinweb.board.repository.PostCrudRepository +import com.example.kotlinweb.board.repository.PostRepository +import org.springframework.context.ApplicationEventPublisher import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service -class BoardService(private val postCrudRepository: PostCrudRepository) { +class BoardService( + private val postRepository: PostRepository, + private val applicationEventPublisher: ApplicationEventPublisher +) { + @Transactional fun savePost(post: Post) { - postCrudRepository.save(post) + postRepository.save(post) + applicationEventPublisher.publishEvent(PostSaveEvent(post.id, "게시글 작성이 완료 되었습니다.")) } @Transactional(readOnly = true) fun findPostById(id: Long): Post? { - return postCrudRepository.findByIdOrNull(id) + return postRepository.findByIdOrNull(id) } @Transactional(readOnly = true) fun findPosts(): MutableList { - return postCrudRepository.findAll() + return postRepository.findAll() } @Transactional fun updatePost(post: Post) { print(post.toString()) - var foundPost: Post = postCrudRepository.findByIdOrNull(post.id) as Post + var foundPost: Post = postRepository.findByIdOrNull(post.id) as Post foundPost.text = post.text foundPost.title = post.title } @Transactional fun deletePost(post: Post) { - var foundPost: Post = postCrudRepository.findById(post.id) as Post + var foundPost: Post = postRepository.findById(post.id) as Post foundPost?.let { - postCrudRepository.delete(post) + postRepository.delete(post) } } } \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/board/service/NotifyService.kt b/src/main/kotlin/com/example/kotlinweb/board/service/NotifyService.kt new file mode 100644 index 0000000..72d4aeb --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/board/service/NotifyService.kt @@ -0,0 +1,32 @@ +package com.example.kotlinweb.board.service + +import com.example.kotlinweb.board.model.Notify +import com.example.kotlinweb.board.repository.NotifyRepository +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Propagation +import org.springframework.transaction.annotation.Transactional +import java.lang.RuntimeException + +@Service +class NotifyService(private val notifyRepository: NotifyRepository) { + +// 트랜잭션이 이미 커밋되거나 롤백되었지만 트랜잭션 리소스가 여전히 활성화되어 있고 액세스할 수 있을 수 있다. +// 결과적으로, 이 시점에서 트리거된 데이터 액세스 코드는 별도의 트랜잭션에서 실행해야 한다고 명시적으로 선언하지 않는 한, +// 원래 트랜잭션에 여전히 "참여"하여 일부 정리(더 이상 커밋하지 않음!)를 수행할 수 있다. +// 따라서: 여기서 호출되는 모든 트랜잭션 작업에는 REQUIRES_NEW 사용하십시오. + + @Transactional(propagation = Propagation.REQUIRES_NEW) + fun saveNotify(notify: Notify) { + notifyRepository.save(notify) +// throw RuntimeException() + } + + fun sendNotify(notifyDTO: NotifyDTO) { + println("Notify Send = $notifyDTO") + } +} + +data class NotifyDTO( + val message: String, + val userId: String +) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 813f792..0f65d15 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -14,4 +14,4 @@ spring: database-platform: H2 show-sql: true hibernate: - ddl-auto: create + ddl-auto: update diff --git a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceTest.kt similarity index 77% rename from src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt rename to src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceTest.kt index dea4254..2e46407 100644 --- a/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceImplTest.kt +++ b/src/test/kotlin/com/example/kotlinweb/board/service/BoardServiceTest.kt @@ -1,25 +1,29 @@ package com.example.kotlinweb.board.service import com.example.kotlinweb.board.model.Post -import com.example.kotlinweb.board.repository.PostCrudRepository +import com.example.kotlinweb.board.repository.PostRepository import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertAll import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest +import org.springframework.context.ApplicationEventPublisher import javax.transaction.Transactional @SpringBootTest -internal class BoardServiceImplTest( - @Autowired val repository: PostCrudRepository +internal class BoardServiceTest( + @Autowired val repository: PostRepository, + @Autowired val applicationEventPublisher: ApplicationEventPublisher ) { @Test + @Tag("fast") @Transactional fun savePostTest() { val post = Post(1L, "Test Title", "KDH", "memo") - val boardService: BoardService = BoardServiceImpl(repository) + val boardService: BoardService = BoardService(repository, applicationEventPublisher) boardService.savePost(post) val savedPost: Post? = boardService.findPostById(1L) savedPost?.let { @@ -29,11 +33,12 @@ internal class BoardServiceImplTest( } @Test + @Tag("fast") @Transactional fun readPostsTest() { val post1 = Post(1L, "Test Title", "KDH", "memo1") val post2 = Post(2L, "Test Title2", "KDH2", "memo2") - val boardService: BoardService = BoardServiceImpl(repository) + val boardService: BoardService = BoardService(repository, applicationEventPublisher) boardService.savePost(post1) boardService.savePost(post2) @@ -54,6 +59,7 @@ internal class BoardServiceImplTest( } @Test + @Tag("fast") @Transactional fun increaseHitCount() { val post1 = Post(1L, "Test Title", "KDH", "memo1") From edd5c5ec02ab2b54a71eb9e0edddd0904080269a Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 17 Nov 2020 14:53:47 +0900 Subject: [PATCH 09/19] deploy --- deploy/mark.yaml | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 deploy/mark.yaml diff --git a/deploy/mark.yaml b/deploy/mark.yaml new file mode 100644 index 0000000..eb9680e --- /dev/null +++ b/deploy/mark.yaml @@ -0,0 +1,46 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mark-app + namespace: i-kakao-com + labels: + app: mark-app +spec: + selector: + matchLabels: + app: mark-app + replicas: 2 + template: + metadata: + labels: + app: mark-app + spec: + containers: + - name: mark-app + image: idock.daumkakao.io/mark-d2hub/mark-repository:lastest + imagePullPolicy: Always + resources: + limits: + cpu: 1 + memory: 1Gi + requests: + cpu: 1 + memory: 768Mi + ports: + - containerPort: 8080 + env: + - name: application_name + value: mark-app + - name: instance_name + value: 8080 + readinessProbe: + httpGet: + path: /health_check.html + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 5 + lifecycle: + preStop: + exec: + command: ["/bin/sleep","2"] + terminationGracePeriodSeconds: 60 \ No newline at end of file From 3466e73f5c6da90aa2ffc7c763dea5dd9d102737 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 17 Nov 2020 14:55:11 +0900 Subject: [PATCH 10/19] deploy --- deploy/mark.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/mark.yaml b/deploy/mark.yaml index eb9680e..711f370 100644 --- a/deploy/mark.yaml +++ b/deploy/mark.yaml @@ -2,7 +2,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: mark-app - namespace: i-kakao-com + namespace: mark-space labels: app: mark-app spec: From b771d92f9c47990cca7903871e53aaf77300a7b5 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 17 Nov 2020 14:55:53 +0900 Subject: [PATCH 11/19] deploy --- deploy/mark.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/mark.yaml b/deploy/mark.yaml index 711f370..0d904c3 100644 --- a/deploy/mark.yaml +++ b/deploy/mark.yaml @@ -17,7 +17,7 @@ spec: spec: containers: - name: mark-app - image: idock.daumkakao.io/mark-d2hub/mark-repository:lastest + image: idock.daumkakao.io/mark-d2hub/mark-repository imagePullPolicy: Always resources: limits: From fc5c2ed393eb6d4cba764838d662ff72ebfe8527 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 17 Nov 2020 14:59:00 +0900 Subject: [PATCH 12/19] deploy --- deploy/mark.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/mark.yaml b/deploy/mark.yaml index 0d904c3..e0b12cf 100644 --- a/deploy/mark.yaml +++ b/deploy/mark.yaml @@ -17,7 +17,7 @@ spec: spec: containers: - name: mark-app - image: idock.daumkakao.io/mark-d2hub/mark-repository + image: idock.daumkakao.io/mark-d2hub/mark-repository:rule0 imagePullPolicy: Always resources: limits: From 4a2f321758642a1647d19d1538a53ec0e290b705 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 17 Nov 2020 15:02:45 +0900 Subject: [PATCH 13/19] deploy --- .../com/example/kotlinweb/board/controller/PostController.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/com/example/kotlinweb/board/controller/PostController.kt b/src/main/kotlin/com/example/kotlinweb/board/controller/PostController.kt index ab0bd76..9d72853 100644 --- a/src/main/kotlin/com/example/kotlinweb/board/controller/PostController.kt +++ b/src/main/kotlin/com/example/kotlinweb/board/controller/PostController.kt @@ -15,6 +15,7 @@ class BoardController(private val boardService: BoardService) { @PostMapping(value = ["/board"]) fun savePost(@RequestBody post: Post): ResponseEntity { + println("hello") return ResponseEntity(boardService.savePost(post), HttpStatus.CREATED); } From 27c34d595a8f9b536ea70093f8260e6bdbf21bdc Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 17 Nov 2020 15:07:40 +0900 Subject: [PATCH 14/19] deploy --- deploy/mark.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/mark.yaml b/deploy/mark.yaml index e0b12cf..1a47229 100644 --- a/deploy/mark.yaml +++ b/deploy/mark.yaml @@ -17,7 +17,7 @@ spec: spec: containers: - name: mark-app - image: idock.daumkakao.io/mark-d2hub/mark-repository:rule0 + image: idock.daumkakao.io/mark-d2hub/mark-repository:mark imagePullPolicy: Always resources: limits: From bccf0de16548de21869a316d4f916f81b6955797 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 17 Nov 2020 15:21:14 +0900 Subject: [PATCH 15/19] deploy --- Dockerfile | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e04d215 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM adoptopenjdk/openjdk11:latest + +ARG HEAP_SIZE +ENV HEAP_SIZE=${HEAP_SIZE:-512M} +ARG NEW_SIZE +ENV NEW_SIZE=${NEW_SIZE:-256M} + +ADD . . + +RUN ["./gradlew", "clean", "build", "-x","test"] + +ENTRYPOINT java -server -Xms${HEAP_SIZE} -Xmx${HEAP_SIZE} -XX:NewSize=${NEW_SIZE} -XX:MaxNewSize=${NEW_SIZE} -Djava.net.preferIPv4Stack=true -Djava.security.egd=file:/dev/./urandom -jar /build/libs/springwebproject-0.0.1-SNAPSHOT.jar \ No newline at end of file From 40ea599f737b307178c412dff842c370543a9f41 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Tue, 17 Nov 2020 15:54:33 +0900 Subject: [PATCH 16/19] deploy --- deploy/mark.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/mark.yaml b/deploy/mark.yaml index 1a47229..bf5e3ce 100644 --- a/deploy/mark.yaml +++ b/deploy/mark.yaml @@ -17,7 +17,7 @@ spec: spec: containers: - name: mark-app - image: idock.daumkakao.io/mark-d2hub/mark-repository:mark + image: idock.daumkakao.io/mark-d2hub/mark-repository:latest imagePullPolicy: Always resources: limits: @@ -25,7 +25,7 @@ spec: memory: 1Gi requests: cpu: 1 - memory: 768Mi + memory: 1Gi ports: - containerPort: 8080 env: From b7af788ee58188eb48e1f6f4f1564c5e4bc71f39 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Wed, 18 Nov 2020 15:48:23 +0900 Subject: [PATCH 17/19] deploy --- deploy/mark.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/mark.yaml b/deploy/mark.yaml index bf5e3ce..514f83c 100644 --- a/deploy/mark.yaml +++ b/deploy/mark.yaml @@ -32,7 +32,7 @@ spec: - name: application_name value: mark-app - name: instance_name - value: 8080 + value: "8080" readinessProbe: httpGet: path: /health_check.html From 464b465f2395e845edb6a2b3f9937338a13c5b21 Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Wed, 18 Nov 2020 18:32:05 +0900 Subject: [PATCH 18/19] deploy --- deploy/mark.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/mark.yaml b/deploy/mark.yaml index 514f83c..4968a36 100644 --- a/deploy/mark.yaml +++ b/deploy/mark.yaml @@ -9,7 +9,7 @@ spec: selector: matchLabels: app: mark-app - replicas: 2 + replicas: 1 template: metadata: labels: From 02a3ef6fcd55bac9ba103fec5238635dafd412ab Mon Sep 17 00:00:00 2001 From: "mark.kang" Date: Thu, 19 Nov 2020 08:53:14 +0900 Subject: [PATCH 19/19] 123 --- deploy/mark.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/mark.yaml b/deploy/mark.yaml index 4968a36..c0e82fd 100644 --- a/deploy/mark.yaml +++ b/deploy/mark.yaml @@ -22,7 +22,7 @@ spec: resources: limits: cpu: 1 - memory: 1Gi + memory: 300Mi requests: cpu: 1 memory: 1Gi