How can you pack ObjectDB in a runnable JAR file? - java

I wanted to know if it is possible to include an ObjectDB database file .odb in a runnable JAR.
The method:
EntityManagerFactory emf = Persistence.createEntityManagerFactory(path);
takes a String path as an argument and not a URL. This means that getResource() does not work. Neither do getResource.getPath() and getResource.toString() work, since they somehow show a distorted path name and during runtime the database file is created outside the jar file.
So I was wondering if it is possible for the .odb file to be created inside the JAR and be manipulated within the JAR.

Why can't you copy your resource to temporary folder using for instance:
FileUtils.copyURLToFile()
(http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/FileUtils.html#copyURLToFile%28java.net.URL,%20java.io.File%29)? And then you can use file path to copy.
Temporary system folder for current user you can find by:
File tempDir = new File(System.getProperty("java.io.tmpdir"));

An ObjectDB database must be a file and cannot be a resource within a file.
Following the solution of rsutormin seems as the right way to go.

Related

Spring does not find file in resources

i have following line
File file = ResourceUtils.getFile("classpath:calculation.csv");
and i also tried
File file = ResourceUtils.getFile("classpath:/calculation.csv");
but both will throw an error
java.io.FileNotFoundException: class path resource [calculation.csv] cannot be resolved to absolute file path because it does not exist
but i do have calculation.csv in by resources folder..
why is this?
I need to read file from resources folder, and it should also work in server enviroment
EDIT:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("calculation.csv").getFile());
works just as fine, so not at all..
EDIT2:
tried with folder.. i have both calculation.csv and csv/calculation.csv in my resources folder now..
none of the above work, with /csv/ added.
what kind of path does this thing want?!
EDIT3:
aaand
File file = new ClassPathResource("calculation.csv").getFile();
is also no go, what even is this..
Loading file (as FILE) wont work. You must use it as resource. Files inside JAR will not work as file anyway. This is also what your "check" code shows.
classLoader.getResource("calculation.csv") works, because you are using classloader to get resource, not filesystem to get file (which is what File api does). It could work, if you would deal with non packed application. Once you pack your app into JAR, file path will be like your/path/to/jar.jar!someResource - note ! mark (and that is what you would see as well). So basicly it will return File instance, you that you wont be able to use anyway, as file system has no access to it.
You could alternatively try to extract it first with ResourceUtiuls#extractJarFileURL(URL jarUrl) and then use extracted file.
I think, that in most cases Class#getResourceAsStream is the way to go and I think that it should fit your needs as well to read content of resource.

Using relative path in a maven project

I have a maven project with these standard directory structures:
src/main/java
src/main/java/pdf/Pdf.java
src/test/resources
src/test/resources/files/x.pdf
In my Pdf.java,
File file = new File("../../../test/resources/files/x.pdf");
Why does it report "No such file or dirctory"? The relative path should work. Right?
Relative paths work relative to the current working directory. Maven does not set it, so it is inherited from whatever value it had in the Java process your code is executing in.
The only reliable way is to figure it out in your own code. Depending on how you do things, there are several ways to do so. See How to get the real path of Java application at runtime? for suggestions. You are most likely looking at this.getClass().getProtectionDomain().getCodeSource().getLocation() and then you know where the class file is and can navigate relative to that.
Why does it report "No such file or dirctory"? The relative path should work. Right?
wrong.
Your classes are compiled to $PROJECT_ROOT/target/classes
and your resources are copied to the same folder keeping their relative paths below src/main/resources.
The file will be located relative to the classpath of which the root is $PROJECT_ROOT/target/classes. Therefore you have to write in your Pdf.java:
File file = new File("/files/x.pdf");
Your relative path will be evaluated from the projects current working directory which is $PROJECT_ROOT (AFAIR).
But it does not matter because you want that to work in your final application and not only in your build environment. Therefore you should access the file with getClass().getResource("/path/to/file/within/classpath") which searches the file in the class path of which the root is $PROJECT_ROOT/target/classes.
No the way you are referencing the files is according to your file system. Java knows about the classpath not the file system if you want to reference something like that you have to use the fully qualified name of the file.
Also I do not know if File constructor works with the classpath since it's an abstraction to manage the file system it will depend where the application is run from. Say it is run from the target directory at the same level as source in that case you have to go one directory up and then on src then test the resources the files and finally in x.pdf.
Since you are using a resources folder I think you want the file to be on the classpath and then you can load a resource with:
InputStream in = this.getClass().getClassLoader()
.getResourceAsStream("<path in classpath>");
Then you can create a FileInputStream or something to wrap around the file. Otherwise use the fully qualiefied name and put it somewere like /home/{user}/files/x.pdf.

Absolute path of a file inside a project package

I've created a file inside a project package using this code:
File xmlFile = new File("src/com/company/project/xml/tags.xml");
I am able to read the file while running from eclipse. However, after creating .jar, I'm unable to read the file. So I want to put absolute path while reading the file from the project package. How it can be done? Help and suggestions are appreciated.
In most cases, IDE's will include no Java files in the resulting Jar. Most IDE's will also include the src directory in the classpath when you run/debug the program from within them.
As a general rule of thumb, never include src in any path, src will simply not exist once the program is built.
Instead you need to make use of Class#getResource or Class#getResourceAsStream, depending on your needs. You should remember, you should never treat an "embedded" resource as a File, as in most cases it won't be, it'll be a stream of bytes in a zip file.
Something like...
URL xmlFile = getClass().getResource("/com/company/project/xml/tags.xml");
will return a URL reference to the resource. Remember, if you need a InputStream, you'll have to Class#getResourceAsStream.
If you want the resource to be writable, then you will need to find a different location to store it, as embedded resources are read only
Try with getClass().getResource()
new File(getClass().getResource("src/com/company/project/xml/tags.xml").toURI());

The correct place to put the config file in Eclipse

I have created a Dynamic Web Project in Eclipse and I have a following Java statement that needs to read a config file:
Document doc= new SAXReader().read(new File(ConstantsUtil.realPath+"appContext.xml"));
Basically, ConstantsUtil.realPath will return an empty string.
I tried putting "appContext.xml" under both "src" folder and under "WEB-INF" folder. However, I will always get the following error:
org.dom4j.DocumentException: appContext.xml (The system cannot find the file specified)
I am really confused: in Eclipse, where is the correct place to put my config xml file?
Thanks in advance.
Your concrete problem is caused by using new File() with a relative path in an environment where you have totally no control over the current working directory of the local disk file system. So, forget it. You need to obtain it by alternate means:
Straight from the classpath (the src folder, there where your Java classes also are) using ClassLoader#getResourceAsStream():
Document doc= new SAXReader().read(Thread.currentThread().getContextClassLoader().getResourceAsStream("appContext.xml"));
Straight from the public webcontent (the WebContent folder, there where /WEB-INF folder resides) using ServletContext#getResourceAsStream():
Document doc= new SAXReader().read(servletContext.getResourceAsStream("/WEB-INF/appContext.xml"));
The ServletContext is in servlets available by the inherited getServletContext() method.
See also:
Where to place and how to read configuration resource files in servlet based application?
getResourceAsStream() vs FileInputStream
What does servletcontext.getRealPath("/") mean and when should I use it
You can embed your config files into your jar/war files
InputStream is = MyClass.class.getResourceAsStream("/com/site/config/config.xml");
You could either create a folder with all your configurations and reference it on the class path of the web application when published on the server, or place them under the WebContent folder, in both cases you need to reference them relatively.
There can be multiple places where you could place your property files. The selection of the location depends on the architeture of the project.
Commonly used location are:
/YourProjectRootFolder/src/main/webapp/WEB-INF/properties/XYZ.properties
: in the same folder where you have your java class files.
YourProjectConfFolderNAme/src/main/resources/XYZ.properties: here all the property files are kept in a seperate location than your project class files.
Both are the same as you need to move all your property files to you server's conf folder.

Java - read file from directory for jar

I have an application that creates a temporary mp3-file and puts it in a directory like C:\
File tempfile = File.createTempFile("something", ".mp3", new File("C:\\));
I'm able to read it by just using that same tempfile again.
Everything works fine in the Eclipse IDE.
But when I export my project for as a Runnable jar, my files are still being made correctly (I can play them with some normal music player like iTunes) but I can't seem to read them anymore in my application.
I found out that I need to use something like getClass().getResource("/relative/path/in/jar.mp3") for using resource files that are in the jar. But this doesn't seem to work if I want to select a file from a certain location in my file system like C:\something.mp3
Can somebody help me on this one?
It seems you dont have file name of the temp files . When you was running your program in eclipse that instance was creating a processing files, but after you made a runable you are not able to read those file that instance in eclipse created, You runable file can create its own temp file and can process them,
To make temp files globe put there (path + name ) entries in some db or property file
For example of you will create a temp file from the blow code
File tempfile = File.createTempFile("out", ".txt", new File("D:\\"));
FileWriter fstream = new FileWriter(tempfile);//write in file
out = new BufferedWriter(fstream);
the out will not be out.txt file it will be
out6654748541383250156.txt // it mean a randum number will be append with file
and you code in runable jar is no able to find these temp files
getClass().getResource() only reads resources that are on your classpath. The path that is passed to getResource() is, in fact, a path relative to any paths on your current classpath. This sounds a bit confusing, so I'll give an example:
If your classpath includes a directory C:\development\resources, you would be able to load any file under this directory using getResource(). For example, there is a file C:\development\resources\mp3\song.mp3. You could load this file by calling
getClass().getResource("mp3/song.mp3");
Bottom line: if you want to read files using getResource(), you will need those files to be on your classpath.
For loading from both privileged JARs and the file system, I have had to use two different mechanisms:
getClass().getClassLoader().getResource(path), and if that returns null,
new File(path).toURI().toURL();
You could turn this into a ResourceResolver strategy that uses the classpath method and one or more file methods (perhaps using different base paths).

Categories

Resources