https://kotlinlang.org logo
#http4k
Title
# http4k
r

Razvan

10/10/2020, 8:31 PM
Hi, for a demo I wrote a test fonction about Lenses like this:
Copy code
@Test
    fun `Lens exemple`() {

        data class User(val name: String, val age: Int)

        val idLens = <http://Path.int|Path.int>().of("id")
        val jsonBody = Body.auto<User>().toLens()

        val user: HttpHandler = routes(
            "users/{id}" bind GET to { r: Request ->
                jsonBody.inject(User("Tom", 30 + idLens.extract(r)), Response(OK))
            }
        )

        val responseOk = user(Request(GET, "users/2"))
        val resposeObject = jsonBody.extract(responseOk)
        resposeObject.age shouldBe 32
    }
But I get a Parser error:
Copy code
Signature Parse error: expected '<' or ';' but got  
	Remaining input:  exemple$User;>;
If I move the
User
class out of the function is all good, but I was wandering it it’s supposed to not work or it’s a bug and should I report it (and if so, to whom is it your fault or Jackson’s).
d

dave

10/10/2020, 8:50 PM
tbh, I don't think I've ever tried it with a local class, but if it doesn't work then it's definitely a Jackson (or possibly even Kotlin?) Issue. We just call through straight to the underlying library. There is at least one know issue with Kotlin 1.4 and Jackson (for inline classes) a this could be another?
👍 1
r

Razvan

10/11/2020, 9:57 AM
Doesn’t look like a Jackson error: This test works OK:
Copy code
@Test
    fun jacksonLocalClass() {
        val json = """{"name":"Tom","age":32}"""

        data class User(val name: String, val age: Int)
        val mapper = jacksonObjectMapper()
        val user = mapper.readValue(json, User::class.java)
        val user2: User = mapper.readValue(json)
        println(user)
        println(user2)
        user shouldNot beNull()
    }
I’ll try to dig around the
Body.auto
lens to see if I can figure it out.
So far what I found out is that the problem happens in
ConfigurableJackson.kt
of
http4k-format-jackson
in the
ObjectMapper.write()
on the line
Copy code
val typeRef = jacksonTypeRef<T>()
then in Jackson’s
TypeReference
class this is an object like
Htto4kTest$Lens exemple$$inlined$auto$2$1@2972
(inlined class looks like something you talked about). So that function calls a JDK
Class.java
to `getGenericSuperclass()`that calls
getGenericInfo()
and there the line
Copy code
String signature = getGenericSignature0();
appears the problem.
signature = "Lcom/fasterxml/jackson/core/type/TypeReference<Ltest/Http4KTest$Lens exemple$User;>;"
the ending does match the unexpected chars the exception is talking about.
d

dave

10/11/2020, 3:06 PM
have you got the entire of that http4klenstest ?
r

Razvan

10/11/2020, 3:07 PM
can’t find how
getGenericSignature0()
is implemented as it’s defined as
Copy code
// Generic signature handling
private native String getGenericSignature0();
Got that debugging that test going in each function/method.
Overkill of time for a simple workaround, but wanted to have a simple exemple to report it to Jackson or Kotlin, but can’t as in only jackson test it does not happen.
d

dave

10/11/2020, 3:22 PM
have you got the simple test that we can use for just the lenses version?
This seems to work ok for me
Copy code
package org.http4k

import org.http4k.core.Body
import org.http4k.core.Method
import org.http4k.core.Request
import org.http4k.format.Jackson.auto
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

class `Bug??` {
    @Test
    fun lensTest() {
        val json = """{"name":"Tom","age":32}"""

        data class User(val name: String, val age: Int)

        assertEquals(Body.auto<User>().toLens()(Request(<http://Method.POST|Method.POST>, "").body(json)), User("Tom", 32))
    }
}
r

Razvan

10/11/2020, 3:26 PM
Simple one that does not work:
Copy code
@Test
    fun `Lens exemple`() {
        data class User(val name: String, val age: Int)
        val jsonBody: BiDiBodyLens<User> = Body.auto<User>().toLens()
        val tom = User("Tom", 30)
        val response = jsonBody.inject(tom,  Response(OK))
        println(response.bodyString())
    }
yes yours work for me too
d

dave

10/12/2020, 8:01 AM
So to summarise - that test fails unless the data class is moved outside of the method. All really that is happening here is that the code is going through several layers of inlining and a lambda. I suppose we could modify the test to successively inline the functions until it works... but at this point TBH I think it does look like a Kotlin compiler issue of some type
r

Razvan

10/12/2020, 10:37 AM
Yes, that's right. I can't see what to do more than that or how to report it, so let's move to something more useful than trying to debug the compiler issues which is way over my head 😄 . Thanks for your time.
3 Views