Unable to access the resources file in jar after packaging : FileSystemNotFoundException - java

Hi I am working on developing a small java application (kinda new to this ) which takes an input file and gives out an web page. Here the HTML template and an image file to the web page are in resource folder.
Below is the way I am accessing the html template file in my code.(I need to read the HTML template as an string)
{
String htmlString;
ClassLoader classLoader = getClass().getClassLoader();
URL fileurl = classLoader.getResource("template.html");
htmlString = String.join("\n", Files.readAllLines(Paths.get(fileurl.toURI())));
}
the code works fine when ran from eclipse but fails when I run it as an jar.(java.nio.file.NoSuchFileException:)
kindly help me in accessing the template file from resources folder and also note that the html takes an image from the same folder. Now the template and image file must be packaged and should be able to run as a single JAR .
update :
Extracted the jar file with 7-zip to see the contents. I can see the files in resources are available with the jar
Thanks!

You have packaged everything into a jar so the pathnames to resources is no longer a valid path to a file. If you added this logging you would see that the path to the jar entry says something like jar:file:/C:/path/to/your.jar!/template.html which cannot be opened by Files.readAllLines:
URI uri = fileurl.toURI();
System.out.println("uri="+uri);
The solution is easy, just locate the resource as InputStream which must be on the classpath:
String htmlString;
ClassLoader classLoader = getClass().getClassLoader();
try(InputStream in = classLoader.getResourceAsStream("template.html")) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
in.transferTo(out);
htmlString = new String(out.toByteArray()); // as platform encoding
}
This works if the res directory is part of your classpath when you run the code in exploded directory, and works in JAR file if the contents of "res" are inside the jar.

Related

How can I get the Url of file that is outside the jar?

I have deployed spring boot app in exploded mode using maven-assembly-plugin. I have made config folder from project’s resource folder.
The problem is that I am not able to get the url to access the file that is in the config folder.
How can I get the url of the file that I have uploaded and stored at this config folder.
File structure
Target folder:
+springdemo-0.0.1-application.zip
+config
+myfolder
-oldfile.png
+springdemo-0.0.1.jar //running this jar file
+start.sh
-springdemo-0.0.1.jar
I want URL of files stored in myfolder. This url will be accessed by 3rd party(for ex. Picasso) to get file data. I am unable to get correct url pointing to this myfolder files.
Its easy, you need to provide the full path of the external application.properties file than what is present in your source code during the startup of the spring-boot.jar application at runtime.
Example: java -jar -Dspring.config.location=file://<>
This external file takes precedence over the one in our jar file.
Note: Not a SpringBoot-specific answer, just the simple Java way.
You can only try to guess the location of the file because there's no way to know the working directory when a Java application is run.
For example, you could try a very simple approach if you control how the Java application is executed:
var configFile = new File("config/application.properties");
This will works as long as the process is started from the same directory where start.sh is (which seems like what you intend).
If it doesn't work, try printing the working directory like this first:
System.out.println("WRK DIR = " + new File(".").getAbsolutePath());
This will tell you what the relative path to your file should be.
So, if this prints <root-dir>/springdemo and you know your config file is under <root-dir>/springdemo/mydir/config/, then the file path should be:
new File("mydir/config/application.properties");
By the way, you can easily read the file with:
// read file into List of lines
Files.readAllLines(configFile);
// specifically, for properties file
var props = new Properties();
props.load(new FileInputStream(configFile));
If for whatever reason you need an URL object instead of a File, it's easy, just call:
URL url = configFile.toURI().toURL()
If you want ALL files under the config dir, you can list them first with:
File[] files = configFile.getParentFile().listFiles();
if (files != null) {
for (File file : files) {
// use file?
}
}

How to get the path of .key file from spring application programmatically?

I need to get the path of a key file that i have placed in the root folder of my spring application. Everything works as expected when i run it locally. But when i deploy the application to the server i get a FileNotFoundException.
File file = new File("testfile.key");
String path = file.getAbsolutePath();
I have tried placing the file in the resource folder as well.
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
File file = new File(classLoader.getResource("testfile.key").getFile());
Just need to pass the file path to another method (3rd party library) which will read the content.
Any help would be much appreciated.
This should be a resource, placed in the resource folder (if using maven).
You can access it using
this.getClass().getResource("testfile.key");
The root for accessing files can change between environments but the root for resources is a directory that's specified during compilation. For maven driven projects this is:
src/main/resources

Accessing an ftl file under WEB-INF in a Java Project in eclipse

I am using Eclipse Neon.2 Release (4.6.2) for my Java Spring MVC Web Application. I am trying to access an ftl file placed in a subfolder under WEB-INF and read its value to a string. I am using the following code:
Resource resource = new ClassPathResource("/src/main/webapp/WEB-INF/jsp/modules/abc/sub1/sub2/message.ftl");
InputStream resourceInputStream = resource.getInputStream();
String message = IOUtils.toString(resourceInputStream, "UTF-8");
But I am getting a file not found exception. The exact path of the file is /my-project/src/main/webapp/WEB-INF/jsp/modules/abc/sub1/sub2/message.ftl
How can I read the contents of that file to a string.
the path should be /WEB-INF/jsp/modules/abc/sub1/sub2/message.ftl. src/main/whatever is a maven convention, your container doesn't know anything about it.
The war file deployed in the container will not have any src/main/*

How to load a JAR stored inside your application resources in a URLClassLoader

I'm trying to load a JAR file in a URLClassLoader. This JAR file is stored in the resources of my project, and its working fine with the following code when I'm running my project using maven:
new URLClassLoader(
new URL[]{MyClass.class.getClassLoader().getResource("dependencies/dependency.jar")},
ClassLoader.getSystemClassLoader().getParent()
);
However, when I build the project using mvn clean install and I then try to run the generate JAR using java -jar myapp.jar it seems like the dependency.jar is not loaded. The dependency.jar file is properly stored inside the project JAR under dependencies/dependency.jar, but it's not read.
I assume that it cannot be loaded from inside a JAR file, but is their a workaround?
I think a solution would be to use getResourceAsStream, but I would then need to transform this stream into a URL.
If possible I'd like to use a solution that wouldn't involve a temporary file created to store the content of dependency.jar.
I believe that your problem is due to the fact that it cannot read a zip in zip, so you should copy your jar file into a temporary file and provide this temporary file to your URLClassLoader as next:
// Get the URL of my jar file
URL url = MyClass.class.getResource("/dependencies/dependency.jar");
// Create my temporary file
Path path = Files.createTempFile("dependency", "jar");
// Delete the file on exit
path.toFile().deleteOnExit();
// Copy the content of my jar into the temporary file
try (InputStream is = url.openStream()) {
Files.copy(is, path, StandardCopyOption.REPLACE_EXISTING);
}
// Create my CL with this new URL
URLClassLoader myCL = new URLClassLoader(
new URL[]{path.toUri().toURL()}, ClassLoader.getSystemClassLoader().getParent()
);

Root directory of eclipse plugin project

I have an RCP application based on eclipse plugins. I have a file and I want to put it inside the root directory of my plugin and access it from there, so it is available on any platform (windows or linux). For example, my plugin name is Test and I have a file TestFile.eap
Currently I am using it form desktop
private String EapName = "C:\\Users\\abc\\Desktop\\TestFile.eap";
I want to put TestFile.eap inside the root directory of Test and access it from there like:
File f = new File(EapName);
How can I get the root of my eclipse plugin?
Thanks!
Use
Bundle bundle = Platform.getBundle("your plugin id");
URL pluginURL = FileLocator.find(bundle, new Path("TestFile.eap"), null);
URL fileURL = FileLocator.toFileURL(pluginURL);
File file = new File(fileURL.getPath());
If your plugin is packaged as a jar (as they usually are) this will extract the file from the jar to a temporary location so that you can access it using File APIs.
Be sure to include the file in the plugin build.properties file.
Two possibilities:
1) The file is static and deployed as part of your plugin:
URL url = new URL("platform:/plugin/my.plugin.id/the/relative/path");
InputStream inputStream = url.openConnection().getInputStream();
2) The file is created on the fly and you need a place to put it:
IPath pluginStatePath = MyPlugin.getDefault().getStateLocation();
IPath filePath = pluginStatePath.append("my/relative/filepath");
For more information on both approaches, see Where do plugins store their state?

Categories