Data Driven Testing – Decoupling test data from test logic

Data-driven testing (DDT) is a term used in the testing of computer software to describe testing done using a table of conditions directly as test inputs and verifiable outputs as well as the process where test environment settings and control are not hard-coded. In the simplest form the tester supplies the inputs from a row in the table and expects the outputs which occur in the same row. The table typically contains values which correspond to boundary or partition input spaces. In the control methodology, test configuration is “read” from a database.

Anything that has a potential to change is separated out from the test logic and moved into an ‘external asset’. This can be a configuration or test dataset. The logic executed in the script is dictated by the data values. The script is simply a “driver” for the data that is held in the data source.

To convey the concept, I’ve created a sample project using TestNG. Pl. note implementation minimized for brevity. You will need following jars in your class path to successfully execute the project:

  1. poi-3.12-beta1-20150228.jar
  2. poi-ooxml-3.12-beta1-20150228.jar
  3. testng-6.8.21.jar
  4. xmlbeans-2.6.0.jar

The above were the versions which I had used for the demonstration. You could use the latest version of the above jars.

I’ve put the test data & expected outcome in an excel called TestData.xls and in my test case I refer it. The excel has multiple sheets which holds data for each test case type.

Below is the source code under test –

package com.sanjit;

/**
 * A simple minimal calculator. Implementation minmized for brevity.
 *
 * @author Sanjit Mohanty
 * @version 0.1
 *
 *
 * Revision History:
 * VERSION DATE AUTHOR COMMENT
 * 0.1 23-Apr-2015 Sanjit Mohanty initial create
 *
 *
 */

public class Calculator {

 public Calculator(){
 }

 public Double sum(Double obj1, Double obj2){
 return obj1+obj2;
 }

 public Double diff(Double obj1, Double obj2){
 return obj1-obj2;
 }

 public Double mul(Double obj1, Double obj2){
 return obj1*obj2;
 }

 public Double div(Double obj1, Double obj2){
 return obj1/obj2;
 }
}

Below is the unit test source code for the above class. Here we refer the excel for input data as well as for the expected outcome. No test data is mentioned here. The same test source runs for different inputs.

</pre>
<pre>package com.sanjit.test;

import java.lang.reflect.Method;

import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import com.sanjit.Calculator;
import com.sanjit.test.util.DataTypeParameter;
import com.sanjit.test.util.ExcelUtils;

/**
 * Test class for
 * {@link com.sanjit.Calculator}
 *
 * A simple example of Data Driven Testing!
 * Test data has been externalized to an excel and is being fed to the test case through TestNG's dataprovider.
 *
 * @author Sanjit Mohanty
 * @version 0.1
 *
 *
 * Revision History:
 * VERSION DATE AUTHOR COMMENT
 * 0.1 23-Apr-2015 Sanjit Mohanty initial create
 *
 *
 */

public class CalculatorTest {
 private Calculator calculator;

 @BeforeMethod
 public void initialize() {
 calculator = new Calculator();
 }

 /*
 * Data Provider feeding test data from an excel with multiple sheets for different test cases
 */
 @DataProvider(name = "testData")
 public Object[][] testData(final Method testMethod) throws Exception {
 DataTypeParameter parameters = testMethod
 .getAnnotation(DataTypeParameter.class);

 Object[][] testObjArray = ExcelUtils
 .getTableArray(
 "D://test//data//TestData.xls",
 parameters.testType()); // Edit the test data excel location accordingly

 return (testObjArray);

 }

 /*
 * Sum Test Case
 */
 @Test(dataProvider = "testData")
 @DataTypeParameter(testType = "SumTest")
 public void testSumChecker(String inputNumber1, String inputNumber2,
 String expectedResult) {
 Assert.assertEquals(
 Double.valueOf(expectedResult),
 calculator.sum(Double.valueOf(inputNumber1),
 Double.valueOf(inputNumber2)));
 }

 /*
 * Difference Test Case
 */
 @Test(dataProvider = "testData")
 @DataTypeParameter(testType = "DiffTest")
 public void testSubChecker(String inputNumber1, String inputNumber2,
 String expectedResult) {
 Assert.assertEquals(
 Double.valueOf(expectedResult),
 calculator.diff(Double.valueOf(inputNumber1),
 Double.valueOf(inputNumber2)));
 }

 /*
 * Multiplication Test Case
 */
 @Test(dataProvider = "testData")
 @DataTypeParameter(testType = "MulTest")
 public void testMulChecker(String inputNumber1, String inputNumber2,
 String expectedResult) {
 Assert.assertEquals(
 Double.valueOf(expectedResult),
 calculator.mul(Double.valueOf(inputNumber1),
 Double.valueOf(inputNumber2)));
 }

 /*
 * Division Test Case
 */
 @Test(dataProvider = "testData")
 @DataTypeParameter(testType = "DivTest")
 public void testDivChecker(String inputNumber1, String inputNumber2,
 String expectedResult) {
 Assert.assertEquals(
 Double.valueOf(expectedResult),
 calculator.div(Double.valueOf(inputNumber1),
 Double.valueOf(inputNumber2)));
 }
}

Below I’ve created a custom annotation to inject parameter into the TestNG data provider. In my case this annotation holds the test case type like SumTest, DiffTest, MulTest etc. Based on the test case type, the corresponding sheet in the excel is parsed by the test source code for the test run.

</pre>
<pre>package com.sanjit.test.util;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;

/**
 * Custom annotation for parameter passing to the data provider.
 *
 * @author Sanjit Mohanty
 * @version 0.1
 *
 *
 * Revision History:
 * VERSION DATE AUTHOR COMMENT
 * 0.1 23-Apr-2015 Sanjit Mohanty initial create
 *
 *
 */

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataTypeParameter {
 String testType();
}

Below is a utility class for reading the excel sheet which has our test data as well as the expected outcome.

<pre>package com.sanjit.test.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.poi.ss.usermodel.WorkbookFactory;

/**
 * Excel parsing utility class
 *
 * @author Sanjit Mohanty
 * @version 0.1
 *
 *
 * Revision History:
 * VERSION DATE AUTHOR COMMENT
 * 0.1 23-Apr-2015 Sanjit Mohanty initial create
 *
 *
 */

public class ExcelUtils {

 private static org.apache.poi.ss.usermodel.Workbook ExcelWBook;
 private static org.apache.poi.ss.usermodel.Sheet ExcelWSheet;

 private static org.apache.poi.ss.usermodel.Cell Cell;
 private static org.apache.poi.ss.usermodel.Row Row;

 public static Object[][] getTableArray(String FilePath, String SheetName)
 throws Exception {

 String[][] tabArray = null;

 try {

 int startRow = 1;
 int startCol = 1;
 int totalCols = 0;
 int totalRows = 0;
 int ci, cj;

 FileInputStream ExcelFile = new FileInputStream(FilePath);

 // Access the required test data sheet
 ExcelWBook = WorkbookFactory.create(ExcelFile);
 ExcelWSheet = ExcelWBook.getSheet(SheetName);

 totalRows = ExcelWSheet.getLastRowNum() + 1;
 if (totalRows >= 0) {
 totalCols = ExcelWSheet.getRow(0).getPhysicalNumberOfCells();
 }

 tabArray = new String[totalRows][totalCols];
 ci = 0;

 for (int i = startRow; i <= totalRows; i++, ci++) {

 cj = 0;

 for (int j = startCol; j <= totalCols; j++, cj++) {

 tabArray[ci][cj] = getCellData(i - 1, j - 1);

 System.out.println(tabArray[ci][cj]);

 }

 }
 }

 catch (FileNotFoundException e) {

 System.out.println("Could not read the Excel sheet");

 e.printStackTrace();

 }

 catch (IOException e) {

 System.out.println("Could not read the Excel sheet");

 e.printStackTrace();

 }

 return (tabArray);

 }

 public static String getCellData(int RowNum, int ColNum) throws Exception {

 try {

 Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);

 int dataType = Cell.getCellType();

 if (dataType == Cell.CELL_TYPE_NUMERIC) {
 return String.valueOf(Cell);

 } else if (dataType == Cell.CELL_TYPE_BLANK) {

 return "";
 } else if (dataType == Cell.CELL_TYPE_STRING) {

 String CellData = Cell.getStringCellValue();

 return CellData;

 }
 } catch (Exception e) {

 System.out.println(e.getMessage());

 throw (e);

 }
 return null;

 }
}

Sonar analysis for an Ant based Java project

Background:

In my previous post, i had explained the steps for installation and configuration of Sonar to analyse a maven based project in eclipse. In an another post, i had explained the usage of sonar-runner for non-maven based project.

In this post, I’m explaining the steps for sonar analysis of an ant based java project. Even if your java project is not Ant based, it is very simple to do the conversion in eclipse.

You just need to import your java project in eclipse and then right-click on your java project and click on export and select “Ant Buildfiles”. With this eclipse will automatically generate “build.xml” file for your java project. As a last step you have to let Eclipse know that it should use “Ant Builder” instead of the default java builder. For this right click on your java project, select “Builders” and click on “New” and select “Ant Builders”. Uncheck all other selected Builders in this window and click OK.

Steps:

  1. Start Sonar server

bin\windows-x86-32\StartSonar.bat  (for 32 bit Windows)

2. Check if Sonar server is running by opening Sonar admin page “http://localhost:9000“. Default credentials – admin/admin.

3. Below is how my Java Project structure looks in eclipse:

4. Download sonar Ant task jar from here. Place this jar in “${ECLIPSE_HOME}\plugins\org.apache.ant_<some_version>\lib” directory.

5. Edit your java project’s Build.xml file to include sonar task as target. You can refer my Build.xml and make changes as per your need:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!-- WARNING: Eclipse auto-generated file.
 Any modifications will be overwritten.
 To include a user specific buildfile here, simply create one in the same
 directory with the processing instruction <?eclipse.ant.import?>
 as the first entry and export the buildfile again. -->
 <project basedir="." default="build" name="CalculatorAntJavaProject" xmlns:sonar="antlib:org.sonar.ant">
 <property environment="env"/>
 <property name="ECLIPSE_HOME" value="../../../eclipse"/>
 <property name="debuglevel" value="source,lines,vars"/>
 <property name="target" value="1.7"/>
 <property name="source" value="1.7"/>
 <property name="src.dir" value="src"/>
 <property name="test.dir" value="test"/>
 <property name="build.dir" value="target"/>
 <property name="classes.dir" value="${build.dir}/classes"/>
 <property name="reports.dir" value="${build.dir}/reports"/>
 <property name="reports.junit.xml.dir" value="${reports.dir}/junit"/>

<path id="JUnit 3.libraryclasspath">
 <pathelement location="${ECLIPSE_HOME}/plugins/org.junit_3.8.2.v3_8_2_v20100427-1100/junit.jar"/>
 </path>

<target depends="build-subprojects,build-project" name="build"/>
 <target name="build-subprojects"/>
 <target depends="init" name="build-project">
 <echo message="${ant.project.name}: ${ant.file}"/>
 <javac debug="true" debuglevel="${debuglevel}" destdir="bin" source="${source}" target="${target}">
 <src path="src"/>
 <classpath refid="CalculatorAntJavaProject.classpath"/>
 </javac>
 <javac debug="true" debuglevel="${debuglevel}" destdir="bin" source="${source}" target="${target}">
 <src path="test"/>
 <classpath refid="CalculatorAntJavaProject.classpath"/>
 </javac>
 </target>
 <target description="Build all projects which reference this project. Useful to propagate changes." name="build-refprojects"/>

<target name="clean" description="Remove all files created by the build/test process.">
 <delete dir="${build.dir}" />
 <delete dir="${reports.dir}" />
 </target>

<target name="init">
 <mkdir dir="${build.dir}"/>
 <mkdir dir="${classes.dir}"/>
 <mkdir dir="${reports.dir}"/>
 <mkdir dir="${reports.junit.xml.dir}"/>
 </target>

<target name="compile" depends="init">
 <javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="JUnit 3.libraryclasspath" fork="true" debug="true" includeAntRuntime="false" />
 <javac srcdir="${test.dir}" destdir="${classes.dir}" classpathref="JUnit 3.libraryclasspath" fork="true" debug="true" includeAntRuntime="false" />
 </target>

<target name="run-tests" depends="compile">
 <taskdef name="junit" classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask">
 <classpath>
 <path refid="JUnit 3.libraryclasspath" />
 </classpath>
 </taskdef>

<junit fork="yes" dir="${basedir}" failureProperty="test.failed">
 <classpath location="${classes.dir}" />
 <classpath refid="JUnit 3.libraryclasspath" />

<formatter type="xml" />
 <batchtest todir="${reports.junit.xml.dir}">
 <fileset dir="${test.dir}">
 <include name="**/*Test.java" />
 </fileset>
 </batchtest>
 </junit>
 </target>

<target name="sonar" depends="compile">
 <!-- Define the Sonar task -->
 <taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
 <classpath path="${ECLIPSE_HOME}/plugins/org.apache.ant_1.8.2.v20120109-1030/lib/sonar-ant-task-1.0.jar" />
 </taskdef>

<property name="sonar.projectDescription" value="Example application using Ant and Jacoco" />
 <property name="sonar.sources" value="${src.dir}" />
 <property name="sonar.tests" value="${test.dir}" />
 <property name="sonar.binaries" value="${classes.dir}" />
 <property name="sonar.surefire.reportsPath" value="${reports.junit.xml.dir}" />

<property name="sonar.core.codeCoveragePlugin" value="jacoco" />
 <property name="sonar.jacoco.antTargets" value="run-tests" />

<sonar:sonar key="com.sanjit.test.CalculatorAntJavaProject" version="0.1-SNAPSHOT" xmlns:sonar="antlib:org.sonar.ant" />
 </target>
 </project>

6. Add “sonar” to Ant command line argument.  Right click on java project -> Select Builders -> Select Ant Builder -> Edit -> Select Main tab -> Add “sonar” to “Arguments” -> Apply -> OK.

7. Build your java project – Select java project -> Click on “Project” from the eclipse main tab -> Click “Build Project”. This will compile your java project, run your unit test cases and do a sonar analysis.

8. Login to your java project dashboard in sonar. This should be now showing all the violations, code coverage and unit test case details for your java project.

Sonar analysis for a non-maven based Java project

Background:

In my previous post, i had explained the steps for installation and configuration of Sonar to analyse a maven based project in eclipse. You can refer the same  here.

With Sonar version greater than 2.6, there has been many refactoring done. One of the major thing was removal of tight coupling of Sonar with maven.  So, what this means is now you can analyse your non-maven based project without much of trouble!

Steps:

  1. Start Sonar server

bin\windows-x86-32\StartSonar.bat  (for 32 bit Windows)

2. Check if Sonar server is running by opening Sonar admin page “http://localhost:9000“. Default credentials – admin/admin.

3. Download “Sonar Java Runner” from here (1.3 zipped version).

4. Unzip the above file and add the “bin” dir to your windows PATH.

5. Create a “sonar-project.properties” file and put this file to the root folder of your java project.

Below is a skeleton of this file. Edit this file as per your project.

# required metadata

sonar.projectKey=sanjit:JavaProject

sonar.projectName=Java Project

sonar.projectVersion=1.0

# path to source directories (required)

sources=D:\\sanjit\\workspace\\test\\JavaProject\\src

# path to test source directories (optional)

#tests=testDir1,testDir2

# path to project binaries (optional), for example directory of Java bytecode

#binaries=binDir

# optional comma-separated list of paths to libraries. Only path to JAR file and path to directory of classes are supported.

#libraries=path/to/library.jar,path/to/classes/dir

# Uncomment those lines if some features of java 5 or java 6 like annotations, enum, ...

# are used in the source code to be analysed

#sonar.java.source=1.5

#sonar.java.target=1.5

# Uncomment this line to analyse a project which is not a java project.

# The value of the property must be the key of the language.

#sonar.language=cobol

# Advanced parameters

#my.property=value

6. Go to the root of your java project and run this command : sonar-runner.bat

Upon successful execution of above command, check in the sonar dashboard. It should now be showing sonar analysis of your project. Below is a snippet of the sonar-runner.bat output for your reference:-

D:\sanjit\workspace\test\JavaProject>sonar-runner.bat

D:\sanjit\app\sonar-runner-1.3\bin\..

Runner configuration file: D:\sanjit\app\sonar-runner-1.3\bin\..\conf\sonar-runner.properties

Project configuration file: D:\sanjit\workspace\test\JavaProject\sonar-project.properties

Runner version: 1.3

Java version: 1.6.0_31, vendor: Sun Microsystems Inc.

OS name: "Windows 7", version: "6.1", arch: "amd64"

Server: http://localhost:9000

Work directory: D:\sanjit\workspace\test\JavaProject\.sonar

17:48:47.493 WARN  .c.p.DefaultDatabase - Derby database should be used for evaluation purpose only

17:48:47.524 INFO      o.s.c.p.Database - Create JDBC datasource

17:48:51.211 INFO  actDatabaseConnector - Initializing Hibernate

17:49:04.913 INFO  .s.b.b.ProjectModule - -------------  Analyzing Java Project

17:49:06.491 INFO  .s.b.ProfileProvider - Selected quality profile : [name=Sonar way,language=java]

17:49:06.521 INFO  nPluginsConfigurator - Configure maven plugins...

17:49:06.650 INFO        org.sonar.INFO - Compare to previous analysis

17:49:06.748 INFO        org.sonar.INFO - Compare over 5 days (2012-05-18)

17:49:06.767 INFO        org.sonar.INFO - Compare over 30 days (2012-04-23)

17:49:06.818 INFO  .b.p.SensorsExecutor - Initializer ProjectFileSystemLogger...

17:49:06.821 INFO  jectFileSystemLogger - Source directories:

17:49:06.822 INFO  jectFileSystemLogger -   D:\sanjit\workspace\test\JavaProject\src

17:49:06.823 INFO  .b.p.SensorsExecutor - Initializer ProjectFileSystemLogger done: 5 ms

17:49:06.866 INFO  p.PhasesTimeProfiler - Sensor JavaSourceImporter...

17:49:07.221 INFO  p.PhasesTimeProfiler - Sensor JavaSourceImporter done: 355 ms

17:49:07.222 INFO  p.PhasesTimeProfiler - Sensor SquidSensor...

17:49:07.354 INFO  .s.p.s.SquidExecutor - Java AST scan...

17:49:07.930 INFO  .s.p.s.SquidExecutor - Java AST scan done: 576 ms

17:49:07.932 INFO  .s.p.s.SquidExecutor - Java Squid scan...

17:49:07.936 INFO  .s.p.s.SquidExecutor - Java Squid scan done: 4 ms

17:49:07.936 INFO  .s.p.s.SquidExecutor - Squid extraction...

17:49:07.967 INFO  .s.p.s.SquidExecutor - Squid extraction done: 31 ms

17:49:07.970 INFO  p.PhasesTimeProfiler - Sensor SquidSensor done: 748 ms

17:49:07.971 INFO  p.PhasesTimeProfiler - Sensor SurefireSensor...

17:49:07.973 INFO  s.p.s.SurefireSensor - parsing D:\sanjit\workspace\test\JavaProject\.sonar\target\surefire-reports

17:49:08.003 INFO  p.PhasesTimeProfiler - Sensor SurefireSensor done: 32 ms

17:49:08.003 INFO  p.PhasesTimeProfiler - Sensor CpdSensor...

17:49:08.004 INFO        org.sonar.INFO - SonarEngine is used

17:49:08.005 INFO  s.p.c.i.IndexFactory - Cross-project analysis disabled

17:49:08.182 INFO  p.PhasesTimeProfiler - Sensor CpdSensor done: 179 ms

17:49:08.183 INFO  p.PhasesTimeProfiler - Sensor CheckstyleSensor...

17:49:08.186 INFO        org.sonar.INFO - Execute Checkstyle 5.5...

17:49:08.227 INFO  ckstyleConfiguration - Checkstyle configuration: D:\sanjit\workspace\test\JavaProject\.sonar\checkstyle.xml

17:49:08.884 INFO        org.sonar.INFO - Execute Checkstyle 5.5 done: 698 ms

17:49:08.891 INFO  p.PhasesTimeProfiler - Sensor CheckstyleSensor done: 708 ms

17:49:08.891 INFO  p.PhasesTimeProfiler - Sensor PmdSensor...

17:49:08.901 INFO        org.sonar.INFO - Execute PMD 4.3...

17:49:08.907 INFO   o.s.p.p.PmdExecutor - Java version: 1.5

17:49:08.950 INFO   o.s.p.p.PmdExecutor - PMD configuration: D:\sanjit\workspace\test\JavaProject\.sonar\pmd.xml

17:49:10.494 INFO        org.sonar.INFO - Execute PMD 4.3 done: 1594 ms

17:49:10.803 INFO  p.PhasesTimeProfiler - Sensor PmdSensor done: 1912 ms

17:49:10.803 INFO  p.PhasesTimeProfiler - Sensor ProfileSensor...

17:49:11.894 INFO  p.PhasesTimeProfiler - Sensor ProfileSensor done: 1091 ms

17:49:11.895 INFO  p.PhasesTimeProfiler - Sensor ProfileEventsSensor...

17:49:12.024 INFO  p.PhasesTimeProfiler - Sensor ProfileEventsSensor done: 129 ms

17:49:12.025 INFO  p.PhasesTimeProfiler - Sensor VersionEventsSensor...

17:49:12.336 INFO  p.PhasesTimeProfiler - Sensor VersionEventsSensor done: 311 ms

17:49:12.338 INFO  p.PhasesTimeProfiler - Sensor CoberturaSensor...

17:49:12.339 INFO  p.PhasesTimeProfiler - Sensor CoberturaSensor done: 1 ms

17:49:12.861 INFO  p.PhasesTimeProfiler - Execute decorators...

17:49:14.875 INFO  .b.p.UpdateStatusJob - ANALYSIS SUCCESSFUL, you can browse http://localhost:9000

17:49:14.882 INFO  b.p.PostJobsExecutor - Executing post-job class org.sonar.plugins.core.batch.IndexProjectPostJob

17:49:16.229 INFO  b.p.PostJobsExecutor - Executing post-job class org.sonar.plugins.dbcleaner.ProjectPurgePostJob

17:49:16.483 INFO  .p.d.p.KeepOneFilter - -> Keep one snapshot per day between 2012-04-25 and 2012-05-23

17:49:16.486 INFO  .p.d.p.KeepOneFilter - -> Keep one snapshot per week between 2011-05-25 and 2012-04-25

17:49:16.489 INFO  .p.d.p.KeepOneFilter - -> Keep one snapshot per month between 2007-05-30 and 2011-05-25

17:49:16.491 INFO  .d.p.DeleteAllFilter - -> Delete data prior to: 2007-05-30

17:49:16.513 INFO  o.s.c.purge.PurgeDao - -> Clean Java Project [id=1]

Total time: 47.133s

Final Memory: 8M/116M

Registering your java application as a windows service

Approach 1: Using “Yet Another Java Service Wrapper (YAJSW)”

Note:- License agreement of YAJSW is based on LGPL.

1.Download YAJSW from here

2. Un-zip the java wrapper. This creates several directories including a bat, conf directory.

3. Start your java application manually in Windows. 

4. Note the Process Id of your java application from the Windows Task Manager.

5. Open command prompt and go to the bat directory under YAJSW installed path. Under it, run the batch file “genConfig.bat <Process Id of your java application>”. This will create “wrapper.conf” configuration file for you under the “conf” directory of YAJSW installed path.

6. Most of the contents in “wrapper.conf” file is automatically set by YAJSW for you during the Step 5 except for few which you can edit manually – “wrapper.ntservice.name”, “wrapper.ntservice.displayname” and “wrapper.ntservice.description”. Provide your service name with which your java application will be registered as windows service. Save your changes.

7. Stop your application which you started in Step 3.

8. Test if your application now starts properly through YAJSW by running the “runConsole.bat” script under the bat dir of YAJSW installed path. If everything is fine, then this script should start your application properly without any exceptions.

9. Incase of no errors/exceptions during Step 8, you can now register your application as windows service by running the script “installService.bat” under bat dir of YAJSW installed path.

10. Check in the windows “services” if your application is successfully added.

11. To start the service, execute the command “startService.bat”. Similarly to stop it, execute the command “stopService.bat”

12. If you want  to de-register your java application as windows service, you can execute the command “uninstallService.bat”

Approach 2: Using “Java Service Wrapper (JSW)”
Note:- License agreement of JSW is based on “GPL/Commercial”.
1. Download JSW from here.
2. Un-zip the java wrapper. This creates several directories including a bin, conf directory.
3. Copy your jar, under the bin dir which got created in Step 1.
4. Edit the wrapper.conf directory under the conf directory which got created in step 1.

  • Provide your main class name as value to “wrapper.java.mainclass”.
  • Create an entry “wrapper.java.classpath.3” below ““wrapper.java.classpath.2″ and assign your jar name to “wrapper.java.classpath.3”.
  • Un-comment “wrapper.app.parameter.1” and assign the complete class name of your main class along with the package name to it.
  • Provide apt values to “wrapper.name”, “wrapper.displayname” and “wrapper.description”.Test if your application now works by running the “TestWrapper.bat” which is available under the bin directory of the java wrapper.

5. Test if your application now works by running the “TestWrapper.bat” which is available under the bin directory of the java wrapper.
6. If everything works fine, then you can now register your java application as windows service by simply running the command “InstallTestWrapper-NT.bat”.
7. Check in the windows “services” if your application is successfully added.
8. To start the service, execute the command “StartTestWrapper-NT.bat”. Similarly to stop it, execute the command “StopTestWrapper-NT.bat”.
9. If you want  to de-register your java application as windows service, you can execute the command “UninstallTestWrapper-NT.bat”

Configuring Sonar In Your Window’s Desktop

1.  Install Sonar Server In Windows

In order to connect sonar maven plugin and/or sonar eclipse plugin to the local sonar server (for example in windows PC), you need to install the sonar server.

Here are the steps :

  • Download and unpack the sonar server zip file from here.
  • Start sonar server:

          bin\windows-x86-32\StartSonar.bat  (for 32 bit Windows)

  • Open Sonar admin page “http://localhost:9000“. Default credentials – admin/admin
  • Either create a new sonar profile by importing all rules files –                                                                                                               (a) Edit configuration given in top right web page: Configuration-> Create . Enter a profile name and select Checkstyle, Findbugs and PMD configuration files.

          (b) Click “Create” and set the new profile as default

  • Or restore the configuration from a backup – Configuration->System->Backup->Restore configuration.

2.  Install Sonar plugin in the Eclipse IDE

  • Help> Install New Software
  • Paste “http://dist.sonar-ide.codehaus.org/eclipse/ into the field named “Work with:” and press Enter.
  • Select: “Sonar Integration for Eclipse..
  • Click Next. Eclipse will then check to see if there are any issues which would prevent a successful installation.
  • Click Finish to begin the installation process. Eclipse will then download and install the necessary components.
  • Once the installation process is finished, Eclipse will ask you if you want to restart the IDE. It’s strongly recommended that you restart IDE.

3.  Eclipse Configuration After Sonar plugin installation

    (a) Server Configuration In Eclipse:-

  • Window > Preferences > Sonar
  • Add
  • Check if Sonar server lists shows a link like  http://localhost:9000. If it doesn’t then add the link as New Sonar Server Connection > Sonar Server URL.
  • Default credentials: admin/admin
  • Click Test Connection . (will get Successfully connected popup)
  • Ok …
  • Finish
  • Apply
  • Ok

   (b) Download “clover.licence” file from here. This is a FREE TRIAL VERSION and it is valid for only 30 days.

   (c) Edit the pom.xml of the maven project to include the below for which you need to run the sonar. Edit proper “licenceLocation” field.


<plugin>

<groupId>com.atlassian.maven.plugins</groupId>

<artifactId>maven-clover2-plugin</artifactId>

<version>2.6.3</version>

<configuration>

<licenseLocation>Give the absolute location of the “clover.license” file</licenseLocation>

</configuration>

<executions>

<execution>

<phase>verify</phase>

<goals>

<goal>instrument</goal>

<goal>check</goal>

</goals>

</execution>

</executions>

</plugin>

4.  Running the Maven project for analysing the code through Sonar.

     (a) Run Sonar on the maven project

          mvn clean install sonar:sonar

     (b) Once the build is succesfull, login to sonar admin page to see the violations. Below is a snippet for the same:

 

5. Configuring Sonar Eclipse

    (a) Link projects to Sonar Eclipse

          This linkage operation can be done by right-clicking on the the project into the “Package explorer”, and then by choosing “Configure ->   Associate with Sonar…”

     

You are now all done with configuration and can start using Sonar Eclipse. Change your eclipse perspective to “Sonar”.

Enabling traces for debugging class loader issues in Websphere Application Server 6.1

Enabling Class loader traces:

 Use the following steps to collect a class loader trace for WebSphere Application server Version 6.1:-

1. Log on to the administrative console.

2. In the left navigational panel, expand Troubleshooting. Click Logs and Trace.

3. Select the application server to be traced, and then on the next page click the Diagnostic Trace link.

4. Select the Configuration tab.

5. Select the Enable Log property.

6. Under Trace Output, select the File radio button, and specify the file name. Also Increase the Maximum file size to 100 MB, and increase the Maximum number of historical files to 10.

7. Select Basic (Compatible) Trace Output Format.

8. Navigate to Logging and Tracing > application_server > Change Log Detail Levels.

9. Under the Configuration tab, specify the trace string suggested.

10.Click Apply and OK. Save your configuration. Select the Synchronize changes with Nodes option if you are using a distributed environment.

 

 

Enabling JVM class loader and bootstrap traces:

To enable the Java Virtual Machine (JVM) class loader and bootstrap traces for Version 6.1, do the following:

1. From the administrative console, select Servers > Application servers, and select the problem server.

2. On the right side, under Server Infrastructure, expand Java and Process Management.

3. Click Process Definition.

4. Under Additional Properties, select Java Virtual Machine.

5. Enable the following Properties by selecting the check boxes located on the left of the property.

– Verbose class loading

– Verbose JNI

6. Click Apply.

7. On right side under Additional Properties, click Custom Properties.

8. Click New.

9. Enter the following custom properties:

– Name: ws.ext.debug

– Value: true

10.Click Apply and OK. Save your configuration. Select the Synchronize

changes with Nodes option if you are using a distributed environment.

 

 

Using the Class Loader Viewer:

 

The Class Loader Viewer in the administrative console can be used to determine how a class is loaded by the class loaders in the WebSphere Application Server.

Enable the Class Loader Viewer service:

If the Class Loader Viewer service is not enabled, the Class Loader Viewer only displays the hierarchy of class loaders and their classpaths, but not the classes actually loaded by each of the class loaders. This also means that the search capability of the Class Loader Viewer is lost.

 To enable the Class Loader Viewer Service, select Servers Application Servers server_name, and then click the Class Loader Viewer Service under the Additional Properties link.

Next, select Enable service at server startup.

Restart the application server for the setting to take effect.

Securing your webservice

Why Web service security if standards like SSL/TLS exists?

  • End-to-end security: Consider an online credit card payment scenario which involves three parties: a cardholder (that’s you), an online merchant, and your bank. Ideally, all parties should be authenticated to one another, and the secure communication path should stretch from the cardholder all the way to the bank. But SSL/TLS is simply not designed for such a scenario; SSL/TLS only handles point-to-point security. Thus, if you rely only on SSL, you cannot send your credit card number to the bank through the merchant without the merchant knowing it. The same goes for Web services, although at a slightly different level. Web service application topologies include all sorts of devices, PCs, proxies, demilitarized zones, gateways, and who knows what else. Consequently, many intermediaries come between two communicating parties. SSL/TLS may secure the path between any two, but not from one end to the other. Something new, therefore, must address this problem.
  • Selective encryption: In an online payment scenario, in practice, many messages travel to and fro among the three parties before the payment itself happens, but conceptually, what happens proves simple: a message travels from the consumer to the merchant to the bank. Such a message may contain two things: information about the goods bought and instructions for the bank to pay the merchant. The bank doesn’t need to know about the former, and the merchant doesn’t need to know about the latter. The message, therefore, must be partitioned in such a way that a merchant cannot see the bank’s part of the message, and vice versa. This is difficult to achieve; it’s impossible with S/MIME or PGP because these standards will encrypt the entire XML document. XML Encryption’s selective encryption feature, in contrast, allows an XML-based solution for such problems.

Web service Security:

  • Authentication: Authentication is used to ensure that parties within a business transaction are really who they claim to be; thus proof of identity is required. This proof can be claimed in various ways. One simple example is by presenting a user ID along with a secret password. A more complex example is one that uses an X.509 certificate issued from a trusted Certificate Authority (such as Verisign). The certificate contains identity credentials and has a pair of private and public keys associated with it. The proof of identity presented by a party includes the certificate itself and a separate piece of information that is digitally signed using the certificate’s private key. By validating the signed information using the public key associated with the party’s certificate, the receiver can authenticate the sender as being the owner of the certificate, thereby validating their identity. When both parties authenticate each other, this is called mutual authentication and is often done between a web service consumer and a web service provider.
  • Data Integrity:  In order to validate the integrity of business information exchanged in a transaction ensuring that a message’s content has not been altered or corrupted during its transmission over the Internet, the data can be digitally signed using security keys. This is the second requirement of the security triad. A common practice is to use the private key of the sender’s X.509 certificate to digitally sign the SOAP body of a web service request. Similarly, SOAP header blocks in a request can also be signed to ensure the integrity of information exchanged in a transaction that is outside the scope of the actual business context (for example, message IDs, security tokens). Likewise, a web services response can be digitally signed to ensure data integrity.
  • Data Confidentiality: Encryption technology can be used to make the information exchanged in web services requests and responses unreadable. The purpose is to ensure that anyone accessing the data in transit, in memory, or after it has been persisted, would need the appropriate algorithms and security keys to decrypt the data before being able to access the actual information.

Web service Security model:

The public key of the Service Provider’s X.509 certificate must be exchanged with the client and configured into the client’s runtime prior to invoking the Service Provider’s services. For both the Consuming Application and the Service Provider, the root certificate of the Certificate Authority (such as Verisign) that issued the parties’ certificates will need to be imported into the local keystores. The Consuming Application’s keystore will have the root certificate of the Service Provider’s certificate. Likewise, the Service Provider’s keystore will require the root certificate of the Consuming Application’s certificate. This is mandatory and allows validation of the digital signatures of the individual certificates that are passed as binary security tokens in the SOAP messages.

A full implementation of all three security requirements would include:

  • The senders of the web services request or response
    • Signing the message with the private key of their X.509 certificate
    • Encrypting the message with the public key of the receiver’s X.509 certificate to ensure that only they can access the message content
  • The receivers of the web services request or response
    • Verifying the signature of the message using the public key of sender to authenticate the sender and to verify integrity of the message
    • Decrypting the message with the private key of their X.509 certificate

Web service Security use case:

1.     Consuming Application processing of web services request

Typically, the Consuming Application will have a Service Proxy or a JAX-RPC stub component that has been generated from an Integrated Development Environment (such as WebSphere Studio Application Developer) using the Service Provider’s WSDL. When a web services invocation is made, the proxy or SOAP runtime on the client system performs the WS-Security functions prior to sending the request.

  • First, the SOAP message is digitally signed. The SOAP runtime may access a keystore to retrieve security keys and certificates as needed. Depending on the WS-Security support your environment provides, you might be able to sign just the SOAP body, or you might be able to sign individual elements within the body.
  • In addition, SOAP header blocks might be signed. The signature is performed using the private key of the Consuming Application’s X.509 certificate. Once the message has been signed, the X.509 certificate itself is included in the SOAP header as a binary security token.
  • The message is encrypted using a symmetric algorithm with a shared key. The key used for the data encryption is encrypted itself using an asymmetric algorithm with the public key associated with the Service Provider’s X.509 certificate. Once the message and shared key have been encrypted, a reference to the X.509 certificate of the Service Provider to whom the request is being sent is included in the SOAP header. This is done because the Service Provider might be using multiple certificates.

2.     Service Provider processing of web services request

When a Service Provider receives a web services request, the request is directed to the SOAP processing engine (SOAP runtime) based on the request’s URL (published access point for the service).

  • The message data and shared key passed in the request are encrypted, so the first step is to identify the X.509 certificate referenced in the SOAP header and retrieve its private key from a keystore. Once the private key is obtained, the shared key can be decrypted using an asymmetric algorithm. With the shared key in the open, the message data can be decrypted using a symmetric algorithm.
  • With the entire message now in the open, the X.509 certificate passed in the SOAP header can be accessed to retrieve its public key. The message’s digital signature is performed with the Consuming Application’s public key. As a result of the the signature’s successful validation, the Service Provider SOAP runtime not only validates the message integrity but also is ensured that the Consuming Application actually signed the message. This process also authenticates the message’s origin/sender because only the sender who owns the certificate has access to the private key used to sign the message. Once the message has been decrypted and the signature validates the SOAP runtime calls the web services implementation.

3.     Service Provider processing of web services response

Once the business logic of the service implementation has executed and a response is available, the same WS-Security operations take place for the web services response message. However, the roles of X.509 key pairs are reversed for digital signature and encryption. The Service Provider’s SOAP runtime digitally signs the message using the private key of its own X.509 certificate. The certificate is included in the SOAP message, and the message is encrypted using a shared key. The key used for the data encryption could be the same key passed in the original request or another randomly generated key, the latter being more typical. The encryption of the shared key is performed using the public key of the certificate that was passed in the request; thus only the sender of the request who has access to the certificate’s private key is the only party that can decrypt the message. Once the message has been signed and encrypted, the Service Provider’s SOAP runtime sends the response to the Consuming Application.

4.     Consuming Application processing of web services response

The Consuming Application’s WS-Security processing of the web services response is very similar to what the Service provider for the request performed.

The Consuming Application receives a web services response with the response directed to the SOAP processing engine (SOAP runtime) based on the original HTTP session. The message data and shared key passed in the response are encrypted. Therefore, the initial step is to retrieve the private key of the certificate associated with the corresponding request to decrypt the shared key using an asymmetric algorithm. With the shared key in the open, the message data can be decrypted using a symmetric algorithm. After the entire message is in the open, the X.509 certificate passed in the SOAP header can be accessed to retrieve its public key. The response message’s digital signature is performed with the Service Provider’s public key. Following the signature’s successful validation, the Consuming Application’s SOAP runtime not only validates the message integrity, but also is ensured that the Service Provider actually signed the message. This process also authenticates the message’s origin/sender because only the sender who owns the certificate has access to the private key used to sign the message. Once the message has been decrypted and the signature validated, the SOAP runtime forwards the response to the Consuming Application.

Cafe Babe ;)

 

Not sure if anyone of you has tried opening a java .class file using some hex editor. If you haven’t yet, try it once!

 

The first thing that you will notice on doing so, is it’s very first 4 byte header “CAFE BABE” 😉

Every java class files are identified by 4 byte header (in hex) CA FE BA BE (first 4 entries). This signature is just an easy way of verifying that a block of data really does claim to be an instance of the Java class format. Every Java binary class, even one that isn’t present on the file system, needs to start with these four bytes.

 

 

The history of this magic number was explained by James Gosling:-

 

“We used to go to lunch at a place called St Michael’s Alley. According to local legend, in the deep dark past, the Grateful Dead used to perform there before they made it big. It was a pretty funky place that was definitely a Grateful Dead Kinda Place. When Jerry died, they even put up a little Buddhist-esque shrine. When we used to go there, we referred to the place as Cafe Dead. Somewhere along the line it was noticed that this was a HEX number. I was re-vamping some file format code and needed a couple of magic numbers: one for the persistent object file, and one for classes. I used CAFEDEAD for the object file format, and in grepping for 4 character hex words that fit after “CAFE” (it seemed to be a good theme) I hit on BABE and decided to use it. At that time, it didn’t seem terribly important or destined to go anywhere but the trash-can of history. So CAFEBABE became the class file format, and CAFEDEAD was the persistent object format. But the persistent object facility went away, and along with it went the use of CAFEDEAD – it was eventually replaced by RMI.”


Overcoming Runtime.exec havoc with JNA

Issue: 

Think of a situation where your java application wants to change the owner & permission of a unix file programmatically. With JRE1.5, the obvious way to achieve this could be the usage of Runtime.exec.  With Unix as runtime, this invokes fork() which makes a complete copy of entire parent process’s address space and exec() then turns that copy to a new process. The disadvantage of this approach is that you will end up with Out Of Memory issues without a good reason.

Solution:

Use Java Native Access to invoke native C POSSIX library!

JNA allows you to call directly into native functions using natural Java method invocation. The Java call looks just like it does in native code. The JNA library uses a small native library stub to dynamically invoke native code. The developer uses a Java interface to describe functions and structures in the target native library. This makes it quite easy to take advantage of native platform features without incurring the high overhead of configuring and building JNI code for multiple platforms.

Below is a java code snippet which changes owner and permission of a unix file without using Runtime.exec. You need to place jna.jar and platform.jar in your classpath for compiling and running this application :-


import com.sun.jna.Library;
import com.sun.jna.Native;

public class FilePermOwnerChange {
public interface POSIX extends Library {
public int chmod(String filename, int mode);
public int chown(String filename, int userId, int groupId);
}

  public static void main(String[] args) {
       POSIX posix = (POSIX) Native.loadLibrary("c", POSIX.class);
       posix.chmod("/tmp/BufCre.txt", 0664); //0664 is just an example
       posix.chown("/tmp/BufCre.txt", 1000, 1000); // 1000 is just an example. Give the UID and GID respectively for the new owner of this file.
  }
}

Making JVM to ignore serialVersionUIDs mismatch

Issue:

If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class which is highly sensitive to the class details and may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. So,  if an older version of a serializable class doesn’t explicitly mention a serialVersionUID then deserialization of that object may fail even though the actual class definition matches.  In such a scenario we just want JVM to ignore differences in these serialVersionUIDs and not throw any exception in case they mismatch!

Solution:

Extend from ObjectInputStream class and override readClassDescriptor() to add logic which compares serialVersionUID of the class in local JVM and serialVersionUID of the stream descriptor and if they vary, then assign localClassDescriptor to the stream descriptor. Then wherever we are creating objects of ObjectInputStream, we use CustomInputStream instead and it deserializes the old object with new serialVersionUID.

import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CustomInputStream extends ObjectInputStream {

    private static Logger logger = LoggerFactory.getLogger(CustomInputStream.class);

    public CustomInputStream(InputStream in) throws IOException {
        super(in);
    }

    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
        ObjectStreamClass resultClassDescriptor = super.readClassDescriptor(); // initially streams descriptor
        Class localClass; // the class in the local JVM that this descriptor represents.
        try {
            localClass = Class.forName(resultClassDescriptor.getName());
        } catch (ClassNotFoundException e) {
            logger.error("No local class for " + resultClassDescriptor.getName(), e);
            return resultClassDescriptor;
        }
        ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass);
        if (localClassDescriptor != null) { // only if class implements serializable
            final long localSUID = localClassDescriptor.getSerialVersionUID();
            final long streamSUID = resultClassDescriptor.getSerialVersionUID();
            if (streamSUID != localSUID) { // check for serialVersionUID mismatch.
                final StringBuffer s = new StringBuffer("Overriding serialized class version mismatch: ");
                s.append("local serialVersionUID = ").append(localSUID);
                s.append(" stream serialVersionUID = ").append(streamSUID);
                Exception e = new InvalidClassException(s.toString());
                logger.error("Potentially Fatal Deserialization Operation.", e);
                resultClassDescriptor = localClassDescriptor; // Use local class descriptor for deserialization
            }
        }
        return resultClassDescriptor;
    }
}