I know this topic has been up a lot of times and I have been looking at stackoverflow for hours after the sollution but still not working. From Eclipse I can't make my jar-file work when exporting a runnable jar-file. The program is working perfectly in Eclipse when I run it but when I try to open the jar-file the screen is going black for a second then nothing happens. I try to open it in command with java -jar nameoffile.jar and there is filenotfoundexception. This is what it looks like in cmd when I have tried to run it.
Do anyone have any suggestions?
Thanks
The problem is how you get your resources.
You put your wav file in src folder an the try get them using FileInputStream, that's not going to work.
If you put your file into the jar you should access them throug:
getClass().getResourceAsStream(filepath)
Something like this.
public class LoadFile {
public static void main(String[] args) throws Exception {
InputStream stream =
LoadFile.class.getResourceAsStream("/songwavs/s1_..._.wav");
AudioSystem.getAudioFileFormat(stream);
AudioSystem.getAudioFileFormat(url);
}
}
That's just an example, the point is that being the resource inside the jar, the ClassLoaders are the tool to get it.
So, inside a non static method you could use:
public void myMethod() throws Exception{
InputStream stream = getClass().getResourceAsStream("/songwavs/s1_..._.wav");
AudioSystem.getAudioFileFormat(stream);
}
In some circumstance the you need to use the Thread classloader like this:
public void myMethod2() throws Exception{
InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("/songwavs/s1_..._.wav");
AudioSystem.getAudioFileFormat(stream);
}
Then you can put read your file both when running from eclipse or from the jar.
Much more could be said about how to package an application and deploy it, but that's just a start.
Related
I have a project structure like this:
main-directory
src
code
images
javaFile1.java
test.java
The compiled project structure is like this:
out
artifacts
production
main-directory
code
images
javaFile1
test
images is directory with many images.
Now the code for test looks like this:
public void doSome(){
System.out.println(this.getClass().getResource("./images/image1.png"));
}
public static void main(String[] args){
test test = new test();
test.doSome();
}
I get the file as file:
--location-- /main-directory/out/production/main-directory/code/images/image1.png
But when I run this.getClass().getResource("./images/image1.png") in javaFile1, it returns null. I am not able to understand that why does javaFile1 not find the resource while test does even though they are in the same directory. I tried some answers from SO, but none of them worked.
I would appreciate any help.
For some reason it fixed when I added "/code/images/image1.png" instead of "./images/image1.png". It might be that resources need the parent directory to find it.
I have a homework and I did it on Linux, Visual Studio Code, and the command line. It was working perfectly fine until I need to debug my code. So I migrated to Windows 10 because I had IntelliJ IDEA installed there. I compiled the code and place the input file "bank.in" in the same folder as the compiled "MyClass.class"
However, when I run the program from IntelliJ, my code catches the exception that it cannot find the file "bank.in" when it is just in the same folder as "MyClass.class".
My method in creating the bank.in was, right clicking the out folder from IntelliJ and adding a new file and adding the bank.in contents from there
I've tried running it through cmd.exe using java MyClass and it works perfectly. No exceptions are caught.
But when run through IntelliJ IDEA, it shows
Cannot find bank.in...
Exiting the program...
This is the part of my code where I input my file.
public void main(String[] args)
{
String fileName = "bank.in";
FileReader bank = null;
BufferedReader bankBuffered = null;
try
{
bank = new FileReader(fileName);
bankBuffered = new BufferedReader(bank);
}
catch(FileNotFoundException f)
{
System.out.printf("%s is not found.%n%n", fileName);
System.out.printf("Exiting the program...%n");
System.exit(0);
}
}
This is my project folder structure
MyProject
-.idea
-encodings.xml
-misc.xml
-modules.xml
-workspace.xml
-out
-MyClass.class
-bank.in
-src
-MyClass.java
When I run it through cmd.exe, it works fine. Is there any workaround through this? Thank you.
I ran into library loading problems after creating a jar from my code via maven. I use intelliJ idea on Ubuntu. I broke the problem down to this situation:
Calling the following code from within idea it prints the path correctly.
package com.myproject;
public class Starter {
public static void main(String[] args) {
File classpathRoot = new File(Starter.class.getResource("/").getPath());
System.out.println(classpathRoot.getPath());
}
}
Output is:
/home/ted/java/myproject/target/classes
When I called mvn install and try to run it from command line using the following command I'm getting a NullPointerException since class.getResource() returns null:
cd /home/ted/java/myproject/target/
java -cp myproject-0.1-SNAPSHOT.jar com.myproject.Starter
same for calling:
cd /home/ted/java/myproject/target/
java -Djava.library.path=. -cp myproject-0.1-SNAPSHOT.jar com.myproject.Starter
It doesn't matter if I use class.getClassLoader().getRessource("") instead. Same problem when accessing single files inside of the target directory instead via class.getClassLoader().getRessource("file.txt").
I want to use this way to load native files in the same directory (not from inside the jar). What's wrong with my approach?
The classpath loading mechanism in the JVM is highly extensible, so it's often hard to guarantee a single method that would work in all cases. e.g. What works in your IDE may not work when running in a container because your IDE and your container probably have highly specialized class loaders with different requirements.
You could take a two tiered approach. If the method above fails, you could get the classpath from the system properties, and scan it for the jar file you're interested in and then extract the directory from that entry.
e.g.
public static void main(String[] args) {
File f = findJarLocation("jaxb-impl.jar");
System.out.println(f);
}
public static File findJarLocation(String entryName) {
String pathSep = System.getProperty("path.separator");
String[] pathEntries = System.getProperty("java.class.path").split(pathSep);
for(String entry : pathEntries) {
File f = new File(entry);
if(f.getName().equals(entryName)) {
return f.getParentFile();
}
}
return null;
}
I have this problem that i have a program that writes and creates a .java file and puts it in my package folder, after this it takes the information from the .java file and uses it in it self. (it creates a new class with a method that i then import).
The problem is that if it wont work until i with eclipse update the "self created file". is there a way to make my main file update the "self created file".
Sorry if this is a duplicate. I just couldn't find it any where.
my code:
package dk.Nicolai.Bonde;
import java.io.*;
public class main {
public String outputString ="Math.sqrt(25)" ;
static String outputPath ="src/output.txt";
/**
* #param args
* #throws UnsupportedEncodingException
* #throws FileNotFoundException
*/
public static void main(String[] args) throws IOException{
new main().doit(args);
}
public void doit(String[] args) throws IOException{
PrintWriter writer = new PrintWriter("src/dk/Nicolai/Bonde/calculate.java", "UTF-8");
writer.println("package dk.Nicolai.Bonde;");
writer.println("public class calculate{");
writer.println("public void calc(){");
writer.println("System.out.println("+outputString+");");
writer.println("}");
writer.println("}");
writer.flush();
writer.close();
calculate calcObj = new calculate();
calcObj.calc();
}
}
Your main mistake is that you expected that it's during runtime automagically compiled into a .class file after save (which a sane IDE such as Eclipse is doing automatically for you behind the scenes everytime you press Ctrl+S). This is thus not true. During runtime, you need to compile it yourself by JavaCompiler and then load by URLClassLoader. A concrete example is given in this related question&answer: How do I programmatically compile and instantiate a Java class?
You'll in the concrete example also notice that you can't do just a new calculate(); thereafter. The classpath won't be auto-refreshed during runtime or so. You'd need to do a Class#forName(), passing the FQN and the URLClassLoader. E.g.
Calculate calculate = (Calculate) Class.forName("com.example.Calculate", true, classLoader);
Your other mistake is that you're relying on the disk file system's current working directory always being the Eclipse project's source root folder. This is not robust. This folder is not present at all when building and distributing the application. You should instead write the file to a fixed/absolute folder elsewhere outside the IDE project's structure. This is also covered in the aforelinked answer.
No, you cannot. You have to manually update resources in Eclipse. Although you can write a plugin for Eclipse which runs your file and update resources.
Eclipse uses directories and files to store its resources but is not direct representation of file system.
Your code could not work, because
calculate is required at compile time of main. You supply it at runtime.
calculate.java will not compiled, so even other techniques to dynamically load classes will not work
If you want to build classes at runtime, consider to use the reflexion API
EDITED with solution (below...)
I have a Splash screen that is packaged into it's own jar. It works.
I can call the Splash.jar from inside another java app by:
Desktop.getDesktop().open(new File("/Applications/Eclipse/Splash.jar"));
and it works just fine. But, that's pretty limited. So, I created a res folder in the new app and dragged the Splash.jar into it.
Now, how do I call it/run it from the main class of the new app??
I looked at all the related posts and see no clear approach...
Thanks
SOLUTION:
I found the solution - so simple. First, the credit to avjava.com for their clear and excellent tutorial on doing this ( Run Another Jar from a Jar ). So, now I can run the Splash (or other .jar) just as hoped for.
The answer is here - posted in the form of complete code:
package test;
import java.io.IOException;
public class RuntimeExecTest1 {
public static void main(String[] args) {
try {
System.out.println("TextEdit I hope");
Runtime runTime = Runtime.getRuntime();
Process process = runTime.exec(
"java -jar /your directory/your app.jar");
try {
Thread.sleep(5000); // keep in open 5000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Closing TextEdit, I hope");
process.destroy(); // kill the process of running the .jar
} catch (IOException e) {
e.printStackTrace();
}
}
}
We don't know how your existing Splash Screen works...
Java AWT support for Splash Screen:
If you are using the Java built-in support for splash screens (as specified in SplashScreen Javadoc) then you need to use a command line switch, or better yet, modify your MANIFEST file in order to reference your Splash Screen:
Manifest-Version: 1.0
Main-Class: Test
SplashScreen-Image: filename.gif
I don't know if, for this particular case, you can reference files in a different JAR. In the worst case, you can unpack the existing JAR (they are just ZIP files) and get the image file in order to include it in your own main jar.
Possibly custom Splash:
If your Splash is created using custom code, then you need the documentation about how to load it. At least, you'd need to add Splash.jar to the classpath of your application and, from your app, call the necessary method or load the appropriate resource.
All the resources and classes contained in .jar files that are added to the classpath are available from your app.
You could create a new URLClassLoader with the Splash.jar and then use reflections to execute the main method.
URL[] urls = new URL[] { new URL("res/Splash.jar") };
ClassLoader cl = new URLClassLoader(urls);
Class<?> clazz = cl.loadClass("splash.Main");
Method method = clazz.getMethod("main", String[].class);
method.invoke(null, new String[0]);
add the resource path to your CLASSPATH envoirment variable and you can use it without modifying your existing code
if your running linux
export CLASSPATH=yourpath;
and if your running windows:
from My Computer right click > properties
OR
if you dont want to add it to CLASSPATH ENV variable,
then
java -classpath="your path to jar" yourclass
Why not define Splash.jar as an external jar and go about using all its routines. Much like JDBC.