How to reference a file in Eclipse that is not in src - java

I'm trying to get a resource for MyBatis. The tutorial states that I will need the following in my Connection Factory:
String resource = "org/mybatis/example/Configuration.xml";
Reader reader = Resources.getResourceAsReader(resource);
sqlMapper = new SqlSessionFactoryBuilder().build(reader);
My directory structure is:
src/
com/
utils/
MyBatisConnectionFactory.java
config/
Configuration.xml
I am having troubles referencing the configuration file. I tried "config/Configuration.xml", "Configuration.xml" and "/config/Configuration.xml".
Anyone have a good idea for what to do?

You can add your config directory as a source-folder (right-click > build path > use as source folder).
Thus your configuration files will go on the root of the classpath and will be accessible via getClass().getResourceAsStream("/Configuration.xml")

Open up the file via the classpath using getResourcesAsStream() rather than Resources.getResourceAsReader() For example:
InputStream is = getClass().getClassLoader().getResourceAsStream(
"src/com/utils/Configuration.xml");
byte[] data = new byte[is.available()];
is.read(data);
is.close();
String fileContents = new String(data);

Related

Java: Getting resource path of the main app instead of jar's

A lot has been discussed already here about getting a resource.
If there is already a solution - please point me to it because I couldn't find.
I have a program which uses several jars.
To one of the jars I added a properties file under main/resources folder.
I've added the following method to the jar project in order to to read it:
public void loadAppPropertiesFile() {
try {
Properties prop = new Properties();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String resourcePath = this.getClass().getClassLoader().getResource("").getPath();
InputStream stream = loader.getResourceAsStream(resourcePath + "\\entities.properties");
prop.load(stream);
String default_ssl = prop.getProperty("default_ssl");
}catch (Exception e){
}
}
The problem (?) is that resourcePath gives me a path to the target\test-clasess but under the calling application directory although the loading code exists in the jar!
This the jar content:
The jar is added to the main project by maven dependency.
How can I overcome this state and read the jar resource file?
Thanks!
I would suggest using the classloader used to load the class, not the context classloader.
Then, you have two options to get at a resource at the root of the jar file:
Use Class.getResourceAsStream, passing in an absolute path (leading /)
Use ClassLoader.getResourceAsStream, passing in a relative path (just "entities.properties")
So either of:
InputStream stream = getClass().getResourceAsStream("/entities.properties");
InputStream stream = getClass().getClassLoader().getResourceAsStream("entities.properties");
Personally I'd use the first option as it's briefer and just as clear.
Can you try this:
InputStream stream = getClass().getClassLoader().getResourceAsStream("entities.properties")

How to read resource file from unit test?

I have a Java-only module in my Android project. In that project I want to have a unit test that reads the contents from a local json file that is stored in the resources folder. Android Studio changes the icon of the resources folder, so I'd think it recognises it as the resources folder.
How I'm reading:
String json = Files.lines(Paths.get("file.json"))
.parallel()
.collect(Collectors.joining());
folder structure:
+project
+app (android)
+module (java only)
+src
+main
+java
+package
-the java file
+resources
-file.json
My question is how can I read the file?
updated below
URL resource1 = getClass().getResource("file.json");
URL resource2 = getClass().getClassLoader().getResource("file.json");
URL resource3 = Thread.currentThread().getContextClassLoader().getResource("file.json");
URL resource4 = ClassLoader.getSystemClassLoader().getResource("file.json");
All these are null.
I've copied the json file to resources/same.package.structure too, but to no success.
Don't need to do all this complicated stuff with ClassLoaders. You have access to test/resources directory from you /test/* classes.
UPD
This is how to deserialize file using its path using SimpleXML. So here source method param is your path to resource file
you should using Paths.get(URI) instead, for example:
ClassLoader loader = ClassLoader.getSystemClassLoader();
String json = Files.lines(Paths.get(loader.getResource("file.json").toURI()))
.parallel()
.collect(Collectors.joining());
this is because you run your tests in android platform, and the resoruces were packaged in a jar, please using BufferedReader.lines instead, for example:
ClassLoader loader = activity.getClassLoader();
BufferedReader in = new BufferedReader(new InputStreamReader(
loader.getResourceAsStream("file.json"),"UTF-8"
));
String json = in.lines()
.parallel()
.collect(Collectors.joining());
Apparently it was a bug, should be fixed now:
https://issuetracker.google.com/issues/63612779
Thank you all for your help

java.lang.NullPointerException while getting a filepath in Java (executing through a jar file)

I am getting an NPE at the point of getting path of a File (an sh file in assets folder).
I have tried to read about NPE i detail from the following thread, but this actually could not solve my problem.
What is a NullPointerException, and how do I fix it?
Following is my code snippet:
File absPathofBash;
url = ClassLoader.class.getResource("assets/forbackingup.sh");
absPathofBash = new File(url.getPath());
Later I'm using it in a ProcessBuilder, as
ProcessBuilder pb = new ProcessBuilder(url.getPath(), param2, param3)
I've also tried getting the absolute path directly, like
absPathofBash = new File("assets/forbackingup.sh").getAbsolutePath();
Using the latter way, I am able to process it, but if I create a jar then the file cannot be found. (although the Jar contains the file within the respective folder assets)
I would be thankful if anyone can help me on that.
Once you have packaged your code as a jar, you can not load files that are inside the jar using file path, instead they are class resources and you have to use this to load:
this.getClass().getClassLoader().getResource("assets/forbackingup.sh");
This way you load assets/forbackingup.sh as an absolute path inside your jar. you also can use this.getClass().getResource() but this way the path must be relative to this class path inside jar.
getResource method gives you an URL, if you want to get directly an InputStream you can use getResourceAsStream
Hope it helps!
Since the file itself is in the jar file, you could try using:
InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileNameFromJar);
In case of jar file , classloader will return URL different than that of when the target file is not embedded inside jar. Refer to answer on link which should help u :
How to use ClassLoader.getResources() in jar file
I got it done by creating a temp file. Though it's not difficult, yet I'm posting the code patch here:
InputStream stream = MyClass.class.getClassLoader().
getResourceAsStream("assets/forbackingup.sh");
File temp = File.createTempFile("forbackingup", ".sh");
OutputStream outputStream =
new FileOutputStream(temp);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = stream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
outputStream.close();
}
Now, we have this temp file here which we can pipe to the ProcessBuilder like,
String _filePath=temp.getPath();
ProcessBuilder pb = new ProcessBuilder(url.getPath(), param2, param3)
Thank you everyone for your considerations.
You can use Path class like :
Path path = Paths.get("data/test-write.txt");
if(!Files.exists(path)){
// can handle null pointer exception
}

cannot read file.properties from resource file

I created a jar file which use a Meta-Inf/config.properties file!!
the problem is that I would like to use Meta-Inf/config.properties from resource file and not from jar file
I tried this
InputStream input = classLoader.getResourceAsStream("META-INF/config.properties");
but this line read the config.properties file from jar and not from resource file!!
I tried also something like:
InputStream input = classLoader.getResourceAsStream("classpath:META-INF/config.properties");
but nothing
any idea
resource file: is only the directory src/main/resources
Ways of Accessing resources :
String pathToPropertyFile = "resources/META-INF/config.properties";
InputStream stream= ClassName.class.getResourceAsStream(pathToImage );
Or
String pathToPropertyFile = "resources/META-INF/config.properties";
InputStream stream= ClassName.class.getResource(pathToImage );
Assuming there is a folder by the name of META-INF under scr/main/resources/

Java Jar file: use resource errors: URI is not hierarchical

I have deployed my app to jar file. When I need to copy data from one file of resource to outside of jar file, I do this code:
URL resourceUrl = getClass().getResource("/resource/data.sav");
File src = new File(resourceUrl.toURI()); //ERROR HERE
File dst = new File(CurrentPath()+"data.sav"); //CurrentPath: path of jar file don't include jar file name
FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst);
// some excute code here
The error I have met is: URI is not hierarchical. this error I don't meet when run in IDE.
If I change above code as some help on other post on StackOverFlow:
InputStream in = Model.class.getClassLoader().getResourceAsStream("/resource/data.sav");
File dst = new File(CurrentPath() + "data.sav");
FileOutputStream out = new FileOutputStream(dst);
//....
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) { //NULL POINTER EXCEPTION
//....
}
You cannot do this
File src = new File(resourceUrl.toURI()); //ERROR HERE
it is not a file!
When you run from the ide you don't have any error, because you don't run a jar file. In the IDE classes and resources are extracted on the file system.
But you can open an InputStream in this way:
InputStream in = Model.class.getClassLoader().getResourceAsStream("/data.sav");
Remove "/resource". Generally the IDEs separates on file system classes and resources. But when the jar is created they are put all together. So the folder level "/resource" is used only for classes and resources separation.
When you get a resource from classloader you have to specify the path that the resource has inside the jar, that is the real package hierarchy.
If for some reason you really need to create a java.io.File object to point to a resource inside of a Jar file, the answer is here: https://stackoverflow.com/a/27149287/155167
File f = new File(getClass().getResource("/MyResource").toExternalForm());
Here is a solution for Eclipse RCP / Plugin developers:
Bundle bundle = Platform.getBundle("resource_from_some_plugin");
URL fileURL = bundle.getEntry("files/test.txt");
File file = null;
try {
URL resolvedFileURL = FileLocator.toFileURL(fileURL);
// We need to use the 3-arg constructor of URI in order to properly escape file system chars
URI resolvedURI = new URI(resolvedFileURL.getProtocol(), resolvedFileURL.getPath(), null);
File file = new File(resolvedURI);
} catch (URISyntaxException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
It's very important to use FileLocator.toFileURL(fileURL) rather than resolve(fileURL)
, cause when the plugin is packed into a jar this will cause Eclipse to create an unpacked version in a temporary location so that the object can be accessed using File. For instance, I guess Lars Vogel has an error in his article - http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/
I got a similiar issues before, and I used the code:
new File(new URI(url.toString().replace(" ","%20")).getSchemeSpecificPart());
instead of the code :
new File(new URI(url.toURI())
to solve the problem
While I stumbled upon this problem myself I'd like to add another option (to the otherwise perfect explanation from #dash1e):
Export the plugin as a folder (not a jar) by adding:
Eclipse-BundleShape: dir
to your MANIFEST.MF.
At least when you export your RCP app with the export wizard (based on a *.product) file this gets respected and will produce a folder.
In addition to the general answers, you can get "URI is not hierarchical" from Unitils library attempting to load a dataset off a .jar file. It may happen when you keep datasets in one maven submodule, but actual tests in another.
There is even a bug UNI-197 filed.

Categories

Resources