Skip to content

java.lang.NullPointerException when upgraded to kotlin 2.0 #519

Open
@hanrw

Description

@hanrw

gradle config

plugins {
    id("org.springframework.boot") version "3.3.0"
    id("io.spring.dependency-management") version "1.1.5"
    kotlin("jvm") version "2.0.0"
    kotlin("plugin.spring") version "2.0.0"
}

group = "com.kotlin.npe"
version = "0.0.1-SNAPSHOT"

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

repositories {
    mavenLocal()

    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
    testImplementation("org.mockito.kotlin:mockito-kotlin:5.3.1")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

kotlin {
    compilerOptions {
        freeCompilerArgs.addAll("-Xjsr305=strict")
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

test

@ExtendWith(MockitoExtension::class)
class UserStatusServiceTest {
    @InjectMocks
    lateinit var target: UserStatusServiceImpl

    @Mock
    lateinit var userStatusRepository: UserStatusRepository

    @Test
    fun addStatus() {
        whenever(
            userStatusRepository.findByUserId(
                1L,
            )
        ).thenReturn(
            Optional.empty()
        )

        target.addStatus(1L)

        val suspension = UserStatus()
        verify(userStatusRepository).save(suspension)
    }
}

service

interface UserStatusService {
    fun addStatus(userId: Long)
}

class UserStatusServiceImpl(private val userStatusRepository: UserStatusRepository) :
    UserStatusService {
    override fun addStatus(userId: Long) {
        val optional = userStatusRepository.findByUserId(userId)
        if (optional.isEmpty) {
            println("[userId: $userId] adding a new status")

            userStatusRepository.save(UserStatus())
        } else {
            println("[userId: $userId] status already exists")
        }
    }
}

repository

@Repository
interface UserStatusRepository : JpaRepository<UserStatus, Long>,
    JpaSpecificationExecutor<UserStatus> {
    fun findByUserId(userId: Long): Optional<UserStatus>
}

data class UserStatus(
    val userId: Long = 1L
)

and got error

WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information
WARNING: Dynamic loading of agents will be disallowed by default in a future release
[userId: 1] adding a new status

java.lang.NullPointerException
	at com.kotlin.npe.reporduce.UserStatusServiceImpl.addStatus(UserStatusService.kt:11)
	at com.kotlin.npe.reporduce.UserStatusServiceTest.addStatus(UserStatusServiceTest.kt:31)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

here's reproducing repo and it works after downgrading to kotlin 1.9.24
archive.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions