Search code examples
javaspring-bootmavengoogle-oauth-java-client

How to get an absolute path to a resource inside the springboot resources folder?


I have a folder located inside of a resources folder in a Java springboot project... screenshot

I am attempting to get the filepath of this file both when running the code locally, AND when the project has been packaged into a jar file (using maven)

The problem is that when the project is packaged, the location of the file changes to something like ...\backend-1.0-SNAPSHOT-exec.jar\BOOT-INF\classes\google-oauth\credential.json

I have attempted multiple methods of referring to this file, but none of them have worked. I have spent probably 4 hours trying to find a way to dynamically refer to the location of this file and I am out of steam.

The current method I have works fine when running locally (except I have to manually strip off leading forward slashes and convert forward slashes to backslashes, which sucks), except once the app is packaged it no longer works (and I have no idea why).

// Get the location of the credential.json file regardless of the OS separator or if the app is running locally or packaged
URL credentialLocationURL = Application.class.getClassLoader().getResource("google-oauth/credential.json");
String credentialLocation = URLDecoder.decode(credentialLocationURL.getPath(), "UTF-8");

// Remove leading slashes, the word 'file:', and replace remaining slashes with the proper system file separator character
credentialLocation = credentialLocation.substring(1);
credentialLocation = credentialLocation.replaceAll("ile:/", "");
credentialLocation = credentialLocation.replace('/', File.separatorChar);


GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JacksonFactory.getDefaultInstance(), new FileReader(credentialLocation));

With this code, the app blows up, citing this error: java.io.FileNotFoundException: C:\Users\My Username\IdeaProjects\sigilLab\backend\target\backend-1.0-SNAPSHOT-exec.jar!\BOOT-INF\classes!\google-oauth\credential.json (The system cannot find the path specified)

I have ALSO attempted this solution, but get a different (albeit similar) error

The code I used for that method:

URL resource = Application.class.getResource("/google-oauth/credential.json");
String credentialLocation = Paths.get(resource.toURI()).toString();


GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JacksonFactory.getDefaultInstance(), new FileReader(credentialLocation));

Error creating bean with name 'com.lessons.services.GoogleOauthService': Invocation o f init method failed; nested exception is java.nio.file.FileSystemNotFoundException

It might also be worth mentioning that I am running this function with the @PostConstruct decorator, which may potentially be running this before the resources file is constructed? I am not entirely familiar with how Springboot handles this.

Any help would be appreciated.


Solution

  • File packaged into jar archive is not a fully-featured file that you can read by FileReader. However, GoogleClientSecrets accepts any Reader, so just use InputStreamReader:

    GoogleClientSecrets.load(JacksonFactory.getDefaultInstance(), new InputStreamReader(Application.class.getResourceAsStream("/google-oauth/credential.json"));