[SOLVED] Issues with serializable lambdas and SAM interfaces

I’m trying to use a java library for distributed background job processing called JobRunr (https://www.jobrunr.io/en/) from Kotlin.
JobRunr works by serializing a lambda containing the code that you want to run in your background job into a database (eg. Redis), where other servers running JobRunr can pick up the lambda, deserialize it and execute it.
JobRunr achieves this with a SAM (Functional) interface, that implements serializable.
It seems that Kotlin does not compile serializable SAM lambdas in the same way as Java does and that causes problems.
Here is the link to an issue I opened on JobRunr’s GitHub about the same problem: https://github.com/jobrunr/jobrunr/issues/63.

Does this issue have a quick and dirty workaround, or do I need to open a YouTrack ticket for this?

Thanks.

The issue AFAICT is that kotlin lambdas aren’t serializable. The fact that it extends Serializable means nothing since that interface is cosmetic at best in java/JVM. You would need to figure out a separate way to serialize kotlin lambdas.
It looks like your code depends on the way java implements serialization for lambdas. For this reason you also prevent using any “normal” implementation of your functional interface.
Maybe you could use reflection to serialize kotlin lambdas. Not sure how to do it exactly though.

You could try opening a ticket but I seem to remember that the desicion to make lambdas not serializable is as designed. That doesn’t mean it can’t be changed. Also it wouldn’t surprise me if there is a ticket for this already.

1 Like

@Wasabi375
Hi,
Do you think I could maybe work around the issue by using an object, and manually implementing the functions, that the java serialized lambda implements, such as:

jobScheduler.enqueue(object: JobLambda {
    override fun run() {
        println("Hello")
    }

    fun writeReplace() {
        TODO("Implementation here")
    }
})

I think that should work.

I ended up just using a Java wrapper method:

public void helloWorldJob(JobScheduler jobScheduler) {
    jobScheduler.enqueue(() -> System.out.println("Hello"));
}
2 Likes