1

I want to start a webservice via an executible jar I create (so that I can eventually use procrun to have it start up as a Windows Service). The webservice is currently started via the command line by calling the main method on the class.

Here is my code so far:

public class test 
{    
    private static boolean stop = false;
    private static Process process;

    public static void start(String[] args) 
    {
        String classpath = "my\\classpath\\test.jar";

        ProcessBuilder processBuilder = new ProcessBuilder("C:\\java\\jdk1.6.0_43\\bin\\java", 
                                                           "-cp", classpath, 
                                                           "com.test.theJavaWebServiceWithAMainMethod");
        try
        {
            process = processBuilder.start();
        }
        catch (IOException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }

    public static void stop(String[] args)
    {
        stop = true;

        process.destroy();
    }

    public static void main(String[] args)
    {
        if (args != null && args.length > 0)
        {
            String command = args[0];

            if ("start".equals(command))
            {
                start(args);
            }
            else if ("stop".equals(command))
            {
                stop(args);
            }
        }
        else
        {
            throw new IllegalArgumentException("command missing");
        }
    }

}

Starting works fine. I see the process start in the task manager and I can now pull up the WSDL. However when I go to kill the process via process.destroy() (by calling the main method with the arguemnt stop), I get a null pointer exception I assume because this is a new instance of the jvm so it doesn't know the process from when I called start. Whats the best way to persist this process object or pid or something so when I go to call stop, I can find and kill the webservice (java process) that is running?

yellavon
  • 2,511
  • 9
  • 42
  • 62

2 Answers2

0

Rather than start your runnable jar as you do, you could convert your program to start as a Windows Service. Then it would be able to react to a Windows-based shutdown request.

Dale
  • 4,421
  • 2
  • 37
  • 68
0

You are executing your 'test' program twice, which results in two completely separate program instances, and they have no reference to each other. So when you call the 'test' program with stop command, theprocess variable is null because one was not created in the current program.

Options:

  • Rewrite your main method to block, waiting for the "stop" command. This would mean the start/stop were not separate asynchronous program executions though. You would start the program, and it would then wait for you to enter a stop command before exiting.

  • You could devise a way to signal the other application 'remotely' ...even though it's all running on the same machine. This is easy to do via a simple network socket, and is a very common approach. (Checkout Tomcat's start/stop command handling for an example....though it's more complex than you need.) To summarize... once running, the main program listens on a server socket. The subsequent "stop program" connects to that server socket as client to notify the main program it should stop.

  • You could use underlying OS tools to find and stop the program. See this answer: How to find and kill running Win-Processes from within Java? . It's hard to do cross platform and generically though.

It's not really clear what it is you want to do though and why you are executing your web service as a separate program via ProcessBuilder. Depending on your requirements, perhaps you could instead do something like this:

public void start(String[] args) 
{
    try
    {
        com.test.theJavaWebServiceWithAMainMethod.main(args);
    }
    catch (IOException e1)
    {
        e1.printStackTrace();
    }
}

That would start your service, of course, and then you could control-c to end the program.

Community
  • 1
  • 1
kaliatech
  • 15,605
  • 4
  • 62
  • 76
  • Thanks for the tips. I was trying out the first point. I added a while loop (while !stop) to the main method, so my application will never terminate, which is fine. I saw the java process for the webservice start up (in addition to my java process for this wrapper application) but the WSDL would not display until I killed my wrapper application. Do you know why this would happen? – yellavon Aug 14 '13 at 18:44
  • Did you sleep in the while loop? If not, then perhaps the while loop was eating 100% CPU and the WSDL service was simply taking too long to start or respond. Instead of a while loop, try reading from System.in. That will block until you press key and not consume CPU cycles. Example: http://stackoverflow.com/questions/6032118/make-the-console-wait-for-an-user-input-to-close – kaliatech Aug 14 '13 at 19:02
  • Thanks for your updated answer. I can actually just call the class directly, didn't think about that :P I added a sleep and called the class directly and the webservice is starting again. – yellavon Aug 15 '13 at 20:18
  • I assume the `stop()` method should kick it out of the while !stop loop should stop it, but I'm having a hard time testing it since the procrun windows service hasn't been developed yet. If I open up another command window and call my WebServiceWrapper.jar main method with stop as the argument, it starts up a second java process and calls the `stop()` method on it and then closes, leaving the first java process with the web service in it running. Any ideas? – yellavon Aug 15 '13 at 20:18
  • It really depends on what exactly you are trying to test. If you want to trigger the stop method asynchronously from another process, you will need to figure out some way to communicate to the running process. (See second bullet point in my answer.) – kaliatech Aug 15 '13 at 21:36