Run runnable with properties (Jitsi) - java

I wanted to create runnable jar of Jitsi, one of the most popular SIP communicator. So, I have packaged Jitsi as a runnable jar. It can be used when this runnable jar is passed appropriate VM arguments, like:
-Dfelix.config.properties=file:lib/felix.client.run.properties
-Djava.util.logging.config.file=lib/logging.properties
-Dnet.java.sip.communicator.SC_HOME_DIR_NAME=Jitsi-dev
My Main class which invoke this runnable jar with those parameters looks like :
public class Main {
public static void main(String[] args) {
try {
Process p = Runtime.getRuntime().exec("java",
"-Dfelix.config.properties=file:lib/felix.client.run.properties",
"-Djava.util.logging.config.file=lib/logging.properties",
"-Dnet.java.sip.communicator.SC_HOME_DIR_NAME=Jitsi-dev,
"-jar", "jitsi.jar");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Of course in my jar you can also find those two properties files (felix.client.run.properties and logging.properties) in lib folder and also previously packed Jitsi in jitsi.jar. Unfortunately, I received an error that the config.properties via command line is not loaded. But when I make a shell script whuch runs jitsi.jar with the same parameters, I am able to run Jitsi. What is wrong with this above code ?

Related

ClassNotFoundError while running java program

I am running a program using a .sh file. The .java file has the main() method and inside it I have an object instantiated from a class of other .java files. It compiled successfully, but when it comes down to executing the file, it shows `
ClassNotFoundException
in themain()method for the first object creation, even though there was a .class file created forFetchData`.
package scheduledExecutor;
public class Executor
{
public static void main()
{
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
FetchData task= new FetchData(); -- show error here for ClassNotFound
executor.scheduleAtFixedRate(task, 1, 310, TimeUnit.SECONDS);
}
}
Can anyone please help?
Try putting FetchData class location in file path and see if it works
You get a ClassNotFoundException at execution time but not during compilation when the path for the compiler includes the class but the ClassPath for the JVM does not include the target class.
Make sure the folder or jar that contains the FetchData class file is in the ClassPath of the JVM when you run the program. Look at the difference between the compiler's Classpath and the one used by the JVM.

ClassLoader always returns null when called from within a jar

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;
}

Update java desktop app

I am trying to develop a module that can update my running Java Desktop App.
The problem is that I have to replace the actual running jar with another jar, all the while displaying an image and a progress bar with the remaining time of the update process.
One solution I thought about is that I can put a jar in my main jar, and when launching the update process, to extract that second jar which will display the image and the progess bar, and also which will replace the old main jar with a new main jar.
My question is if this is possible and how can I do it.
I do not have a lot of experience with java and java packaging so if you have any examples or links, it would be of great help for me.
Thank you very much.
R.
Run this code when press UPDATE button ..
if(Desktop.isDesktopSupported()){
try {
Desktop.getDesktop().open(new File("update.jar"));
System.exit(0);
} catch (IOException ex) {
}
}
This will open update.jar and close main.jar. Now run this code from main class of update.jar
//wait sometime for terminate main.jar
try{
Thread.sleep(5000);
} catch(Exception e){
e.printStackTrace();
}
if(isUpdateVersionAvailable()) { //first check update from database
if(copyMainJarFileFromServer()){ //copy newMain.jar from server and paste
new File("main.jar").delete(); //delete main.jar
rename(new File("newMain.jar")); //rename newMain.jar to main.jar
}
}
boolean isUpdateVersionAvailable() {
//todo
}
boolean copyMainJarFileFromServer() {
//todo
}
void rename(File file){
file.renameTo(new File("main.jar"));
}
You can have a starter jar that checks for updates and launches the app from the main jar.
It will show start logo, an image, that standard java can display at start-up.
The start0er could also be used to restart the app in another interface language.
package starter;
...
public class StarterApp {
public static void main(String[] args) {
String workDir = System.getProperty("user.dir");
Path mainJar = Paths.get(workDir + "...");
Path nextMainJar = Paths.get(workDir + "...");
if (Files.exists(nextMainJar)) {
Files.copy(nextMainJar, mainJar, StandardCopyAction.REPLACE_EXISTING);
}
URLClassLoader classLoader = new URLClassLoader(new URL[] {mainJar.toURL()});
Class<?> appClass = classLoader.find("mainjar.MainApp");
... instantiate the app
}
As you see the main jar must not be loaded from too early, maybe not be on the class path entirely, and hence the use of a separate ClassLoader. The same might probably be done with the main jar on the class path of the starter app, and using Class.forName("mainjar.MainApp"). The Class-Path can be specified in META-INF/MANIFEST.MF.
The secundary jars may reside in a lib/ directory.
For those readers wanting more modular, service oriented, updateable apps, one could make an OSGi application, a container for bundles (=jars), that provide exchangable services and life-time control.

External program execution

I am indebted always.
How can I do to start the external program of java, but it does not work.
In the following program, although I will work if started from the command line,but,It does not work when i run in eclipse on.
I am out error that appears is, and can not load the main class is missing or(エラー:メインクラスがみつからないかロードできません).
How will be able to run an external program in eclipse on what if?
Please kindly advise Thank you.
package test.jersey.resources;
public class Execute02 {
public static void main(String[] args) {
String filename = "C:\\Users\\omiz12032\\workspace3\\TestJavaServlet\\src\\test\\jersey\\resources\\start.bat";
try {
Process proc = Runtime.getRuntime().exec(filename);
System.out.println("実行中");
proc.waitFor();
System.out.println("実行終了");
} catch( Exception e ) {
System.out.println(e);
}
}
}
You're calling Runtime.exec(String) which delegates to Runtime.exec(String[], String[], File) in two steps, result in nulls for second and third parameters.
Those are envp and dir. Inheriting envp (aka Environment Variables) from your Java process shouldn't be a problem. The bigger problem is dir which is the working directory. If the .bat file you're calling is not well-written (not ready for being executed outside its directory) it'll fail to resolve its dependencies when using your program's working directory. Try the following:
File workingDir = new File("C:\\Users\\omiz12032\\workspace3\\TestJavaServlet\\src\\test\\jersey\\resources");
// the no-array call of exec tokenizes your command which may lead to unexpected results if it contains spaces
// also you can put arguments here as well as separate array elements
String[] command = { "start.bat" }; // for example { "start.bat", "--fooBar" }
Process proc = Runtime.getRuntime().exec(command, null, workingDir);

How to launch a resource jar from inside another java app - with Solution

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.

Categories