Start/Kill appium server within java code


#1

Hi,
I would like start the appium server on the beginning of the execution & kill it after the tests has finished.
Till now i had to start the server from GUI with the Launch button but i want to save that extra manual operation.
I tried the following code however it only opens the Appium client without Launching it.
Process proc = Runtime.getRuntime().exec("/Applications/Appium.app/Contents/MacOS/Appium");
Can someone assist with a simple code sample how it can be achieved?
Any help will be most appreciated!


#2

Hi! I am thinking about it!
I think that it is not correct to communicate with Appium UI app. The correct way is to launch/kill node by itself.

Only NodeJS! Only hardcore!

Actually I was thinking about implementation of the standalone maven artifact for Appium/java-client package which could provide ability to launch Appium nodeJS server programmatically. There is an API which can help to achive this. stackoverflow.com. Slideshare.

But it requires java 8. I think @jonahss doesn’t appriciate migration of the java-client to java 8 for now. So it should be the standalone artifact.

I am interested too…


#3

Refer to this topic for help.


#4

Thanks Hasan!
i will first try to run it from terminal (i am using Mac) & once this will work we will formalize it to code.
So according your previous post i need to run the below in the terminal right?
Few questions:

  • I guess my UI Appium.app is irrelevant for this right?
  • so i download the 1.3.1 from github & i want to use /bin/sh with the relevant command as you post.
    i can see in the Appium.js file however i am not sure what is the equivalent path to the windows node.exe on mac?
    Thanks in advance for your help…

“cmd /c “C:/Program Files (x86)/Appium/node.exe” “C:/Program Files (x86)/Appium/node_modules/appium/bin/Appium.js” --address 127.0.0.1 --chromedriver-port 9516 --bootstrap-port 4725 --selendroid-port 8082 --no-reset --local-timezone”


#5

I tried this in the past and I’ve started from running a shell command from Java app. I was thinking to start appium in a separate thread…
After some research I have this:

public class RuntimeExec {
    public StreamWrapper getStreamWrapper(InputStream is, String type){
        return new StreamWrapper(is, type);
    }
    private class StreamWrapper extends Thread {
        InputStream is = null;
        String type = null;
        String message = null;

        StreamWrapper(InputStream is, String type) {
            this.is = is;
            this.type = type;
        }

        public void run() {
            try {
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                StringBuffer buffer = new StringBuffer();
                String line = null;
                while ( (line = br.readLine()) != null) {
                    buffer.append(line);//.append("\n");
                }
                message = buffer.toString();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }
    // this is where the action is
    public static void startAppium(String comand) {
        Runtime rt = Runtime.getRuntime();
        RuntimeExec rte = new RuntimeExec();
        StreamWrapper error, output;

        try {
            Process proc = rt.exec(comand);
            error = rte.getStreamWrapper(proc.getErrorStream(), "ERROR");
            output = rte.getStreamWrapper(proc.getInputStream(), "OUTPUT");
            int exitVal = 0;

            BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String s;
            while((s = stdInput.readLine()) != null){
                System.out.println(s);
                if(s.contains("Appium REST http")){
                    System.out.println("STARTED!");
                }
            }

            error.start();
            output.start();
            error.join(3000);
            output.join(3000);
            exitVal = proc.waitFor();
            System.out.println("Output: "+output.message+"\nError: "+error.message);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

What remains is to start appium like this:

RuntimeExec appiumObj = new RuntimeExec();
appiumObj.startAppium("appium");

Not sure if it is the correct approach, but it seems to be working :smile:


#6
public class SampleJavaTest {
private static Process process;
private static String APPIUMSERVERSTART = "node /home/adminuser/Java_Projects/Appium/appium";    

public static void startAppiumServer() throws IOException, InterruptedException {
    Runtime runtime = Runtime.getRuntime();
    process = runtime.exec(APPIUMSERVERSTART);
    Thread.sleep(5000);
    if (process != null) {
        System.out.println("Appium server started");
    }
}

public static void stopAppiumServer() throws IOException {
    if (process != null) {
        process.destroy();
    }
    System.out.println("Appium server stop");
}

public static void main(String args[]) throws IOException, InterruptedException {        
    startAppiumServer();
    stopAppiumServer();
}

}


#7
  • You either run it from the terminal or automate the process of that using Java as I mentioned in this post.
  • If you are gonna use the donwnloaded UI Appium, then its location on your system is very relevant as you have to include that location when starting the server. If you are gonna download the Github version of Appium, then the UI Appium is irrelevant in this case and you just need to refer to the location of the Github repository.
  • The answer is there.

#8

Hi Priyank_Shah,
Thanks for the code sample however this is that exact code i used but i am missing the following:

  • What is the path i should give for the runtime.exec()
    Thanks…

#9

Since i am using direct code from my local repo. hence i gave to “node </home/adminuser/Java_Projects/Appium/appium>”. you can use the directory where your appium is stored.
If you had installed appium using brew. then you just need to invoke “appium” command in runtime.exec(APPIUMCOMMAND).

Thanks,
Priyank Shah


#10

Hi Hassan i was able to start the server via terminal as you suggested!!!
i saw posts how to implement it by CommandLine command = new CommandLine(“cmd”);
what is the practice on mac? (i want to start stop the server via code naturally)


#11

On Mac, it should be similar, but you have to change

CommandLine command = new CommandLine(“cmd”);

to be:

CommandLine command = new CommandLine("/bin/sh");


#12

What about the using of environment variables? We can reach agreement about system variable name, unify all drafts above and propose a new pull request.

But firstly…
I have a question. Anybody knows how to get appium node state? Port of the node which is already launched?


#13

I think if you can check using “netstat -anp | grep <appium_port>” using java code.


#14

It needs to think about…

I am thinking about these variants… AndroidDriver and IOSDriver require remote URL. If node has been launched automatically or before test script is started they need to know port. If we could receive actual port number we would use:

new AndroidDriver(Capabilities);
new IOSDriver(Capabilities);

What are you think about it? Above is for the local starting.


#15

I think to remote starting, the same daemon process you need to run (using ssh) that will give you port numbers.


#16

You can use the following command to accomplish that:

echo off & FOR /F “usebackq tokens=2” %a in (TASKLIST ^| findstr /I node.exe) do (FOR /F “usebackq tokens=2” %b in (netstat -nao ^| findstr /R /C:"%a") do echo %b)

Run it from inside your Java application, parse the returned value and get the port number from it :smile:


#17

Thanks for suggestions! I will try it.


#18

@Hassan_Radi
I tried your suggestion for starting appium server through the following java code.
Somehow the server is not starting.When i check using the command sudo lsof -i :4723 there are no process running on the port 4723.
But when i try the same command manually in a terminal without /bin/sh the server starts successfully
Am i missing something here?

I am using Java 8 , Xcode 6.1 , MAC 10.10, Appium 1.3.1

public class Runner {

static String APPIUMCOMMAND = “/bin/sh /Applications/Appium.app/Contents/Resources/node/bin/node /Applications/Appium.app/Contents/Resources/node_modules/appium/bin/appium.js --address 0.0.0.0 --port 4723”;

public static void main(String[] args) throws ExecuteException, IOException {
startAppiumServer();
}

public static void startAppiumServer() throws ExecuteException, IOException {

DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
Executor executor = new DefaultExecutor();
executor.setExitValue(1);
executor.execute(new CommandLine(APPIUMCOMMAND), resultHandler);
}

Thanks in advance for your time.
Regards Srinidhi


#19

See this for help…


#20

Hi folks first of all thanks for helping me overcome this obstacle.
at the end my solution for starting & stopping the Appium server was simple,
i created 2 shell scripts files, one for starting the server & the other for stopping it.

Start server file include the following data:
/Applications/Appium.app/Contents/Resources/node/bin/node /Applications/Appium.app/Contents/Resources/node_modules/appium/bin/appium.js --address 127.0.0.1 --chromedriver-port 9516 --bootstrap-port 4725 --no-reset --local-timezone

Stop server file include the following data:
killall node

The java code for starting & Stopping the server was:
//Start Appium server
Runtime.getRuntime().exec("/startAppium");
//Stop Appium server
Runtime.getRuntime().exec("/stopAppium");

Hope it helps future developers!!!
Cheers…