Maven module dependency and resources - maven

I have a maven Project say ProjectA, and there is a class say ClassA in this project which uses the files from resource folder, I am using following way to read from resource:
String fileName = IPToGeoMapper.class.getResource("/resourceFile.txt").getFile();
File resourceFile = new File(fileName);
and it works like charm.
Now, when I create artifact out of this project (I have tried extracting the created jar and it has resourceFile.txt packed in the jar), and use that as a dependency in other project say ProjectB, ClassA no more finds the resourceFile.txt as it tries to browse though resources folder of ProjectB.
I want the best global solution which will work in all the projects where I import artifact created from ProjectA
What is the best way to handle this?

Try this way , I am taking an example of reading a property file.
Properties propfile = new Properties();
propfile.load(PropertyUtils.class.getClassLoader()
.getResourceAsStream(
"applicationprops.properties"));
BufferedReader reader = new BufferedReader(new InputStreamReader(ClassA.class.getClassLoader().getResourceAsStream("file.txt")));
StringBuilder out = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
}
System.out.println(out.toString()); //Prints the string content read from input stream
reader.close();

Related

Java I/O help. Jar Cannot Open File: URI is Not Hierarchal

I have been searching for 3 days now nonstop looking at every post I can find. My program runs on IntelliJ, but cannot run on an executable. Your help would be appreciated :)
More importantly, where can I find a in depth user-friendly tutorial? Is there a course or book I can pay for? On Udemy, the java classes completely fail to mention I/O such as classpath and URI. TutorialsPoint briefly goes over I/O buts its not indepth. Did I miss something? Is there an easier way to do all this??
Similar posts that have not worked for me:
Java Jar file: use resource errors: URI is not hierarchical
https://stackoverflow.com/a/27149287/155167
I am trying to load an excel file. I am using Maven. Apache POI says it needs a File. So InputStream does not work. http://poi.apache.org/components/spreadsheet/quick-guide.html#FileInputStream
When I java -jar jarFile, it gives me the error:
C:\Users\1010\Documents\Personal\MonsterManager>java -jar monsterManagerVer3.jar
Exception in thread "main" java.lang.IllegalArgumentException: URI is not hierarchical
at java.base/java.io.File.<init>(File.java:421)
at LoadExcel.<init>(LoadExcel.java:62)
at monsterRunner.<init>(monsterRunner.java:13)
at monsterRunner.main(monsterRunner.java:24)
Here is the code
public LoadExcel() throws IOException, URISyntaxException, InvalidFormatException {
mNames = null;
URL ins = this.getClass().getResource("/excel_List.xlsx");
if (ins == null)
throw new FileNotFoundException("The XLSX file didn't exist on the classpath");
ins.toString().replace(" ","%20"); //<-Runs without this part
File file = new File(ins.toURI()); //this is line 62
// File f = new File(getClass().getResource("/MyResource").toExternalForm());
//String path = this.getClass().getClassLoader().getResource("/excel_List.xlsx").toExternalForm();
//File file = new File(path);
OPCPackage pkg = OPCPackage.open(file);
XSSFWorkbook wb = new XSSFWorkbook(pkg);
//FileInputStream fis=new FileInputStream(new File(excelFile));
// XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet sheet = wb.getSheetAt(0);
loadExcel(sheet);
cacheNames();
// fis.close();
wb.close();
}
If it helps here is the path to the excel file:
src\main\resources\excel_List.xlsx
UPDATE:
so I took the excel file out of the resources folder
\nameOfMyProgram\excel_List.xlsx
and now I get this error.
I tried several versions of using the classLoader, Class and Thread to solve this error from Different ways of loading a file as an InputStream
but I still cannot get it to compile.
Error and my code
If you have to use File object do not put xls-file into resources directory.
Maven puts all files from resources directory into jar.
Java can not create File object based on file in jar-file.
Put your xls-file somewhere in file system and create File object based on its URL.
Since your xls-file is not a resource do not use getResource.
Its URL is its full filename (with path).
This code below works with jar executable
String path = new File("excel_List.xlsx").getAbsoluteFile().toString();
File file = new File(path);
if(!file.exists()){
JOptionPane.showMessageDialog(null,"File not found!");
System.exit(0);
}
OPCPackage pkg = OPCPackage.open(file);
XSSFWorkbook wb = new XSSFWorkbook(pkg);

Spring cannot find the file via specified path

My files hierarchy:
>resources:
>static:
>css:
>json:
>networks:
>network-list.json
>js:
>img:
I've tried to create a new file via:
File jsonNetworkDetailsFile = new File("/json/networks/network-list.json");
File jsonNetworkDetailsFile = new File("static/json/networks/network-list.json");
File jsonNetworkDetailsFile = new File("../json/networks/network-list.json");
File jsonNetworkDetailsFile = new File("../../json/networks/network-list.json");
File jsonNetworkDetailsFile = new File("/json/networks/network-list.json");
...and some more. None of it works.
I'm still getting the
java.io.FileNotFoundException: the system cannot find the path specified
What's the proper way?
EDIT
Found a solution. Had to include full path to the file like:
File jsonNetworkDetailsFile = new File("src/main/resources/static/json/networks/Turtlecoin/turtlecoin-pools.json");
EDIT2
As TwiN stated - it's impossible to reference a file through File object as soon as the app is packed into .jar. A proper solution would include:
InputStream jsonNetworkDetailsFile = new ClassPathResource("/static/json/networks/network-list.json").getInputStream();
InputStream is = new ClassPathResource("/someFile.txt").getInputStream();
where /someFile.txt is in your resources folder.
As mentioned in the documentation for ClassPathResource:
Supports resolution as java.io.File if the class path resource resides
in the file system, but not for resources in a JAR. Always supports
resolution as URL.
In other words, you'll want to use the getInputStream() method for your case:
InputStream is = new ClassPathResource("/someFile.txt").getInputStream();
try {
String contents = new String(FileCopyUtils.copyToByteArray(is), StandardCharsets.UTF_8);
System.out.println(contents); // do something with the content here
is.close();
} catch (IOException e) {
e.printStackTrace();
}
I'm mentioning this because ClassPathResource also has a getFile() method.
For more details, see reference
Try something like this :
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("classpath:static/json/networks/network-list.json").getFile());
You could also use :
#Value(value = "static/json/networks/network-list.json")
private Resource myFile;
And then :
myFile.getInputStream()
(will only work on a class annoted with #Component, #Service... etc)
you can try this to load files from ressources :
ClassLoader loader = Thread.currentThread().
getContextClassLoader();
InputStream configStream = loader.getResourceAsStream("/static/json/networks/network-list.json");
I think you should give the exact location to File object. Another solution:
File currDir = new File(".");
String path = currDir.getAbsolutePath();
// String path = "C:\\ExternalFiles\\"; // Or you can give staticly
File jsonNetworkDetailsFile = new File(path);
Hope it helps.

cannot load and read from properties file

My grade java project has the following structure.
As you can see the resources folder is in present in the class path.
But when I run the following in a class under java folder
new File("somefile.txt").exists()
I get FileNotFoundException.
Could anyone help me find why I am not able to access this file.
This is in the class path.
You can use.
ClassLoader classLoader = getClass().getClassLoader();
String filePath= classLoader.getResource("filename").getFile();
new File(filePath).exists();
For more info, you can go through this tutorial.
You can resolve your issue like below
Properties prop = new Properties();
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("somefile.txt");
if (inputStream != null) {
prop.load(inputStream);
} else {
throw new FileNotFoundException("Property file '" + fileName + "' not found in the classpath");
}
I found it from the post How to read properties file in Java

Difference between (guava) Resources.getResource("bddconf.xml") and properties.getClass().getResourceAsStream("bddconf.xml");

In a maven war project, i use jetty-maven-plugin as developpement container.
i filtered some resources files, and in particular let's name it "bddconf.xml".
This file is filtered by maven and put in target/classes directory.
An old home-made bdd fwk search after this file with this snippet :
Properties properties = new Properties();
InputStream inputstream = properties.getClass().getResourceAsStream("/bddconf.xml");
When i run this snippet, in my webapp (in jetty), inputStream is null.
Whereas with this snippet, in the same method :
import com.google.common.io.Resources;
String file = Resources.getResource("bddconf.xml").getFile();
File file2 = new File(file);
logger.info("Does bdd file exists : [" + file2.exists() + "] file : [" + file2.toString() + "]");
// Does bdd file exists : [true] file : [..path..\target\classes\bbdconf.xml]
It works, so what's the difference between this two methods ?
May be Properties class and guava Resources class have different ClassLoaders (with different privileges), because Class.getResource() and Resources.getResource() do the same job for you. You can look at the sources of guava:
public static URL getResource(String resourceName) {
URL url = Resources.class.getClassLoader().getResource(resourceName);
checkArgument(url != null, "resource %s not found.", resourceName);
return url;
}
Class.getResource:
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResource(name);
}
return cl.getResource(name);

How do I access a file inside an OSGi bundle?

I am new to OSGi and created an OSGi-bundle which I run in the Apache Felix OSGi-container.
There is a file resource contained in the bundle, which I need to pass to a method as a java.io.File. To instantiate a File-object, either an URI in the "file"-scheme or the path as string is necessary. How do I retrieve any of those in a clean way?
I tried using the
context.getBundle().getResource("/myfile") (where context is of type org.osgi.framework.BundleContext) which returns the URI bundle://6.0:0/myfile.
But this URI can't be converted to a File-instance using the File(URI uri) constructor since it has the "bundle"-scheme.
One could try to construct a path to the location knowing the working directory and exploiting the bundleId of my bundle, but I doubt this is the best practice.
Any ideas?
Since the file is inside your bundle, there is no way for you to get to it using a standard File. The URL you get from Bundle.getResource() is the correct way to get to these resources, since the OSGi APIs are intended to also work on systems without an actual file system. I would always try to stick to the OSGi API instead of using framework-specific solutions.
So, if you have control over the method, I would update it to take a URL, or maybe even an InputStream (since you probably just want to read from it). For convenience, you can always provide a helper method that does take a File.
If you don't have control over the method, you will have to write some helper method that takes the URL, streams it out to a file (for instance, File.createTempFile() will probably do the trick.
Maybe the API is confusable, but You can access a file inside an OSGI bundle like this:
URL url = context.getBundle().getResource("com/my/weager/impl/test.txt");
// The url maybe like this: bundle://2.0:2/com/my/weager/impl/test.txt
// But this url is not a real file path :(, you could't use it as a file.
// This url should be handled by the specific URLHandlersBundleStreamHandler,
// you can look up details in BundleRevisionImpl.createURL(int port, String path)
System.out.println(url.toString());
BufferedReader br =new BufferedReader(new InputStreamReader(url.openConnection().getInputStream()));
while(br.ready()){
System.out.println(br.readLine());
}
br.close();
getResource will find the resource through the whole OSGI container just like OSGI classloader theory.
getEntry will find the resource from local bundle. and the return url could be convert to file but inputStream.
Here is a question same with this: No access to Bundle Resource/File (OSGi)
Hope this helping you.
What I use is getClassLoader().getResourceAsStream():
InputStream inStream = new java.io.BufferedInputStream(this.getClass().getClassLoader().getResourceAsStream(fileName));
This way the file will be loaded from your resource dir. FileName should contain the path after "src/main/resources".
Full example here:
static public byte[] readFileAsBytes(Class c, String fileName) throws IOException {
InputStream inStream = new java.io.BufferedInputStream(c.getClassLoader().getResourceAsStream(fileName));
ByteArrayOutputStream out = new ByteArrayOutputStream();
int nbytes = 0;
byte[] buffer = new byte[100000];
try {
while ((nbytes = inStream.read(buffer)) != -1) {
out.write(buffer, 0, nbytes);
}
return out.toByteArray();
} finally {
if (inStream != null) {
inStream.close();
}
if (out != null) {
out.close();
}
}
}

Resources