Java Command Line when daemon is running - java

We all know what the code below does
class Demo{
public static void main(String b[]){
System.out.println("Argument one = "+b[0]);
System.out.println("Argument two = "+b[1]);
}
}
My question (infact curiosity) is, if this application is a daemon that is running and java based server waiting for clients to do socket stuff with it, can I run the application again, and pass new parameters to it ? Basically I am looking at not implementing a cli kinda thing. I need it simple.
Edit : I want to change / add more parameters at runtime. But if I run the app with new parameters, wont it start another instance ?

No, you can't modify the arguments passed after the application started.
The array used to retreive the parameters is populated when it starts and cannot be altered.
If the application is a server, you should be able to implement a CLI rather easily with a simple thread waiting for input.

Seems like you have an existing application that is being run as a command line application right now. It is being invoked as and when required from command line passing the appropriate command line parameters. And now what you would like to do is host this same application as a daemon service which gets invoked as and when the parameters come over a port it is listening to.
Assuming your goal is the above and for whatever reason you want to retain the above main() signature, the key is to realize that the main() method is also like any other static method which can be invoked by a class reference. So the following is possible:
class SocketListener extends Thread {
public void run() {
// Code for listening to socket that calls invokeDemo()
// method below once it detects the appropriate args.
}
private void invokeDemo(String[] args) {
// You can invoke the main method as any other static method.
Demo.main(args);
}
}
This would just treat Demo class as part of a library it is using and not launch any other application. If you do want to launch it as an application (because of some special reason), you would need to use the Process and Runtime classes of java.

Related

Appropriate way to implement a cli Application which also uses the service profile with Micronaut

I've no problem in creating a REST Server or a Picocli CLI Application.
But what if I want to have both in one Application?
The thing is, I want to have an Application which provides some business logic via REST Server (no problem there), but in some other cases I want to trigger the business logic via CLI without starting the HTTP Server (eg. for CI/CD).
I'm not sure if I run into problems if I start the app via
PicocliRunner.run(Application.class, args) and if a specific argument is given run the Server with Micronaut.run(Application.class);, since they create a different context.
Does anyone know a proper way to achieve this?
This is how I solved it:
import io.micronaut.configuration.picocli.PicocliRunner;
import io.micronaut.runtime.Micronaut;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
#Command(
name = "RestAndCliExample",
description = "...",
mixinStandardHelpOptions = true
)
public class Application implements Runnable {
private enum Mode {serve, run}
#Parameters(index = "0", description = "Execution mode: ${COMPLETION-CANDIDATES}")
private Mode mode;
public static void main(String[] args) throws Exception {
args = new String[]{"run"};
PicocliRunner.run(Application.class, args);
}
public void run() {
if (Mode.serve.equals(mode)) {
// Start REST API
Micronaut.run(Application.class);
} else {
// TODO run code directly
}
}
}
One way to accomplish this is to #Inject the ApplicationContext into your #Command-annotated class. This allows your command to use the same application context instead of needing to start a separate one.
Then, in your run method, you can start the REST server by obtaining the EmbeddedServer from the application context and calling start on it, or you can execute the functionality directly without the REST server.
See also this answer for more detail: https://stackoverflow.com/a/56751733/1446916

Can we execute a program without main() method?

Can we execute a program without main method and how in java tell me any example. have you done that kind of example.
Yes, it's possible:
public class MyClass {
static {
Runnable r = new Runnable() {
public void run() {
// whatever you like
}
};
Thread t = new Thread(r)
t.start();
t.join();
}
}
Now you run java passing this class to the command. Java loads the class before attempting to run its main (which doesn't exist), but in loading the class, it fires the static block, which halts until the thread finishes.
If the thread finishes without exiting, java will complain there's no main method, but by that time the thread could have run anything for any duration.
You'll have to catch some exceptions in there, but it will work.
public class TestWithoutMain {
// static block executes first
static{
System.out.println("Program without main");
System.exit(0);
}
}
Note : This works well in JDK1.7 old versions(build 1.7.0-ea-b19)
from jdk 1.7(build1.7.0-ea-b85),It gives run time Exception
Yes, sequence is as follows:
jvm loads class
executes static blocks
looks for main method and invokes it
So, if there's code in a static block, it will be executed. But there's no point in doing that.
How to test that:
public final class Test {
static {
System.out.println("FOO");
}
}
Then if you try to run the class (either form command line with java Test or with an IDE), the result is:
Error will be this.
FOO
java.lang.NoSuchMethodError: main
and ans is that no you can not execute program without main method but the thing is that u can use it either way means partial.
and how ever you can achieve by using static block like this.
static{
System.out.println("Program without main executing into the environment.");
System.exit(0);
}
In Java 9 and beyond you can use JShell to execute Java code without requiring a main method. Not suitable for a stand alone application, but great for quickly testing your code and prototyping changes.
Unless its is web application, I don't think that is possible for any stand alone application which is being self executable, the Runtime should know the entry point, The runtime design such a way that main method is an entry point.

Lotus Notes: Java Runs Fine when on an Agent, but fails when on a java lib

I created a Web Service Consumer.
I want to call a method that is named setCredentials so I can pass my authentication information to the service.
I have two entities that import the web service consumer, an agent and a java library, meant to be called from LotusScript.
The strange thing is that on my agent everything works fine. Library compiles OK, but when it is executed from LotusScript and reaches that line
stub.setCredentials("xxxx","ttttt");
Java throws a java.lang.nosuchmethod error. What can I be doing wrong?
Thank you so much in advance for your help.
Update:
Maybe I didn't explain fully. The action occurs fully inside java. This is sort of a test. On LotusScript I am just calling the constructor with the sequence GetClass/CreateObject. The code is inside the constructor (For test sake). And it looks precisely the same, both on my test agent and on java library. Answering your question, Jason, no , setCredentials is part of a certain lotus.domino.types.PortTypeBase Interface. When I consume the .wsdl to create a web service consumer, I can see from the generated .java files that my interface extends portTypeBase and Remote
It is not possible to call a Java Web Service consumer from LotusScript (LS2J). This is detailed in SPR SODY7UDKE8 / APAR LO42772. This also applies to calling a Java agent which in turn calls a Java consumer.
You will need to create a LotusScript consumer to access the web service in LotusScript. However there are known limitations in LotusScript which can prevent some web services from being consumed.
40 character variable/method limit
Extremely large SOAP messages can cause performance/crash issues.
Reserved keywords mismatch in LS/WSDL/SOAP.
That said I created the following sample Provider.
Class wsClass
Function hello ( helloText As String) As String
hello = "Hello " + helloText
End Function
End Class
In the NSF it was stored I set it to only allow authenticated users.
I then created a LS consumer and Java Consumer libraries from the generated WSDL.
After that I created the following sample code.
LotusScript
Use "LsWebServiceConsumer"
Sub Initialize
Dim stub As New Wsclass
Dim answer As String
Call stub.Setcredentials("testuser", "password")
answer = stub.Hello("world")
MsgBox answer
End Sub
JAVA (added consumer library to agent)
import lotus.domino.*;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
WsClass stub = new WsClassServiceLocator().getDomino();
stub.setCredentials("testuser", "password");
System.out.println(stub.HELLO("world"));
} catch(Exception e) {
e.printStackTrace();
}
}
}
Both of these worked as expected with their own respective consumer.

Using monit with java

I am using the tool monit to start/stop a process. I have a java file as follows:
class test {
public void start()
{
//do something
}
public void stop()
{
//do something
}
}
I want to call the start func when a start command is issued from monit and vice versa. I cannot seem to find a good tutorial explaining what steps I need to take for executing the start and stop method. do I need to write a bash script? and monit will call the bash script which in turn calls the java method?
The entry point into a java program is the main method.
public static void main(String [] args)
{
// args carry the command line arguments.
}
In your case, you should create an instance of test and call start() method on that instance.
public static void main(String [] args)
{
test obj = new test();
obj.start();
}
Java's Runtime class provides an option to add a shutdown hook that gets called when the java program is being terminated. You write a simple thread class that has access to the test instance created in the main method above so that when the shutdown hook thread's run method is called, you delegate it to test instance's stop method.
Hope this helps.

Preferred way of application initialization

Do you guys have your own little framework for project startups ? I mean, every time one needs to do the same things at the beginning:
Context initialization - ideally after arguments are processed. Sometimes without interactive user input, sometimes with input reader. Sometimes we need to load properties, sometimes not. Then we need to get a class out of context and run its method. Programming....programming until writing shell script to place everything on classpath.
It's true that it differs according to the actual needs. But it seems to me, that I'm doing always almost the same, again and again from the scratch. Sometimes I realize that I'm postponing my work just because I don't want to do these annoying startups.
It would be great if there was some kind of universal Main class doing reflection to specified bean, context initialization, argument parsing, interactive user input reading and have the programmer do the important things...All setup might be done via spring configuration. I think I'll have to do it by myself.
I'd appreciate your ideas
EDIT: What I'll do: Some kind of startup class which will get user and developer arguments( path to spring context file, bean to setup with user arguments and bean to instantiate, supply with spring context and run). Lighweight api for argument parsing, maybe something for interactive user input which might be tough
I use an abstract base class from which all of my command line utilities are launched. The initialization process has some basic startup lifecyel methods defined. I don't use command line arguments
public abstract class MyAppBase {
public abstract String[] getSpringConfigResource();
public void loadConsoleApplication() {
try {
preLoad();
initializeSpring();
loadConfiguration();
loadDynamicComponents();
postApplicationLoad();
}
catch (Exception ex) {
handleStartupException("error initialzing application", ex);
}
}
...
}
Concrete subclasses look something like:
public class MyApp extends MyAppBase {
public String[] getSpringConfigResource() {
return new String[] { "someapp/appctx.xml", "util/appctx2.xml" };
}
protected void postApplicationLoad() {
SomeServer server = springCtx.getBean("server");
server.start();
}
public static void main(String args[]) {
initLogging("com/me/myAppLog4j.xml", MyApp.class);
MyApp myApp = new MyApp ();
myApp.loadConsoleApplication();
}
}
For some reason none of my swing based non-interactive apps use command line arguments (args[]), since these tend to be services with installers and properties files.

Categories