I'm trying to implement a new service to our application using Google Drive Java API v3 that is responsible for uploading files to a specific folder in Google Team Drive. I use the service account that my company has created specifically for this project and also generated a JSON file from Google Developer Console that contains a private key. I have also shared the folder to the service account using its email [email protected] and granted rights of Content Manager to the shared Team Drive. Furthermore, G Suite domain-wide of authority has not been granted to this service account for a few reasons.
What am I trying to achieve here:
I want to build and return an authorized Google Drive client service using the service account’s generated private key and therefore be able to send the requests to upload files to the folder in Google Team Drive.
What I currently use:
- IntelliJ IDEA IntelliJ IDEA 2018.1.7 (Ultimate Edition)
- Spring Boot 2
- Java 10.0.1
What is the problem:
I’m unable to return the authorized Google Drive client service successfully and the requests to upload files are not being sent at all. What makes it more confusing is that there are no exceptions thrown. However, a credential is returned successfully with the access token and an expiration time.
What I have already read/found:
Using OAuth2.0 for Server to Server Application: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
Java Quickstart on creating simple requests to the Drive API: https://developers.google.com/drive/api/v3/quickstart/java
JavaDoc reference for the Drive API: https://developers.google.com/resources/api-libraries/documentation/drive/v3/java/latest/
How to upload file to google drive with service account credential: How to upload file to google drive with service account credential
How to access Team Drive using service account with Google Drive .NET API v3: How to access Team Drive using service account with Google Drive .NET API v3
Authentication to upload files in my drive using Google drive API client library for Java Authentication to upload files in my drive using Google drive API client library for Java
What I have already tried:
- Using GoogleCredential-class to return the credential (that class appeared to be deprecated: https://googleapis.dev/java/google-api-client/latest/)
- Finding replacement for the deprecated class by looking into Github projects and tutorials
- Update and check all the missing dependencies in pom.xml
- Checked the settings of the shared Team Drive to make sure it is shared with the service account
- Added logs to make sure the problem is really what I described above
- Tried Java Quickstart on creating simple requests to the Drive API-tutorial (however, that turned out to be not completely suitable for our project's needs)
The relevant part of ContractStateUpdateService.java:
File fileMetadata = new File();
fileMetadata.setName(fileTitle);
// setting the id of folder to which the file must be inserted to
fileMetadata.setParents(Collections.singletonList("dumbFolderId"));
fileMetadata.setMimeType("application/pdf");
byte[] pdfBytes = Base64.getDecoder().decode(base64File.getBytes(StandardCharsets.UTF_8));
InputStream inputStream = new ByteArrayInputStream(pdfBytes);
// decoding base64 to PDF and its contents to a byte array without saving the file on the file system
InputStreamContent mediaContent = new InputStreamContent("application/pdf", inputStream);
logger.info("Starting to send the request to drive api");
File file = DriveUtils.getDriveService().files().create(fileMetadata, mediaContent).execute();
logger.info("Succesfully uploaded file: " + file.getDriveId());
DriveUtils.java:
public class DriveUtils {
private static final String APPLICATION_NAME = "Google Drive Service";
// setting the Drive scope since it is essential to access Team Drive
private static List<String> SCOPES = Collections.singletonList(DriveScopes.DRIVE);
// private key is stored at the root of the project for now
private static String PRIVATE_KEY_PATH = "/path/to/private_key.json";
private static final Logger logger = LoggerFactory.getLogger(DriveUtils.class);
// build and return an authorized drive client service
public static Drive getDriveService() throws IOException, GeneralSecurityException {
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredentials credentials;
try (FileInputStream inputStream = new FileInputStream(PRIVATE_KEY_PATH)){
credentials = ServiceAccountCredentials.fromStream(inputStream).createScoped(SCOPES);
credentials.refreshIfExpired();
AccessToken token = credentials.getAccessToken();
logger.info("credentials: " + token.getTokenValue());
} catch (FileNotFoundException ex) {
logger.error("File not found: {}", PRIVATE_KEY_PATH);
throw new FileNotFoundException("File not found: " + ex.getMessage());
}
logger.info("Instantiating client next");
// Instantiating a client: this is where the client should be built but nothing happens... no exceptions!
Drive service = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, (HttpRequestInitializer) credentials)
.setApplicationName(APPLICATION_NAME)
.build();
// this log should appear immediately after the client has been instantiated but still nothing happens
logger.info("Client instantiated");
return service;
}
}
pom.xml:
<!-- https://mvnrepository.com/artifact/com.google.api-client/google-api-client -->
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.29.2</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-drive</artifactId>
<version>v3-rev165-1.25.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.auth/google-auth-library-oauth2-http -->
<dependency>
<groupId>com.google.auth</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
<version>0.16.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security.oauth/spring-security-oauth2 -->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.oauth-client/google-oauth-client-jetty -->
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>1.29.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
I'm sure I'm missing something here and I apologize for my English in advance. Any help will be appreciated.
TranslationClient
and that was because my system time was not synchronized and the token was expired even before use. This could be a reason for you as well although it is just a guess based on my experience. – Navjot Singh