Selenium + Java APIs

Supporting Java APIs for Selenium

Created by Kavan Sheth

Best viewed in Chrome, Firefox, Opera or A browser supporting HTML5. Use arrow keys ( up ↑, down ↓, left ←, right ↑) to navigate. Uses Reveal.js by Hakim El Hattab Press ESC to enter the slide overview.


  • You might be wondering if this is about selenium why are we discussing Java APIs, Selenium provides you ability to imitate user actions like clicking, pressing keys, waiting till something happens or interacting with browser windows, But still you will need many other things to complete a framework.
  • And here we will explore Java APIs to see that these "many other things" are easily achievable by use of many freely available Java APIs.
  • and this will also help you to understand what selenium can do and what Java ? so you will not end up asking question in a forum like can selenium read data from excel file?
  • Just one thing, Using existing APIs you are reducing your efforts, but also you are introducing dependency. So take some effort to make sure that you are depending on someone/something reliable :). also don't forget to read License agreement.


connect to Unix/Linux env using SSH


  • Many times you can't automate everything using selenium, you might face situation in which some prerequisites/actions must be performed on a unix/linux environment before moving further or Some unix based validation is must to pass your testcase.
  • To connect to a unix/linux environment you need to use standard protocols like telnet, ssh.
  • There are many free open source java based APIs available for this like JSch, Apache Commons Net, JTA(site went offline :( ) ...
  • I found JSch suitable to my needs and easy to use. So we will discuss about it here. but you can use any of such available APIs


public static String runCommand(String Command, String envHost, String envUser, String envPass )
	String output = null;
	int exitStatus = 0;
		  JSch jsch=new JSch();  
		  //To avoid Strict key checking(Explained on next page)
		  JSch.setConfig("StrictHostKeyChecking", "no"); 
		  //create a session
		  Session session=jsch.getSession(envUser, envHost, 22);
		  //set password
		  //few configurations
		  //connect to your session
		  String command=Command;
		  //Open channel to execute command and get input stream for output
		  Channel channel=session.openChannel("exec");
		  InputStream in=channel.getInputStream();

		  //while channel is open, read output data from input stream 
		  byte[] tmp=new byte[1024];
			  int, 0, 1024);
			  output = new String(tmp, 0, i);
			  if(in.available()>0) continue; 
			  exitStatus= channel.getExitStatus();
			try{Thread.sleep(1000);}catch(Exception ee){}
		catch(Exception e){
	   if (exitStatus == 0)
		   return output.replaceAll("[\\n\\r]", "");
		   return "";

Few Points

  • While connecting to unix environment you may get following kind of warning and you need to ascertain host's validity. JSch.setConfig("StrictHostKeyChecking", "no"); was used to avoid such warnings.
  • Above function can be used like following: output=runCommand("date", envHost, envUserName, envPassword );
  • which will return output without any newline character, you may parse it for required text to ascertain that whether required action is completed successfully or not.



  • During automation framework development, you may come across requirement of providing report or failure notification via Email.
  • If you are unaware of power of Java, it might sound scary or at least time consuming to you. But with existing Java APIs this task is very easily achievable.
  • JavaMail API provides very easy way to add mail utility in your project.
  • You will be able to find very detailed tutorial online, but first have look at resources provided at official JavaMail site


send mail with attachment from your GMail Account

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.activation.*;
import javax.mail.Transport;
import javax.mail.Multipart;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

public class MailClient extends Authenticator{

* @author : Eran Chinthaka
* @date : Apr 13, 2008

// Edit these settings with your username and password
private String gmailUserName = "";
private String gmailPassword = "password";

public void postMail(String recipients[], String subject,
String message, String from) throws MessagingException {
		boolean debug = false;
		//Set the host smtp address
		Properties props = new Properties();
		props.setProperty("mail.transport.protocol", "smtp");
		props.setProperty("", "");
		props.put("mail.smtp.auth", "true");
		props.put("mail.smtp.port", "465");
		props.put("mail.smtp.socketFactory.port", "465");
		props.put("mail.smtp.socketFactory.class", "");
		props.put("mail.smtp.socketFactory.fallback", "false");
		props.setProperty("mail.smtp.quitwait", "false");
		Session session = Session.getDefaultInstance(props, this);
		// create a message
		Message msg = new MimeMessage(session);
		// set the from and to address
		InternetAddress addressFrom = new InternetAddress(from);
		InternetAddress[] addressTo = 
		new InternetAddress[recipients.length];
		for (int i = 0; i < recipients.length; i++) {
		addressTo[i] = new InternetAddress(recipients[i]);
		msg.setRecipients(Message.RecipientType.TO, addressTo);
		// Setting the Subject and Content Type
		//set text here
		MimeBodyPart messagePart = new MimeBodyPart();             
		// Set the email attachment file 
		MimeBodyPart attachmentPart = new MimeBodyPart(); 
		FileDataSource fileDataSource = new FileDataSource("fileName") {                 
		    public String getContentType() {               
		    return "application/octet-stream"; 
		attachmentPart.setDataHandler(new DataHandler(fileDataSource));            
		Multipart multipart = new MimeMultipart(); 

	public PasswordAuthentication getPasswordAuthentication() {
	return new PasswordAuthentication(gmailUserName, gmailPassword);
	public static String getDateTime() 
	        DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
	        Date date = new Date();
	        return dateFormat.format(date);
	public static void main(String[] args)
		MailClient myMail = new MailClient();
		String[] recipients={"",""}; 
	    	myMail.postMail(recipients,"Status "+ getDateTime(), "msg line 1\n msg line 2\n msg line 3\n ", "");
	    catch(Exception e)

Few Points

  • For above code to work, you need to download from here, which contains mail.jar, add mail.jar to your project(if you are using eclipse, create a separate folder for libs and then copy mail.jar under it. right click on jar and add into build path)
  • You don't need to understand every thing of above code, but if you know basic Java, you will be able to understand idea behind it and change according to your needs.
  • Apart from this, includes demo folder, which contains good amount of examples like to monitor your mailbox (you can enhance it to trigger some action based on received mail), or to send multipart mails (another mail as attachment of first one). So it is upto you how to leverage it to fulfil your requirements.


Java Database Connectivity

Connecting to Database

run SQL quey

read Data from resultset

Database Connection

  • For database connection you need to have specific driver for DBMS system you are using like Oracle, SQL server, MySQL, MS Access ...
  • Once you download required driver, you need to load driver class using Class.forname method
  • then DriverManager.getConnection() method with appropriate url and authentication details returns connection which we can use to retrieve data from relation database using structured query language(SQL).

Oracle Database Connection

  • Jar: You need to download ojdbc6.jar or required version from here
  • Once you add jar to your build path, no need to explicitly load driver class or register it. (except you are working with some older version)
  • So you are good to open a DB connection
  • Syntax: Connection conn = DriverManager.getConnection(url, dbUsername, dbPass);
  • URL format: jdbc:oracle:thin:@<host>:<port>:<SID>
      • host- machine on which your database is hosted
      • SID - which uniquely identifies your database instance
      • Port - On which your database service listens (usually 1521)
if (conn == null)
	String url  ="jdbc:oracle:thin:@" + dbHost + ":1521:" + dbSID;
		conn = DriverManager.getConnection(url, dbUsername, dbPass);
	catch(Exception e){

MS Access Database Connection

  • You don't need to download any driver if you are using 32 bit JVM, for 64bit you can download it from here.
  • You need to load driver using Class.forname. e.g. Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
  • Now you are ready to open a DB connection
  • Syntax: Connection conn = DriverManager.getConnection(url, dbUsername, dbPass);
  • URL format: jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\\Database1.accdb
try {
if (connection == null) {
	String database = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\\database1.accdb";
	connection = DriverManager.getConnection(database, "", "");
} catch (Exception ex) {

MySQL Database Installation

  • MySQL is an open source database, now owned by Oracle.
  • One can download MySQL for free from
  • While installing MySQL, you will be asked to configure TCP/IP, by default it will be 3306, MySQL provides Web client for Database Management which connects to server using this port over TCP/IP.
  • MySQL Database can be managed from command line client, but there are GUI based utilities, like MySQL workbench or phpMyAdmin(Installed using xampp), I used phpMyAdmin, which provides PHP based web interface to manage MySQL database.
  • Once installed, just start your tomcat server, and go to http://localhost/phpmyadmin/ it will login to root user of mysql, if you want specific user then need to modify it in of phpMyAdmin($cfg['Servers'][$i]['user'] = 'root'; and $cfg['Servers'][$i]['password'] = 'abc';)
By any chance if you get error "Connection for controluser as defined in your configuration failed." while working with phpMyAdmin then try using any of the solution given here.

MySQL Database Connection

  • You need to download MySQL Connecter/J from here.
  • You need to load driver using Class.forname. e.g. Class.forName("com.mysql.jdbc.Driver");
  • Now you are ready to open a DB connection
  • Syntax: Connection conn = DriverManager.getConnection(url, dbUsername, dbPass);
  • URL format: jdbc:mysql://localhost/test. If you are not using default port 3306 then use jdbc:mysql://localhost:<port>/test. Here, "test" is database name so change accordingly.
Connection connection;
try {
	String database = "jdbc:mysql://localhost/test";
 	connection = DriverManager.getConnection(database, "root", "abc");
catch(Exception e)

Create SQL statement

  • Once you have connection, you need to create SQL statement and execute it.
  • Your SQL can either be a query or an update statement. for query you need to use executeQuery() function which returns a result set, and for update you need to use executeUpdate() which returns an int(updated rows)
stmt = conn.createStatement();
String sql;
sql = "SELECT id, first, last, age FROM Employees";
ResultSet rs = stmt.executeQuery(sql);

Read ResultSet

  • ResultSet is nothing but just data retrieved in table format.
  • ResultSet had different get methods like getInt(), getString(), getObject() etc.. which takes column index or column name as argument and return column value in desired format like int, String or object respectively. Column index starts from 1.
 //Retrieve by column name
 int id  = rs.getInt("id");
 int age = rs.getInt("age");
 String first = rs.getString(3); 
 String last = rs.getString("last");


Reading, Writing, Handling Files


  • File Input/Output is a bit complex in Java because of plenty of Input/Output Streams (deals with bytes) and Reader/Writers(deals with characters). But basic IO is simple and you can easily carry out operations like reading csv files or writing to files.
  • provides good tutorial for file IO, so if you are interested in more detail, please go through it.
  • Reading from file can be divided into two parts
    1. Reading raw data (mainly String) and
    2. Parsing
  • Similarly Writing to file can be divided into two parts
    1. Formatting and
    2. Writing formatted data(mainly String) to a file

Read lines from a file

	FileInputStream fstream = new FileInputStream(  new".").getCanonicalPath() +"\\data.txt");
	DataInputStream in = new DataInputStream(fstream);
	BufferedReader br = new BufferedReader(new InputStreamReader(in));
	String strLine;
	while ((strLine = br.readLine()) != null) 
} catch (FileNotFoundException e) {
} catch (IOException e) {

Here we created BufferedReader from Streams, which can also be created from readers as following:

FileReader fstream = new FileReader(  new".").getCanonicalPath() +"\\data.txt");
BufferedReader br = new BufferedReader(fstream);

Best way to work with streams/reader is to first identify function you are interested in, like here we are interested in readLine(), then look at constructor of that stream/reader and supply required stream or reader.


  • If you are dealing with csv or any other delimited file then split() function of String class is what you should look at.
  • Syntax: public String[] split(String regex)
  • here Regex is regular expression specifying delimiters, which will return array consisting of delimited Strings
  • You can specify multiple delimiters like strLine.split("[,\\r\\n]+"), which will split string using ',' or '\n' or '\r', + specifies one or more occurrence of any of the delimiter.
  • Once you are able to parse your data you can store it in any collection and use later on.

Formatting a String

  • Formatter class provides a very wide range of conversions which is quite helpful in transforming data into required format, following examples from JavaDocs will help to get you idea about it.
  • // Format a string containing a date.
    import java.util.Calendar;
    import java.util.GregorianCalendar;
    import static java.util.Calendar.*;
    Calendar c = new GregorianCalendar(1995, MAY, 23);
    String s = String.format("Duke's Birthday: %1$tb %1$te, %1$tY", c);
    // -> s == "Duke's Birthday: May 23, 1995"
    StringBuilder sb = new StringBuilder();
    // Send all output to the Appendable object sb
    Formatter formatter = new Formatter(sb, Locale.US);
    // Explicit argument indices may be used to re-order output.
    formatter.format("%4$2s %3$2s %2$2s %1$2s", "a", "b", "c", "d")
    // -> " d  c  b  a"
    // Optional locale as the first argument can be used to get
    // locale-specific formatting of numbers.  The precision and width can be
    // given to round and align the value.
    formatter.format(Locale.FRANCE, "e = %+10.4f", Math.E);
    // -> "e =    +2,7183"

Writing to a File

FileWriter writer1 = new FileWriter(new".").getCanonicalPath() +"\\data.txt", false); 
BufferedWriter o1 = new BufferedWriter(writer1);
for (String data: stringArray )
{	o1.write( "my " + data);
catch(Exception e)
PrintWriter outputStream = null;
try {
	outputStream = new PrintWriter(new FileWriter("characteroutput.txt"));

	String l;
	while (String data: stringArray) {

Handling a File

Apache POI


  • HSSF is pure java implementation of the Excel '97 (-2007) file format(.xls).
  • While XSSF is pure Java implementation of Excel 2007 OOXML(.xlsx) file format.
  • "HSSF and XSSF provides ways to read spreadsheets create, modify, read and write XLS spreadsheets."

How to Use?


  • Here we will just see a simple example of HSSF, which I did long back.
  • Consider an Excel file having a sheet with columns like, scriptname, CostPrice, Quantity, Price , Valuation(Price*Quantity), Profit(Valuation-(CostPrice*Quantity)). (it will be easier if you are little bit aware of stock market.)
  • there was need to update Price cell every day for different stocks and Valuation and Profit gets calculated based on that.
  • Following is code for this scenario. Even if you don't get scenario, code is updated with comments so you will get idea about how to use different functions of HSSF API.


public static void writeToExcelHSSF(String filename, PrintWriter logger)
        //Create a workbook, as here we are trying to modify an Existing file need to provide FileInputStream as argument               
        HSSFWorkbook wb = new HSSFWorkbook(new FileInputStream(path + xlsFile));
        //FileOutputStream will be needed while writing changes back to a xls file
        FileOutputStream stream = new FileOutputStream(path + "final1.xls");
        //Get sheet by providing index of the sheet
        HSSFSheet sheet = wb.getSheetAt(0);
        //Creating a evaluator, it will be used to evaluate formula of a cell
        HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb); 
        //Get numder of rows of a sheet 
        int rows = sheet.getPhysicalNumberOfRows();
        System.out.println("Sheet " + wb.getNumberOfSheets() + " \"" + wb.getSheetName(0) + "\" has " + rows	+ " row(s).");
        //Create a row object;
        HSSFRow row;
        //Different cell objects
        HSSFCell scriptCell;
        HSSFCell priceCell;
        HSSFCell valuationCell;
        HSSFCell profitCell;
        String scriptName;
        for(int k=1;k< rows;k++){
        		    //get row based on index(row number)	
        		    row = sheet.getRow(k);
        		    //get particular cell of a row 					
        		    scriptCell = row.getCell(9);
        		    //get string value from the cell
        		    scriptName =scriptCell.getStringCellValue();
        		    priceCell =row.getCell(5);
        		    valuationCell =row.getCell(6);
        		    profitCell =row.getCell(7);
        		    //set value in a cell, (here parseStocks is just a user defined function to fetch value of a stock)
        		    priceCell.setCellValue(parseStocks(path + filename,scriptName));
        		    //Trigger cache clearance, so evaluation of formula on this cell is done with latest value
        		    //Re-evaluate formula of a cell
        //writing back workbook to output stream
    catch( IOException e)


Java Excel API

  • Java Excel API is just another API to manipulate Excel files.
  • You can start using JExcel, By going through Andykhan's tutorial
  • So not going into details of it.

JExcel Vs. POI

Following are few points by rgettman at here

  • Perhaps the most significant difference is that Java JXL does not support the Excel 2007+ ".xlsx" format; it only supports the old BIFF (binary) ".xls" format. Apache POI supports both with a common design.
  • Additionally, the Java portion of the JXL API was last updated in 2009 (3 years, 4 months ago as I write this), although it looks like there is a C# API. Apache POI is actively maintained.
  • JXL doesn't support Conditional Formatting, Apache POI does, although this is not that significant, because you can conditionally format cells with your own code.
  • JXL doesn't support rich text formatting, i.e. different formatting within a text string; Apache POI does support it.
  • JXL only supports certain text rotations: horizontal/vertical, +/- 45 degrees, and stacked; Apache POI supports any integer number of degrees plus stacked.
  • JXL doesn't support drawing shapes; Apache POI does.
  • JXL supports most Page Setup settings such as Landscape/Portrait, Margins, Paper size, and Zoom. Apache POI supports all of that plus Repeating Rows and Columns.
  • JXL doesn't support Split Panes; Apache POI does.
  • JXL doesn't support Chart creation or manipulation; that support isn't there yet in Apache POI, but an API is slowly starting to form.
  • Apache POI has a more extensive set of documentation and examples available than JXL.



  • Logging is most important for a large application
  • For a small application we can easily debug or place required messages, recompile and check again, but consider a large application which is complex to debug and compilation takes time, In such applications if logging is proper we can track down issues from logs only or narrow down area for debugging.
  • If logging is done correctly, in long run it can save a lot of time.
  • But main concern for logging is, if we log all detail, we may run out of space required to store logs and also performance impact on application because of file IO involved
  • And that is why API like log4j is quite useful, because it takes care of both of the above concerns. log4j libs not only minimize the performance hit on application due to logging but also provide a way to manage log granularity at runtime.


  • Log4j2 is new and faster version of log4j.
  • You can configure log4j2 using either JSON file or xml file. here we will see xml file only.
  • log4j2.xml file have two parts,
    • Appenders - logger profile - how you wants a logger to behave
    • Loggers - Where you provide appenderRef which specify which logger to use for logging
  • Appenders can be of different type like, console appender, file appender, RollingFile appender ...


<?xml version="1.0" encoding="UTF-8"?> 
    <RollingFile name="Rolling-default" fileName="logs/bssauto.log"
      <PatternLayout pattern="%d %t %-5p %c{2} - %m%n"/> 
          <TimeBasedTriggeringPolicy />
          <SizeBasedTriggeringPolicy size="10 MB" />
    <Console name="STDOUT" target="SYSTEM_OUT"> 
      <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> 
    <File name="FileLogger" fileName="logs/bssauto.log" append="false"> 
      <PatternLayout pattern="%d %t %-5p %c{2} - %m%n"/> 
    <Root level="trace"> 
      <AppenderRef ref="Rolling-default"/>

Log outputs so you can have idea about patterns used

Log output for RollingFile and File appender

2014-08-04 18:22:44,127 main TRACE tests.PayGoTests - entry params(100018)
2014-08-04 18:22:44,135 main INFO  tests.PayGoTests - Running create BAN with PricePlan flow : PP 100018 
2014-08-04 18:22:44,139 main TRACE tests.PayGoTests - entry params(http://optimus-z2:9260, ChromeDriver: chrome on WIN8 (265acb7076f7ee33e9dcf46742ea6610), rkadm, rkadm)
2014-08-04 18:22:46,184 main INFO  tests.PayGoTests - Not already logged in. need to login.
2014-08-04 18:22:47,834 main TRACE tests.PayGoTests - exit with(com.redknee.bssauto.pages.HomePage@121b9a0)
2014-08-04 18:22:47,836 main TRACE tests.PayGoTests - entry params(com.redknee.bssauto.pages.HomePage@121b9a0, 97035, GSM, 1)

Log output for STDOUT

2014-10-13 01:17:09,901 TRACE [main] tests.PayGoTests ( - entry params(100018)
2014-10-13 01:17:09,917 INFO  [main] tests.PayGoTests ( - Running create BAN with PricePlan flow : PP 100018 
2014-10-13 01:17:09,918 TRACE [main] flow.PayGoFlows ( - entry params(http://hibbert:9260, ChromeDriver: chrome on WIN8 (035fac047d681e18221ea8489aba5310), rkadm, rkadm)
2014-10-13 01:17:22,070 INFO  [main] flow.PayGoFlows ( - Not already logged in. need to login.
2014-10-13 01:17:28,822 TRACE [main] flow.PayGoFlows ( - exit with(com.redknee.bssauto.pages.HomePage@ae525c)
2014-10-13 01:17:28,823 TRACE [main] flow.PayGoFlows ( - entry params(com.redknee.bssauto.pages.HomePage@ae525c, 55692, GSM, 1)

How to use

  • Once you add log4j2.jar into you build path and create a log4j2.xml file, nothing much to do.
  • You can create logger as following:
  • private static Logger logger=  LogManager.getLogger("myLogger");
  • getLogger() takes unique key as argument to distinguish between loggers
  • now you are ready to use logger, you can call logger.debug(),, logger.trace(), logger.error(), logger.fatal()
  • You can get more details about logger methods here
catch(NoSuchElementException e)
	logger.error("Seems Page is not Loaded. stack trace :" + e);
	logger.catching(e);"Catching Exception")
	return logger.exit(null);	

Logging Levels

  • Log4j2 supports different log levels like, ALL, ERROR, TRACE, DEBUG, INFO, FATAL
  • in config xml you can specify log level for which you want to do logging like <Root level="trace">, all level with higher priority will be logged and levels with lower priorities will be ignored
  • Default priority can be found in JavaDocs like,
    • lower number - high priority, higher number - low priority

Logging Layouts

  • Log4j2 supports multiple layouts like JSONLayout, HTMLLayout, PatternLayout, XMLLayout and few Others.
  • We saw PatternLayout in our example, which is "a flexible layout configurable with pattern strings".
  • All information regarding different layouts can be found at
  • We will see just one example for HTMLLayout, rest you can get from given link.

Logging Layouts - HTMLLayout

  • To Change your logging output to HTML format, you just need to change one line in your Log4j2.xml
  • Instead of providing PatternLayout as
  • <PatternLayout pattern="%d %t %-5p %c{2} - %m%n"/>
    you need to provide HTMLLayout as following
    <HTMLLayout charset="UTF-8" title="log"></HTMLLayout>
  • Also change extention of the log file to .html
  • and now your logs will be generated in HTML format as following:

How to change Log Level at RunTime?

  • Recently came across this question in a forum. This stackoverflow answer explains it very clearly.
  • There are two ways, if your application is rich and you want to access logger programmatically from any other available GUI of your system, you can use following snippet
  • LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    Configuration config = ctx.getConfiguration();
    LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME); 
    ctx.updateLoggers();  // This causes all Loggers to refetch information from their LoggerConfig.
  • But if you don't want to put extra efforts, you can enable JMX port for your application
  • and use JConsole.exe to access your log4j2 loggers using "org.apache.logging.log4j2.Loggers" bean
  • More info regarding JMX is available here