Developer

phoen1x

A clever man solves a problem, a wise man avoids it.
— Albert Einstein

Virtual assistant with Spring Rest and Selenium

1st of April 2017

picture

Contents

Preface

The goal of this tutorial is to enable my virtual assistant Skylar “the scholar” to remote control a web browser. Since a few years Skylar is able to say “good morning” when I get out of bed and enter the living room. But also since a few years I find myself manually open a web browser with online music. So I chose Selenium to automate this task because in the past years it came in handy way beyond unit testing.

Concept

I try to follow unit testing approach

public class SeleniumTest {
    private static WebDriver driver;

    @BeforeClass
    public static void setUp(){
        driver = ...
    }
}

quick and dirty with a singleton pattern

@Component
@Scope(BeanDefinition.SCOPE_SINGLETON)
public class SeleniumConnection {
    private WebDriver webDriver;
    ...
}

See finished »source code«

Demo

Watch the example video above in fullscreen mode. On the right side you see two command line shells. The Spring REST demo (top) and the Selenium Server (bottom). There are multiple options to implement web crawling in Selenium but in my »example source code« I use XPath to extract the web links

// String xpath="//h2/a";    Get all 'a tags' that follow after a 'h2 tag'
public List<WebElement> sessionHtmlElements(String xpath) {
    return seleniumConnection.getSession()
                             .findElements(By.xpath(xpath));
}

and then »randomly chose one WebElement«.

public int linkClick(List<WebElement> links) {
    int randomLink = ThreadLocalRandom.current()
                                      .nextInt(0, links.size());
    links.get(randomLink).click();
}

Docker

I prepared a virtual machine so that you don’t have to install any fancy software versions on your computer. Just leave the tutorial with this GitHub link and come back later to read the details and the conclusion.

Start a Selenium Server

The current Java WebDriver is unable to connect to a running web browser session. So we have to start a Selenium Standalone Server which will act as a proxy to open and close Firefox.

# make shure a JDK and Firefox is installed
firefox --version
javac -version

# download the engine to open close web browsers
curl -o selenium-server-standalone.jar \
    http://selenium-release.storage.googleapis.com/3.5/selenium-server-standalone-3.5.3.jar

# download Linux driver to handle Firefox
# for Windows/Mac see https://github.com/mozilla/geckodriver/releases
curl -L -o geckodriver.tgz \
    https://github.com/mozilla/geckodriver/releases/download/v0.18.0/geckodriver-v0.18.0-linux64.tar.gz
tar xf geckodriver.tgz

# -debug  >  to see more information
# -Dwebdriver.gecko.driver="PATH_FILESYSTEM" > how to interact with Firefox
# -jar selenium-server-standalone.jar > start the Selenium engine
java -debug -Dwebdriver.gecko.driver="./geckodriver" -jar selenium-server-standalone.jar

Remote control the web browser

The Spring Rest demo uses the singleton pattern to connect to the same web browser session. With the lazy initialization of the Webdriver we can start/stop Firefox whenever we want and even use a »Spring Cloud Config Server« to change the Selenium Server connection at runtime.

# download project
git clone https://github.com/phoen1x/software-assistent-spring-rest-selenium.git
cd software-assistent-spring-rest-selenium/spring-rest

# start Spring Rest
./mvnw spring-boot:run

# use your favorite way to send HTTP GET requests
firefox http://localhost:8080/api/selenium/webpage/crawl?html=true
curl -i http://localhost:8080/api/selenium/webpage/crawl

# close web browser
curl -i http://localhost:8080/api/selenium/session/close

Conclusion

The KISS approach with the singleton pattern works even better than anticipated but leaves a lot to improve. So please leave a comment in the GitHub issue section if you know of a better approach.

Happy coding and use the gained knowledge responsibly!

Beyond unit testing and this tutorial

In the end I like to mention that sometimes you tend to overlook the power of the Selenium IDE. It will not open the web browser for you but it can prevent you from writing a lot of Java code. Just hit record and the Firefox Plugin will write the Selenium program for you. I learned that lesson working with some secretaries that I introduced to my unit testing tool. Against all odds the ladies grow fond of the program and handled their own “software problems” without the guidence of the IT department within just a few days…

Back ...