Hey guys, does anyone have a hint what I did wrong...
# announcements
p
Hey guys, does anyone have a hint what I did wrong here?
Copy code
var email: String? = "default"
        set(value) {
            field = setEmail(value)
        }

    fun setEmail(value: String?): String? {
        val emailRegex = Regex("^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*\$")
        val isValidEmail = value != null && emailRegex.matches(value)
        return if (isValidEmail) value else null
    }
The shown field is part of a representation of an old legacy db, which might has a "wrong" email adress in it. Its set by jpa, but I would like to perform the shown operation when the field is set to filter out "wrong" emails. The function is tested and is returning the correct result. However, email is always set as "default". What did I do wrong here? Thanks ahead!
n
In your
setEmail
function, you never actually set the email. You need a statement such as
email = value
, instead of just returning
value
. You also should be able to move the whole contents of the
setEmail
function into the
set(value)
function, though I'm not 100% sure JPA will use it (I'm pretty sure, though, because Kotlin names the generated get and set functions pretty predictably for precisely this reason).
p
well, I thought I did it in the setter:
field = setEmail(value)
First, I had the method body in the setter, but I just moved it out of it to test the regex is working correctly.
n
The problem is that your setter never gets called. JPA presumably goes to find a function called
setEmail
and passes in the email. Because you created a separate function named
setEmail
, Kotlin probably didn't name your setter
setEmail
, so it's that separate function that gets called, and that function never sets anything.
m
yeah that should be it, your setEmail() overrides the var email: set()
when you declare a public var in a class, kotlin creates getEmail() and setEmail() functions in order to be compatible with Java I believe
p
Well, I guess I have a misunderstanding of setters. :
Copy code
class TestEmployee {
        var email: String? = "test"
            private set(value) {
                field = "setter"
            }
    }

    @Test
    fun `should set field correctly`() {
        TestEmployee().email shouldBe "setter"
    }
org.opentest4j.AssertionFailedError: expected:<"setter"> but was:<"test">
I thought that is the correct way to do it.
n
A setter is the function that gets invoked when you assign to a variable:
Copy code
class TestEmployee {
        var email: String? = "test"
            private set(value) {
                field = "setter"
            }
    }
    @Test
    fun `should set field correctly`() {
        val emp = TestEmployee()
        emp.email = "anythingYouSay"
        emp.email shouldBe "setter"
    }
When you say
emp.email = "something"
, your setter gets called with
"something"
as the parameter named
value
. In the setter above, the setter ignores the parameter, but typically you'd use it for something.
For validation logic like what you have, you'd put that in the setter to guarantee that no matter what someone tries to set the email to, it will always be valid or null. So if I tried to do this:
Copy code
myEmployee.email = "notanemail"
the
email
would just be null.
In the test code you put, it looks like you were assuming that a setter was a way to give a variable a default value? Is that right?
p
Thanks for the explanation. I found the error by running your example: My setter was marked
private
. I didn't realize it until I tried to run your example and the IDE prompted me with the setter being private..
n
Ah, that's also true. But your test would have failed anyway, because you never actually called the setter.
p
So, just for clarity: Sometimes the most simple concepts don't come to mind..
Now let's see what JPA does.. 😛
m
emp.email = "blah" will call the setter
that code gets converted to emp.setEmail("blah") if I'm not mistaken
j
Mmmm there should be a lint error in
setEmail
...
p
Okay, I'm back: It works as expected. Thanks a lot for the patience I guys, I'm still baffled that I didn't set it up correctly right from the start. Have a good one!
👍 1
m
One last remark: your
setEmail()
function has a bad name, since it doesn’t set anything. A better name would be
checkEmail
or
validEmailOrNull
, for example.
👍 1