I am writing a program that connects to a web host that has a directory containing a couple JAR files. Then, a GUI shows the JAR name and when you double click on the name, it will open the JAR file.
The problem that I am having is, not all of the JAR files have the main method in the same place, so I need some way of finding the main class.
I have tried doing an approach like this:
File file = new File("website/test.jar");
JarFile jar = new JarFile(file);
String mainClass = jar.getManifest().getMainAttributes().get("Main-Class").toString();
However, I get:
Exception in thread "main" java.util.zip.ZipException: error in opening zip file
On the line where a JarFile object is created. I have thought of two solutions: go through all the class files in the JAR and search for the one that contains the main method, or create a text file in the directory that tells the main file of each JAR.
I would prefer to use the first solution, because it does not actually require me to do extra steps every time I upload another JAR. However, I am concerned that it is kind of a "brute-force" alternative, and it feels inefficient.
Have any of you experienced a similar problems?
Thanks a lot!
See this :
http://docs.oracle.com/javase/tutorial/deployment/jar/jarclassloader.html
Related
Both class.getResource(FILE_NAME) and class.getClass().getClassLoader().getResource(FILE_NAME) run perfectly inside my eclipse but the same code getting failed to locate the file which is inside the jar file, when run as an executable jar in windows machine.
I have gone through all related links available for this problem (well, not exactly the same issue but 90% in sync), asked for solution but no reply came from any of those posts, so I'm posting my issue as a separate question hoping for help on this.
In total, 4 cases I have ran to resolve but none worked so far and I'm out of ideas now.
class.getClass().getClassLoader().getResource("/resources/readme.txt");
class.getResource("/resources/readme.txt");
class.getClass().getClassLoader().getResource("resources/readme.txt");
class.getResource("resources/readme.txt");
Ouf of all the above 4 cases, only 2 cases ran successfully in eclipse which are as mentioned below.
class.getResource("/resources/readme.txt");
class.getClass().getClassLoader().getResource("resources/readme.txt");
The other 2 cases just throwing me Exception in thread "main" java.lang.NullPointerException
Coming to the executable jar, all 4 cases are throwing me the Exception in thread "main" java.lang.NullPointerException.
So I have created a folder named resources where my jar is residing and placed my files inside this folder and ran the jar. Now the jar is running without any issues referring to the files inside the resources folder I created. So wherever I run this jar (windows, linux etc.,) I need to create a resources folder and place my files under the folder. Now the question is, can it be possible to make my jar refer the resources folder which is inside the jar itself?
Any help on this is much appreciated!
To get your txt file:
File yourFileIsHere = new File("resources/readme.txt");
Where put your file?
In the same location of your jar, example:
myapp/yourjar.jar
myapp/resources/readme.txt
If you want read file inside of your "src" folder:
InputStream yourInputStream = new YourClass().getClass().getClassLoader().getResourceAsStream("readme.txt");
If you are using Spring:
org.springframework.util.ResourceUtils.getFile("classpath:readme.txt")
Otherwise:
import com.google.common.io.Resources
byte[] byteSource = Resources.asByteSource(Resources.getResource("readme.txt")).read()
method class.getClass().getClassLoader().getResource() may take 3 prefixes: url:, classpath: and file: each prefix tells what is your base of search. If you want to search inside your jar use classpath: prefix. That tells your classloader to search everywhere within your classpath. Here is one example how to deal with it with Spring tools. Look also at ResourceLoader class in Spring
I understand that there are many similar questions and answers, but none of the answers fit what I am trying to do. I have a file called gui.java and I am trying to turn it into a jar file, LifeGame.jar I keep the .java and the .class in a folder, and when I try to archive it, it works, but when I try to run the file, it gives me Could not find or load main class gui. I do give a manifest called "META-INF:MANIFEST.MF" and the folder is stored on my desktop.The manifest looks like:
Main-Class: gui
I would like some advice on what to do and how to fix this problem. (As I have already said, I understand this is a clone of many other questions, but the examples I've seen don't work for me in my situation)
EDIT:
Some details on my scenario:
I have multiple classes in gui.java but only one of them is public, the rest aren't private of public. It is on my desktop and when I try java gui it gives the same error as when I try archiving it into a Jar.
Name of your main class should be gui. check your .class file which is created to be gui.class or any other. It doesn't matter the name of .java file but the name of .class file.
I have a library which is used by a program. This library loads a special directory in the resources folder.
in the library I have the method
public class DataRegistry{
public static File getSpecialDirectory(){
String resourceName = Thread.currentThread().getContextClassLoader().getResource("data").getFile().replace("%20", " ");
File file = new File(resourceName);
return file;
}
}
in my program I have the main method
public static void main(String args[]){
System.out.println(Data.getSpecialDirectory());
}
When I execute the getSpecialDirectory() in a junit test within the data program, the resource is fetched and all is well.
When I execute the getSpecialDirectory() in the main method outside the data program (imported jar) I get the jars data directory and not the directory the program executing the thread is expecting.
I figured getting the parent class loader would have solved this issue... I believe I may have a fundamental issue in my understanding here.
For clarity:
(library)
Line 15 of this file: https://gist.github.com/AnthonyClink/11275442
(Usage)
Line 31 of this file:
https://gist.github.com/AnthonyClink/11275661
My poms may have something to do with it, so sharing them is probably important:\
(Library)
https://github.com/Clinkworks/Neptical/blob/master/pom.xml
(Usage)
https://github.com/Clinkworks/Neptical-Maven-Plugin/blob/master/pom.xml
Maven uses the target/classes and target/test-classes directories to compose the classpath used to run unit tests. The content of your src/main/resources and src/test/resources gets copied to these locations together with the compiled java sources (the .class files).
java.lang.ClassLoader.getResource returns a java.net.URL.
In the unit test situation, ClassLoader.getResource returns a file:// schemed URL, and your code works as expected.
When your code is executed when packaged in a jar file, ClassLoader.getResource no longer returns a file:// schemed URL. It can't because the resource is no longer a separate entity in a file system - it's buried inside the jar file. What you actually get is a jar:file:// schemed URL.
jar: URLs cannot be accessed through a [java.io.File] object.
If you only need to read the content of the resource you should use java.lang.ClassLoader.getResourceAsStream(...) and read the content from that.
Note that it is not possible to update the content of class loader resources.
Do you want the directory where the Java program was loaded from ? Can try
File f = new File(".").getCanconicalFile();
Or if you want all the places could try parsing the classpath from System.env or use the default class loader
If you want a directory relative to the jar from where your classes were loaded: Quoting from http://www.nakov.com/blog/2008/06/11/finding-the-directory-where-your-java-class-file-is-loaded-from/
URL classesRootDir = getClass().getProtectionDomain().getCodeSource().getLocation();
The above returns the base directory used when loading your .class
files. It does not contain the package. It contains the classpath
directory only. For example, in a console application the above
returns someting like this:
file:/C:/Documents%20and%20Settings/Administrator/workspace/TestPrj/bin/
In a Web application it returns someting like this:
file:/C:/Tomcat/webapps/MyApp/WEB-INF/classes/
FYI This might apply if the user id running program cannot read all folders: http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getProtectionDomain%28%29
or pass a .class object of the calling class as a parameter and get its classloader
There is no guarantee that you have a directory for your resources as far as I know. Java provide methods to get a resource as a InputStream, but nothing that can easily get the File for a resource, although it is possible to get the URL for a given resource.
If you need a special working directory in your application, I recommend having that passed as a system property, a program parameter, a web application parameter, or something else that lets you know where your application files are. You can even populate this directory with a ZIP file that you include as a resource in your application, as the ZIP libraries in Java do accept input streams as parameters.
While user #tgkprog is right and his answer correct, I can hardly imagine that you really want what you seem to have asked for and what he correctly answered in (3). Please edit your question and explain
what the output should look like if resourceName would be printed to the console,
if you really want the JAR file's location (in my test case that would be something like file:/C:/Users/Alexander/.m2/repository/com/clinkworks/neptical/0.0.1-SNAPSHOT/data, which does not make sense because you do not want to read from or even write to the local Maven cache),
or if you maybe rather want to read a resource directly from the JAR file or any other location such as the current working directory etc.
Otherwise I am afraid there is no good way to answer the question.
I had problems while finding the path of file(s) in Netbeans..
Problem is already solved (checked answer).
Today I noticed another problem: When project is finished,
I have to execute the generated .jar to launch the program, but it doesn't work because an error occurs: NullPointer (where to load a file) when accessing/openning jar outside Netbeans.
Is it possible to open a file with the class file in Java/Netbeans which works in Netbeans and even in any directory?
I've found already some threads about my problem in site but none was helpful.
Code:
File file = new File(URLDecoder.decode(this.getClass().getResource("file.xml").getFile(), "UTF-8"));
The problem you have is that File only refer to files on the filesystem, not files in jars.
If you want a more generic locator, use a URL which is what getResource provides. However, usually you don't need to know the location of the file, you just need its contents, in which case you can use getResourceAsInputStream()
This all assumes your class path is configured correctly.
Yes, you should be able to load a file anywhere on your file system that the java process has access to. You just need to have the path explicitly set in your getResource call.
For example:
File file = new File(URLDecoder.decode(this.getClass().getResource("C:\\foo\\bar\\file.xml").getFile(), "UTF-8"));
I'm not able to give this question an apt title so apology for that.
I am making a modularised application. I load various jar files at runtime and invoke particular method of a particular class (of the jar file) at run time.
The jar file has some supported file. Now my jar file uses another application , lets say abc which is located in the same directory where i have kept the jar file. When i run the jar file then
new File(".").getAbsolutePath()
gives the correct path (this is where abc is located) and program runs fine. But when i load this jar file dynamically and invoke method using reflection above code gives the path of the parent program and abc is not found at that path.
Now my question is how do i find the path in which my jar file exists when i'm running my jar file's code using reflection.
Please let me know if you need more explanation.
Try something like this:
public static void main(String[] args) {
System.out.println(StringUtils.class.getResource("StringUtils.class"));
}
(Note: StringUtils is present on my classpath as a Maven dependency at the time) This gives me:
jar:file:/home/******/.m2/repository/org/apache/commons/commons-lang3/3.4/commons-lang3-3.4.jar!/org/apache/commons/lang3/StringUtils.class
Since the class is in a JAR file, it also gives me the location of the class file within the JAR.