Loading a resource in a JAR file - java

I have a Java project in Netbeans. It runs fine with Maven. So I assembled it. It contains the following code to load a file that is in the JAR:
ClassLoader loader = MyClass.class.getClassLoader();
SERVICE_URL = loader.getResource("my.wsdl");
This returns a URL like:
jar:file:/path/to/my/file/MyClass-1.0-SNAPSHOT-jar-with-dependencies.jar!/my.wsdl
but the library that needs this parameter doesn't appear to be able to use it.
Is there any way this file can be in the JAR and be referred to from the code like this?

You may have to use ClassLoader.getResourceAsStream(), copy it to a temporary file, and then create a URL with File.toURI().toURL()

Related

Docker Class.forName doesn't find class

I'm running a server in a docker image openjdk:8-jdk-slim.
Inside this server, using spring boot, I receive from the frontend a protobuf file, compile it and add the generated class to the classpath in runtime. I then proceed to use java reflection to get the added class, with the method Class.forName().
Outside of docker, when running in my pc, it works like a charm. However, when I run in docker when I try to access using the method Class.forName(), with the same class name I use when not in docker, it doesn't find the class.
Is there something that I am missing because it is docker?
Edit for more information:
I'm running a maven build inside docker. What I have in this specific operation is an endpoint that receives a byte array, which corresponds to a protobuf file. I "construct" a file with this byte array, save it in a specific folder. I proceed to compile it with the protoc compiler, which generates a .java file, which I save in a specific folder. This folder corresponds to a package, which we will call "xxx.yyy.zzz".
When I try to add the class to the classpath, using this code -
File newClass = new File(relativePath);
URL url = newClass.toURI().toURL();
URLClassLoader classLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
Method newMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
newMethod.setAccessible(true);
newMethod.invoke(classLoader, url);
I provide the relativePath to the .class file but it isn't added to the classpath. I know that the .class file is generated in the correct way and is saved in the specific folder.

Load library jars with javassist

I am trying to analyze the code of a java project.
I have the project to be analyzed in a jar that I add to javassist path using insertClassPath function. Everything works fine if I try to access a class form the project.
The problem is that I need to access also the classes from the libraries the project uses.
I tried to add the library to the class path just like i did with the project jar, but I get a NotFoundException so i guess I am not giving the right path.
The code looks like this:
String jarFileName = "C:/Users/diana/Desktop/Test/ckjm.jar";
ClassPool pool = ClassPool.getDefault();
try{
pool.insertClassPath(jarFileName);
pool.insertClassPath("C:/Users/diana/Desktop/Test/ckjm/lib/bcel-5.2.jar");
} catch (NotFoundException e) {
System.out.println("error loading jar!!");
}
I used the harcoded string just for testing purpose. The jar is in the lib folder or the project that was archived to a jar.
I am not sure how can i add a jar that is contained in another jar.
Note: if i keep the library as a separate jar (and give the path like: "C:/Users/diana/Desktop/Test/bcel-5.2.jar") it woks fine
Any help would be appreciated
If your target JAR is inside another JAR, you can use a LoaderClassPath created using a URLClassLoader which is defined using a JarURLConnection URL path of the JAR.
So assume you have a target JAR, inner.jar, embedded inside another JAR, C:/Users/diana/outer.jar.
Let's assume it is in a subdirectory called lib.
The URL of the outer JAR would be file:/C:/Users/diana/outer.jar.
The URL of the inner JAR would be jar:file:/C:/Users/diana/outer.jar!/lib/inner.jar.
You code to load this classpath would be:
URL cpUrl = new URL("jar:file:/C:/Users/diana/outer.jar!/lib/inner.jar");
URLClassLoader cpUrlLoader = new URLClassLoader(new URL[]{cpUrl});
pool.insertClassPath(new LoaderClassPath(cpUrlLoader));

Java code cannot find resource file after build and clean in Netbeans IDE?

I really need your help to solve my own problem. Now, I'm dealing with small code app. In that project folder contain some resource files (*.xlsx, *.png,...). I placed them in current folder with code file. I just wonder that when I run my code in netbean ide, it just worked find.
After I build code project, I get a jar file in "dist" directory. I run it. It open normally since app used JFrame as user interface. However, when I execute some function of that app, it showed me the error log. Here is the error message:
java.io.FileNotFoundException:
src\sample.xlsx (The system cannot find the path specified)
What's the matter out there?
Here is some pieces of my code:
copyFile(new File("src\\sample.xlsx"),
new File(txtout.getText()+"\\sample.xlsx"));
Node: copyFile function is used for copy file from source to dest.
Here is my project folder structure in Netbean IDE:
Project Name
Source Pakage(src)
myClass.java, sample.xlsx, etc
First, never reference src directly, the directory will not exist once the program is built. Second, you can not access resources which have been embedded within in the application context via a File reference, they simply no longer exist on the file system.
Instead, you need to use Class#getResource or Class#getResourceAsStream
URL url = getClass().getResource("/sample.xlsx");
InputStream is = getClass().getResourceAsStream("/sample.xlsx");
// Don't forget to manage your streams appropriately...
Well you can create a folder named resources under the src folder put your resources in it and use them in your code by using getResourceAsStream() and getResource() methods that can access the embedded resources.Clean and Build will compile the code and embed the contents of the resources folder into the application’s .jar file.
Ways of Accessing resources :
String pathToImage = "resources/images/filling.png";
InputStream stream= ClassName.class.getResourceAsStream(pathToImage );
String pathToImage = "resources/images/filling.png";
InputStream stream= ClassName.class.getResource(pathToImage );
please refer the link information

Java get folder in same directory as Jar

Say I have an exported Jar file on my Desktop, and then a folder I want to access so my jar file can load files from it. How can I access that folder without hard coding the path?
See here: https://stackoverflow.com/a/6849255/514463
Pick one of your classes that you want the directory of, e.g.: Test:
String path = Test.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");
If I clearly understand, you may use relative path when you try to access folder. For example, if you run your jar as a standalone application, relative path "." will be a folder that contains your jar. So, when you place names.txt file next to your jar, you can get access to it with:
new File("./names.txt");
Hope I understood you right way and this will help.
The following code should provide the directory containing the JAR file:
URL url = getClass().getProtectionDomain().getCodeSource().getLocation();
File directory = new File(url.toURI()).getParentFile();
Hmmm...
I heard this question so often, and it always boils down to this: How to load resources at runtime?
The main reason for this type of question is, that one is developping an application and now wants to create a distributable package. This normally ends in something like that:
... / my-application-folder
| -- lib / *.jar
| -- main.jar
| -- config.properties
There could be several configuration files. A configuration for the application itself, a configuration for a logging framework that is used, etc. It does not matter. If you want to access such resources, you should do it in two steps:
1) Make sure all folders containing your resources (such configuration files are resources) are part of the classpath. If you run your JAR file (here main.jar) with a java -jar main.jar command, this JAR file should contain a manifest file containing the directory . and all needed library JARs in the class-path entry. [Alternative: Maybe all your config files are located in a config/ subfolder. Then this folder must be part of the class-path.]
2) Inside your application you access such resources with a class loader:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
URL url = loader.getResource(neededResource);
// do something with url, e.g. open stream, read from it, and close stream
If you have a user customizable path, there are several possibilities. You could for example pass a system property to the application, as Reddy suggested in his comment. You could also have a property in a configuration file, which you are loading in the beginning part of your application. However, you have the path to this customizable folder in hand (at runtime). Then you do the following:
String customizablePath = getCustomizablePath();
URL customizablePathURL = new File(customizablePath).toURI().toURL();
ClassLoader loader = new URLClassLoader(new URL[] {customizablePathURL});
Then you can continue like above.
File f = new File("Folder")
This File object points to "Folder" directory in the the working directory of the Jar.

Java Build Path

I have a quick question about altering the build path as the code is running.
For example, I have a class which downloads a .jar file from the internet and then into the same directory as the code is running from. How, if possible, could I load the jar into the build path to access the classes within the .jar file?
Some suggested amendments / comments:
Remove the jar: prefix and the !/ suffix - these are note required and are probably confusing the matter
Can you verify the jar file exists:
System.out.println(new File(new URL("file://test.jar")).exists());
Amend your class declaration to the following (get the File object to generate the URL for you, to avoid problems):
URL[] classes = new URL[] { new File("test.jar").toURI().toURL() };
This worked for my test example, using commons-codec as the jar, and loading the Base64 class

Categories

Resources