0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kotlinサーバーサイドプログラミング実践開発で詰まった箇所の対応

Posted at

この記事について

Kotlin学習のため、以下の「Kotlin サーバーサイドプログラミング実践開発」を読んでいました。書籍の動作確認環境はcorretto-11でしたが、coretto-17を使用したところ複数詰まる箇所があったため共有します。

MyBatisGeneratorのバージョンが違う(5章、6章)

書籍だと以下のバージョンが指定されていますが、これでは動作しませんでした。

id("com.arenagod.gradle.MybatisGenerator") version "2.4"

以下のバージョンを指定すると、動作しました。

id("com.thinkimi.gradle.MybatisGenerator") version "2.4"

BookWithRentalMapperExtentions.ktがコンパイルエラーになる(6章-4)

書籍では、下記のような記述でBookWithRentalMapperを使用するExtentionsが書かれています。import含めて書籍の内容と揃えてもコンパイルエラーとなってしまいました。


private val columnList = listOf(...)

fun BookWithRentalMapper.select(): List<BookWithRentalRecord> {
    val selectStatement = select(columnList).from(Book, "b") {
        leftJoin(Rental, "r") {
            on(Book.id, equalTo(Rental.bookId)
        }
    }
    return selectMany(selectStatement)
}

そこで、以下のサイトの記述を真似て、直接SQLを書いたところ動作しました。

@Mapper
interface BookWithRentalMapper {

    @Select(
        "SELECT b.id, b.title, b.author, b.release_date, r.user_id, r.rental_datetime, r.return_deadline FROM book b left join rental r on b.id = r.book_id"
    )
    @Results(
        id = "BookWithRentalResult",
        value = [
            Result(column = "id", property = "id", id = true),
            Result(column = "title", property = "title"),
            Result(column = "author", property = "author"),
            Result(column = "release_date", property = "releaseDate"),
            Result(column = "user_id", property = "userId"),
            Result(column = "rental_datetime", property = "rentalDatetime"),
            Result(column = "return_deadline", property = "returnDeadline")
        ]
    )
    fun selectMany(): List<BookWithRentalRecord>
}

MyBatis+Kotlinで調べても公式ドキュメント含めて情報が少ない気がします。。。
あまりこの組み合わせはメジャーじゃないのでしょうか?

SecurityConfigがコンパイルエラーになる(7章-1)

バージョンの都合か書籍のSecurityConfigの内容をそのまま使用することが出来なかったです。そこで以下のように書き換えました。

'authorizeRequests()' はバージョン 6.1 以降は非推奨かつ廃止予定になっていますのように非推奨の書き方だらけですが、SpringSecurityの詳細を学ぶことが主目的では無いため良いとしました。

package com.book.manager.bookmanager.presentation.config

import com.book.manager.bookmanager.application.service.AuthenticationService
import com.book.manager.bookmanager.application.service.BookManagerUserDetailsService
import com.book.manager.bookmanager.domain.enum.RoleType
import com.book.manager.bookmanager.presentation.handler.BookManagerAccessDeniedHandler
import com.book.manager.bookmanager.presentation.handler.BookManagerAuthenticationEntryPoint
import com.book.manager.bookmanager.presentation.handler.BookManagerAuthenticationFailurehandler
import com.book.manager.bookmanager.presentation.handler.BookManagerAuthenticationSuccessHandler
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.web.SecurityFilterChain
import org.springframework.web.cors.CorsConfiguration
import org.springframework.web.cors.CorsConfigurationSource
import org.springframework.web.cors.UrlBasedCorsConfigurationSource

@Configuration
@EnableWebSecurity
class SecurityConfig(
    private val authenticationService: AuthenticationService
) {
    @Bean
    fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
        http.authorizeRequests()
            .requestMatchers("/login").permitAll()
            .requestMatchers("/admin/**").hasAuthority(RoleType.ADMIN.toString())
            .anyRequest().authenticated()
            .and()
            .csrf().disable()
            .formLogin()
            .loginPage("/login")
            .loginProcessingUrl("/login")
            .usernameParameter("email")
            .passwordParameter("pass")
            .successHandler(BookManagerAuthenticationSuccessHandler())
            .failureHandler(BookManagerAuthenticationFailurehandler())
            .and()
            .exceptionHandling()
            .authenticationEntryPoint(BookManagerAuthenticationEntryPoint())
            .accessDeniedHandler(BookManagerAccessDeniedHandler())
            .and()
            .cors()
            .configurationSource(corsConfigurationSource())

        return http.build()
    }

    @Bean
    fun authenticationProvider(): DaoAuthenticationProvider {
        val provider = DaoAuthenticationProvider()
        provider.setUserDetailsService(BookManagerUserDetailsService(authenticationService))
        provider.setPasswordEncoder(BCryptPasswordEncoder())
        return provider
    }

    private fun corsConfigurationSource(): CorsConfigurationSource {
        val corsConfiguration = CorsConfiguration()
        corsConfiguration.addAllowedMethod(CorsConfiguration.ALL)
        corsConfiguration.addAllowedHeader(CorsConfiguration.ALL)
        corsConfiguration.addAllowedOrigin(CorsConfiguration.ALL)
        corsConfiguration.allowCredentials = true

        val corsConfigurationSource = UrlBasedCorsConfigurationSource()
        corsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration)

        return corsConfigurationSource
    }
}

フロントエンドが立ち上げられなかった(7章)

おそらく私の環境起因ですが、フロントエンドサーバーを立ち上げることが出来ず、全てAPIを直接叩きました。

URLがサンプルコードから見つけられず、手打ちしていました。大変だったので主要なURLを置いておきま

ログイン
curl -i -c cookie.txt -H 'Content-Type:application/x-www-form-urlencoded' -X POST -d 'email=user@example.com' -d 'pass=password' http://localhost:8080/login
本の登録
curl -i -b cookie.txt -H 'Content-Type:application/json' -X POST -d '{"id": 101, "title": "New Book", "author": "yamayamaKo", "release_date": "2020-12-12"}' http://localhost:8080/admin/book/register
本の一覧
curl -i -b cookie.txt http://localhost:8080/book/list
レンタル開始
curl -b cookie.txt -H 'Content-Type:application/json' -X POST -d '{"book_id": 100}' http://localhost:8080/rental/start
レンタル終了
curl -b cookie.txt -X DELETE http://localhost:8080/rental/end/100

終わりに

サーバーサイドKotlinの書籍の数が少ない気がしますが、2025年2月時点だと何を読むのが良いのでしょうか?

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?