Tuesday, March 28, 2017

Quick steps to installing gnome-session and Metacity on RedHat and configuring vnc

The following is a quick guide to installing gnome-session and Metacity on RedHat and to configure VNC to use them.


Install gnome-session

sudo yum install gnome-session

Install Metacity

sudo yum install metacity


Configure VNC


cp /root/.vnc/xstartup /root/.vnc/xstartup.backup
vi $HOME/.vnc/xstartup
If the file contains the line twm & then remove it
Add the following to the bottom of the file:


gnome-session&
metacity&


Save your changes
Restart vncserver

Friday, February 10, 2017

JBoss EAP - Override Deployment Content

JBoss EAP - Override Deployment Content

A deployment overlay can be used to overlay content into an existing deployment without physically modifying the contents of the deployment archive. This can override deployment descriptors, JAR files, classes, JSP pages, and other files at runtime.

When defining a deployment overlay, you specify the file on a file system that will replace the file in the deployment archive. You must also specify which deployments should be affected by the deployment overlay. Any affected deployments must be redeployed in order for the changes to take effect.

JBoss CLI

Start the JBoss application server and run the jboss-cli command tool in the bin folder of your JBoss EAP install directory
  jboss-cli.sh --controller=: -c

Example:
  jboss-cli.sh --controller=localhost:9999 -c

Find name of deployments

[standalone@localhost:9999 /] /deployment=*:read-attribute(name=name)
{
    "outcome" => "success",
    "result" => [{
        "address" => [("deployment" => "my-app.war")],
        "outcome" => "success",
        "result" => "my-app.war"
     }]
}

Deployment overlay help

Display all the help for the deployment-overlay command

deployment-overlay --help

List links

Lists deployments the overlay is linked to:

  • deployment-overlay list-links --name=overlay_name [-l] [--server-groups=server_group_name(,server_group_name)*]

Example:
deployment-overlay list-links --name=my-app-deployment-overlay

Add action

Use the deployment-overlay add management CLI command to add a deployment overlay. Once created, you can add content to an existing overlay, link the overlay to a deployment, or remove the overlay.

Depending on the arguments the action:

  • always creates a new overlay with content;
  • optionally links it to the specified existing deployments;
  • also optionally re-deploys the affected (linked) deployments.

Options

  • name
    • overlay_name
  • content
    • archive_path=fs_path(,archive_path=fs_path)*. Comma-separated list that maps the file on the file system to the file in the archive that it will replace.
  • server-groups/all-server-groups
    • server_group_name(,server-group-name)*. In a managed domain, specify the applicable server groups by using --server-groups or specify all server groups with --all-server-groups.
  • deployments
    • deployment_name(,deployment_name)*. Comma-separated list of deployments to which this overlay will be linked.
  • wildcards
    • wildcard_name(,wildcard_name)*
  • redeploy-affected
    • Redeploys all affected deployments.
  • headers
    • {operation_header (;operation_header)*}


Examples
deployment-overlay add --name=my-app-deployment-overlay --content=WEB-INF/jboss-web.xml=/app/jboss-eap-6.4/standalone/deployment-overlay/jboss-web.xml --deployments=my-app.war --redeploy-affected

Nested deployments
If you have an zipped deployment with multiple zipped JAR's, WARs, etc. containing artifacts you want overlaying, then you need to include the name of the nested archive in the --content option. For example, if the EAR archive contains a war module in the root folder with the name my-app.war, then the following command overlays the WEB-INF/jboss-web.xml inside the sub-deployment my-app.war.
 deployment-overlay add --name=myOverlay --content=/my-app.war/WEB-INF/jboss-web.xml=/app/jboss-eap-6.4/standalone/deployment-overlay/jboss-web.xml --deployments=test.ear --redeploy-affected
Overlay Classes
 deployment-overlay add --name=classOverlay --content=/WEB-INF/classes/com/mydomain/MyClass.class=/app/jboss-eap-6.4/standalone/deployment-overlay/bin/com/mydomain/MyClass.class --deployments=my-app.war --redeploy-affected

Remove action

Depending on the arguments the action may:

  • unlink deployments (if --deployments or --wildcards argument is specified);
  • remove content (if --content argument is specified);
  • remove the overlay altogether with its content and links;
  • re-deploy affected deployments.

Options

  • name
    • overlay_name
  • content
    • archive_path=(,archive_path)*
  • server-groups/all-relevant-server-groups
    • server_group_name(,server_group_name)* 
  • deployments
    • deployment_name(,deployment_name)*
  • wildcards
    • wildcard_name(,wildcard_name)*
  • redeploy-affected
  • headers
    • {operation_header (;operation_header)*}


Examples
Unlink deployments
deployment-overlay remove --name=my-app-deployment-overlay --deployments=my-app.war



Tuesday, June 28, 2016

Play Framework 2.5 and Vue sample CRUD single page application

In my previous post I shared a link to a sample application I had built using the Play framework. That application works and is fine but the one thing I wanted to change was to have a Javascript template framework on the front-end so that I can easily update portions of the webpage with AJAX request and response calls to and from the server. There are many different approaches to accomplish this; you can do it all with Javascript but there are frameworks and libraries available that make this sort of thing a lot easier and cleaner to do. I have used Javascript template engines like Handlebars or DustJs in the past and they have worked quite nicely. There are even more modern frameworks available now that go the extra mile and make things even simpler and more powerful. AngularJS comes to mind. I spent some time learning and seeing how I can use AngularJS for my Play application but in the end I opted to use Vue.js instead. Vue was a lot easier to learn and to get up and running with than AngularJS was and it works amazingly well.

I started by creating a default Play application and reused most of the business-side logic I had used in the previous version of the app. I then created a folder in the root of my project called 'vue' and I put all my Vue related files in there. I am using Play as a RESTful service and Vue as a client-side rendering framework. The only Play Scala template I have is the index.scala.html page which references the bundled javascript file and defines the root element for the Vue application. The only reason I have this index file within Play is to do with the Javascript routing provided by Play. Having said that I think in the long run I will move the index file into the Vue project in order to make use of Vue's hot-reload feature.

If you are interested in this sample application I have built you can clone / downloaded it from here.

Introduction

This application is used to showcase the Play framework as well as Vue.js while learning basic Spanish phrases. This application makes use of the following:

Installing

Running

  • Open a command terminal and change into the sample application root directory
  • Run activator:
    • activator run
  • Run webpack: 
    • webpack --watch
  • Open the following link in a browser:
    • http://localhost:9000

Screenshots







Monday, June 27, 2016

Play Framework 2.5 sample CRUD application

I have had an interest in the Play framework for a number of year now and I have built a few small applications using the framework. The Play framework has evolved over time and in order to keep up to date with the most recent changes it's useful to try and build your own application. I have built a very simple CRUD application for this purpose.

If you are interested in application you can clone / downloaded it from here.

Introduction

This application is used to showcase Play framework while learning basic Spanish phrases. This application makes use of the following:

Installing

Running

  • Open a command terminal and change into the sample application root directory
  • Run activator:
    • activator run

Screenshots






Monday, February 1, 2016

Useful commands to monitor and troubleshoot HornetQ in JBoss EAP 6

The JBoss Enterprise Application Platform (JBoss EAP) is a Java EE application server runtime platform used for building, deploying, and hosting Java applications and services. JBoss EAP 6 is Java EE 6 certified with Red Hat support.

HornetQ is an open source project to build a multi-protocol, embeddable, very high performance, clustered, asynchronous messaging system and is also developed by Red Hat. HornetQ is the Java Message Service (JMS) provider for JBoss EAP 6 and is configured as the Messaging Subsystem.

The following contains a collection of useful commands and steps in monitoring and troubleshooting HornetQ. Note that the commands below were run on a Windows machine with a default standalone setup of JBoss EAP with the messaging subsytem configured and a test queue created.

Before you continue if you are attempting to do this in a production environment then it is very important to backup your messaging data folders or anything else you may need. 

Finding the message count of a queue

  • Open a command prompt and run the jboss-cli script from within the JBOSS_HOME bin directory:
    • %JBOSS_HOME%/bin/jboss-cli.bat -c 
/subsystem=messaging/hornetq-server=default/jms-queue=testQueue/:count-messages
  • If the outcome was a success the result should contain how many messages are in the queue. 

Listing the messages in a queue

  • Still connected to the JBoss command line interface run the following command:
/subsystem=messaging/hornetq-server=default/jms-queue=testQueue/:list-messages

Moving messages

  • You can move all messages from a one queue to another:
/subsystem=messaging/hornetq-server=default/jms-queue=testQueue/:move-messages(other-queue-name=destinationQueue)
  • You can move a message from one queue to another if you know the message id of the message you want to move. You should be able to get this from listing the message as described earlier:
/subsystem=messaging/hornetq-server=default/jms-queue=testQueue/:move-message(other-queue-name=destinationQueue,message-id=ID5e1b49b7-15a2-11e5-a905-89636a1272dc)

List prepared transactions

  • You can list prepared transaction on the HornetQ server by running the following command:
/subsystem=messaging/hornetq-server=default/:list-prepared-transactions

Commit prepared transactions

  • If you need to force commit a prepared transaction you can do so by providing the transaction-as-base-64 value found in the list-prepared-transaction command for the following command:
/subsystem=messaging/hornetq-server=default/:commit-prepared-transaction(transaction-as-base-64=AAAAAAAAAAAAAP__wADIWogIO3NWnRrMAADsLwAAAAIAAAAAAAAAAAAAAAAAAP__wADIWogIO3NWnRrMAADsFzEHAgIA)

Java utility applications

HornetQ has a number of Java utility applications that can be run in order to perform certain tasks, these classes can be found in the %JBOSS_HOME%\modules\system\layers\base\org\hornetq directory. 

ExportJournal

  • Use this class to export the journal data. You can use it as a main class or through its native method exportJournal(String, String, String, int, int, String), example as main method:
java -cp %JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-commons-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-core-client-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-jms-client-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-jms-server-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-journal-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-server-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\jboss\logging\main\jboss-logging-3.1.2.GA-redhat-1.jar \
org.hornetq.core.journal.impl.ExportJournal %JBOSS_HOME%\standalone\data\messagingjournal hornetq-data hq 10485760 %JBOSS_HOME%\tmp\journalExport.dmp

XmlDataExporter

  • Read the journal, page, and large-message data from a stopped instance of HornetQ and save it in an XML format to a file, example:
java -cp %JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-commons-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-core-client-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-jms-client-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-jms-server-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-journal-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-server-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\jboss\logging\main\jboss-logging-3.1.2.GA-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\jboss\netty\main\netty-3.2.6.Final.jar \
org.hornetq.core.persistence.impl.journal.XmlDataExporter %JBOSS_HOME%/standalone/data/messagingbindings %JBOSS_HOME%/standalone/data/messagingjournal %JBOSS_HOME%/standalone/data/messagingpaging $JBOSS_HOME/standalone/data/messaginglargemessages > journal-export.xml

XmlDataImporter

  • Read XML output generate by the org.hornetq.core.persistence.impl.journal.XmlDataExporter class, create a core session, and send the messages to a running instance of HornetQ, example:
java -cp %JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-commons-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-core-client-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-jms-client-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-jms-server-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-journal-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-server-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\jboss\logging\main\jboss-logging-3.1.2.GA-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\jboss\netty\main\netty-3.2.6.Final.jar \
org.hornetq.core.persistence.impl.journal.XmlDataImporter journal-export.xml localhost 5445

PrintData

  • PrintData writes a human-readable interpretation of the contents of a HornetQ Journal, example:
java -cp %JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-commons-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-core-client-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-jms-client-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-jms-server-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-journal-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-server-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\jboss\logging\main\jboss-logging-3.1.2.GA-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\jboss\netty\main\netty-3.2.6.Final.jar \
org.hornetq.core.persistence.impl.journal.PrintData standalone/data/messagingbindings/ standalone/data/messagingjournal/ > printData.log

PrintPages

  • PrintPages writes a human-readable interpretation of the contents of a HornetQ Journal and its pages, example:
java -cp %JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-commons-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-core-client-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-jms-client-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-jms-server-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-journal-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\hornetq\main\hornetq-server-2.3.12.Final-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\jboss\logging\main\jboss-logging-3.1.2.GA-redhat-1.jar;%JBOSS_HOME%\modules\system\layers\base\org\jboss\netty\main\netty-3.2.6.Final.jar \
org.hornetq.core.paging.PrintPages standalone/data/messagingpaging/ standalone/data/messagingjournal/ > printPages.log

Thursday, January 28, 2016

Java client authentication for JBoss EAP over SSL

In order for a Java client to authenticate with JBoss EAP over SSL the following steps will need to be performed:


  • Create keystores for the server and client 
  • Configure a HTTPS connector in JBoss EAP 
  • Include the SSL configuration in your client application

Create keystores for the server and client 

The following steps describe how to create keystores for the server and the client and how to import these keystores into the truststores. In order for this exercise the keys generated are self-signed.

In order to complete the below you will need Java installed and the Java bin directory added to your systems Path variable.

Server keystore


Create the server's keystore 


  • Open a terminal / command prompt
  • Run the following command:
 
 keytool -genkeypair -alias jbossweb -keyalg RSA -keysize 1024 -keystore jbossweb.keystore -validity 3650 -keypass jbosswebpass -storepass jbosswebpass
  • -genkeypair (previously named genkey)
    • Generates a key pair
  • -alias
    • alias name of the entry to process
  • -keyalg                
    • key algorithm name
  • -keysize              
    • key bit size
  • -keystore            
    • keystore name
  • -keypass                  
    • key password
  • -storepass                
    • keystore password

Export the server's public key


  • Run the following command:
 
 keytool -exportcert -alias jbossweb -keystore jbossweb.keystore -file jbossweb.cer -keypass jbosswebpass -storepass jbosswebpass
  • -exportcert (previously named export) 
    • Exports certificate
  • -alias
    • alias name of the entry to process
  • -keystore            
    • keystore name
  • -file                  
    • output file name
  • -keypass                  
    • key password
  • -storepass                
    • keystore password

Client keystore


Create the client's keystore private/public key


  • Run the following command:
 
 keytool -genkeypair -alias client -keyalg RSA -keysize 1024 -keystore client.keystore -keypass clientpass -storepass clientpass -validity 3650
  • -genkeypair (previously named genkey)
    • Generates a key pair
  • -alias
    • alias name of the entry to process
  • -keyalg                
    • key algorithm name
  • -keysize              
    • key bit size
  • -keystore            
    • keystore name
  • -keypass                  
    • key password
  • -storepass                
    • keystore password
  • -validity
    • validity number of days

Export the client's public key


  • Run the following command:
 
 keytool -exportcert -alias client -file client.cer -keystore client.keystore -keypass clientpass -storepass clientpass
  • -exportcert (previously named export) 
    • Exports certificate
  • -alias
    • alias name of the entry to process
  • -file                  
    • output file name
  • -keystore            
    • keystore name
  • -keypass                  
    • key password
  • -storepass                
    • keystore password

Server truststore


  • Add the client's public key to the truststore of the server

 
 keytool -importcert -trustcacerts -alias client -file client.cer -keystore jbossweb.keystore -keypass jbosswebpass -storepass jbosswebpass
  • importcert (previously named import)
    • Imports a certificate or a certificate chain
  • -trustcacerts                   
    • trust certificates from cacerts
  • -alias
    • alias name of the entry to process
  • -file                  
    • input file name
  • -keystore
    • keystore name
  • -keypass
    • key password
  • -storepass
    • keystore password

Client truststore


  • Add the server's public key to the truststore of the client
 
 keytool -importcert -trustcacerts -alias jbossweb -file jbossweb.cer -keystore client.keystore -keypass clientpass -storepass clientpass
  • importcert (previously named import)
    • Imports a certificate or a certificate chain
  • -trustcacerts                   
    • trust certificates from cacerts
  • -alias
    • alias name of the entry to process
  • -file                  
    • input file name
  • -keystore
    • keystore name
  • -keypass
    • key password
  • -storepass
    • keystore password

More information on how to use the keytool command can be found here.

Configure a HTTPS connector in JBoss EAP 6


  • Open the JBoss EAP configuration file for your server, for example if you are using default standalone configuration then open the standalone.xml within the JBOSS_HOME/bin directory. 
  • Add a HTTPS connector to the org.jboss.as.web subsystem. You can add it after the HTTP connector that should already be there, example:
 
 <subsystem xmlns="urn:jboss:domain:web:2.2" default-virtual-server="default-host" native="false">
   <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
   <connector name="HTTPS" protocol="HTTP/1.1" scheme="https" socket-binding="https" secure="true">
     <ssl name="https"
       key-alias="jbossweb"
       password="jbosswebpass"
       certificate-key-file="${jboss.server.config.dir}/server.keystore"
       verify-client="true"
       ca-certificate-file="${jboss.server.config.dir}/server.keystore"/>
   </connector>

   <virtual-server name="default-host" enable-welcome-root="true">
     <alias name="localhost"/>
     <alias name="example.com"/>
   </virtual-server>
 </subsystem>
  • In the above example the keystore (certificate-key-file) is also used as the truststore ( ca-certificate-file).
  • The verify-client attribute is equivalent to Tomcats clientAuth attribute. 
  • When using keytool to create keystores, JBoss will compare the value you enter in the name against the hostname and will complain if it does not match You can set the following JVM argument to have JBoss ignore the hostname:
  • -Dorg.jboss.security.ignoreHttpsHost=true

Include the SSL configuration in your client application

  • Within your standalone client application the following properties will need to be set to point to the client's keystore/truststore. 
  • Adding these system properties will set the keystore/truststore for the whole JVM.
 
 System.setProperty("javax.net.ssl.keyStore", "/path/to/client.keystore");
 System.setProperty("javax.net.ssl.keyStorePassword", "clientpass");
 System.setProperty("javax.net.ssl.trustStore", "/path/to/client.keystore");
 System.setProperty("javax.net.ssl.trustStorePassword", "clientpass");
  • Once those properties are set you should be able to make the necessary HTTPS call (an example would be a webservice request over SSL).



Thursday, March 12, 2015

Selenium JUnit Testing

I recently put together a Selenium JUnit testing project to automate testing for a web project I am working on. Having never done or worked on a Selenium project before I did a little research into finding out how it works and what approach best suits me. The following describes a few things I decided upon.

Selenium is used to automate tests through a web browser. Jenkins was used to run the tests from this project after a successful build of and deploy of the web application.

Useful Resources

Here are a couple of useful links where you can find more information on Selenium:

I decided on the following design principles for the Selenium test project:

Each test should run in its own session

  • Starting a new session means closing the browser and opening it again. The disadvantage to this is that it takes longer to complete a test however the advantage means that any previously run tests don’t pollute the session for the currently running test.
  • The change to the above also means that within Eclipse you can choose to run all tests by running the test suite or you could also selectively choose an individual test to run as each test can be run independently from each other. You could do the same within Buildr or through the command line.

Spring Support

Spring support has been added to the test project classes so that we could take advantage of the following:
  • Dependency injection, example would be connection to the database
  • The ability to run the test cases for different environments based on a spring profile setting
  • Use of Spring support classes, example: jdbctemplate
Important notes to keep in mind:
  • Tests are NOT transactional. Selenium opens a browser and users the applications configured transaction manager.

DbUnit

DbUnit is a JUnit extension targeted at database-driven projects that puts your database into a known state between test runs. DbUnit has the ability to export and import your database data to and from XML datasets.

The tests should not rely on data already in the database since I did not have a dedicated test database and the state of the database is not guaranteed. In certain scenarios we could write tests that use data from the database where we know the data is not going to change. DbUnit is used to populate the database with test data before we run the test and then it removes the data from the database at the end of the test run.

Please refer to the following link in finding out the recommended best practices for DbUnit:
The test project is also using the Spring Test DbUnit project to integrated with the Spring testing framework. It allows you to setup and teardown database tables using simple annotations as well as checking expected table contents once a test completes.

Page Object Model Design Pattern

The Page Object Model is a design pattern to create Object Repository for web UI elements. The following principles apply:
  • Under this model, for each web page in the application there should be corresponding page class
  • This Page class will find the WebElements of that web page and also contains Page methods which perform operations on those WebElements
  • Name of these methods should be given as per the task they are performing i.e., if a loader is waiting for payment gateway to be appear, POM method name can be waitForPaymentScreenDisplay()
Here are some of the advantages of applying the Page Object Model Design Pattern:
  • Page Object Patten says operations and flows in the UI should be separated from verification. This concept makes our code clean and easy to understand
  • Second benefit is the object repository is independent of testcases, so we can use the same object repository for a different purpose with different tools. For example, we can integrate POM with TestNG/JUnit for functional testing and at the same time with JBehave/Cucumber for acceptance testing
  • The number of lines of code are reduced and optimized because of the reusable page methods in the POM classes
  • Methods get more realistic names which can easily be mapped to the operation happening in the UI, i.e. if after clicking on the button we land on the home page, the method name could be 'gotoHomePage()'
Some useful links:

PageFactory and Selenium Support Annotations

The PageFactory class provides a convenient way of initialising the Page Object fields:
  page = PageFactory.initElements(new FirefoxDriver(), TestPage.class);
It can be used to map Page Object properties to fields with matching ids or names. To make it even easier we can do this with the @FindBy annotation:
 @FindBy(id="myFieldId")
 private WebElement myField;
One problem is that every time we call a method on the WebElement the driver will go and find it on the current page again. In an AJAX-heavy application this is what you would like to happen, but in the some cases we know that the element is always going to be there and won't change. We also know that we won't be navigating away from the page and returning. It would be handy if we could "cache" the element once we'd looked it up:
  // The element is now looked up using the name attribute,
  // and we never look it up once it has been used the first time 
  @FindBy(name="myFieldId")
  @CacheLookup
  private WebElement myField;
For more information on the PageFactory please read the following link:

Waiting for an element to exist before looking it up

Selenium tests require a browser to open and a page to load before the code attempts to lookup the expected elements in the page. Selenium has a number of settings to try and cater for this scenario:

Implicit Wait

We can tell Selenium that we would like it to wait for a certain amount of time before throwing an exception when it cannot find the element on the page. Implicit waits will be in place for the entire time the browser is open. This means that any search for elements on the page could take the time the implicit wait is set for.
  WebDriver driver = new FirefoxDriver();
  driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
  driver.get("http://url_that_delays_loading");
  WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));
During Implicit wait if the Web Driver cannot find it immediately because of its availability, the WebDriver will wait for the mentioned time and it will not try to find the element again during the specified time period. Once the specified time is over, it will try to search the element once again the last time before throwing exception. The default setting is zero. Once we set a time, the Web Driver waits for the period of the WebDriver object instance.

FluentWait

Each FluentWait instance defines the maximum amount of time to wait for a condition, as well as the frequency with which to check the condition. Furthermore, the user may configure the wait to ignore specific types of exceptions whilst waiting, such as NoSuchElementExceptions when searching for an element on the page.

If you have an element which sometime appears in just 1 second and some time it takes minutes to appear than it is better to use fluent wait, as this will try to find the element again and again until it finds it or until the final timer runs out.
 // Waiting 30 seconds for an element to be present on the page, checking
 // for its presence once every 5 seconds.
 Wait wait = new FluentWait(driver)
   .withTimeout(30, SECONDS)
   .pollingEvery(5, SECONDS)
   .ignoring(NoSuchElementException.class);
 
 WebElement foo = wait.until(new Function() {
   public WebElement apply(WebDriver driver) {
     return driver.findElement(By.id("foo"));
   }
 });
Another case where FluentWait can and is used is when certain events on a page cause the DOM tree to be modified, you can end up with a StaleElementException to the reference you have of that element. When this happens you will need to reinitialise the element or look it up again after the DOM tree has been rebuilt. A StaleElementException is thrown when the element you were interacting is destroyed and then recreated. An example of where this happens in the Meterflow application is on showing a Modal dialog and trying to enter values in input texts to submit a form. Here is an example of code that you can use in this scenario:
 
 public MyPage waitForModalDialogToShow() {
   final Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(30, TimeUnit.SECONDS)
     .pollingEvery(5, TimeUnit.SECONDS)
     .ignoring(NoSuchElementException.class, StaleElementReferenceException.class);
   
   wait.until(new Function<WebDriver, WebElement>() {
     public WebElement apply(WebDriver driver) {
       return driver.findElement(By.id("myModelDialog"));
     }
   });
   
   return this;
 }
In situations where you are using the FindBy annotations on a PO class and not explicitly calling driver.findElement and the DOM was changed due to some user events you may also need to reinitialise the PO object so that the fields are looked up again after the DOM has been recreated. To do this you can call the following static method on the PageFactory class:
 
 /**
  * Reinitialise a PageObject by replacing the fields of an already instantiated Page Object. 
  */
  public void initElements() {
    PageFactory.initElements(driver, this);
  }

Explicit WebDriverWait

The WebDriverWait is a specialization of FluentWait that uses WebDriver instances. It is more extendible in the means that you can set it up to wait for any condition you might like. Usually, you can use some of the prebuilt ExpectedConditions to wait for elements to become clickable, visible, invisible, etc.

There can be an instance when a particular element takes more than a minute to load. In that case you don't want to set a huge time to Implicit wait because then your browser will wait the same time for every element. To avoid that situation you can put a separate time on the required element.
  WebDriverWait wait = new WebDriverWait(driver, 10);
  WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

Selenium Locator Strategies

There are 8 locators that Selenium’s commands support:
  1. id - Ids are the most preferred way to locate elements on a page, fast and reliable way to locate elements
  2. name - An efficient way to locate an element but unlike Ids, name attributes don’t have to be unique in a page
  3. identifier - Combination of id and name, first checks the @id attribute and if no match is found it tries the @name attribute
  4. css - Locate an element by using CSS selectors to find the element in the page
  5. xpath - Locate an element using an XPath query
  6. link - Locate a link element ("a" tag) by the text used within the link tag
  7. dom - Locate elements that match the JavaScript expression referring to an element in the DOM of the page
  8. ui - Selenium IDE extension (http://ttwhy.org/code/ui-doc.html)

FindBy annotation support

The @FindBy annotation supports the following locators:
id
 My text
 
 @FindBy(id="elementId")
 private WebElement myElement;
name
 
 My text
 @FindBy(name="elementName")
 private WebElement myElement;
className
  
block
 
 @FindBy(className="element-css")
 private WebElement myElement;
css
 
block
block
Google
 @FindBy(css="div.element-css")
 private WebElement myElementEx1;

 @FindBy(css="div.element-css[id='myElementId']")
 private WebElement myElementEx2;

 @FindBy(css="input[name='textName'][type='text']")
 private WebElement myElementEx3;

 @FindBy(css="a[name='link']")  
 private WebElement myElementEx4;
linkText
 Google
 @FindBy(linkText="Google")
 private WebElement myElement;
partialLinkText
 Google
 @FindBy(partialLinkText="Goo")
 private WebElement myElement;
tagName
 
 Link1
 
 Link2

 Link3
 
 @FindBy(tagName = "a")
 private List myLinks;
xpath
  
block
 
 @FindBy(xpath="//span[@class='element-css']")
 private WebElement myElement;

A few examples

  • Finding a cell in a table generated by Primefaces, an example of what the generated html table would look like:
 <div id="myFormId:myTableId" class="ui-datatable ui-widget">
  <div class="ui-datatable-tablewrapper">
    <table role="grid">
      <thead id="myFormId:myTableId_head">
        <tr role="row">
          <th id="myFormId:myTableId:j_idt44" class="ui-state-default" role="columnheader">
            <span class="ui-column-title">Column 1</span>
          </th>
          <th id="myFormId:myTableId:j_idt45" class="ui-state-default" role="columnheader">
            <span class="ui-column-title">Column 2</span>
          </th>
        </tr>
      </thead>
      <tfoot id="myFormId:myTableId_foot"/>
      <tbody id="myFormId:myTableId_data" class="ui-datatable-data ui-widget-content">
        <tr class="ui-widget-content ui-datatable-even ui-datatable-selectable" role="row">
          <td role="gridcell">
            <span id="myFormId:myTableId:0:col1">Row 1 - Value of column 1</span>
          </td>
          <td role="gridcell">
            <span id="myFormId:myTableId:0:col2">Row 1 - Value of column 2</span>
          </td>
        </tr>
        <tr class="ui-widget-content ui-datatable-even ui-datatable-selectable" role="row">
          <td role="gridcell">
            <span id="myFormId:myTableId:2:col1">Row 2 - Value of column 1</span>
          </td>
          <td role="gridcell">
            <span id="myFormId:myTableId:2:col2">Row 2 - Value of column 2</span>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
 </div>
 // find all the table cells that match the css selector
 @FindBy(css="div[id='myFormId:myTableId'] > div > table > tbody > tr > td > span")

 // same as above but won't only check the next element in tree and will keep searching until a match is found
 @FindBy(css="div[id='myFormId:myTableId'] table td span")

 // find all the table cells that match the xpath query
 @FindBy(xpath="//div[@id='myFormId:myTableId']/div/table/tbody/tr/td/span")

 // same as above but won't only check the next element in tree and will keep searching until a match is found
 @FindBy(xpath="//div[@id='myFormId:myTableId']//table//td//span")

 // to find a cell that contains text
 @FindBy(xpath="//div[@id='myFormId:myTableId']//table//td//span[contains(text(),'Row 1 - Value of column 1')]")
  • Find an element whose ID matches part of an expression, the following examples use an "a" link element but can be any valid html tag:
 <a id="j_idt38:myLink" href="/tmp.xhtml" class="ui-link ui-widget">Tmp</a>
 // css strategy to find an element whose ID starts with 'j_idt38'
 @FindBy(css="a[id^='j_idt38']")

 // css strategy to find an element whose ID ends with 'myLink'
 @FindBy(css="a[id$='myLink']")

 // css strategy to find an element whose ID contains 'myLink'
 @FindBy(css="a[id*='myLink']")

 // xpath query strategy to find an element whose ID contains 'myLink'
 @FindBy(xpath="//a[contains(@id, 'myLink')]")
  • Perform Javascript actions, the following example describes a javascript event being carried out when the mouse hovers over certain menu items:
 <li id="topNavFrm:adminSubmenu">
  <a href="#">
    <span />
    <span >Administration</span>
    <span />
  </a>
  <ul role="menu">
    <li id="topNavFrm:usersSubMenu">
      <a href="#">
        <span />
        <span>Users</span>
        <span />
      </a>
      <ul>
        <li>
          <a id="topNavFrm:userGroupMenuItem" href="/users/groups.xhtml">
            <span>User Groups</span>
          </a>
        </li>
        <li>
          <a href="/users/users.xhtml">
            <span>Users</span>
          </a>
        </li>
      </ul>
    </li>
  </ul>
 </li>
 @FindBy(id="topNavFrm:adminSubmenu")
 private WebElement adminMenu;

 public UsersAdminPage mouseOverUsersDetailMenu() {
   Actions action = new Actions(driver);
   action.moveToElement(adminMenu).perform();
       
   WebElement usersSubElement = adminMenu.findElement(By.cssSelector("li[id='topNavFrm:usersSubMenu'] a"));
   action.moveToElement(usersSubElement);
       
   WebElement usersAdminSubElement = adminMenu.findElement(By.id("topNavFrm:usersMenuItem"));
   action.moveToElement(usersAdminSubElement);
       
   action.click();
   action.perform();
  
   return this;
 }

XPath Query Testing

Testing XPath queries can be done within the browser, this sections shows examples of how you could do it with some of them:

Chrome

To type in an xpath to search a page:
  • Press F12 to open Chrome Developer Tool
  • In "Elements" panel, press Ctrl+F
  • In the search box, type in XPath or CSS Selector, if elements are found, they will be highlighted in yellow.
To copy an xpath from an element in the page (same can be done to retrieve CSS path):
  • Right click on element and select Inspect Element
  • In elements view right click on element line and select Copy XPath

Firefox

To type in an xpath to search a page:
  • Install Firebug
  • Install Firepath
  • Press F12 to open Firebug
  • Switch to FirePath panel
  • In dropdown, select XPathor CSS
  • Type in to locate
To copy an xpath from an element in the page:
  • Click on Inspect element button and place your tip of cursor on any element for which you want to find XPath
  • Right Click on highlighted code and Select Copy XPath