java.lang.NoSuchMethodError: 'com.google.protobuf.Timestamp com.google.protobuf.Timestamp$Builder.build()'

901 views
Skip to first unread message

Daniele Segato

unread,
Mar 2, 2023, 5:35:54 AM3/2/23
to Protocol Buffers
Hi,

I get runtime errors when I try to use the com.google.protobuf:protobuf-java-util to convert a long to a Timestamp.

I believe the issue is that the protobuf-java-util does not support kotlin

Here's the stacktrace, followed by my build.gradle.kts for the project

    'com.google.protobuf.Timestamp com.google.protobuf.Timestamp$Builder.build()'
java.lang.NoSuchMethodError: 'com.google.protobuf.Timestamp com.google.protobuf.Timestamp$Builder.build()'
    at com.google.protobuf.util.Timestamps.<clinit>(Timestamps.java:73)
    at nhc.protobuf.util.TimestampsKtKt.toProtoTimestamp(TimestampsKt.kt:7)
    at nhc.protobuf.util.TimestampsKtTest.toTimestamp(TimestampsKtTest.kt:16)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:108)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40)
    at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:60)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)


Could not initialize class com.google.protobuf.util.Timestamps
java.lang.NoClassDefFoundError: Could not initialize class com.google.protobuf.util.Timestamps
    at nhc.protobuf.util.TimestampsKtKt.toMillisTimestamp(TimestampsKt.kt:11)
    at nhc.protobuf.util.TimestampsKtTest.toMillisTimestamp(TimestampsKtTest.kt:26)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:108)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40)
    at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:60)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)


My project is configured like this:


    
    plugins {
        id("java-library")
        id("org.jetbrains.kotlin.jvm") version "1.8.10"
        id("com.google.protobuf") version "0.9.1"
    }

    java {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }

    kotlin {
        jvmToolchain(17)
    }

    tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
        kotlinOptions.jvmTarget = "17"
    }

    protobuf {
        protoc {
            artifact = "com.google.protobuf:protoc:3.21.9"
        }

        // Generates the java Protobuf-lite code for the Protobufs in this project. See
        // https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
        // for more information.
        generateProtoTasks {
            // see https://github.com/google/protobuf-gradle-plugin/issues/518
            // see https://github.com/google/protobuf-gradle-plugin/issues/491
            ofSourceSet("main").forEach { task ->
                task.builtins {
                    getByName("java") {
                        option("lite")
                    }
                    id("kotlin") {
                        option("lite")
                    }
                }
            }
        }
    }

    dependencies {
        api("com.google.protobuf:protobuf-javalite:3.21.9")
        api("com.google.protobuf:protobuf-kotlin-lite:3.21.9")
        api("com.google.protobuf:protobuf-java-util:3.21.9")
    }

Should I open a bug or a feature request on https://github.com/protocolbuffers/protobuf/issues/ ?

Thanks in advance,
Daniele

Daniele Segato

unread,
Mar 2, 2023, 5:44:10 AM3/2/23
to Protocol Buffers
I forgot, this is the class that produce the error

    import com.google.protobuf.Timestamp
    import com.google.protobuf.util.Timestamps  
  
    fun Long.toProtoTimestamp(): Timestamp {
        return Timestamps.fromMillis(this) // this is what's failing
    }
    
    fun Timestamp.toMillisTimestamp(): Long {
        return Timestamps.toMillis(this)
    }


and the tests

    @Test
    fun toTimestamp() {
        val timestampLong = 1668178299L
        val expected = timestamp {
            seconds = 1668178
            nanos = 299000000
        }
        assertEquals(expected, timestampLong.toProtoTimestamp())
    }

    @Test
    fun toMillisTimestamp() {
        val timestamp = timestamp {
            seconds = 1668178
            nanos = 299000000
        }
        val expected = 1668178299L
        assertEquals(expected, timestamp.toMillisTimestamp())
    }

Daniele Segato

unread,
Apr 18, 2023, 3:29:11 AM4/18/23
to Protocol Buffers
anyone?

On Thursday, March 2, 2023 at 11:35:54 AM UTC+1 Daniele Segato wrote:

Jerry Berg

unread,
Apr 20, 2023, 11:31:15 AM4/20/23
to Protocol Buffers
Hi Daniele,

I'm having difficulty reproducing this issue. Do you have a project on GitHub or some other location where I can clone it and try it out?

Thanks,
Jerry

Daniele Segato

unread,
Apr 21, 2023, 3:56:45 PM4/21/23
to Jerry Berg, Protocol Buffers
Hi,

It's part of a product of my company, I cannot disclose the code. I'll see if I can manage to create a small project on GitHub to reproduce it.

But I won't be able to do it until the end of next week.

I'll update here.

Thank you!
Daniele

--
You received this message because you are subscribed to a topic in the Google Groups "Protocol Buffers" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/protobuf/mvf2tJWrTXE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to protobuf+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/protobuf/8f7ec431-9ac9-44d7-b29f-694709616b38n%40googlegroups.com.

Jerry Berg

unread,
Apr 21, 2023, 5:48:54 PM4/21/23
to Daniele Segato, Protocol Buffers
SGTM

You received this message because you are subscribed to the Google Groups "Protocol Buffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to protobuf+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/protobuf/CAND5yRvHzz%3DtW2pkvFTzbZz0kmMtrVumGV1ZSC8JO1fDA0UszA%40mail.gmail.com.


--
Jerry Berg | Software Engineer | gb...@google.com | 720-808-1188

Daniele Segato

unread,
Apr 28, 2023, 4:50:10 AM4/28/23
to Protocol Buffers
Hi there,

sorry for the wait.

I can tell you how to reproduce it, but I think I now know where the issue come from: the com.google.protobuf:protobuf-java-util library doesn't support "lite".

When I encounter this error I never went past the failing test.
But trying to reproduce the issue in isolation I actually did that and got a different error in my small android app

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:checkDebugDuplicateClasses'.
Caused by: org.gradle.workers.internal.DefaultWorkerExecutor$WorkExecutionException: A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
Caused by: java.lang.RuntimeException: Duplicate class com.google.protobuf.AbstractMessageLite found in modules protobuf-java-3.21.9 (com.google.protobuf:protobuf-java:3.21.9) and protobuf-javalite-3.21.9 (com.google.protobuf:protobuf-javalite:3.21.9)
Duplicate class com.google.protobuf.AbstractMessageLite$Builder found in modules protobuf-java-3.21.9 (com.google.protobuf:protobuf-java:3.21.9) and protobuf-javalite-3.21.9 (com.google.protobuf:protobuf-javalite:3.21.9)
[...]

this prompt me to look into the dependencies of the utility and I saw it depends on the non-lite version of protobuf.

So I figured: wait, does it mean that if I use the full one instead of lite I won't have the issue?
turns out: yes, if I use the full one I do not have the exceptions above....

foolish by me not to check the dependencies and assuming the utility lib would work for both the lite and full version

Looking again at the exceptions I got from my unit tests:

'com.google.protobuf.Timestamp com.google.protobuf.Timestamp$Builder.build()'
java.lang.NoSuchMethodError: 'com.google.protobuf.Timestamp com.google.protobuf.Timestamp$Builder.build()'
at com.google.protobuf.util.Timestamps.<clinit>(Timestamps.java:73)
at com.example.protolib.ProtobufUtilsKt.toProtoTimestamp(ProtobufUtils.kt:7)
at com.example.protolib.ProtbufUtilsTest.toTimestamp(ProtbufUtilsTest.kt:15)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
Could not initialize class com.google.protobuf.util.Timestamps
java.lang.NoClassDefFoundError: Could not initialize class com.google.protobuf.util.Timestamps
at com.example.protolib.ProtobufUtilsKt.toMillisTimestamp(ProtobufUtils.kt:11)
at com.example.protolib.ProtbufUtilsTest.toMillisTimestamp(ProtbufUtilsTest.kt:25)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)


I guess the issue here is that the implementation of Timestamps differ from lite to full protobuf and the util link via reflection to the full one.

Which turn my question in: is there an utility library for the lite version, possibly one that does NOT use reflection?
I implemented the utilities methods I needed myself in my project right now, thinking I would replace it with the official utility when I figured out this issue.
Now I guess I'll have to write my own utilities methods whenever I need to do something.


If you want to reproduce the error this below is the code you need, run the unit test and you'll reproduce the error
and if you switch to the full version (dependencies + comment option lite in the build.gradle.kts file) and run the unit test again it will go away
(I've added some comment)
=========
create a java library module in intellij / android studio called "protolib" and use these codes (with gradle wrapper 8.0)

settings.gradle.kts (this should be fairly standard)

pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {

        google()
        mavenCentral()
    }
}
rootProject.name = "ProtobuffUtilIssue"
include(":protolib")



build.gradle.kts

import com.google.protobuf.gradle.id

plugins {
    id("java-library")
    id("org.jetbrains.kotlin.jvm")
    id("com.google.protobuf") version "0.9.1"
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"

}


protobuf {
    protoc {
        artifact = "com.google.protobuf:protoc:3.21.9"
    }

    generateProtoTasks {

        ofSourceSet("main").forEach { task ->
            task.builtins {
                getByName("java") {
                    option("lite") // comment for full version
                }
                id("kotlin") {
                    option("lite")
 // comment for full version

                }
            }
        }
    }
}

dependencies {
    api("com.google.protobuf:protobuf-javalite:3.21.9")
    api("com.google.protobuf:protobuf-kotlin-lite:3.21.9")

    // swap the above 2 dependencies for these one for full version
//    api("com.google.protobuf:protobuf-java:3.21.9")
//    api("com.google.protobuf:protobuf-kotlin:3.21.9")

    implementation("com.google.protobuf:protobuf-java-util:3.21.9")

    testImplementation("junit:junit:4.13.2")
    testImplementation("org.jetbrains.kotlin:kotlin-test:1.8.10")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit:1.8.10")
}




src/main/java/com/example/protolib/ProtobufUtils.kt

package com.example.protolib


import com.google.protobuf.Timestamp
import com.google.protobuf.util.Timestamps

fun Long.toProtoTimestamp(): Timestamp {
    return Timestamps.fromMillis(this)
}

fun Timestamp.toMillisTimestamp(): Long {
    return Timestamps.toMillis(this)
}




src/test/java/com/example/protolib/ProtbufUtilsTest.kt (unit test!)

package com.example.protolib

import com.google.protobuf.timestamp
import kotlin.test.Test
import kotlin.test.assertEquals

class ProtbufUtilsTest {

    @Test
    fun toTimestamp() {
        val timestampLong = 1668178299L
        val expected = timestamp {
            seconds = 1668178
            nanos = 299000000
        }
        assertEquals(expected, timestampLong.toProtoTimestamp())
    }

    @Test
    fun toMillisTimestamp() {
        val timestamp = timestamp {
            seconds = 1668178
            nanos = 299000000
        }
        val expected = 1668178299L
        assertEquals(expected, timestamp.toMillisTimestamp())
    }
}


========
Reply all
Reply to author
Forward
0 new messages