Hi. Since upgrading to 1.1.3 I have the following ...
# announcements
k
Hi. Since upgrading to 1.1.3 I have the following issue: I have this value object
Copy code
@Embeddable
data class RouterId(val routerId: String) {

    init {
        val octets = routerId.split(":")

        if (octets.size != 6) {
            throw IllegalArgumentException("$routerId does not consist of 6 octets")
        }

        for (octet in octets) {
            Integer.parseInt(octet, 16)
        }
    }

    override fun toString(): String {
        return routerId
    }
}
which now fails with
Copy code
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.text.StringsKt__StringsKt.split, parameter $receiver
	at kotlin.text.StringsKt__StringsKt.split(Strings.kt) ~[kotlin-stdlib-1.1.3.jar:1.1.3]
	at kotlin.text.StringsKt__StringsKt.split$default(Strings.kt:1153) ~[kotlin-stdlib-1.1.3.jar:1.1.3]
	at domain.model.aircraft.RouterId.<init>(RouterId.kt:9) ~[main/:na]
        ....
during creation with JPA. In my
build.gradle
I use
Copy code
plugins {
    id "org.jetbrains.kotlin.jvm" version "1.1.3"
    id "org.jetbrains.kotlin.plugin.noarg" version "1.1.3"
    id "org.jetbrains.kotlin.plugin.jpa" version "1.1.3"

    id "org.springframework.boot" version "1.5.4.RELEASE"
}
any suggestions? The code runs fine using
1.1.2
.
c
kschlesselmann: I believe, it should not actually run in 1.1.2, probably 1.1.3 fixes the bug. the no-arg plugin generates a no-arg constructor, and you have
init {}
which works with a constructor parameter. JPA will call no-arg constructor, then your init will run and will find a
routerId == null
.
k
Yreah, I thought something like that. The code really works in 1.1.2. So what would you suggest in this case?
l
you could just make
routerId
optional or provide a default value like
0:0:0:0:0:0
k
@lovis But this would defeat the purpose of a proper value object
l
I kind of agree, but data classes are not value objects. Your problem is that your framework needs a constructor that you don’t want, so that’s imho the best workaround.
or you move the creation logic to a companion object. (aka factory method) whoops that won’t help here. (but it would be better anyway because now you actually throw in the constructor, which is imho bad)
but what what will break if you use a default
routerId
? you could even add a method
isValid
or something that checks for that particular one
the more I think about it I really don’t see how it defeats the purpose of a value object
k
Why is this data class no value object?
l
because the jvm does not support value objects (aka structs). so data classes are still reference objects, just with an
equals
implementation that makes it behave like a value object would. however, I’m being pedantic here, sorry 😉
The important part is that a “value object” should * be immutable ☑️ * have no identity (i.e equals depends on the fields, not on the object identity) ☑️ * be created in a valid state ☑️ and using
0:0:0:0:0:0
seems like a valid state for the object itself
k
So kotlin wonÄt complain if the routerId is still a val which gets modified by JPA later on?
I'm quite aware that those are not real value objects because the JVM doesn't support that 😉
l
like i said i was being pedantic. it didn’t help you so i’m sorry about that 🙂 it shouldn’t complain. but I don’t know how your framework works, for gson, which uses reflection it does work like that
k
I'm using hibernate here. It was so nice to just use the plugin and have unwanted constructors generated … damn JPA 😛
😄 1