Running .jar file within JSP page - java

I'm trying to develop a website that takes user input and converts to a text file. The text file is then used as an input for a .jar file. (e.g. java -jar encoder.jar -i text.txt), the jar then outputs a .bin file for the user to download.
This jar is designed to be run from command line and I really don't know the best way to implement it within a .jsp page. I have created a few java test classes but nothing has worked so far.
Does anyone have any suggestions on possible methods?

An alternative to running it as an external process is to invoke its main class in the current JVM:
Extract/open META-INF/MANIFEST.MF of the jar
Identify the Main-Class:. Say it is called EncoderMainClass
Invoke its main method: EncoderMainClass.main("-i", "text.txt")
This aught to be faster because a new OS process does not need to be created, but there may be security considerations.

Have you tried somrthing like this,
Create a java file
use a ProcessBuilder and start a new JVM.
Here is something to get you started:
ProcessBuilder pb = new ProcessBuilder("/path/to/java", "-jar", "your.jar", "thetextfile.txt");
pb.directory(new File("preferred/working/directory"));
Process p = pb.start();
ps: do handle to destroy process else it will eat up all memory

You can put this jar to the web application on the classpath and use it's class and methods. Better if you have javadoc if you don't have sources. But even if not in classpath you can try the example or this example.

Related

executing bash commands from a specific directory

From my application I have to execute an external jar of which I do not have the source.
Given an input file, it processes it, creates an "output" directory and puts in it an mxml output file. Problem is: it creates said directory in tomcat/bin instead of inside the directory of the original file.
Here's what I've tried so far.
Initially
Process p = new ProcessBuilder("java -jar "+newfile.getParent()+"\\converter.jar "+newfile.getPath()+" -mxml").start();
Then, seeing how from console the "output" directory was created in the directory the command was called from, I tried:
String startSim[] = {"cd "+newfile.getParent()+"\\" , "java -jar converter.jar "+newfile.getName()+" -mxml"};
try {
Runtime.getRuntime().exec(startSim).waitFor();
} catch (Exception e) {
e.printStackTrace();
System.out.println("Log non creato.");
}
But with this I get the "file not found" exception for the first instruction. Does anyone know how to possibly solve this problem? I'd like to avoid having to reach for my output file all the way in my tomcat/bin directory.
Thanks for any suggestion!
Paolo
P.s.: by the way, before trying all this I tried simply calling the method I need from the library, but had the same exact problem. So I resolved to execute the jar, instead. And here we are. :)
You can set working directory using ProcessBuilder.directory() method:
ProcessBuilder pb = new ProcessBuilder();
pb.directory(new File("mydirectory"));
pb.command(......);
etc
This does not work for you when you are using Runtime.exec() because cd command is a functionality of shell. You could solve it using this technique but you have to create platform specific command with prefix like cmd /c on windows or /bin/sh on Linux. This way is definitely not recommended.
But in your specific case you do not neither first nor second solution. Actually you are starting one java process from another. Why? you can easily invoke the main() method of the second process directly.
Take a look on META-INF/MANIFEST.mf file from converter.jar. Field Main-Class contains the fully qualified name of main class. Let's say it is com.converters.Main (just for example). In this case you can invoke
com.converters.Main.main(new String[] {newFile.getPath(), "-mxml"});
directly from your code. Just add the jar to your classpath.
Concerning to changing working directory in this case. Check again whether you really need this or your converters.jar supports parameter that does this.
A lazy approach to this may be going to the root directory and descending from there to your tomcat bin directory .

How do I execute a Jar file in a new process and close the original Jar?

I have 2 jar files. I want Jar A to open Jar B then have jar A terminate, leaving Jar B running. How would I go about doing this?
EDIT: I meant I want JarA open in one instance of the JVM, then I want JarA to exectue JarB in a new instance of the JVM then JarA uses system.exit(0)
To start a new JVM you would start external java process just like any other OS command, look up the documentation on ProcessBuilder
ProcessBuilder pb = new ProcessBuilder("java", "-classpath", "B.jar", "B.BMain");
Process p = pb.start();
There are lot of caveats to starting external process in Java, you will find lot of material here on SO searching for Process and ProcessBuilder
jar files don't run or terminate; that is the jvm, started for example by the command java. For example when you run the following command:
java -classpath A.jar A.Main
A new jvm is started and it executes the main method of the class A.Main
Now that method Main.main(), can call methods of classes in B.jar, if it was in classpath. For example if the command was
java -classpath A.jar;B.jar pkg.A
Then in A.Main.main there can be
B.SomeClass.SomeMethod()
Where B is in B.jar
Is this what you mean when you say "open B.jar"? Note that this does not "close" the other "A.jar", whatever that may mean.
Do you want to launch a new JVM instance for running the other Jar, and then terminate? This is not so common.
Alternatively, you could just include Jar B into the classpath and use the classes it provides from within the code in Jar A.
Assuming, even after reading below answers, that you still want to invoke "JAR-B" in a separate JVM process which is not attached to parent process "JAR-A", your best bet perhaps is to use something similar to "cmd /start" (for windows) or using 'sh ... &' (for *nix) (from your java program in JAR-A)
I had a possible and partial answer:
So if you are using Java on Windows, then you can use
new ProcessBuilder("java", "-classpath", "B.jar", "B.Main").inheritIO().start();
This will not only start the process, but it will begin it in the same Command Prompt Window. For quitting JAR A, include a System.exit(0); in JAR A's main method right after creating process B.
For Linux builds, I'm not really sure, as I'm stuck in the same/similar issue for my program.
Create a new process in Java, exit the current process
EDIT: I did post my answer in the above question of mine. :)

java/shellscript code to find out if a jar file is already running on current machine

How do I find out if a specific JAR file is running on my machine or not? I just want to ensure that a specific JAR is only executed once at any time-- so if another request to execute the same jar comes in then I should not again invoke that jar.
I can use code for the above either as java code (which I will add to that JAR itself) or as shellscript (which I will use to invoke the jar file).
The machine will be a Linux machine-- either CentOS, or Debian or Ubuntu or Amazon Linux.
jps is a simple command-line tool that prints out the currently running JVMs and what they're running. You can invoke this from a shell script.
jps -l will dump out the JVM process id and the main class that it's executing. I suspect that's the most appropriate for your requirement.
Noting your comment re. jps being not supported, if it's a valid worry that you can't easily mitigate via testing when you upgrade a JDK/JRE, then perhaps use something like:
pgrep -lf java
Try to create a new jar,
create a class inside with like this (not yet functional code, just a scribble):
static ServerSocket unicorn;
public void load(){
unicorn=new ServerSocket(39483); // whatever-port
URLClassLoader myloader = new URLClassLoader(new URL[]{this.getClass().getResource("/META-INF/specific.jar")});
... // do all your unique stuff
Runtime.addShutdownHook(new Runnable(){unicorn.close();})
}
Place your specific.jar inside the new.jar. If ever another instance of this jar try to be load, a exception will be thrown: Socket already in use.

Run jar file from java application [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Run Java program into another Program
i try to run jar file from java application which was created in eclipse.
when i run jar file using below source code then fire Unable to access jarfile error
Process process = run.exec("java -jar TestJava.jar");
InputStream inError = process.getErrorStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inError));
System.out.println("Error=" + bufferedReader.readLine());
Sounds like TestJava.jar is in a different directory. If you're running this code within Eclipse, then the present working directory is going to be the same as your Eclipse project's folder (unless you've configured it differently, this is Eclipse's default run location). Either specify a path to TestJava.jar via an absolute path or a path relative to the present working directory.
One other thing you'll need to be mindful of - you need to consume both the error stream and the output stream of the Process you're creating. The default output/error stream buffer sizes of Process instances are not very big and, if full, will cause that Process to block indefinitely for more buffer space. I recommend consuming each stream in a separate Thread.
Set the working directory where this process should run. Set the working directory using the below statement.
Runtime.getRuntime().exec(command, null, new File("path_to_directory"));
First try the java -jar command on cmd window and see if you can run TestJava.jar. Then try running the same command from your code.
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("java -jar TestJava.jar");
System.exit(0);
You need to supply the full path to the Java command.
For example, under windows you'd need something like
C:/Program Files/java/jre/bin/java.exe
ProcessBuilder & Runtime.exec don't take the system path into account when trying to execute your command

How to Run sh file from java in linux as background process

I need to run Sh file from java class.In that java main class is from main class it calls another sh file it takes data from db writes to csv file.It should run continuously.in back ground how to make this run.I made thread as setDaemon.But I am not sure that is it running Back end or not?? When i am running manually that sh file is creating but when i am running backend i did't get any log file or logs.
The "&" works in this case like "|" etc.:
Runtime.getRuntime().exec("./test.sh &");
(I made a test on Debian with and endless loop in a shell script and the java got back the control after starting the script)
Good article http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
Its for the old way but gives good insight.
Article I haven't read of converting to the new way:
From Runtime.exec() to ProcessBuilder

Categories