Monday, February 26, 2018

How to Configure Firebase Cloud Storage bucket for cross-origin access (CORS)

If you have ever tried to download data stored in Firebase Cloud Storage directly in your browser you may have come across this error:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '' is therefore not allowed access

In order to fix this error you will need to run through a couple of steps to configure Firebase Cloud Storage for CORS. The following steps can be taken in order to do this:

GSUtil

There are at least two approaches to configure the cloud storage with GSUtil:

Cloud shell within Google Cloud Platform

You can manage Compute Engine resources like virtual machine instances using the gcloud command-line tool in a Cloud Shell session.
  • The following instructions outline how to start the session
  • Google Cloud Shell is free for customers of Google Cloud Platform which isn't free

Install GSUtil

Gsutil is a tool that enables you to access Google Cloud Storage from the command-line and is needed to configure Firebase Cloud Storage for CORS.
  • If you are behind a corporate proxy or firewall, the tool may not be able to access the internet with its default settings during installation. In this case you could use one of the self-contained versioned archives as detailed here.
  • Once you have successfully run gcloud init and been authenticated you can configure CORS
  • With the cors.json file created run the following command to deploy the configuration to your storage: 
    • bin/gsutil.cmd -d cors set  gs://

That should be all you need to do. 

Monday, February 12, 2018

Vue.js, NUXT.js, Vuex, Firebase persisted authentication, Axios

I created the following application to demonstrate how to handle authentication with Firebase within a Nuxt (Vue) application. I wanted to make sure the application stayed logged in as long as the Firebase authentication token hadn't expired. User should not be logged out when:
  • The browser is refreshed
  • The browser is closed and restarted and the Firebase token is still valid (persisted sessions)
You can grab the example from Github and you can see below for a brief outline of the steps I took to setup configure the application:

Firebase Project

  • Signup / Login to the Firebase console and Create a new project by clicking the Add project icon and following the instructions for creating your project. 
  • Setup authentication within your new Firebase project by clicking on the authentication menu in the left navigation bar. Click on the sign-in method tab and select the Email/Password provider from the list of sign-in methods. Enable it and click save.

Create Vue+NUXT application

Install the necessary dependencies

  • yarn add @nuxtjs/axios body-parser express express-session firebase jwt-decode vuex  

Configure and initialise Firebase

  • Add Firebase configuration settings by creating a development (and production) configuration file to your application and adding your Firebase  project settings to it
  • Locate your Firebase application configuration settings by logging into your Firebase console and searching for: Add Firebase to you Web Application
  • Create a file that will export the instance of your Firebase application
  • The example application also makes use query the Firebase realtime database. If you are wanting to run the example application be sure to create your own database in your Firebase project

Create express server API 

  • Create an express server API to handle the login and logout posts for the user. On receiving a post request from the client the user ID is stored in the session and the access token is stored in a cookie
  • Modify your nuxt.config.js file so that it includes a section for the serverMiddleware and also has @nuxtjs/axios module defined

Create Vuex actions and mutations

  • Add Vuex to your application and choose between the classic or module mode. I opted for the module mode
  • Inside your root store file define the nuxtServerInit action. This action is used to save the currently logged in user to the session
  • Inside your stores users module add the necessary getters, actions and mutations needed to save the user ID to the store. We include our login and logout actions here that use axios to send a post request to the server 

Create check authentication middleware

  • Create a check authentication middleware action and add the necessary configuration to nuxt.config.js so that it will be called for every route
  • The middleware component will check to see if the user is stored in the session or if the access token is found in the cookie. If it finds a match the store is initialised with the user ID. 

Create protected resource

  • Create a page that will only be accessible if a user has successfully been authenticated
  • Create the authenticated middleware action that will be called for every protected page. This action checks to see if a user is authenticated, if not the user is redirected to the sign in page

Create SignIn and SignUp pages

  • Create a page to allow the user to sign in to the application
  • Create a page to allow a user to register as a new user to the application

Run your Application

  • npm run dev
  • If all was configured successfully you should be able to sign up, sign in, reload page and still be signed in, close browser and reopen browser and still be logged in (as long as access token is still valid) and finally be able to sign out of the application

Wednesday, November 22, 2017

Offline web application with Angular

Last month I wrote a blog about a Progressive Web Application in Vue.js and subsequently I investigated how one could do this all in Angular (version 5.0.1). I am new to Angular and have just started to learn it. I like Vue very much but for an existing work project already using Angular I hope to learn the framework. This doesn't mean I am going to throw Vue out the window, on the contrary I just signed up for the online Vue Master Class just starting out on vueschool.io. I think learning Angular on top of it will only improve my skills in Javascript and and increase my understanding of modern web frameworks.

Angular PWA Example

After reading the quick start documentation on the Angular website in order to get familiar with Angular I went about searching the web for information on how to build PWA application with Angular. I found the following article really useful and built the sample Angular project based on the information I found here:

A new Angular Service Worker — creating automatic progressive web apps. 


The example application they have is called PWAtter and you can find it on GitHub. The example I created and have on GitHub is a very basic Angular application with SW configuration and support based on the articles mentioned in the links above. 

A short note on running the application, to run it in dev you can run the "npm run start" command line. Running in Dev doesn't enable Service Worker support. To run it with the Service Worker support you need to run in production mode and with a http server, the command for the project is "npm run serve-prod-ngsw".

Thursday, November 2, 2017

Storytellers - a Vue, NUXT, SSR, Vuetify, Firebase [Auth, Firestore, Storage, Functions] application

I am trying to develop an web application from the ground up in order for me to really learn and understand modern web development. I wrote a blog entry when I first started out and I have continued to work on the sample application.

There is very little you can do with the application but it covers a lot of ground already. I have managed to covers all the tiers I am trying to learn:


Hopefully, if I have time, I can add more functionality to it so that it looks and feels like a proper functional application.

What is the web application about? Well at the moment it allows a user to upload images to Firebase storage and displays thumbnails on the home screen. Sounds amazing. Ultimately I would like to 'expand' on that :-) and end up with a community driven application providing a platform for the creative and artistic to share and collaborate their stories and ideas with one another.

Yeah so arguably that idea is pointless and ... yeah it might be ... but it allows me to try many different things and covers many different technology stacks so I am going to learn a lot by doing this.

I don't expect anyone to be interested in "collaborating" with me in development but I want to keep this opensource and invite anyone out there who is keen and able to contribute to the development of this project. Feel free to fork the repository, raise issues and submit pull requests.

Tuesday, October 24, 2017

Offline web application with Vue.js

I have recently been learning Vue and in so doing a million other things, it seems, to do with modern web frameworks like Vue. Vue is described as:

The Progressive JavaScript Framework

So what is a Progressive Web App? Wikipedia explains it as follows:

Progressive Web App (PWA) is a term used to denote web applications that use the latest web technologies. Progressive Web Apps, also known as Installable Web Apps or Hybrid Web Apps, are regular web pages or websites, but can appear to the user like traditional applications or native mobile applications. The application type attempts to combine features offered by most modern browsers with the benefits of mobile experience.

The following characteristics make up a PWA:

Progressive

Work for every user, regardless of browser choice because they’re built with progressive enhancement as a core tenet.

Responsive

Fit any form factor: desktop, mobile, tablet, or forms yet to emerge.

Connectivity independent

Service workers allow work offline, or on low quality networks.

App-like

Feel like an app to the user with app-style interactions and navigation.

Fresh

Always up-to-date thanks to the service worker update process.

Safe

Served via HTTPS to prevent snooping and ensure content hasn’t been tampered with.

Discoverable

Are identifiable as “applications” thanks to W3C manifests and service worker registration scope allowing search engines to find them.

Re-engageable

Make re-engagement easy through features like push notifications.

Installable

Allow users to “keep” apps they find most useful on their home screen without the hassle of an app store.

Linkable

Easily shared via a URL and do not require complex installation.

For me I was quite keen to see how the connectivity independent characteristic could work so that regardless of whether or not a user is online they could still work away as if they were connected. I started reading up on service workers to get an initial understanding of the concepts.

I found the following links most helpful:


Over and above that there are these two vue-cli templates designed to give you a running application with all the PWA features configured and ready to use:


The Vuetify example is based off the vue-pwa-boilerplate just with Vuetify semantic material components.

I took these examples and created my own vuetify-pwa application. The goal was to have some web navigation between pages and to be able to complete some forms and submit them regardless of internet connectivity. Once online the goal is to auto sync the changes with the server. This background sync hasn't been implemented yet and hopefully I can get to update this later on when it is done.

Monday, October 23, 2017

Vue.js, NUXT.js, Vuetify.js, Firebase authentication

Please note I have a more recent blog entry regarding authentication with Firebase + Nuxt that not only uses the session to store the user ID but a cookie to store the access token. It also makes use of the Nuxt Axios module to make server posts on login and logoff. 

I previously wrote a blog detailing a few steps to get a sample Vue + Vuetify + Nuxt application running on Heroku cloud platform. In this blog I want to share a sample application I did that has all of the above but also Firebase authentication.

Framework Overview

In a nutshell this is what the example application covers:

Vue.js

The sample application is built using the Vue.js framework, a progressive framework for building user interfaces.

NUXT.js

It is also built on top of NUXT.js, a framework for creating Universal Vue.js Applications. I chose NUXT.js because I wanted to build a server-rendered Vue application. I didn't need to use NUXT, there is an in-depth guide I could have followed but NUXT is supposed to make building universal web application easier. That sounds good to me.

Vuetify

For the UI components and page layouts I make use of Vuetify.js, a semantic component framework for Vue.js. Why Vuetify and not many other options that are available, like what can be seen in this comparison blog post? A lot of these frameworks are new to me, Vuetify seemed like a popular choice with a stable backing and it supported server side rendering with NUXT.

Firebase Authentication 

The application integrates with Firebase in order to authenticate users.

Vue CLI Templates

Getting familiar with NUXT and Vuetify I went over the following Vue CLI templates:
They were both very useful and instrumental in getting an initial understanding into their framework. But things started to get a little less simple and a lot more fuzzy when I started to integrate Firebase authentication with my app. Of course there is a lot I need to learn (and still need to learn). GitHub issues for both these projects were quite helpful in searching for answers to questions I had:

The problem

I needed a way to authenticate users through Firebase authentication and to handle state on the server as well as the client. Firebase web authentication is run on the client side. I wanted to be able to logout a user when the user logs out and also keep a user logged in when the user refreshes their browser. There seems to be a number of different approaches to this problem and I settled on the following:
  1. Configure the application to run an express server so that I could handle server POSTS and  GETS if needs be (example sign in and sign out post) and store any information in the session in case I need to access it again from the server. The following link on the NUXT website helped me configure my custom server: https://nuxtjs.org/examples/auth-routes/. Oh and yeah it has an example of an auth use case except it didn't quite fit my scenario.
  2. Configure a pages middleware function that gets called for every secure page, not for sign in and sign up pages. This function will be responsible to see if the user is authenticated or not by either checking the session (server) or analysing the firebaseApp variable to see if the current user exists or not. 
The above means I don't store the logged in user in any store like Vuex, Firebase seems to store the user in localStorage in a variable called "authuser". That way it can keep the user signed in.

Sample Code

The sample code for the project I did can be found here:
Once cloned you should be able to change into the ui folder and run the following commands to test it out:
  • npm install
  • npm run build
  • npm run dev-custom-server
You could also just examine the code...maybe there is something useful there you will find. Like I said at the beginning this is all very new to me so most likely there are a lot of things wrong with the way I have done it. I hope not. But nevertheless I learned a lot.

Friday, October 20, 2017

Audit logging in JBoss EAP 6

A security domain in JBoss can be configured to write information to a log file or do some custom action like send an email notification all for audit purposes. You can configure the security domain via the admin console / jboss-cli / edit the standalone.xml file directly.

Open the admin console and navigate to Configuration -> Security -> Security Domains. Choose the View link from the list of domains you want to edit. Select the audit tab. For example if you want to configure the default other domain you will notice that there are no provider modules listed. Provider modules are used to provide this audit mechanism. By default JBoss uses org.jboss.security.audit.providers.LogAuditProvider. This isn't listed in the table here and is disabled by default.

Enable the LogAuditProvider for the application server 

A log appender needs to be configured, this can be done via the CLI or edit the standalone configuration file manually. 

CLI
/profile=full-ha/subsystem=logging/periodic-rotating-file-handler=AUDIT/:add(suffix=.yyyy-MM-dd,formatter=%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n,level=TRACE,file={"relative-to" => "jboss.server.log.dir","path" => "audit.log"})
/profile=full-ha/subsystem=logging/logger=org.jboss.security.audit/:add(level=TRACE,category=org.jboss.security,handlers=["AUDIT"])

The above should generate the following configuration in your standalone.xml file:
<periodic-rotating-file-handler name="AUDIT" autoflush="true">
  <level name="TRACE"/>
  <formatter>
    <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
  </formatter>
  <file relative-to="jboss.server.log.dir" path="audit.log"/>
  <suffix value=".yyyy-MM-dd"/>
  <append value="true"/>
</periodic-rotating-file-handler>
<logger category="org.jboss.security">
  <level name="TRACE"/>
  <handlers>
    <handler name="AUDIT"/>
  </handlers>
</logger>

Disable the LogAuditProvider for a single web application


The above log configuration applies to all applications deployed to the application server. To disable this logging for a particular application you can include a jboss-web.xml file in your WEB-INF directory that has the disable-audit element defined with a false value, example:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
  <security-domain>java:/jaas/other</security-domain>
  <disable-audit>false</disable-audit>
</jboss-web>

As mentioned above the auditing uses provider modules and the default is org.jboss.security.audit.providers.LogAuditProvider. You can use this one or implement your own. The LogAuditProvider can be found in the picketbox-4.1.1.Final-redhat-1.jar and extends abstract class: AbstractAuditProvider

Wednesday, September 20, 2017

Vue + Vuetify + Nuxt + Heroku

I want to learn how to build a SSR front-end application in Vue and have been playing around with Vuetify, Nuxt.js and Heroku. These are the steps I followed to get the Vuetify Nuxt.js starter template deployed to Heroku.

Create GitHub repository

I created a GitHub repository and cloned it to a directory on my local computer.

Initialise starter template

  • Before you begin make sure you have Node.js and vue-cli installed
  • Open a command prompt and change into the directory of your git project
  • Follow the instructions on the vuetify/nuxt github project

Install Heroku CLI

The Heroku Command Line Interface (CLI), formerly known as the Heroku Toolbelt, is a tool for creating and managing Heroku apps from the command line / shell of various operating systems.

Follow these instructions to install the Heroku CLI to your computer. 

Create an Heroku App

Heroku manages app deployments with Git. You can create an Heroku App online or through the Command Line Interface with or without an existing Git repository.

Create an Heroku App without an existing Git repository

Follow these instructions to create your Heroku app.

Create an Heroku App with an existing Git repository

Follow these instructions to create your Heroku app from an existing Git repository.

Heroku Deployment Configuration

I followed the steps outlined in the Nuxt.js support web page for Heroku apps. Although it didn't quite work on deployment as npm start was not building the application. I changed the package.json script section to build and then run on start. Not sure if this is correct but it worked for me.

  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt build && nuxt start",
    "generate": "nuxt generate",
    "heroku-postbuild": "npm run build"
  }
But I made sure to run all the other commands mentioned in their instructions:
 $ heroku config:set NPM_CONFIG_PRODUCTION=false
 Setting NPM_CONFIG_PRODUCTION and restarting my-app-123... done, v3
 NPM_CONFIG_PRODUCTION: false

 $ heroku config:set HOST=0.0.0.0
 Setting HOST and restarting my-app-123... done, v4
 HOST: 0.0.0.0

 $ heroku config:set NODE_ENV=production
 Setting NODE_ENV and restarting my-app-123... done, v5
 NODE_ENV: production

Heroku Deployment 

To deploy your application (via Git) to Heroku you should run the following command:
  • git push heroku master
If you want to deploy code to Heroku from a non-master branch of your local repository use the following syntax to ensure it is pushed to the remote’s master branch, example:
  • git push heroku mybranch:master
Heroku apps expect the app directory structure at the root of the repository. If your app is inside a subdirectory in your repository, it won’t run when pushed to Heroku. Git allows you to push a subtree of your repository, example:
 git push heroku `git subtree split --prefix appsubdirectory mybranch`:master
I got the following error when doing this:
error: unable to push to unqualified destination: master The destination refspec neither matches an existing ref on the remote nor begins with refs/, and we are unable to guess a prefix based on the source ref.
In order for me to resolve this I changed the push command to the following (this only needed to be done once):
 git push heroku `git subtree split --prefix appsubdirectory mybranch`:refs/heads/master

Heroku Local

In order to troubleshoot your application you can use the following command to run locally:
  • heroku local

Node.js Support

The following page has some useful information for Node.js application running on Heroku. 
Example would be to always specify the node version as outlined in this page

Wednesday, September 13, 2017

Vue + Webpack + Bootstrap

I created a simple Vue, Webpack and Bootstrap template to showcase how to integrate Bootstrap with Vue using Webpack.

Dependencies 

Required Dependencies

  • bootstrap
  • css-loader
  • file-loader

Optional Dependencies 

  • jquery
  • popper.js

 package.js

{
  "name": "vue-webpack-bootstrap-template",
  "description": "A Vue.js project",
  "version": "1.0.0",
  "author": "",
  "private": true,
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
  },
  "dependencies": {
    "bootstrap": "4.0.0-beta",
    "jquery": "^3.2.1",
    "popper.js": "^1.12.5",
    "vue": "^2.3.3"
  },
  "devDependencies": {
    "babel-core": "^6.0.0",
    "babel-loader": "^6.0.0",
    "babel-preset-env": "^1.5.1",
    "cross-env": "^3.0.0",
    "css-loader": "^0.25.0",
    "file-loader": "^0.9.0",
    "style-loader": "^0.18.2",
    "url-loader": "^0.5.9",
    "vue-loader": "^12.1.0",
    "vue-template-compiler": "^2.3.3",
    "webpack": "^2.6.1",
    "webpack-dev-server": "^2.4.5"
  }
}

Webpack Configuration

Loaders

The following loaders need to be added to the webpack.config.js
 
 {
   test: /\.(png|jpg|gif|svg)$/,
   loader: 'file-loader',
   options: {
     name: '[name].[ext]?[hash]'
   }
 },
 {
   test: /\.css$/,
   loaders: ['style-loader','css-loader']
 },
 {
   test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
   loader: 'url-loader?limit=10000&mimetype=application/font-woff'
 },
 {
   test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
   loader: 'url-loader?limit=10000&mimetype=application/octet-stream'
 },
 {
   test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
   loader: 'file-loader'
 }

Provide Plugin

If you optionally want to use Bootstrap for the components that make use of JQuery and Popper.js you will need to add the following plugin:
 new webpack.ProvidePlugin({
   $: 'jquery',
   jQuery: 'jquery',
  'window.jQuery': 'jquery',
   Popper: ['popper.js', 'default'],
   // In case you imported plugins individually, you must also require them here:
   Util: "exports-loader?Util!bootstrap/js/dist/util",
   Dropdown: "exports-loader?Dropdown!bootstrap/js/dist/dropdown"
 })

Main.js

require('bootstrap/dist/css/bootstrap.css')

import Vue from 'vue'
import App from './App.vue'

import 'bootstrap'

new Vue({
  el: '#app',
  render: h => h(App)
})

BootstrapVue

Instead of doing the above you could use BootstrapVue dependency that is a library that creates Vue Bootstrap components. The following GitHub project is a simple bootstrap-vue template.

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 ~/.vnc/xstartup ~/.vnc/xstartup.backup
vi ~/.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

SSL Encryption for Web Server

Secure Sockets Layer (SSL) encrypts network traffic between two systems. Traffic between the two systems is encrypted using a two-way key, generated during the handshake phase of the connection and known only by those two systems.

In order for a browser to connect with JBoss EAP over SSL the following steps will need to be performed:
  • Create keystore containing public and private keys for the server
  • Configure a HTTPS connector in JBoss EAP 

In order for a Java client application 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

SSL Encryption Keys and Certificate

For secure exchange of the two-way encryption key, SSL makes use of Public Key Infrastructure (PKI), a method of encryption that utilizes a key pair. A key pair consists of two separate but matching cryptographic keys:

  • public key - shared with others and used to encrypt data
  • private key - kept secret and used to decrypt data that has been encrypted using the public key

When a client requests a secure connection, a handshake phase takes place before secure communication can begin. During the SSL handshake the server passes its public key to the client in the form of a certificate. The certificate contains:

  • the identity of the server (its URL)
  • the public key of the server
  • a digital signature that validates the certificate. You can purchase a certificate from a Certificate Authority (CA), or you can use a self-signed certificate. Self-signed certificates are not considered trustworthy but are appropriate for internal testing purposes.

The client then validates the certificate and makes a decision about whether the certificate is trusted or not.

If the certificate is trusted, the client generates the two-way encryption key for the SSL connection, encrypts it using the public key of the server, and sends it back to the server.

The server decrypts the two-way encryption key, using its private key, and further communication between the two machines over this connection is encrypted using the two-way encryption key.

Generate a keystore containing public and private keys.

keytool -genkeypair -alias jbossweb -keyalg RSA -keysize 1024 -keystore server.jks -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

Subject Alternative Name

When generating the keystore you might need to set the subject alternative name, Chrome for instance will block access to a site that just uses the common name field and not the subject alternative name. In order to specify a subject alternative name you can use the ext option in the keytool command like:
keytool -genkeypair -alias jbossweb -keyalg RSA -keysize 1024 -keystore server.jks -validity 3650 -keypass jbosswebpass -storepass jbosswebpass -ext SAN=dns:test.example.com

Verify the key

The following command is quite useful to print information on the keystore:
keytool -list -v -keystore server.jks

Generate a certificate signing request.

keytool -certreq -keyalg RSA -alias jbossweb -keystore server.jks -file certreq.csr

Test the newly generated certificate signing request.

openssl req -in certreq.csr -noout -text

CA signed / self-signed certificate

  • Submit your certificate signing request to a Certificate Authority (CA) who can authenticate your certificate so that it is considered trustworthy by third-party clients. The CA supplies you with a signed certificate, and optionally with one or more intermediate certificates.
keytool -import -trustcacerts -alias jbossweb -keystore server.jks -file server.crt
  • If you get the following error: "keytool error: java.lang.Exception: Failed to establish chain from reply" it might be because you need to import root certificates. You should be able to know if you need this by whoever issued the CA to you. You will need to do the following:
  • Import root certificate to cacerts which will be available at JAVA_HOME/jre/lib/security folder using following command:
 keytool -importcert -alias root -file Root.cer -keystore cacerts
  • Import root certificate using following command:
 keytool -importcert -alias root -file Root.cer -keystore server.jks
  • Import intermediate certificate using following command
 keytool -importcert -alias sub -file Sub.cer -keystore server.jks
  • Import site certificate using following command:
 keytool -trustcacerts -importcert -alias jbossweb -file server.crt -keystore jbossprep.jks
  • If you only need certificate for testing or internal purposes, you can use a self-signed certificate. You can export one from the keystore you created in the first step above:
keytool -export -alias jbossweb -keystore server.jks -file server.crt

Create keystores for the Java client application

The following steps describe how to create keystores for the client and how to import these keystores into the truststores. 

Export the server's public key

  • Export the server public key created in the above steps by running the following command:
 
 keytool -exportcert -alias jbossweb -keystore server.jks -file server.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

Create the client's keystore private/public key


  • Run the following command:
 
 keytool -genkeypair -alias clientalias -keyalg RSA -keysize 1024 -keystore client.jks -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
  • -storetype
    • keystore type. Default is jks, for PKCS12 use -storetype PKCS12

Subject Alternative Name

The same as why mentioned above to specify a subject alternative name you can use the ext option in the keytool command like:
 
 keytool -genkeypair -alias clientalias -keyalg RSA -keysize 1024 -keystore client.jks -keypass clientpass -storepass clientpass -validity 3650 -ext SAN=dns:test.example.com

Export the client's public key

  • Run the following command:
 
 keytool -exportcert -alias clientalias -file client.cer -keystore client.jks -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. The following imports the clients public key into the existing server.jks
 
 keytool -importcert -trustcacerts -alias clientalias -file client.cer -keystore server.jks -keypass jbosswebpass -storepass jbosswebpass
  • Instead of doing the above you could also add the client's public key to a truststore file
 
 keytool -importcert -trustcacerts -alias clientalias -file client.cer -keystore truststore.jks -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 server.cer -keystore client.jks -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.

Export private key from server keystore

If you ever need to export your server JKS keytool format to PKCS #12 format and the private key you can follow these steps:
  • Save JKS as PKCS:
 
keytool -importkeystore -srckeystore server.jks -destkeystore keystore.p12 -deststoretype PKCS12 -srcalias jbossweb -deststorepass jbosswebpass -destkeypass jbosswebpass
  • Export certificate using openssl:
 
openssl pkcs12 -in keystore.p12  -nokeys -out cert.pem
  • Export unencrypted private key:
 
openssl pkcs12 -in keystore.p12  -nodes -nocerts -out key.pem
  • Verify that the Certificate and your Private Key go together:
 
diff <(openssl x509 -noout -in server.cer -modulus) <(openssl rsa -noout -in key.pem -modulus -passin pass:jbosswebpass)

Configure a HTTPS connector in JBoss EAP 6

Create a secure connector, named HTTPS, which uses the https scheme, the https socket binding (which defaults to 8443), and is set to be secure. This can be done via CLI or by editing the standalone.xml configuration file directly, this is what an example one-way SSL authentication HTTPS connector configuration looks like:
<subsystem xmlns="urn:jboss:domain:web:2.2" default-virtual-server="default-host" native="false">
  <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}/keys/server.jks" cipher-suite="RSA" protocol="TLSv1"/>
  </connector>
  <virtual-server name="default-host" enable-welcome-root="true">
    <alias name="localhost"/>
    <alias name="example.com"/>
  </virtual-server>
</subsystem>

The following example is for two-way SSL authentication:
<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.jks"
       verify-client="true"
       ca-certificate-password="jbosswebpass"
       ca-certificate-file="${jboss.server.config.dir}/truststore.jks"/>
   </connector>

   <virtual-server name="default-host" enable-welcome-root="true">
     <alias name="localhost"/>
     <alias name="example.com"/>
   </virtual-server>
 </subsystem>
  • The verify-client attribute is equivalent to Tomcats clientAuth attribute. When this value is set to true it means the SSL stack should require a valid certificate chain from the client before accepting a connection.
  • 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

Standalone Java 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.jks");
 System.setProperty("javax.net.ssl.keyStorePassword", "clientpass");
 System.setProperty("javax.net.ssl.trustStore", "/path/to/client.jks");
 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).

Browser as the Client

In order to test the certificates through a browser you will need to import all the certificates (root, intermediates and the certificate you got back from the CA). If you have configured JBoss above to verify-client then you will also need to import the client.p12 keystore into the browser. The following applies to windows:

Server Certificate

  • Open internet connections, an easy way to do it is by running: inetcpl.cpl
  • Go to the content tab
  • Certificates
  • Trusted Root Certification Authorities 
  • Import
  • Choose the CA signed / self-signed certificate (server.crt)

Client Keystore

  • Open internet connections, an easy way to do it is by running: inetcpl.cpl
  • Go to the content tab
  • Certificates
  • Personal 
  • Import
  • Choose the PKCS12 client keystore (client.p12)

Configuring Debug Options

In order to print debug options you can run your java application / JBoss application server with this addtional system parameter:
 -Djavax.net.debug=ssl,handshake
or
 -Djavax.net.debug=all

Keystore Explorer

Keystore Explorer is an open source GUI replacement for the Java command-line utilities keytool and jarsigner. KeyStore Explorer presents their functionality, and more, via an intuitive graphical user interface.

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