Using Google Drive API Libraries and Play with Java freezes/locks up application when attempting to save credentials

Dan

I am using the Google Drive API libraries/code in my Play Framework application using Java. I have the credentials set correctly in my GCP project in the API section. I am still learning how these Google libraries and the code I am using is from some posts I found, so I do not understand why it freezes and not sure how to fix it.

I have code that works fine when running the application locally (http://localhost:9000). However, when I run on the server, it freezes/locks up when it attempts to save the credentials - it never returns an error or message. I have waited up to 15 minutes with no response. Here is the line of code:

credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");

Here is the class that I am using:

package google;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets.Details;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.FileContent;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;

import controllers.GlobalUtilities.StringControl;
import play.Configuration;
import play.Logger;

public class GoogleDrive {

    /** Application name. */
    private static final String APPLICATION_NAME = "PTP";

    /** Directory to store user credentials for this application. */
    private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"),
            ".credentials/ptpgoogledrive");

    /** Global instance of the {@link FileDataStoreFactory}. */
    private static FileDataStoreFactory DATA_STORE_FACTORY;

    /** Global instance of the JSON factory. */
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

    /** Global instance of the HTTP transport. */
    private static HttpTransport HTTP_TRANSPORT;

    /**
     * Global instance of the scopes required by this quickstart.
     *
     * If modifying these scopes, delete your previously saved credentials at
     * ~/.credentials/drive-java-quickstart
     */
    // private static final List<String> SCOPES =
    // Arrays.asList(DriveScopes.DRIVE_METADATA_READONLY);
    private static final List<String> SCOPES = Arrays.asList(DriveScopes.DRIVE);

    static {
        try {
            HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
            DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
        } catch (Throwable t) {
            t.printStackTrace();
            System.exit(1);
        }
    }

    /**
     * Creates an authorized Credential object.
     * 
     * @return an authorized Credential object.
     * @throws IOException
     */
    @SuppressWarnings("deprecation")
    public static Credential authorize() throws IOException {
        Credential credential = null;
        String credentialsFileName = "";
        try {
            Logger.info("GoogleDrive: authorize: Starting...");

            // Set up the credentials...
            String clientID = Configuration.root().getString("google.drive.credentials.clientID");
            String clientSecret = Configuration.root().getString("google.drive.credentials.clientSecret");
            String authURI = Configuration.root().getString("google.drive.credentials.authURI");
            String tokenURI = Configuration.root().getString("google.drive.credentials.tokenURI");
            Logger.info("GoogleDrive: authorize: clientID = " + clientID);
            Logger.info("GoogleDrive: authorize: clientSecret = " + clientSecret);
            Logger.info("GoogleDrive: authorize: authURI = " + authURI);
            Logger.info("GoogleDrive: authorize: tokenURI = " + tokenURI);

            GoogleClientSecrets.Details details = new Details();
            details.setClientId(clientID);
            details.setClientSecret(clientSecret);
            details.setAuthUri(authURI);
            details.setTokenUri(tokenURI);
            GoogleClientSecrets clientSecrets = new GoogleClientSecrets().setInstalled(details);

            Logger.info("GoogleDrive: authorize: Found client secrets...");
            if (clientSecrets == null) {
                Logger.info("GoogleDrive: authorize: GoogleClientSecrets is null...");
            }

            // Build flow and trigger user authorization request...
            Logger.info("GoogleDrive: authorize: Setting GoogleAuthorizationCodeFlow...");
            GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY,
                    clientSecrets, SCOPES).setDataStoreFactory(DATA_STORE_FACTORY).setAccessType("offline").build();
            Logger.info("GoogleDrive: authorize: GoogleAuthorizationCodeFlow has been set...");
            Logger.info("GoogleDrive: authorize: Setting credenital...");
            credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
            Logger.info("GoogleDrive: authorize: Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());

        } catch (IOException ex) {
            System.out.println(ex.toString());
            System.out.println("Could not find file " + credentialsFileName);
            ex.printStackTrace();
        }
        Logger.info("GoogleDrive: authorize: Ending...");
        return credential;
    }

    /**
     * Build and return an authorized Drive client service.
     * 
     * @return an authorized Drive client service
     * @throws IOException
     */
    public static Drive getDriveService() throws IOException {
        Logger.info("GoogleDrive: getDriveService: Starting...");
        Credential credential = null;
        Drive googleDrive = null;
        try {
            credential = authorize();
            googleDrive = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
                    .setApplicationName(APPLICATION_NAME).build();
        } catch (IOException ex) {
            System.out.println(ex.toString());
            ex.printStackTrace();
        }
        return googleDrive;
    }

    public static String getPath() {
        String s = GoogleDrive.class.getName();
        int i = s.lastIndexOf(".");
        if (i > -1)
            s = s.substring(i + 1);
        s = s + ".class";
        System.out.println("Class Name: " + s);
        Object testPath = GoogleDrive.class.getResource(s);
        System.out.println("Current Path: " + testPath);
        return "";
    }

    public static String uploadFile(java.io.File file) throws IOException {
        String fileID = "";
        try {
            Logger.info("GoogleDrive: uploadFile: Starting File Upload...");
            // Build a new authorized API client service.
            Drive service = getDriveService();
            Logger.info("GoogleDrive: uploadFile: Completed Drive Service...");
            String fullFilePath = file.getAbsolutePath();
            Logger.info("GoogleDrive: uploadFile: Full File Path: " + fullFilePath);
            File fileMetadata = new File();
            String fileName = StringControl.rightBack(fullFilePath, "\\");
            String fileContentType = getContentType(fileName);
            Logger.info("GoogleDrive: uploadFile: File Content Type: " + fileContentType);
            fileMetadata.setName(fileName);
            Logger.info("GoogleDrive: uploadFile: File Name = " + fileName);
            // Set the folder...
            String folderID = Configuration.root().getString("google.drive.folderid");
            Logger.info("GoogleDrive: uploadFile: Folder ID = " + folderID);
            fileMetadata.setParents(Collections.singletonList(folderID));

            java.io.File filePath = new java.io.File(fullFilePath);
            FileContent mediaContent = new FileContent(fileContentType, filePath);
            File fileToUpload = service.files().create(fileMetadata, mediaContent).setFields("id, parents").execute();
            fileID = fileToUpload.getId();
            Logger.info("GoogleDrive: uploadFile: File ID: " + fileID);
        } catch (Exception ex) {
            System.out.println(ex.toString());
            ex.printStackTrace();
        }
        Logger.info("GoogleDrive: uploadFile: Ending File Upload...");
        return fileID;
    }

    public static String getContentType(String filePath) throws Exception {
        String type = "";
        try {
            Path path = Paths.get(filePath);
            type = Files.probeContentType(path);
            System.out.println(type);
        } catch (Exception ex) {
            System.out.println(ex.toString());
            ex.printStackTrace();
        }
        return type;
    }

}

I have a bunch of logging to determine where the code freezes and here is the output:

GoogleDrive: uploadFile: Starting File Upload...
GoogleDrive: getDriveService: Starting...
GoogleDrive: authorize: Starting...
GoogleDrive: authorize: clientID = (my client ID)
GoogleDrive: authorize: clientSecret = (my client secret)
GoogleDrive: authorize: authURI = https://accounts.google.com/o/oauth2/auth
GoogleDrive: authorize: tokenURI = https://accounts.google.com/o/oauth2/token
GoogleDrive: authorize: Found client secrets...
GoogleDrive: authorize: Setting GoogleAuthorizationCodeFlow...
GoogleDrive: authorize: GoogleAuthorizationCodeFlow has been set...
GoogleDrive: authorize: Setting credenital...

As you can see, it never gets to the next logging output:

Logger.info("GoogleDrive: authorize: Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());

I appreciate if you could show me what I am missing with a sample or fixing my code above. Thanks in advance.

Dan

My answer to this was to use a Service Account instead of OAuth2.

I created a Service Account in my Google Cloud Platform project:

https://console.cloud.google.com/iam-admin/serviceaccounts/

I used the default account for my Compute Engine instance and created the key needed and downloaded the file to my machine and referenced in my code above.

The files are uploaded without a problem.

Here is my final code:

package google;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.FileContent;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;

import controllers.GlobalUtilities.StringControl;
import play.Configuration;
import play.Logger;

public class GoogleDrive {

    /** Application name. */
    private static final String APPLICATION_NAME = "PTP";

    /** Directory to store user credentials for this application. */
    private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"),
            ".credentials/ptpgoogledrive");

    /** Global instance of the {@link FileDataStoreFactory}. */
    private static FileDataStoreFactory DATA_STORE_FACTORY;

    /** Global instance of the JSON factory. */
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

    /** Global instance of the HTTP transport. */
    private static HttpTransport HTTP_TRANSPORT;

    /**
     * Global instance of the scopes required by this quickstart.
     *
     * If modifying these scopes, delete your previously saved credentials at
     * ~/.credentials/drive-java-quickstart
     */
    private static final List<String> SCOPES = Arrays.asList(DriveScopes.DRIVE);

    static {
        try {
            HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
            DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
        } catch (Throwable t) {
            t.printStackTrace();
            System.exit(1);
        }
    }

    /**
     * Creates an authorized Credential object.
     * 
     * @return an authorized Credential object.
     * @throws IOException
     */
    @SuppressWarnings("deprecation")
    public static GoogleCredential authorize() throws IOException {
        GoogleCredential credential = null;
        String credentialsFileName = "";
        try {
            Logger.info("GoogleDrive: authorize: Starting...");

            Logger.info("GoogleDrive: authorize: Getting credentialsFileName path...");
            credentialsFileName = Configuration.root().getString("google.drive.credentials.file");
            Logger.info("GoogleDrive: authorize: credentialsFileName = " + credentialsFileName);

            Logger.info("GoogleDrive: authorize: Setting InputStream...");
            InputStream in = GoogleDrive.class.getClassLoader().getResourceAsStream(credentialsFileName);
            if (in == null) {
                Logger.info("GoogleDrive: authorize: InputStream is null");
            }
            Logger.info("GoogleDrive: authorize: InputStream set...");

            Logger.info("GoogleDrive: authorize: Setting credential...");
            credential = GoogleCredential.fromStream(in, HTTP_TRANSPORT, JSON_FACTORY)
                    .createScoped(Collections.singleton(DriveScopes.DRIVE));
        } catch (IOException ex) {
            System.out.println(ex.toString());
            System.out.println("Could not find file " + credentialsFileName);
            ex.printStackTrace();
        }
        Logger.info("GoogleDrive: authorize: Ending...");
        return credential;
    }

    /**
     * Build and return an authorized Drive client service.
     * 
     * @return an authorized Drive client service
     * @throws IOException
     */
    public static Drive getDriveService() throws IOException {
        Logger.info("GoogleDrive: getDriveService: Starting...");
        GoogleCredential credential = null;
        Drive googleDrive = null;
        try {
            credential = authorize();
            Logger.info("GoogleDrive: getDriveService: Credentials set...");
            googleDrive = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
                    .setApplicationName(APPLICATION_NAME).build();
        } catch (IOException ex) {
            System.out.println(ex.toString());
            ex.printStackTrace();
        }
        return googleDrive;
    }

    public static String getPath() {
        String s = GoogleDrive.class.getName();
        int i = s.lastIndexOf(".");
        if (i > -1)
            s = s.substring(i + 1);
        s = s + ".class";
        System.out.println("Class Name: " + s);
        Object testPath = GoogleDrive.class.getResource(s);
        System.out.println("Current Path: " + testPath);
        return "";
    }

    public static String uploadFile(java.io.File file, String folderIDToFind) throws IOException {
        String fileID = "";
        String fileName = "";
        try {
            Logger.info("GoogleDrive: uploadFile: Starting File Upload...");
            // Build a new authorized API client service.
            Drive service = getDriveService();
            Logger.info("GoogleDrive: uploadFile: Completed Drive Service...");

            // Set the folder...
            String folderID = Configuration.root().getString("google.drive.folderid");
            Logger.info("GoogleDrive: uploadFile: Folder ID = " + folderID);

            String folderIDToUse = getSubfolderID(service, folderID, folderIDToFind);

            String fullFilePath = file.getAbsolutePath();
            Logger.info("GoogleDrive: uploadFile: Full File Path: " + fullFilePath);
            File fileMetadata = new File();

            // Let's see what slashes exist to get the correct file name...
            if (fullFilePath.contains("/")) {
                fileName = StringControl.rightBack(fullFilePath, "/");
            } else {
                fileName = StringControl.rightBack(fullFilePath, "\\");
            }
            String fileContentType = getContentType(fileName);
            Logger.info("GoogleDrive: uploadFile: File Content Type: " + fileContentType);
            fileMetadata.setName(fileName);
            Logger.info("GoogleDrive: uploadFile: File Name = " + fileName);

            Logger.info("GoogleDrive: uploadFile: Setting the folder...");
            fileMetadata.setParents(Collections.singletonList(folderIDToUse));
            Logger.info("GoogleDrive: uploadFile: Folder set...");

            // Team Drive settings...
            fileMetadata.set("supportsTeamDrives", true);

            java.io.File filePath = new java.io.File(fullFilePath);

            FileContent mediaContent = new FileContent(fileContentType, filePath);

            File fileToUpload = service.files().create(fileMetadata, mediaContent).setSupportsTeamDrives(true)
                    .setFields("id, parents").execute();

            fileID = fileToUpload.getId();
            Logger.info("GoogleDrive: uploadFile: File ID: " + fileID);
        } catch (Exception ex) {
            System.out.println(ex.toString());
            ex.printStackTrace();
        }
        Logger.info("GoogleDrive: uploadFile: Ending File Upload...");
        return fileID;
    }

    public static String getContentType(String filePath) throws Exception {
        String type = "";
        try {
            Path path = Paths.get(filePath);
            type = Files.probeContentType(path);
            System.out.println(type);
        } catch (Exception ex) {
            System.out.println(ex.toString());
            ex.printStackTrace();
        }
        return type;
    }

    public static String getSubfolderID(Drive service, String parentFolderID, String folderKeyToGet) {
        // We need to see if the folder exists based on the ID...
        String folderID = "";
        Boolean foundFolder = false;
        FileList result = null;
        File newFolder = null;

        // Set the drive query...
        String driveQuery = "mimeType='application/vnd.google-apps.folder' and '" + parentFolderID
                + "' in parents and name contains '" + folderKeyToGet + "' and trashed=false";

        try {
            result = service.files().list().setQ(driveQuery).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        for (File folder : result.getFiles()) {
            System.out.printf("Found folder: %s (%s)\n", folder.getName(), folder.getId());
            foundFolder = true;
            folderID = folder.getId();
        }
        if (foundFolder != true) {
            // Need to create the folder...
            File fileMetadata = new File();
            fileMetadata.setName(folderKeyToGet);
            fileMetadata.setTeamDriveId(parentFolderID);
            fileMetadata.set("supportsTeamDrives", true);
            fileMetadata.setMimeType("application/vnd.google-apps.folder");
            fileMetadata.setParents(Collections.singletonList(parentFolderID));

            try {
                newFolder = service.files().create(fileMetadata).setSupportsTeamDrives(true).setFields("id, parents")
                        .execute();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // Send back the folder ID...
            folderID = newFolder.getId();
            System.out.println("Folder ID: " + newFolder.getId());
        }

        return folderID;
    }


}

I hope this helps the next guy.

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Google Drive Api for installed application c#

分類Dev

Do you need to migrate to Drive API when using https://spreadsheets.google.com/feeds/

分類Dev

Error: The permission type field is required when creating permission using Google Drive API

分類Dev

Google People API | Request had invalid authentication credentials - Authorization Bearer header not setting up

分類Dev

Google Play Game Services VS Google Drive

分類Dev

Google Drive Rest API

分類Dev

Get file buffer using Google Drive API and async/await

分類Dev

Unable to get list of all files using google drive API

分類Dev

new spreadsheet not visible in google drive using .NET API

分類Dev

java.lang.ClassNotFoundException: play.core.server.NettyServer when more play libraries are added to build.sbt

分類Dev

GOOGLE_APPLICATION_CREDENTIALSエラー

分類Dev

java.lang.NoClassDefFoundError:com.google.api.services.drive.Drive

分類Dev

Google Drive API - Not listing specific shared drive

分類Dev

Detect in application the Google Play origin

分類Dev

"The tenant for tenant guid ... does not exist" when using client credentials flow (daemon) to access Microsoft Graph API

分類Dev

Does Google Play library have backwards compatibility support? (And other libraries)

分類Dev

Attempting to use Google Play Services, Google Sign in, keep getting an Error Code 10

分類Dev

Striping down google play services only to google drive related methods

分類Dev

"Network is unreachable" when attempting to ping google, but internal addresses work

分類Dev

Google Drive API get AppProperties with API Key

分類Dev

Insufficient Permission when trying to create a folder on Google Drive via API(v3)

分類Dev

CORS error when trying to open files from Google Drive v2 API

分類Dev

Unable to download file from Google Drive using API - node.js

分類Dev

Using Google drive to store apps data in structured format- similar to dropbox datastore API

分類Dev

How to separate the files from Google Drive in the Response only using Rest API

分類Dev

How can I upload a new revision to an specific file in Google Drive using the REST API?

分類Dev

Google Drive Apiは非推奨になりました(Google Playゲーム->保存済みゲーム)

分類Dev

Google Drive API(Java)で403 UserPermissionsエラーを解決する方法

分類Dev

Error in using Google Play Services

Related 関連記事

  1. 1

    Google Drive Api for installed application c#

  2. 2

    Do you need to migrate to Drive API when using https://spreadsheets.google.com/feeds/

  3. 3

    Error: The permission type field is required when creating permission using Google Drive API

  4. 4

    Google People API | Request had invalid authentication credentials - Authorization Bearer header not setting up

  5. 5

    Google Play Game Services VS Google Drive

  6. 6

    Google Drive Rest API

  7. 7

    Get file buffer using Google Drive API and async/await

  8. 8

    Unable to get list of all files using google drive API

  9. 9

    new spreadsheet not visible in google drive using .NET API

  10. 10

    java.lang.ClassNotFoundException: play.core.server.NettyServer when more play libraries are added to build.sbt

  11. 11

    GOOGLE_APPLICATION_CREDENTIALSエラー

  12. 12

    java.lang.NoClassDefFoundError:com.google.api.services.drive.Drive

  13. 13

    Google Drive API - Not listing specific shared drive

  14. 14

    Detect in application the Google Play origin

  15. 15

    "The tenant for tenant guid ... does not exist" when using client credentials flow (daemon) to access Microsoft Graph API

  16. 16

    Does Google Play library have backwards compatibility support? (And other libraries)

  17. 17

    Attempting to use Google Play Services, Google Sign in, keep getting an Error Code 10

  18. 18

    Striping down google play services only to google drive related methods

  19. 19

    "Network is unreachable" when attempting to ping google, but internal addresses work

  20. 20

    Google Drive API get AppProperties with API Key

  21. 21

    Insufficient Permission when trying to create a folder on Google Drive via API(v3)

  22. 22

    CORS error when trying to open files from Google Drive v2 API

  23. 23

    Unable to download file from Google Drive using API - node.js

  24. 24

    Using Google drive to store apps data in structured format- similar to dropbox datastore API

  25. 25

    How to separate the files from Google Drive in the Response only using Rest API

  26. 26

    How can I upload a new revision to an specific file in Google Drive using the REST API?

  27. 27

    Google Drive Apiは非推奨になりました(Google Playゲーム->保存済みゲーム)

  28. 28

    Google Drive API(Java)で403 UserPermissionsエラーを解決する方法

  29. 29

    Error in using Google Play Services

ホットタグ

アーカイブ