Akka persistence spanner library causing NoSuchMethodError for google pubsub library

I am adding akka persistence spanner in a project which is already using pubsub from google.
Adding com.lightbend.akka:akka-persistence-spanner_2.12:1.0.0.RC3 library to the project is causing the following error during the method call Subscriber.startAsync().awaitRunning() (from pubsub library com.google.cloud:google-cloud-pubsub:1.108.0).

Caused by: java.lang.NoSuchMethodError: com.google.iam.v1.SetIamPolicyRequest.getDefaultInstance()Lcom/google/iam/v1/SetIamPolicyRequest;

Looks like the the akka-persistence-spanner library contains classes with same package name and class name as the ones in com.google.api.grpc:proto-google-iam-v1 and is causing this error.

In pom.xml, adding com.google.api.grpc:proto-google-iam-v1 library first and then including akka-persistence-spanner library seems to make it work with google spanner instance and pubsub for the application logic. This change is breaking tests using SpannerKit as I believe SpannerKit is expecting the classes redefined in akka persistence spanner library.

Is there a way to make the library work in both test and application?

Note: Adding spanner tag as per https://github.com/akka/akka-persistence-spanner doesn’t seem to work.

Hi @amaldevs,

this sounds like akka-persistence-spanner and google’s pubsub library depend on different version of the same artifact X. If the newer version of the artifact X is binary compatible with the oldest, you can solve the issue by forcing the use of the newer version adding it as a dependency.

The problems may come if the two versions of artifact X are non binary compatible, then you will need to work on a more elaborate solution. A solution worth investigating is to get a different version of the google pubsub library (newer or older) such that the transitive dependencies between google pubsub dependencies and akka-persistence-spanner dependencies align. That’s a long shot though. Your last chance, and an expensive one, is to build your own google pubsub or akka-persistence-spanner library with shaded dependecies.

Cheers,

Thanks @ignasi35 for the quick response. I will spend some more time in figuring out the artifact causing this issue and also trying out the different versions of pubsub library.

Hi @ignasi35,

I spend some more time figuring out the root cause.

Akka-persistence-spanner project is using akka-grpc to generate classes from google .proto files for cloud spanner and is including the generated classes as part of final jar. These generated classes have same package and class names as google libraries but doesn’t guarantee the same interface. For example, compiling https://github.com/googleapis/googleapis/blob/master/google/iam/v1/iam_policy.proto and the resulting class doesn’t have the getDefaultInstance() method expected by pubsub library.
I tried to find a pubsub library which could work with the compiled proto file without any luck.

To give some more context about the issue faced. The class SetIamPolicyRequest.class present inside akka-persistence-spanner jar (not as a dependency) is also present in proto-google-iam-v1 jar. During execution, it comes down to the first one mentioned in classpath.
It is easy to control the order from IDE or build tool as java is picking up the one from proto-google-iam-v1. But when we are using target/lib/* in classpath specification as it is usually done for docker runs, the order is getting changed (alphabetical).

Looks like the only remaining option is to build my own akka-persistence-spanner library with shaded dependencies.

Is there any reason to keep the com.google.* classes within akka-persistence-spanner jar while the java libraries could be used as dependencies instead? Especially when cloud spanner is used for akka persistence, the application is likely to contain other tools and libraries related to GCP.