calling java methods from a terminal - java

Suppose I have a java program, myProgram.jar, which I have running on a server. To start the program I would type this into the terminal:
>java -jar myProgram.jar
and the program would continue to run indefinitely. Now what about if the program had a function such as
void processInput(String text){
//process the text
}
and I wanted to SSH into the server and call this function with a particular string? so I could log into my server at any time and alter the state of my program. Is this possible?

This can be done, but not easily.
There are standard ways to achieve what you probably want: MBeans. Take a look at http://docs.oracle.com/javase/tutorial/jmx/mbeans/standard.html

You'll have a number of options here. The simplest would be if you only needed to provide your custom text as an argument at startup to the Java program - in which case you any arguments at the end of your java command would be passed as a String array into your programs main method.
Otherwise, you'll be looking to to implement some sort of remote procedure call (RPC). You could use something like Java RMI (remote method invocation) - where your main execution of your program starts, and you could use child executions of your program (or another client library all together) that calls methods within your main execution while it is still running. If you wanted to extend this further, you could have it host web services over standard HTTP, and use SOAP or REST calls.
There are many additional options and variations here, depending upon your exact requirements.
+1 for DagR's suggestion - again, depending upon exactly what you're looking to do, JMX may be a good fit for this as well.

You could implement a Java client application that calls methods on the Java application running on the server using RMI. Then when you ssh into the server you can run your client application with the parameters you need and have it call the methods in the other program.

Related

What is java currently doing?

I'm writing scripts with a Java api which compile to class files and are executed out of my perspective on a virtual machine (I don't have access to this virtual machine and can't debug my class files from within.) These scripts require observable data to execute and don't run properly unless they've been executed within this virtual machine. As a consequence of the way that these class files are executed, to my knowledge, I can't debug them with my IDE's built-in debugger.
I don't really have the coding vocabulary to even search for answers to that last statement, so please correct me if I'm wrong.
Anyways, the only way which I've determined will allow me to debug these scripts is the classic print-statement method. It's horrible. But it works. And it seems that the entire community for the api uses this method.
I had the idea that I could use reflection to grab information from my classes as they're executing, but this still doesn't give me access to the line-by-line debugging that I'm looking for.
What I'd like to do is monitor the execution of my script step-by-step (every calculation the VM does) and store information about those calculations (variable "foo" in class "bar" becomes 4 on line "soandso") as a sort of running cache which dumps to the system console whenever an error occurs.
Is this possible?
You can take a look at dynamic proxies.
Here is a very good explanation of it.
With a dynamic proxy you can output (log, send as mail, ...) the method that is beeing called and the parameters that are passed to the method.
It's not exactly what you are looking for but maybe it will help you.

Managing Powershell Sessions Using Java

I want to be able to manage Powershell PSSessions using Java. For example I want to have separate Java methods for starting sessions and ending them. Is there an easy way to have these methods? I'm thinking there could be a Powershell API, or stuff like that.
Quick answer: No.
Longer answer: You could create one yourself, but you should try and avoid this.
PowerShell is a set of .NET types (the various System.Management.Automation namespaces), there is not even a C API. But you could wrap enough of the PowerShell types in something you could call from Java and then use that. However as you cannot run Java in the same process part of that adapter/proxy layer will need to perform inter-process communications this is not going to be an easy task.
If your requirements were to just be able to run a PSH script then you can launch a PowerShell process with the right command line, eg. to run script.ps1
%windir%\System32\WindowsPowershell\v1.0\Powershell.exe -file path-to-script.ps1
By reading from standard input in the script, and controlling standard input of the child process you could pass commands to a coöperating script:
while (($in = [console]::in.ReadLine()) -ne $null) {
Write-Debug "Input: '$in'"
if ($in -match '^\s*exit\s*$') { break; }
}

How to build a command line interface in java for an existing web based application

I have created a web based application using JSP and Servlets and the application uses an SQL Server DB as its backend.
The architecture is like this:
I have all my business logic in a jar file
I have created my views using JSPs and am using servlets to interact with my business logic jar
The jar connects to the database to persist and hydrate information, which is relayed to the JSP by my servlets.
My web application runs on a remote Tomcat server.
Now, I have been given a new requirement. I have to create a command line interface, where I should be able to specify a list of commands and hit enter (or alternatively, create a set of commands and save it in a .bat file or something, and run it), so that my application performs the necessary actions. Basically, I have to create a command line interface, which can be used along with the GUI i already have (JSPs).
I am totally new to this. Can anyone throw light on where and how I can start?
Any little help is greatly appreciated.
EDIT
This is what my web application does. User can see a list of test scripts (written in Selenium WebDriver). He can choose script(s), choose a host on where to run them from, and click "Run", and the test executes on the said machines.
Now, I want a command line interface, which will eliminate the need for the GUI. Let's say, I simply want the user to be able to type a command like "execute My_Script_1", and the script should be executed.
The test scripts, the selenium drivers, everything reside on the App server.
My command line interface should be able to work on Windows command prompt.
Thank you.
Are you using Spring?
Can you specify, what exactly your CLI should do?
You may do, what Thomas said.
You also may use template engines like Velocity.. To form your output.
Use some kind of JavaCurses-like library to make your output... Look well.
Specifying commands...
Hm.. think about your business logic what exactly you are showing to user.
Remember webapp ui is webapp ui. Console ui is different. And user expects different behaviour
So commands like
show goods category="for kids"
Will be great.
Also don't forget about different help commands
yourJarName.jar --help / -h and etc
If your are want to write application with interactive mode... think about help command there.
You say you have your business logic in a JAR.
Why not starting another project with this JAR as a dependency and build it as an executable jar ?
Then simply use System.in and System.out to interact with the user.
EDIT :
So your application is hosted. Do you have an API like REST or SOAP or any other ?
Then you can build a client reading a string that the user has written, parsing it and calling the right service in your API.
I see two options:
Create a client-side CLI that generates the same data your server
receives. In other words, you don't modify your server code, and you create a
client-side CLI module (with jQuery for example) that parses the command lines and sends
exactly the same thing your actual GUI sends.
Set up a text area in your web app (decorated as a CLI) that reacts
on each Enter key pressed, and sends the line(s) to your server. On
your server, you can create a utility class (say CLIParser.java for
instance), and use Args4j to parse the received command,
validate it and run it.
Have you looked at Primefaces terminal? http://www.primefaces.org/showcase/ui/misc/terminal.xhtml
You data structure looks simple enough. Also you mentioned you designed your application the way the business logic is separated from the front end.
In this case you may consider exposing your business logic as a REST based WebService. It should not be that hard since you have layered structure in your application.
Looks like a few methods:
list scripts - returns a list of available scripts list hosts
returns a list of available hosts run script(scriptName, hostAddress)
runs script scriptName on a host with on address hostAddress possibly returns the results if your application supports this
All three look like a good candidates for GET methods.
You may consider Jersey or Resteasy or another framework.
You can find plenty tutorials for both of them. Take a look for example here.
From your command line application you can make calls to your web service in different ways. Just because I used to work with Jersey JAX-RS implementation most of the time, I found use of Jersey client(the latest stable version) the most convenient. Here you can find a short tutorial how you can do it from your command line application with Jersey client. JBoss also has a client API as a part of their framework(also fully certified JAX-RS implementation). You may even decide not to use any client API and do all the work manually utilizing HttpURLConnection, but I would not recommend. There is no big difference in using client API or do all the work manually with HttpURLConnection for the simple service, but you never know when your application becomes not that simple because of new requirements your client could not think of at the beginning.
Hope that helps

How to restart a java program from within java?

I have a java program that is quite large and we want to make it so the user can quit the app and login as another user. To do this we would like to shut down the app and restart it so it presents the login dialog to the user. The problem is that the application is quite large and is poorly written. It has a lot of static variables that hold some sort of state info. Ideally I would like to rewrite the app to handle a situation where these can all be cleared out, but in reality we need to provide this functionality asap.
What I was thinking would be the easiest would be to simply stop the app and start a new vm. However, it seems surprisingly difficult to stop and application and start the same app while shutting down the current one. Does anyone have experience doing this?
EDIT: we are pursuing using Runtime.exec to call the same app again, but exec() wants to block so we have to jump through hoops to get it to work on every platform (Windows, Mac, Linux). I would prefer a platform independent way of doing it.
If you can modify the code, maybe you can exit the program and use the Runtime class (java.lang.Runtime) to start the same program again (with the same arguments?) using the exec() method.
http://download.oracle.com/javase/6/docs/api/java/lang/Runtime.html
Edit: That is to say, you first run the new process, and then exit the program. The other way would of course be much more difficult or impossible(?). :)
If you truly want to stop the JVM and restart it, then you'll have to write some wrapper script (shell script or batch file, depending on your OS) that does it. You could use a special return code from System.exit() to indicate that the application should be restarted.
And that's probably the best way to do it. You could play some classloader tricks, in which your create a custom classloader that to load the application's classes. However, there are a lot of ways for this to go wrong: for example the application code might call System.exit() in some hidden place, or it might contain code that retains internal references in classes loaded by the bootstrap classloader.
Static members are associated with the classloader:classname. You can create your own classloader and instantiate your app via that. Then when you want to restart, throw away the classloader and create a new one. This is how app engines like JBoss are able to reload applications on the fly.
You can use Runtime or ProcessBuilder to relaunch your application but you probably have to modify your application a little bit as I'm pretty sure you don't have a way to retrieve the java executable full path from within the JVM.
I suggest you to implement a launcher (as an executable or a script) and use the java return code to know if you need to exit or if you need to exit or restart.

Executing a class in remote jvm

I have a small test class that I want to run on a particular jvm that's already up and running (basically it's an web application running on Tomcat) . The reason I want to do this is I want to execute a small test class (with the main method and all) within that jvm so that I get the same environment (loaded and initialized classes) for my test class.
Is it possible to indicate that ,say through a jvm parameter, that it should not initialize a new vm to execute my class but instead go and execute on the remote vm and show me the result here, on my console. So the local jvm acts as a kind of thin proxy ?
I am not aware in case there are some tools that should make this possible .Also heard somewhere that java 6 jvm comes with an option like this , is that true ?
Please help me.
Thanks,
After reading this question and the answers, I decided to roll my own little utility: remoteJunit
It is lightweight and dynamically loads classes from the client to the server JVM. It uses HTTP for communication.
You might want to take a look at btrace. It allows you to run code in an already started JVM provided you don't change the state of the variables inside that JVM. With this kind of tracing, you might be able solve your problem in a different way. Not by running extra code in form of a new class but by adding safe code to and existing class running inside a JVM.
For instance, you might System.out.println the name of the file when there is a call to File.exists.
You might find JMX useful. Register an MBean in the server process. Invoke it with visualvm (or jconsole). (tutorial) Never tried it myself, mind.
RMI would also do the magic.
http://java.sun.com/javase/6/docs/technotes/guides/rmi/index.html
Make your web application start an RMI registry and register your service
beans there.
Then in other JVM you can run a program that queries the RMI registry
started by your web application for the services you want to verify
and you are done.
I assume "small test class" is basically some debugging code you want to run to monitor your real application, which is deployed remotely on a Tomcat. If this is the case, you should connect your Eclipse debugger remotely to the Tomcat instance, so you can set a breakpoint at interesting locations and then use the Display view of Eclipse to run any arbitrary code you might need to perform advanced debugging code. As java supports Hot Code Replacement using the debug mechanism, you can also change existing code on the remote side with new code at runtime.

Categories

Resources