NoClassDefFoundError for ProtoEnum after upgrading Square Wire libraries

541 Views Asked by At

After upgrading my com.squareup.wire libraries from 1.8 to 3.4+ (to address security vulnerabilities), I get the NoClassDefFoundError below when trying to deserialize an object from JSON:

java.lang.NoClassDefFoundError: com/squareup/wire/ProtoEnum
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
    at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800)
    at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    at java.base/java.lang.Class.getDeclaredFields0(Native Method)
    at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3061)
    at java.base/java.lang.Class.getField0(Class.java:3246)
    at java.base/java.lang.Class.getField(Class.java:1997)
    at com.squareup.wire.ProtoAdapter$Companion.get(ProtoAdapter.kt:257)
    at com.squareup.wire.internal.ReflectionKt.createRuntimeMessageAdapter(reflection.kt:95)
    at com.squareup.wire.WireTypeAdapterFactory.create(WireTypeAdapterFactory.kt:82)
    at com.google.gson.Gson.getAdapter(Gson.java:489)
    at com.google.gson.Gson.fromJson(Gson.java:962)
    at com.google.gson.Gson.fromJson(Gson.java:928)
    at com.google.gson.Gson.fromJson(Gson.java:877)
    at com.google.gson.Gson.fromJson(Gson.java:848)
    at <...>.OrderMessageProcessor.deserializeOrder(OrderMessageProcessor.java:164)
    ...
Caused by: java.lang.ClassNotFoundException: com.squareup.wire.ProtoEnum
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    ... 78 more

Where do I get this ProtoEnum class from?

build.gradle

// without this I get NoClassDefFoundError: kotlin/enums/EnumEntriesKt
implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.9.10'

implementation 'com.squareup.wire:wire-runtime:4.9.1'
implementation 'com.squareup.wire:wire-gson-support:4.9.1'

OrderMessageProcessor.java

import com.amazonaws.services.sqs.model.Message;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.squareup.wire.WireTypeAdapterFactory;
// ...

public class OrderMessageProcessor {

    private static final Gson WIRE_GSON = new GsonBuilder()
        .registerTypeAdapterFactory(new WireTypeAdapterFactory())
        .create();

    // ...

    protected Order deserializeOrder(Message message) {
        return WIRE_GSON.fromJson(message.getBody(), Order.class);
    }

Order.java

public final class Order extends com.squareup.wire.Message {

    public final String order_date;

    // more fields and a Message.Builder<Order> inner class...

Note that using other deserialization libraries like Jackson's ObjectMapper are problematic because the Order class has no zero-arg constructor and no setter methods. I do not own the Order class and cannot modify it.

I tried using various versions of the com.squareup.wire libraries between 3.4 and the latest, 4.9.1. They all result in the same NoClassDefFoundError. Reverting to version 1.8 works.

1

There are 1 best solutions below

0
On

I figured it out. The Order class that I am deserializing extends the Message class from version 1.x of the com.squareup.wire library, and this uses the ProtoEnum class, which no longer exists in later versions.

No solution yet, but that is the cause of the problem.

UPDATE

Assuming the producer of the serialized Order doesn't upgrade to a compatible version of Square Wire, I may need to generate the Order class myself from the protobuf schema using my version of Square Wire.