using a library file from within jar - java

This is a follow up of this question
What I try to do:
I have an eclipse project that uses th Sigar library in order to get the cpu information (among others). In order to do that Sigar needs a library file to work. Each CPU/OS have a different file, all of which are available.I have to pack this into a jar, that other can use my application as a library.
What I did:
added the available library files to my project and can access them like so
System.setProperty("org.hyperic.sigar.path",System.class.getResource("/lib").getPath());
System.load(System.class.getResource(getClass().getResource(
"/lib/libsigar-amd64-linux.so").toString()).getPath());
Both of these seems to work if i run my application as a stand alone application.
When i pack it to a jar and try to run it from an other project, it just doesn't work. I cant make it to see the directory or the file.
This is the structure of my project
I have tried to access the file with any path i could think of, but all returned a NullPointerException.
How can I do this? Using a temp file? I am not sure how i should do this, i would like to load the whole folder and not just one file, since i dont know the hardware/OS of the client application.

Related

Deployed spring boot jar file to Docker - how to access and change static resources

I'm kinda new to spring and web development as a whole.
My question is:
When you build a spring boot project (using Maven) into jar file and deploy it via Docker, everything is in one jar file. How can you access your resources (css, js, images, html...) if you want to edit something? Like change something in css file or add something to html page. Is it even possible? Or do you have to build a new jar file everytime, when you need to change something (in frontend)? Also, when there are being uploaded some images or other files, where are they stored? This stuff is very confusing for me and i can't find any related books or help at all.
Thanks for help!
when you package any java program it is nothing but a zip file. Based on what kind of package it is, you wither name it as a Jar or War.
Jar == Java archive
War == Web archive
Now, given the fact that jar and war both are essentially a zip archive, it gives you flexibility to extract and modify them just like any other zip file.
On windows, I think softwares like 7zip let you update the jar inline. I have done it multiple times, especially when I wanted to change application.properties alone on cloud machines, and no other code changes were required. In such cases, building the whole jar and transferring it again to cloud machine could be time consuming. So I would just extract the contents, update whatever I want to, and rezip the package.
Here is the commands you can use -
jar xf jar-file
This should extract the files into a directory.
This SO thread will guide you towards creating jar files.
Something like jar cf myJar.jar ** should be enough to generate a jar file IMO, but syntax might vary.
The jar file is actually just a zip file containing all the files and classes of your application, so technically you can change files in it like any other zip archive. Best practice is to build the jar file using Maven or Gradle from source every time you need something changed.
It's good practice to keep the source in version control using Git, and tag each build in the git repository - that way you can easily keep track of changes to the jar file by looking at what's in git at the time of the build.

How to use a jar file with shared object in another java project

I have some C files which I wanted to use in my java-android project. Used JNI wrappers and NDK to create SO. I was able to access the C methods from my java code. Everything works fine.
Now I want to create a jar file of this project, for providing it further to other developers(So that the C code can be hidden from others).
This is where I am facing some issues. When I am trying to use the created JAR in some other project I start getting the "UnsatisfiedLink Error" while loading the SO.
The SO is loading perfectly fine in the same project, however when creating the jar with same project and trying to use it in another project, it is causing issues.
*Using Eclipse.
When using eclipse/ant, you need to distribute your .jar and your .so files separately. Other developers will have to reintegrate the .so files themselves inside their lib/ABI folders.
You may find some hacky ways to get .so files integrated using additional jar files containing only the .so files, but that doesn't change the fact that you need to distribute them separately.
To distribute your library with its .so files as a single file, you should build an .aar instead of a .jar. Android Studio/gradle can directly consume these, with .so files integrated directly under the jni/ABI folders of the aar file.

Using a Jar file inside a java application

I've tried searching through java documentation. I could not find anything on opening a jar file inside of a java application. To further explain what I`m trying to do I will use an example. MinecraftForge has a folder where all of the mods get loaded from using jar files.
I would like to be able to put jar files inside a folder that will be used by the application. Is this possible and could somebody point me in the right direction.

How to access Jar file located within source folders?

in my Java project I am using an H2 in-memory database, for which I have to load the JDBC driver when I initialize my application. I want/need to load the H2 .jar file dynamically, so I do the following:
String classname = "org.h2.Driver";
URL u = new URL("jar:file:libs/h2.jar!/");
URLClassLoader ucl = new URLClassLoader(new URL[] { u });
Driver d = (Driver) Class.forName(classname, true, ucl).newInstance();
DriverManager.registerDriver(new DriverShim(d));
When I put the H2 .jar file into a "libs" folder outside my Java source code folder (that is, in Eclipse, this "libs" directory is on the same level as the "src" folder), then this approach works fine. However, unfortunately I have to put this H2 .jar file into a folder within the source code folder tree, but below the main class folder.
For example, my Java package structure looks like this in Eclipse:
<project>/src/my/app/MyApp.java // main class of my application
<project>/src/my/app/sub/package/h2.jar // how to access this?
<project>/libs/h2.jar // loading from here works
I know this is stupid, but unfortunately I have to work with this strange setup. But what I don't know: how can I edit my Java code (listed above) in order to work with this setup?
EDIT: This has to work outside Eclipse as well, so adding the JAR file to the Java Build Path in Eclipse is no option for me.
EDIT2: I already tried to load "jar:file:my/app/sub/package/h2.jar!/", but that did not work for me.
Thanks in advance for all helpful ideas!
Kind regards, Matthias
In some frameworks referring to files inside JARs can be done using the classpath: prefix. I doubt URLClassLoader supports it natively, but it's worth a try (e.g. classpath:/my/app/sub/package/h2.jar). But since that doesn't work with URLClassLoader, here are other ways:
One way to do it would be to write your own ClassLoader which reads the JAR file from classpath (using getResourceAsStream), uncompresses it (using ZipInputStream) to memory (e.g. a map of byte arrays) and loads the classes from there.
Another, slightly easier way, is to read the JAR file from classpath and write it into a temporary file. Then you can use the plain URLClassLoader to load classes from it. This has the disadvantage that the file must be written to a file and the file probably cannot be removed until the JVM exits (unless using Java 7 or higher).
I'm using the second approach (copying to a temp file) in one project, though I'm using it to launch an external process. I would be curious to hear why you have such a requirement. If it's just a matter of having the whole application in one JAR, there are numerous simpler methods for achieving that (Maven Assembly Plugin, Maven Shade Plugin, Jar Jar Links, One-JAR to name a few).
No it's not a homework, but an online build system that uses my classes under my/app/* and several other classes (not from me) to automatically build the whole solution. Anyway, I can't give you more details on the internals of this system, as I don't know them. As said, I simply have to live with it, and that is why I am asking here...
Sounds like you are working in a WTF environment (does it have a name?), so here are some ways to start hacking around it:
Find out more about your environment, especially absolute file paths of the following: directory where the source files are saved, directory where the generated .class files are saved, and the current working directory when the program is run.
If you can get any kind of output of what your program prints during runtime, you can put into your application some debug code where you use File.listFiles() to crawl the machine's directory trees. If you can get output only from what happens when compiling, it might be possible to execute your own code during compile by creating your own annotation processor (apt is part of javac since Java 6), though I'm not sure whether the annotation processor must be compiled first separately.
The working directory can be read from the user.dir system property and the location of class files can be probably gotten from the java.class.path system property (unless custom class loaders are used). There is no guarantee that a JAR file in the source directory would be copied to the classpath, so you might need to do some looking around.
Then when you know the file path of the JAR file, then you can get an URL to it using new File("path/to/h2.jar").toURI().toURL() which you can then pass to URLClassLoader.
If nothing else works, upload the source code of the libraries and compile them together with your project.
In the long run, try to replace the WTF build environment with one that uses a standard build tool (such as Maven) and a common CI server (such as Jenkins). It's normal for projects to have lots of library dependencies, so you shouldn't need to hack around a build environment to use them.

home folder changes when using java classes from matlab

I am writing a java application with a matlab ui. For this I use java objects in matlab as explained here: http://www.mathworks.com/help/techdoc/matlab_external/f4873.html
those java classes reference (using a relative path) to resources in some other folder in the parent map. In eclipse or as an executable jar this all works fine.
The problem is that when classes are used in matlab the homefolder changes. So instead of looking in JAR/resources or PROJECTMAP/resources it looks for the resources in MATLAB/resources and returns a file not found exception.
how I currently solved it is kinda lame:
I simply put a copy of the resource folder in the MATLAB directory which makes the code execute.
Yet this is a poor solution.
What I would want is
1: to include the resource folder in the jar (generated in eclipse) an make it possible to use these classes in matlab (in short: independency current directory)
2: Being able to run the same code from eclipse (to debug/profile...).
3: That the code should execute independantly of the location the jar is in as long as it is added to the matlab classpath. (so the jar does not have to be in a specific folder (eg MATLAB folder))
So I 'simply' need a way to specify the location of the resource folder in my code as to achieve 1,2,3 (1,2 most important).
Not sure how you're reading and what you're doing with these resources (so this might not be the correct solution for your case), but you indeed might want to put these on your classpath. If you put them in their own source folder in eclipse you can setup your build to include them in your jar. (Maven by convention has a /src/main/resources directory that is for sticking arbitrary files into a the compiled jar).
With these resources on the classpath... You can then use the classloader to load files through getClass().getResourceAsStream() or getResource() and run with it.

Categories

Resources