GoogleCloudPlatform / GoogleCloudPlatform/kotlin-samples
Migrating Kotlin Jar/AppEngine Project: Exception in thread “Timer-0”
- Dominant language
- Kotlin
- Stars
- 286
- Forks
- 85
- PR merge metrics
- No merged PRs in 30d
Description
# Overview
There is an issue when attempting to migrate a Kotlin AppEngine project from an old MacBook Pro (MBP) to a new MBP, when running the `Main` method and building a *.jar* file locally.
The `Main` method in IntelliJ fails intermittently on the new MBP. The old *.jar* runs as expected on the new MBP, and the new *.jar* runs as expected on the old MBP.
**Expected**
1. Run existing local *.jar* file from Kotlin project on the old MBP.
2. Clone Kotlin project from GitHub repository into local IntelliJ project on new MBP.
3. Build *.jar* on new MBP.
4. Run *.jar* on new MBP.
5. Host *.jar* on Google AppEngine instance.
**Observed**
1. Running *.jar* on existing MBP works as expected.
4. Running `main` method with the same code runs intermittently on the new MBP after the GitHub repo is cloned locally.
# Error
**The `Main` method runs on the old MBP as expected, but not on the new MBP with the following error.**
> Exception in thread "Timer-0" com.google.cloud.storage.StorageException: 401 Unauthorized
at com.google.cloud.storage.spi.v1.HttpStorageRpc.translate(HttpStorageRpc.java:229)
at com.google.cloud.storage.spi.v1.HttpStorageRpc.create(HttpStorageRpc.java:310)
at com.google.cloud.storage.StorageImpl$3.call(StorageImpl.java:196)
at com.google.cloud.storage.StorageImpl$3.call(StorageImpl.java:193)
at com.google.api.gax.retrying.DirectRetryingExecutor.submit(DirectRetryingExecutor.java:105)
at com.google.cloud.RetryHelper.run(RetryHelper.java:76)
at com.google.cloud.RetryHelper.runWithRetries(RetryHelper.java:50)
at com.google.cloud.storage.StorageImpl.internalCreate(StorageImpl.java:192)
at com.google.cloud.storage.StorageImpl.create(StorageImpl.java:154)
at content.SaveContentKt.saveContent(SaveContent.kt:38)
at content.ContentTasks.generateContent(ContentTasks.kt:55)
at content.ContentTasks.run(ContentTasks.kt:41)
at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
at java.base/java.util.TimerThread.run(Timer.java:506)
Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:150)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:554)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:474)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:591)
at com.google.cloud.storage.spi.v1.HttpStorageRpc.create(HttpStorageRpc.java:307)
... 12 more
## Configuration
The *gradle-wrapper.properties* **Gradle**, IntelliJ Preferences **Gradle JVM**, Project **SDK**, Run/Debug Configurations **JRE**, and Project **language level** versions are the same across both machines.
*Preferences* > *Gradle*
- *Use Gradle from:* `'gradle-wrapper.properties' file`(Gradle 6.0.1)
- *Gradle JVM:* `Library/Java/JavaVirtualMachines/12.0.1`
*File* > *Project Structure...* > *Project*
- *Project SDK:* `12.0.1`
- *Project language level:* `11`
*Running .jar file*: *Project Structure* > *Project Settings* > *Artifacts* > *Add* > *JAR* > *From modules with dependencies...*
- *Module:* `coinverse-media.main`
- *Main Class:* `Initialization`
Lastly, build artifact and run *.jar* file.
*build.gradle*
```Kotlin
buildscript {
ext.kotlin_version = '1.3.61'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id 'java'
id 'org.jetbrains.kotlin.jvm' version '1.2.51'
}
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation 'com.squareup.retrofit2:retrofit:2.7.0'
implementation 'com.squareup.retrofit2:converter-gson:2.7.0'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.7.0'
implementation 'com.google.firebase:firebase-admin:6.12.0'
implementation 'com.google.cloud:google-cloud-storage:1.102.0'
implementation 'com.google.apis:google-api-services-youtube:v3-rev20190827-1.30.1'
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
```
# Attempted Solutions
1. *Invalidate Caches / Restart...*: This appears to fix the issue for a few times running the `Main` method, then the error continues to show.
2. `./gradlew clean build`
3. Gradle > Reimport All Gradle Projects
4. Updating to the latest [Gradle version][1].
5. Ensure existing MBP and new MBP are running on the same IntelliJ/Project/Run configurations.
6. Potentially related build dependency conflict issue: [Guava Dependency Breaking Jar Built With Kotlin][2].
# Build Data
- [Build scan results][3]
- Stack trace
> 6:09:42 PM: Executing task 'assemble'...
> Task :compileKotlin UP-TO-DATE
> Task :compileJava NO-SOURCE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :inspectClassesForKotlinIC UP-TO-DATE
> Task :jar UP-TO-DATE
> Task :assemble UP-TO-DATE
> BUILD SUCCESSFUL in 75ms
3 actionable tasks: 3 up-to-date
6:09:42 PM: Task execution finished 'assemble'.
- Hidden files
[![enter image description here][4]][4]
Here is the [StackOverflow post](https://stackoverflow.com/questions/59525001/kotlin-jar-error-exception-in-thread-timer-0-storageexception-401-unauthoriz?noredirect=1#comment105245056_59525001). I'll update each platform once the solution is found.
[1]: https://gradle.org/releases/
[2]: https://stackoverflow.com/questions/52881622/guava-dependency-breaking-jar-built-with-kotlin
[3]: https://scans.gradle.com/s/exa2ynrifkfua
[4]: https://i.stack.imgur.com/T4Piy.png
Contributor guide
Research direction
Start at content/SaveContent.kt:38 and the calls from content/ContentTasks.kt:41 and :55, then inspect how the Main method obtains Google Cloud Storage access. Reproduce the jar run on both machines and compare the authentication and project configuration involved in the 401 response. Done means the cause is identified and storage creation succeeds reliably on the new machine.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- google-cloud, kotlin
- Domain
- backend, cloud
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100