How to fix "Could not find policy 'pick_first'" with Google TTS java client?
Asked Answered
C

7

15

I can't make a request using Google TTS Client library in java. Each time it throws a bunch of exceptions.

I just try to get a list of available voices.

    GoogleCredentials creds = null;
    TextToSpeechClient textToSpeechClient = null;
    try {
        creds = GoogleCredentials.fromStream(new FileInputStream(credsFile));
        TextToSpeechSettings settings = TextToSpeechSettings.newBuilder().setCredentialsProvider(FixedCredentialsProvider.create(creds)).build();
        textToSpeechClient = TextToSpeechClient.create(settings);
    } catch (IOException e) {
        e.printStackTrace();
        System.exit(-2);
    }

    if (cmd.hasOption('l')) {
        ListVoicesRequest request = ListVoicesRequest.getDefaultInstance();
        ListVoicesResponse response = textToSpeechClient.listVoices(request);
        List<Voice> voices = response.getVoicesList();
        System.out.println("Available voices :");
        for (Voice v : voices) {
            System.out.printf(" - %s, [%d]: %s/%s", v.getName(), v.getLanguageCodesCount(), v.getLanguageCodes(0), v.getSsmlGender());
        }
        textToSpeechClient.close();
        System.exit(0);
    }

I first thought it came from the credentials file. But it's not, the file is correctly located.

And I get this.

avr. 02, 2019 11:36:46 PM io.grpc.internal.ManagedChannelImpl$1 uncaughtException
SEVERE: [Channel<1>: (texttospeech.googleapis.com:443)] Uncaught exception in the SynchronizationContext. Panic!
java.lang.IllegalStateException: Could not find policy 'pick_first'. Make sure its implementation is either registered to LoadBalancerRegistry or included in META-INF/services/io.grpc.LoadBalancerProvider from your jar files.
        at io.grpc.internal.AutoConfiguredLoadBalancerFactory$AutoConfiguredLoadBalancer.<init>(AutoConfiguredLoadBalancerFactory.java:93)
        at io.grpc.internal.AutoConfiguredLoadBalancerFactory.newLoadBalancer(AutoConfiguredLoadBalancerFactory.java:64)
        at io.grpc.internal.ManagedChannelImpl.exitIdleMode(ManagedChannelImpl.java:357)
        at io.grpc.internal.ManagedChannelImpl$ChannelTransportProvider$1ExitIdleModeForTransport.run(ManagedChannelImpl.java:455)
        at io.grpc.SynchronizationContext.drain(SynchronizationContext.java:101)
        at io.grpc.SynchronizationContext.execute(SynchronizationContext.java:130)
        at io.grpc.internal.ManagedChannelImpl$ChannelTransportProvider.get(ManagedChannelImpl.java:459)
        (...) a whole bunch of other lines

How to fix this error ?

Note that I'm using the latest google-cloud-texttospeech library (version 0.85.0-beta).

Costrel answered 2/4, 2019 at 21:48 Comment(4)
What is "policy 'pick_first'" and where is its implementation? Also, do the words "caused by" appear in the whole bunch of other lines ?Edholm
I don't know what "policy 'pick_first'" is. Here's the next Caused by : Caused by: io.grpc.StatusRuntimeException: INTERNAL: Panic! This is a bug!. This does not help much. However, I think its related to google's servers load balancing. In this context, 'pick_first' would mean "pick first available server". But it looks like the client doesn't know how to handle this strategy.Bedivere
Often a stack trace will contain more than one Caused by:. Usually the last one points to the part of the code where the exception is occurring. I always look for lines in the stack trace, after the last Caused by: that contain methods that I wrote, i.e. not 3rd party code. I asked about "pick_first" because it appears in the stack trace you posted: Could not find policy 'pick_first'Edholm
Here's the full stacktrace : https://pastebin.com/D7LqvhqT. The problem is that I can't see the problem in my code. The stacktrace refers to this line in my main() : textToSpeechClient.listVoices(request);Bedivere
D
16

If you're using Gradle with the ShadowJar plugin, this is all you need to get it to merge the contents of service files from the various gRPC libraries:

shadowJar {
    mergeServiceFiles()
}

Discovered from a thread here.

Daimon answered 18/8, 2020 at 17:52 Comment(1)
For more context, in your build.gradle file put in the dependency of ` id("com.github.johnrengelman.shadow") version "7.1.2"`, and then do something like tasks.shadowJar { archiveBaseName.set("appName") archiveVersion.set("0.0.1") mergeServiceFiles() manifest { attributes["Main-Class"] = "com.appName.ApplicationKt" } }Calliper
D
8

The io.grpc library registers classes from a file in your META-INF/services.

So, create a file named io.grpc.LoadBalancerProvider in that folder with the content:

io.grpc.internal.PickFirstLoadBalancerProvider

The library should find the class that way.

Dabchick answered 12/4, 2019 at 15:17 Comment(4)
Thanks ! But I ended up not using this library anymore, I did the http requests myself.Bedivere
Unfortunately, adding this file did not fix the jar issue above in the project.Gymnastic
@Gymnastic make sure you put the file in the correct place. Take a look at this github thread (link to relevant comment - here )Stidham
For future folks, my solution using Maven was to do a few different things using the github thread: I needed to update the pom to use the Services Resource Transfromer, and add the transformers included in this commentTerisateriyaki
V
8

Another solution. Hope can help somebody.

Problem is the package name of io.grpc.INTERNAL.PickFirstLoadBalacerProvider class. Insert below code lines before you use grpc.

import com.google.cloud.internal.PickFirstLoadBalancer;
...
LoadBalancerRegistry.getDefaultRegistry().register(new PickFirstLoadBalancerProvider());

LoadBalancerProviders are registered at map in the LoadBalancerRegistry and key of map is the name of class (not exactly but does not matter). So LoadBalancerRegistry returns newly registered class to the grpc.

Vanegas answered 11/6, 2021 at 2:20 Comment(2)
Thanks. This helped me. Needed to register grpclb LoadBalancerRegistry.getDefaultRegistry().register(GrpclbLoadBalancerProvider())Zoe
thanks. works for me. but my import is import io.grpc.LoadBalancerRegistry;Bioastronautics
R
5

If you use Maven and the maven-shade plugin, be sure to configure the ServicesResourceTransformer:

<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>

Roam answered 18/3, 2022 at 17:36 Comment(0)
S
3

You can also create multiple entries in io.grpc.LoadBalancerProvider. For Google's Pub/Sub library (Google Chat bot messaging middleware), I see the following:

io.grpc.grpclb.GrpclbLoadBalancerProvider
io.grpc.internal.PickFirstLoadBalancerProvider
io.grpc.util.SecretRoundRobinLoadBalancerProvider$Provider

Multiple entries is a problem if you are creating a fat/shaded jar, since the entries overwrite each other.

Sulphurous answered 6/5, 2019 at 19:11 Comment(0)
M
0

In our case, the error had to do with the fact that the ServiceLoader mechanism uses the "thread context class loader" rather than the "class loader of the current class" (which is used for practically everything else). These two ClassLoaders are often the same for simple applications, because the "system" ClassLoader (the one made for the JVM at startup) is also the "thread context" ClassLoader. This is usually true, unless you have multiple class loaders being managed in your code, or if you are integrating an embedded JVM into C/C++. I'm adding this answer so that people can see another possible explanation and solution. The answer to this is a pattern like:

ClassLoader save = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
try {
   // do the thing that currently gives you a ServiceLoader error
} finally {
   Thread.currentThread().setContextClassLoader(save);
}
Milling answered 22/1, 2024 at 23:3 Comment(0)
A
-1

This probably happens because you have dependency which is already included in some other dependency but with different version.

Atli answered 22/5, 2022 at 12:24 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Crofoot

© 2022 - 2025 — McMap. All rights reserved.