Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with replacing Java DTO classes with Kotlin Data classes

Tags:

java

kotlin

dto

I read about Kotlin data classes and thought that they could be pretty useful in cases with describing data transfer objects (DTOs). In my Java project I already has DTO classes written on Java, something like:

public class Tweet {
    private String id;
    private String profileId;
    private String message;

    public Tweet() {}

    public String getId() {
        return id;
    }

    public String getProfileId() {
        return profileId;
    }

    public String getMessage() {
        return message;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setProfileId(String profileId) {
        this.profileId = profileId;
    }

    public Tweet setMessage(String message) {
        this.message = message;
        return this;
    }
}

These DTO classes are stored in separate artifact which I add as a dependency to other artifacts. So, I decided to replace it with Kotlin classes and rewrote mentioned Tweet class on Kotlin, so it started to looks like:

data class Tweet(var id: String? = null,
                 var profileId: String? = null,
                 var message: String? = null)

It's my first experience with Kotlin, so possibly there are something that can looks ugly, but my main issue is - when I try to rebuild artifacts which use my DTOs as dependencies, I get such exception:

at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992) at io.vertx.core.json.Json.decodeValue(Json.java:117) at gk.tweetsched.api.repository.TweetRepository.get(TweetRepository.java:51) at gk.tweetsched.api.repository.TweetRepositoryTest.testGet(TweetRepositoryTest.java:68) Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.DefaultConstructorMarker at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 67 more

As I see according that stacktrace Jackson couldn't deserialize JSON to Tweet Kotlin class.

Here is my Java method where I get that exception:

public Tweet get(String id) {
    try (Jedis jedis = pool.getResource()) {
        return Json.decodeValue(jedis.hget(TWEETS_HASH, id), Tweet.class);
    } catch (Exception e) {
        LOGGER.error(e);
    }
    return null;
}

Where Json class is from 'io.vertx.core.json' package.

How can I fix that issue? Which additional configurations should I make in my Java projects to use Kotlin classes?

like image 818
Gleb Avatar asked Jun 25 '18 09:06

Gleb


1 Answers

By default Jackson needs a parameterless constructor to deserialize JSON to a class - Kotlin data classes do not have one, so you need to add a Jackson module to handle this:

jackson-module-kotlin

Edit: I've read the source for io.vertx.core.json.Json class and it seems that both object mappers used by the class are stored in public static fields.

So to register jackson-module-kotlin you need to include this snippet in your application initialization code (or anywhere else really as long as it is executed before you attempt to deserialize any Kotlin data classes):

Json.mapper.registerModule(new KotlinModule())
Json.prettyMapper.registerModule(new KotlinModule()) 
like image 114
Konrad Botor Avatar answered Oct 29 '22 01:10

Konrad Botor