1*55e87721SMatt Gilbride# Troubleshooting 2*55e87721SMatt Gilbride 3*55e87721SMatt Gilbride## Logging 4*55e87721SMatt Gilbride 5*55e87721SMatt GilbrideOur libraries use the Java logging API via `java.util.logging` package. 6*55e87721SMatt GilbrideConfiguring logging level reveals various facts that help your troubleshooting, 7*55e87721SMatt Gilbrideincluding: 8*55e87721SMatt Gilbride 9*55e87721SMatt Gilbride- The timing of underlying client-server communication 10*55e87721SMatt Gilbride- Request and response message headers 11*55e87721SMatt Gilbride- Verbose messages in underlying dependency libraries 12*55e87721SMatt Gilbride 13*55e87721SMatt GilbrideWhile there are various ways to configure the logging, 14*55e87721SMatt Gilbrideto quickly enable verbose logging for the Google Cloud Java libraries, create 15*55e87721SMatt Gilbridea file `logging.properties` with the following content: 16*55e87721SMatt Gilbride 17*55e87721SMatt Gilbride``` 18*55e87721SMatt Gilbride# run java program pointing to this properties file with the java arg 19*55e87721SMatt Gilbride# -Djava.util.logging.config.file=path/to/logging.properties 20*55e87721SMatt Gilbridehandlers=java.util.logging.ConsoleHandler 21*55e87721SMatt Gilbridejava.util.logging.SimpleFormatter.format=%1$tF %1$tT,%1$tL %4$-8s %3$-50s - %5$s %6$s%n 22*55e87721SMatt Gilbride 23*55e87721SMatt Gilbride# --- ConsoleHandler --- 24*55e87721SMatt Gilbridejava.util.logging.ConsoleHandler.level=ALL 25*55e87721SMatt Gilbridejava.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter 26*55e87721SMatt Gilbride.level=INFO 27*55e87721SMatt Gilbride 28*55e87721SMatt Gilbride# --- Specify logging level for certain packages --- 29*55e87721SMatt Gilbride# com.google.api is for HTTP 1.1 layer 30*55e87721SMatt Gilbridecom.google.api.level=ALL 31*55e87721SMatt Gilbride# io.grpc is for gRPC + Netty layer 32*55e87721SMatt Gilbrideio.grpc.level=FINE 33*55e87721SMatt Gilbride# com.google.auth is for authentication 34*55e87721SMatt Gilbridecom.google.auth.level=FINE 35*55e87721SMatt Gilbride 36*55e87721SMatt Gilbride# Example when we want to specify storge library's level. This works when 37*55e87721SMatt Gilbride# the target Cloud library uses the logging API. 38*55e87721SMatt Gilbridecom.google.cloud.storage.level=INFO 39*55e87721SMatt Gilbride``` 40*55e87721SMatt Gilbride 41*55e87721SMatt Gilbrideand run your application with `-Djava.util.logging.config.file=path/to/logging.properties` 42*55e87721SMatt Gilbrideas the "VM argument" (not "Program argument"). 43*55e87721SMatt Gilbride 44*55e87721SMatt GilbrideIf you use IntelliJ, you specify the VM argument in "Run/Debug Configuration": 45*55e87721SMatt Gilbride 46*55e87721SMatt Gilbride 47*55e87721SMatt Gilbride 48*55e87721SMatt GilbrideIf the JVM of your program is running with the configuration correctly, you see 49*55e87721SMatt Gilbridethe FINE-level logging in your console. Example output: 50*55e87721SMatt Gilbride 51*55e87721SMatt Gilbride``` 52*55e87721SMatt Gilbride2023-04-05 13:03:01,761 FINE com.google.auth.oauth2.DefaultCredentialsProvider - Attempting to load credentials from well known file: /usr/local/google/home/suztomo/.config/gcloud/application_default_credentials.json 53*55e87721SMatt Gilbride2023-04-05 13:03:01,847 FINE io.grpc.ManagedChannelRegistry - Unable to find OkHttpChannelProvider 54*55e87721SMatt Gilbridejava.lang.ClassNotFoundException: io.grpc.okhttp.OkHttpChannelProvider 55*55e87721SMatt Gilbride at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581) 56*55e87721SMatt Gilbride at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) 57*55e87721SMatt Gilbride at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) 58*55e87721SMatt Gilbride at java.base/java.lang.Class.forName0(Native Method) 59*55e87721SMatt Gilbride at java.base/java.lang.Class.forName(Class.java:315) 60*55e87721SMatt Gilbride... 61*55e87721SMatt Gilbride``` 62*55e87721SMatt Gilbride 63*55e87721SMatt GilbrideNote that you may see many stacktraces printed there. 64*55e87721SMatt GilbrideAs long as it's "FINE" level, they are not errors. 65*55e87721SMatt Gilbride 66*55e87721SMatt GilbrideThis is just one way to configure logging level. 67*55e87721SMatt GilbrideFor more details about Java logging API usage, see [Java Logging Overview]( 68*55e87721SMatt Gilbridehttps://docs.oracle.com/javase/8/docs/technotes/guides/logging/overview.html). 69*55e87721SMatt Gilbride 70*55e87721SMatt Gilbride## ALPN is not configured properly 71*55e87721SMatt Gilbride 72*55e87721SMatt GilbrideIf you see exceptions related to `ALPN is not configured properly`, such as: 73*55e87721SMatt Gilbride 74*55e87721SMatt Gilbride``` 75*55e87721SMatt GilbrideCaused by: java.lang.IllegalArgumentException: ALPN is not configured properly. See https://github.com/grpc/grpc-java/blob/master/SECURITY.md#troubleshooting for more information. 76*55e87721SMatt Gilbride``` 77*55e87721SMatt Gilbride 78*55e87721SMatt GilbridePlease use the [compatibility checker](https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-util/google-cloud-compat-checker) to see if your environment is compatible with grpc-based clients. The incompatibility can mean that: 79*55e87721SMatt Gilbride- You are not on a [supported platform](https://github.com/googleapis/google-cloud-java/#supported-platforms). 80*55e87721SMatt Gilbride- There are classpath conflicts with `netty`. 81*55e87721SMatt Gilbride- Or, you are seeing any of the conflicts specified in [gRPC Troubleshooting guide](https://github.com/grpc/grpc-java/blob/master/SECURITY.md#troubleshooting). 82*55e87721SMatt Gilbride 83*55e87721SMatt Gilbride## ClassNotFoundException, NoSuchMethodError, NoClassDefFoundError 84*55e87721SMatt Gilbride 85*55e87721SMatt GilbrideThese errors are usually caused by having multiple versions or conflicting versions of the same dependency in the classpath. 86*55e87721SMatt GilbrideUsually these dependency conflicts occur with `guava` or `protobuf-java`. 87*55e87721SMatt Gilbride 88*55e87721SMatt GilbrideThere may be multiple sources for classpath conflicts: 89*55e87721SMatt Gilbride- Multiple versions of the same transitive dependency in the dependency tree 90*55e87721SMatt Gilbride- Your runtime classpath has different versions of dependencies than what you specified in the build 91*55e87721SMatt Gilbride 92*55e87721SMatt GilbrideFor example, if you have a direct or a transitive dependency on Guava version 19.0, 93*55e87721SMatt Gilbrideand `google-cloud-java` uses Guava version 30.0, 94*55e87721SMatt Gilbridethen `google-cloud-java` could be using Guava methods that don't exist in Guava 19.0, 95*55e87721SMatt Gilbrideand cause `NoSuchMethodError`. 96*55e87721SMatt Gilbride 97*55e87721SMatt GilbrideSimilarily, if your classpath has an older version of `protobuf-java`, 98*55e87721SMatt Gilbridebut `google-cloud-java` requires a newer version, 99*55e87721SMatt Gilbride then you might see `NoClassDefFoundError` that fails to initialize `google-cloud-java` classes. For example: 100*55e87721SMatt Gilbride 101*55e87721SMatt Gilbride``` 102*55e87721SMatt Gilbridejava.lang.NoClassDefFoundError: Could not initialize class com.google.pubsub.v1.PubsubMessage$AttributesDefaultEntryHolder 103*55e87721SMatt Gilbride``` 104*55e87721SMatt Gilbride 105*55e87721SMatt Gilbride### Validate the conflict 106*55e87721SMatt Gilbride 107*55e87721SMatt GilbrideCheck the dependency tree to see if you have multiple versions of the same dependencies: 108*55e87721SMatt Gilbride 109*55e87721SMatt Gilbride``` 110*55e87721SMatt Gilbride$ mvn dependency:tree 111*55e87721SMatt Gilbride``` 112*55e87721SMatt Gilbride 113*55e87721SMatt GilbrideLook for versions of potentially conflicting dependencies like `guava`, `protobuf-java`, etc. 114*55e87721SMatt Gilbride 115*55e87721SMatt GilbrideIf you experience the error only during runtime, then your runtime environment 116*55e87721SMatt Gilbridemight be introducing conflicting JARs into your runtime classpath. A typical case 117*55e87721SMatt Gilbrideis that Hadoop, Spark, or other server software that your application runs on 118*55e87721SMatt Gilbridehas conflicting versions `netty`, `guava`, or `protobuf-java` JARs in the classpath. 119*55e87721SMatt Gilbride 120*55e87721SMatt Gilbride### Detecting conflicts during build 121*55e87721SMatt Gilbride 122*55e87721SMatt GilbrideTo detect dependency linkage errors at compile time, add the 123*55e87721SMatt Gilbride[Linkage Checker Enforcer Rule](https://github.com/GoogleCloudPlatform/cloud-opensource-java/tree/master/enforcer-rules) 124*55e87721SMatt Gilbridein your pom.xml: 125*55e87721SMatt Gilbride 126*55e87721SMatt Gilbride``` 127*55e87721SMatt Gilbride <plugin> 128*55e87721SMatt Gilbride <groupId>org.apache.maven.plugins</groupId> 129*55e87721SMatt Gilbride <artifactId>maven-enforcer-plugin</artifactId> 130*55e87721SMatt Gilbride <version>3.0.0-M3</version> 131*55e87721SMatt Gilbride <dependencies> 132*55e87721SMatt Gilbride <dependency> 133*55e87721SMatt Gilbride <groupId>com.google.cloud.tools</groupId> 134*55e87721SMatt Gilbride <artifactId>linkage-checker-enforcer-rules</artifactId> 135*55e87721SMatt Gilbride <version>1.5.7</version> 136*55e87721SMatt Gilbride </dependency> 137*55e87721SMatt Gilbride </dependencies> 138*55e87721SMatt Gilbride <executions> 139*55e87721SMatt Gilbride <execution> 140*55e87721SMatt Gilbride <id>enforce-linkage-checker</id> 141*55e87721SMatt Gilbride <!-- Important! Should run after compile --> 142*55e87721SMatt Gilbride <phase>verify</phase> 143*55e87721SMatt Gilbride <goals> 144*55e87721SMatt Gilbride <goal>enforce</goal> 145*55e87721SMatt Gilbride </goals> 146*55e87721SMatt Gilbride <configuration> 147*55e87721SMatt Gilbride <rules> 148*55e87721SMatt Gilbride <LinkageCheckerRule 149*55e87721SMatt Gilbride implementation="com.google.cloud.tools.dependencies.enforcer.LinkageCheckerRule"/> 150*55e87721SMatt Gilbride </rules> 151*55e87721SMatt Gilbride </configuration> 152*55e87721SMatt Gilbride </execution> 153*55e87721SMatt Gilbride </executions> 154*55e87721SMatt Gilbride </plugin> 155*55e87721SMatt Gilbride``` 156*55e87721SMatt Gilbride 157*55e87721SMatt GilbrideThere is no way to detect runtime classpath conflicts though. You need to be fully 158*55e87721SMatt Gilbrideaware of which JARs/classes are included in the runtime classpath 159*55e87721SMatt Gilbrideas every server environment is different. 160*55e87721SMatt Gilbride 161*55e87721SMatt Gilbride### Resolving the conflict 162*55e87721SMatt Gilbride 163*55e87721SMatt GilbrideThere are different strategies to resolve conflicts, but you must understand the root cause of the conflicts. For example: 164*55e87721SMatt Gilbride 165*55e87721SMatt Gilbride- If you have control over the dependency tree, upgrade 166*55e87721SMatt Gilbride offending dependencies (for example, upgrading Guava version). This is the 167*55e87721SMatt Gilbride least hackish approach, but it is a lot of work that can require multiple releases 168*55e87721SMatt Gilbride of multiple libraries to sync everything up. 169*55e87721SMatt Gilbride- If you can't modify and push new versions of your dependencies, import 170*55e87721SMatt Gilbride `com.google.cloud:libraries-bom:25.1.0` (or a more recent version) and use that to 171*55e87721SMatt Gilbride select consistent dependency versions. This is the easiest route. 172*55e87721SMatt Gilbride For example, this is how you can depend on consistent versions of Guava and 173*55e87721SMatt Gilbride `com.google.cloud:google-cloud-storage` without explicitly setting the version of either one: 174*55e87721SMatt Gilbride 175*55e87721SMatt Gilbride``` 176*55e87721SMatt Gilbride ... 177*55e87721SMatt Gilbride <dependencyManagement> 178*55e87721SMatt Gilbride <dependencies> 179*55e87721SMatt Gilbride <dependency> 180*55e87721SMatt Gilbride <groupId>com.google.cloud</groupId> 181*55e87721SMatt Gilbride <artifactId>libraries-bom</artifactId> 182*55e87721SMatt Gilbride <version>25.1.0</version> 183*55e87721SMatt Gilbride <type>pom</type> 184*55e87721SMatt Gilbride <scope>import</scope> 185*55e87721SMatt Gilbride </dependency> 186*55e87721SMatt Gilbride </dependencies> 187*55e87721SMatt Gilbride </dependencyManagement> 188*55e87721SMatt Gilbride ... 189*55e87721SMatt Gilbride <dependencies> 190*55e87721SMatt Gilbride <dependency> 191*55e87721SMatt Gilbride <groupId>com.google.cloud</groupId> 192*55e87721SMatt Gilbride <artifactId>google-cloud-storage</artifactId> 193*55e87721SMatt Gilbride </dependency> 194*55e87721SMatt Gilbride <dependency> 195*55e87721SMatt Gilbride <groupId>com.google.guava</groupId> 196*55e87721SMatt Gilbride <artifactId>guava</artifactId> 197*55e87721SMatt Gilbride </dependency> 198*55e87721SMatt Gilbride ... 199*55e87721SMatt Gilbride </dependencies> 200*55e87721SMatt Gilbride ... 201*55e87721SMatt Gilbride``` 202*55e87721SMatt Gilbride 203*55e87721SMatt Gilbride- If changing dependency versions causes other failures, 204*55e87721SMatt Gilbride consider [shading dependencies](https://maven.apache.org/plugins/maven-shade-plugin/) 205*55e87721SMatt Gilbride that conflict with `google-cloud-java`. 206*55e87721SMatt Gilbride 207*55e87721SMatt Gilbride For example, to shade `guava` and `protobuf-java`: 208*55e87721SMatt Gilbride 209*55e87721SMatt Gilbride``` 210*55e87721SMatt Gilbride <plugin> 211*55e87721SMatt Gilbride <groupId>org.apache.maven.plugins</groupId> 212*55e87721SMatt Gilbride <artifactId>maven-shade-plugin</artifactId> 213*55e87721SMatt Gilbride <version>...</version> 214*55e87721SMatt Gilbride <executions> 215*55e87721SMatt Gilbride <execution> 216*55e87721SMatt Gilbride <phase>package</phase> 217*55e87721SMatt Gilbride <goals> 218*55e87721SMatt Gilbride <goal>shade</goal> 219*55e87721SMatt Gilbride </goals> 220*55e87721SMatt Gilbride <configuration> 221*55e87721SMatt Gilbride <keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope> 222*55e87721SMatt Gilbride <relocations> 223*55e87721SMatt Gilbride <!-- move protobuf to a shaded package --> 224*55e87721SMatt Gilbride <relocation> 225*55e87721SMatt Gilbride <pattern>com.google.protobuf</pattern> 226*55e87721SMatt Gilbride <shadedPattern>myapp.shaded.com.google.protobuf</shadedPattern> 227*55e87721SMatt Gilbride </relocation> 228*55e87721SMatt Gilbride <!-- move Guava to a shaded package --> 229*55e87721SMatt Gilbride <relocation> 230*55e87721SMatt Gilbride <pattern>com.google.common</pattern> 231*55e87721SMatt Gilbride <shadedPattern>myapp.shaded.com.google.common</shadedPattern> 232*55e87721SMatt Gilbride </relocation> 233*55e87721SMatt Gilbride </relocations> 234*55e87721SMatt Gilbride </configuration> 235*55e87721SMatt Gilbride </execution> 236*55e87721SMatt Gilbride </executions> 237*55e87721SMatt Gilbride </plugin> 238*55e87721SMatt Gilbride``` 239