0

I'm getting this error when I try to connect to a google cloud instance through jdbc. Not really sure why it's occurring but here's the full error:

Exception in thread "main" java.lang.NoSuchMethodError: 'com.google.api.client.json.JsonParser com.google.api.client.json.JsonFactory.createJsonParser(java.io.InputStream, java.nio.charset.Charset)'
        at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:77)
        at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:73)
        at com.google.auth.oauth2.GoogleCredentials.fromStream(GoogleCredentials.java:101)
        at com.google.auth.oauth2.DefaultCredentialsProvider.getDefaultCredentialsUnsynchronized(DefaultCredentialsProvider.java:107)
        at com.google.auth.oauth2.DefaultCredentialsProvider.getDefaultCredentials(DefaultCredentialsProvider.java:55)
        at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:66)
        at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:48)
        at com.google.cloud.sql.core.CoreSocketFactory$ApplicationDefaultCredentialFactory.create(CoreSocketFactory.java:299)
        at com.google.cloud.sql.core.CoreSocketFactory.getInstance(CoreSocketFactory.java:126)
        at com.google.cloud.sql.core.CoreSocketFactory.connect(CoreSocketFactory.java:185)
        at com.google.cloud.sql.postgres.SocketFactory.createSocket(SocketFactory.java:73)
        at org.postgresql.core.PGStream.<init>(PGStream.java:73)
        at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:93)
        at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:197)
        at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
        at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:211)
        at org.postgresql.Driver.makeConnection(Driver.java:459)
        at org.postgresql.Driver.connect(Driver.java:261)
        at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
        at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:251)
        at App.main(App.java:12)

And here's the script (the instance name and password have been voided by "..." for privacy:

import java.sql.Connection;
import java.sql.DriverManager;

public class App
{
    public static void main(String args[])
    {
        Connection c = null;
        try
        {
           Class.forName("org.postgresql.Driver");
           c = DriverManager.getConnection("jdbc:postgresql:///<postgres>?cloudSqlInstance=<...:database>&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=<postgres>&password=<...>");
        }
        catch (Exception e)
        {
           e.printStackTrace();
           System.err.println(e.getClass().getName()+": "+e.getMessage());
           System.exit(0);
        }
        System.out.println("Opened database successfully");
     }
}
CodeMonkey
  • 97
  • 2
  • 9
  • Does this answer your question? [java.lang.ClassNotFoundException: com.mysql.jdbc.Driver in Eclipse](https://stackoverflow.com/questions/17484764/java-lang-classnotfoundexception-com-mysql-jdbc-driver-in-eclipse) – Christos Karapapas Apr 19 '20 at 07:20
  • @CodeMonkey it could be due to missing libraries in your project since it's complaining about `NoSuchMethodError`. I have posted an answer below; try it out and let me know if it helps. – Adithya Upadhya Apr 19 '20 at 07:42

1 Answers1

0

It could be a problem with missing "socket factory" libraries. What's the build tool that you're using? Is it Maven or Gradle?

Try including this library in your project and see if it works.

Maven:

<dependency>
    <groupId>com.google.cloud.sql</groupId>
    <artifactId>postgres-socket-factory</artifactId>
    <version>1.0.15</version>
</dependency>

Gradle:

compile 'com.google.cloud.sql:postgres-socket-factory:1.0.15'

And also my friend, please don't cram everything into the connection string. Use Properties in your DriverManager Constructor.

String url = "jdbc:postgresql:///<DATABASE_NAME>";

Properties props = new Properties();
props.setProperty("user", "<user>");
props.setProperty("password", "<password>");
props.setProperty("socketFactory", "com.google.cloud.sql.postgres.SocketFactory");
props.setProperty("cloudSqlInstance", "<instance>");

// Fill rest of the properties here (if any)
Connection conn = DriverManager.getConnection(url, props);


EDIT: A better approach than hardcoding these props in your code would be to store all config data in an XML file or config file and load properties from <yourProject>.xml or <yourProject>.config.

And then use properties.load(...) or properties.loadFromXML(...). Documentation.

Adithya Upadhya
  • 2,239
  • 20
  • 28
  • 1
    This looks like an attempt to answer the [other question of the op](https://stackoverflow.com/questions/61299538/java-lang-noclassdeffounderror-com-google-cloud-sql-core-coresocketfactory). Have you posted it on the wrong question? – Mark Rotteveel Apr 19 '20 at 15:41
  • @Mark Hmmm... Looks like OP posted a duplicate question. In fact, both of these questions are related. If something changes, OP should ideally edit the existing question and post updates rather than post a duplicate question for following up on new errors. I wasn't aware that this question is a duplicate. Sigh, so much for trying to help folks around here... – Adithya Upadhya Apr 19 '20 at 17:53