I'm working on transitioning to Google Cloud MySQL. We are currently connected to our own managed mysql server and it is working fine. We are using four separate MySql connections so the setup is not straightforward. Here are my changes specifically for Google Cloud MySQL
pom.xml:
<dependencies>
....
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-sql-mysql</artifactId>
</dependency>
<dependency>
<groupId>com.google.cloud.sql</groupId>
<artifactId>mysql-socket-factory-connector-j-8</artifactId>
</dependency>
.....
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-gcp-dependencies</artifactId>
<version>5.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
application.properties:
spring.cloud.gcp.project-id=PROJECT_ID
spring.cloud.gcp.credentials.location=classpath:CREDENTIAL_FILE_LOCATION
spring.cloud.gcp.sql.enabled=false
userdb.read.datasource.url=jdbc:mysql:///DB_NAME?cloudSqlInstance=INSTANCE_NAME&socketFactory=com.google.cloud.sql.mysql.SocketFactory
userdb.read.datasource.username=USERNAME
userdb.read.datasource.password=PASSWORD
userdb.read.datasource.tomcat.max-wait=5000
userdb.read.datasource.tomcat.max-active=2
userdb.read.datasource.tomcat.test-on-borrow=true
# THREE MORE SIMILAR CONNECTION SETTINGS
I have configured the credentials in addition to the connection settings. The rest of my code is as is, what do you think I'm doing wrong? Below is the error I'm getting:
: HikariPool-1 - Exception during pool initialization.
java.sql.SQLNonTransientConnectionException: Could not create connection to database server.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:111) ~[mysql-connector-j-8.1.0.jar:8.1.0]
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:98) ~[mysql-connector-j-8.1.0.jar:8.1.0]
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:90) ~[mysql-connector-j-8.1.0.jar:8.1.0]
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:64) ~[mysql-connector-j-8.1.0.jar:8.1.0]
at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:995) ~[mysql-connector-j-8.1.0.jar:8.1.0]
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:809) ~[mysql-connector-j-8.1.0.jar:8.1.0]
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:440) ~[mysql-connector-j-8.1.0.jar:8.1.0]
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:239) ~[mysql-connector-j-8.1.0.jar:8.1.0]
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:188) ~[mysql-connector-j-8.1.0.jar:8.1.0
Caused by: java.lang.RuntimeException: Unable to obtain credentials to communicate with the Cloud SQL API
at com.google.cloud.sql.core.ApplicationDefaultCredentialFactory.getCredentials(ApplicationDefaultCredentialFactory.java:42) ~[jdbc-socket-factory-core-1.14.1.jar:1.14.1]
at com.google.cloud.sql.core.ApplicationDefaultCredentialFactory.create(ApplicationDefaultCredentialFactory.java:32) ~[jdbc-socket-factory-core-1.14.1.jar:1.14.1]
at com.google.cloud.sql.core.CoreSocketFactory.apiFetcher(CoreSocketFactory.java:417) ~[jdbc-socket-factory-core-1.14.1.jar:1.14.1]
at com.google.cloud.sql.core.CoreSocketFactory.lambda$getCloudSqlInstance$0(CoreSocketFactory.java:396) ~[jdbc-socket-factory-core-1.14.1.jar:1.14.1]
at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708) ~[?:?]
Caused by: java.io.IOException: Your default credentials were not found. To set up Application Default Credentials for your environment, see https://cloud.google.com/docs/authentication/external/set-up-adc.
at com.google.auth.oauth2.DefaultCredentialsProvider.getDefaultCredentials(DefaultCredentialsProvider.java:127) ~[google-auth-library-oauth2-http-1.20.0.jar:1.20.0]
at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:129) ~[google-auth-library-oauth2-http-1.20.0.jar:1.20.0]
at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:101) ~[google-auth-library-oauth2-http-1.20.0.jar:1.20.0]
at com.google.cloud.sql.core.ApplicationDefaultCredentialFactory.getCredentials(ApplicationDefaultCredentialFactory.java:40) ~[jdbc-socket-factory-core-1.14.1.jar:1.14.1]
at com.google.cloud.sql.core.ApplicationDefaultCredentialFactory.create(ApplicationDefaultCredentialFactory.java:32) ~[jdbc-socket-factory-core-1.14.1.jar:1.14.1]
at com.google.cloud.sql.core.CoreSocketFactory.apiFetcher(CoreSocketFactory.java:417) ~[jdbc-socket-factory-core-1.14.1.jar:1.14.1]
at com.google.cloud.sql.core.CoreSocketFactory.lambda$getCloudSqlInstance$0(CoreSocketFactory.java:396) ~[jdbc-socket-factory-core-1.14.1.jar:1.14.1]
at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708) ~[?:?]
After spending many hours, the solution turns out to be very simple. Adding it here in case some folks run into the similar issue. I was using spring.cloud.gcp.credentials.location
property to set the credentials but the google cloud sql connection factory library doesn't care about that. We need to use gcloud auth application-default login
command to create and credential and gcloud command saves it in your folder: /Users/your_user_name/.config/gcloud/application_default_credentials.json . The spring boot app automatically picks it up, not need to set it using with spring.cloud.gcp.credentials.location file.