I am new to Java programming. Using eclipse for coding. I want to execute JarFile.jar. Following code works fine when placing JarFile.jar inside the same directory where the project is created.
public class CmdTest2
{
public static void main(String[] args)
{
final String dosCommand = "java -jar \"D:\\Java_codes\\CmdTest2\JarFile.jar\"
try
{
final Process process = Runtime.getRuntime().exec(dosCommand);
final InputStream in = process.getInputStream();
int ch;
while((ch = in.read()) != -1)
{
System.out.print((char)ch);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
But I want to execute the jar file from any other directory (say E:\Test\JarFile.jar). How can I do that? (i.e. changing directory through as well as triggering jar file).
In continuation to above pl. let me know how to run MS-DOS commands through Java.
Related
I have a spring boot project and out of which i have created a jar, and i am calling this jar from another project by passing arguments.
Not able to get the output and it is getting stuck.
The below is the project from which i am getting a jar.
public class Demo1Application {
public static void main(String[] args) {
System.out.println("jar called");
for(String arg : args) {
System.out.println("next argument is"+ arg );
}
SpringApplication.run(Demo1Application.class, args);
}
}
Its a simple spring boot main class.
The below is the class of another project from which i want to invoke this jar by passing arguments.
public class AAAAAAAAAAAAAAAAA {
public static void main(String[] args) throws IOException, InterruptedException {
File jarFile = new File("D:\\NewConfigWorkSpace\\Demo1\\target\\Demo1-0.0.1-SNAPSHOT.jar");
Process p = Runtime.getRuntime().exec("java -jar D:\\NewConfigWorkSpace\\Demo1\\target\\Demo1-0.0.1-SNAPSHOT.jar bisnu mohan");
p.waitFor();
System.out.println("finished");
}
}
How to see the console when i am calling the jar, how to track how much execution has been happened.
What you need is the input stream of created process. This is what is normally returned to a console when you run your application.
Process p = Runtime.getRuntime().exec("java -jar D:\\NewConfigWorkSpace\\Demo1\\target\\Demo1-0.0.1-SNAPSHOT.jar bisnu mohan");
InputStream inputStream = p.getInputStream();
You can then read contents of it and print to a console of a running process like this:
StringBuilder outputLines = new StringBuilder();
String output;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
logger.info("Command execution output: " + line);
outputLines.append(line).append("\n");
}
} finally {
output = outputLines.toString().trim();
}
It would also be a good idea to handle error stream the same way, because you can then see if your subprocess returns some errors.
InputStream errorStream = p.getErrorStream();
Use this streams handling in a separate threads so they don't block each other.
From my point of view, you don't need to execute JAR via command line.
If you include JAR into your project you can just import SpringApplication from JAR and run it directly like this:
public class AAAAAAAAAAAAAAAAA {
public static void main(String[] args) throws IOException, InterruptedException {
SpringApplication.run(Demo1Application.class, args);
}
}
I'm on Windows, and i try to work on a Java application that was written to be use on a Linux OS, because the program will launch some shell script at some point.
I have WSL (Windows Subsystem for Linux, also know as Ubuntu bash), so executing shell script should not be a problem, but i have an error : 0x80070057
The code that launch the external process :
public Process startProcess(List<String> commands ) throws IOException {
ProcessBuilder etProcessBuilder= new ProcessBuilder(commands);
Process etProcess = etProcessBuilder.start();
ProcessOutputReader stdReader= new ProcessOutputReader(etProcess.getInputStream(), LOGGER::info);
ProcessOutputReader errReader= new ProcessOutputReader(etProcess.getErrorStream(), LOGGER::error);
new Thread(stdReader).start();
new Thread(errReader).start();
return etProcess;
}
The commands param are set with with something like this :
"/mnt/d/some/path/scripts/initEAF.sh"
"-argForTheScript"
"some value"
"-anotherArg"
"other value"
I also tried to add "bash.exe" as first command, but it doesn't seems to work.
The ProcessOutputReaderis a class to log the stream from the process
class ProcessOutputReader implements Runnable {
private final InputStream inputStream;
private Consumer<String> loggingFunction;
ProcessOutputReader(InputStream inputStream, Consumer<String> loggingFunction) {
this.inputStream = inputStream;
this.loggingFunction = loggingFunction;
}
private BufferedReader getBufferedReader(InputStream is) {
return new BufferedReader(new InputStreamReader(is));
}
#Override
public void run() {
BufferedReader br = getBufferedReader(inputStream);
String ligne;
try {
while ((ligne = br.readLine()) != null) {
loggingFunction.accept(ligne);
}
} catch (IOException e) {
LOGGER.error("Error occur while reading the output of process ", e);
}
}
}
Any idea is welcome.
*.sh is not an executable file.
You need run it by a shell, such as bash xxx.sh -args or sh xxx.sh -args if your java app run inside wsl.
If your java app run on Windows, it should be bash.exe -c xxx.sh
I have a java project, which complied into an executable jar file v-agent-exe.jar. This jar is a log server, log rows is sent to it for processing.
I can execute it by using this command:
`java -jar v-agent-exe.jar -a watch -f config.ini`.
After executed, this jar file will create a ServerSocket at port 1235 and listen for incoming data from clients. After data received, the program will process the data and send the result back to the client. When I execute the jar from CMD windows, the processing is working perfect.
Now I am trying to wrap the Jar file as a Windows service (I am using Windows 10). I created a "Windows service project"
in Visual studio like below:
- Caller class have call() method to execute the jar file using process.
- AgentService is the service, which execute Caller->call() in another thread.
- Program is the main entry to load AgentService.
Caller.cs
public class Caller
{
static Process proc;
public Process GetProcess(){
return proc;
}
public void call() {
try
{
String dir = AppDomain.CurrentDomain.BaseDirectory;
proc = new Process
{
StartInfo = new ProcessStartInfo
{
WorkingDirectory = dir,
FileName = "java.exe",
Arguments = #"-jar v-agent-exe.jar -a watch -f config.ini",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
CreateNoWindow = true
}
};
proc.Start();
while (!proc.StandardError.EndOfStream)
{
string line = proc.StandardError.ReadLine();
}
}
catch (Exception ex) {
VAgentService.writeLog("Error when call process: " + ex.Message);
}
}
}
AgentService
public partial class AgentService : ServiceBase
{
private string jarPath;
private string iniPath;
static Process proc;
Caller caller;
public AgentService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
writeLog("On start");
try
{
caller = new Caller();
writeLog("Prepare to launch thread");
Thread t = new Thread(new ThreadStart(caller.call));
t.Start();
}
catch (Exception ex)
{
EventLog.WriteEntry("Demo error: " + ex.Message);
}
}
protected override void OnStop()
{
proc = caller.GetProcess();
if (proc != null && !proc.HasExited)
{
proc.Kill();
}
else
{
...
}
}
}
Program.cs
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(String[] args)
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new AgentService()
};
ServiceBase.Run(ServicesToRun);
}
}
After build the the service project, I have AgentService.exe.
I install it to my system using:
sc create VAgentLogging binpath= %CD%\AgentService.exe depend= lmhosts start= auto
After start the service in service.msc, I can telnet to port "1235" which the java process is listening (I am sure about
only the jar running in this port). According to the
log of java program, it still can received some part of data but seem like it cannot send back to client or something,
which cause the followed process cannot be done.
I think my problem is: the jar file can executed as standalone but somehow it sucks when wrapped under my service project.
I haven't posted the jar's code yet because I think the error is related to the Windows service project. If you need the java code, please tell me and I will update it here.
Any help would be appreciated.
My bat file is:
#echo off
java -cp * MyTimerTasker
I try to run main function in MyTimerTaskerClass.
All jars and bat file are in same folder.
When I try to run bat file with double click, it runs.
When I try to run with right click and run as administrator, command window shows and disappears but my main function does not start.
When I try to run with task scheduler, it never starts.
Edit: My main class.
public class MyTimerTasker {
public static void main(String[] args) throws IOException {
FTPDownloadFiles ftpDownloadFiles = new FTPDownloadFiles();
System.out.println("Running ...");
DatabaseTask databaseTask = new DatabaseTask();
databaseTask.connectToDatabase();
ftpDownloadFiles.downloadFiles();
try {
databaseTask.parseFiles(JdbcConnection.filesPath);
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
finally {
try {
databaseTask.closeConnection();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
You are adding the classpath of all the files in the working directory. You should add the name of the jar to the classpath.
If you start as administrator, it starts in another directory (same if you start as a scheduled task).
You will have to set your working directory in the batchfile:
cd /d "%~dp0"
This will change the working directory to the folder, where your batchfile resides.
Is it possible to launch a Java program from another Java program, just as if I were launching it using another Java command? When calling the main() method of a program from another program directly, the Java context is common to these both executions. I'm trying to have one Java context per thread.
Illustration:
src/com/project/ProjectLauncher.java
public class ProjectLauncher {
static {
PropertyConfigurator.configure("log4j.properties");
}
public static void main(String[] args) {
Logger.getLogger(ProjectLauncher.class).info("started!");
// Logs well as expected.
}
}
test/com/project/TestProject.java
public class TestProject extends TestCase {
public void testProject() {
ProjectLauncher.main(null);
Logger.getLogger(TestProject.class).info("tested!");
// The above line logs well, while log4j has been initialized in ProjectLauncher.
// I would like it to need its own initialization in this class.
}
}
I tried to launch the main method in another thread/runnable, but the logger is still initialized by ProjectLauncher.
Well when you start a Java process, its a new Instance of JVM. If you wish to start another JVM instance, then you need to start a separate process of it.
i.e.
List<String> command = new ArrayList<String>();
command.add("java");
command.add("ProjectLauncher");
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
final Process process = builder.start();
try {
process.waitFor();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
//if you wish to read the output of it then below code else you can omit it.
InputStream is = process.getErrorStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
Logger.getLogger(MyClass.class.getName()).severe(line);
}
Above we are ultimately starting a new process which in reality is java ProjectLauncher. In case if the class is not already compiled, then you will have to compile it similar to above but using javac instead of java and ProjectLauncher.java instead of ProjectLauncher etc.