Behavioral Design Pattern – The Visitor Pattern

Visitor Pattern is one of the behavioral design pattern which is used when we have to manage algorithms, relationships & responsibilities on a group of similar kind of objects at runtime, thus decoupling the operations from the object’s structure. So, Visitor pattern can provide additional functionality to a class without actually changing it.

The pattern should be used when you have distinct & unrelated operations to perform across a structure of objects. This avoids adding in code throughout your object structure that is better kept separate, so it encourages cleaner code. In summary, if you want to decouple some logical code from the elements that you’re using as input, visitor is probably the best pattern for the job.

On the downside, the arguments & return types for the visiting methods needs to be known in advance, so the Visitor pattern is not good for situations where these visited classes are subject to change. Every time a new type of Element is added, every Visitor derived class must be amended.

Also, it can be difficult to refactor the Visitor pattern into code that wasn’t already designed with the pattern in mind. And, when you do add your Visitor code, it can look obscure. The Visitor is powerful, but you should make sure to use it only when necessary.

Let’s try to illustrate the pattern with an example. Below is the class diagram for ease of reference –

classdiagram_1

First, let’s create our general visitable  interface:


package com.sanjit;

public interface ShoppingItem {
      public void accept(Visitor visitor);
}

  

Now, we’ll create a concrete implementation of our interface, Games :


package com.sanjit;

public class Games implements ShoppingItem {

      private double price;
      private int qty;

      public double getPrice() {
            return price;
      }

      public void setPrice(double price) {
            this.price = price;
      }

      public int getQty() {
            return qty;
      }

      public void setQty(int qty) {
            this.qty = qty;
      }

      @Override
      public void accept(Visitor visitor) {
            visitor.visit(this);
      }
}

  

and now for the Music:


package com.sanjit;

public class Music implements ShoppingItem {

      private double price;
      private int qty;

      public double getPrice() {
            return price;
      }

      public void setPrice(double price) {
            this.price = price;
      }

      public int getQty() {
            return qty;
      }

      public void setQty(int qty) {
            this.qty = qty;
      }

      @Override
      public void accept(Visitor visitor) {
            visitor.visit(this);
      }
}

As you can see it’s just a simple POJO, with the extra accept method added to allow the visitor access to the element. We could add in other types here to handle other items.

Now we’ll move on to the Visitor interface. For each different type of concrete element here, we’ll need to add a visit method. As we’ll just deal with Games & Music for now, this is as simple as:


package com.sanjit;

public interface Visitor {
      void visit(Games items);
      void visit(Music items);
}

The implementation of the Visitor can then deal with the specifics of what to do when we visit a Game or Music.


package com.sanjit;

public class CartVisitor implements Visitor {

      private double cartCost;

      public double getCartCost() {
            return cartCost;
      }

      public void setCartCost(double cartCost) {
            this.cartCost = cartCost;
      }

      @Override
      public void visit(Music items) {
         cartCost += items.getQty() * items.getPrice();
      }

      @Override
      public void visit(Games items) {
            cartCost += items.getQty() * items.getPrice();
      }
}

As you can see it’s a simple formula, but the point is that all the calculation for cart is done in one central place.

To drive this visitor, we’ll need a way of iterating through our shopping cart, as follows:


package com.sanjit;

import java.util.List;

public class Cart {

      private List<ShoppingItem> items;

      public List<ShoppingItem> getItems() {
            return items;
      }

      public void setItems(List<ShoppingItem> items) {
            this.items = items;
      }

      public void calculateCartPrice() {

            CartVisitor cartVisitor = new CartVisitor();

            for(ShoppingItem item:items){
                  item.accept(cartVisitor);
            }

            System.out.println("Total Cart Cost: " + cartVisitor.getCartCost());
      }
}

Note that if we had other types of item here, once the visitor implements a method to visit that item, we could easily calculate the total cart cost.

The whole point of this pattern is to allow you separate out certain logic from the elements themselves, keeping your data classes simple.

Now the main class for test purpose:-


package com.sanjit;

import java.util.ArrayList;

import java.util.List;

public class Main {

          public static void main(String[] args) {

            Music m = new Music();
            m.setPrice(50);
            m.setQty(10);

            Games g = new Games();
            g.setPrice(100);
            g.setQty(100);

            List<ShoppingItem> items = new ArrayList<ShoppingItem>();
            items.add(m);
            items.add(g);

            Cart cart = new Cart();
            cart.setItems(items);
            cart.calculateCartPrice();
      }

}

Output on running the Main class:

Total Cart Cost: 10500.0

Creating signed rpm in Linux

Recently someone came up to me with this query – How to generate a signed rpm in linux?

After building your RPM package, it’s a good idea to sign the package with your own GPG Key to make sure the package is authentic.  Well, before you could sign an rpm package at build time, you must create a gpg key and a passphrase
Below are steps for the same –
  1. Generate a signature key – 
———–clip———
[xxx@yyy]$ gpg –gen-key
gpg (GnuPG) 1.4.5; Copyright (C) 2006 Free Software Foundation, Inc.
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions. See the file COPYING for details.
Please select what kind of key you want:
   (1) DSA and Elgamal (default)
   (2) DSA (sign only)
   (5) RSA (sign only)
Your selection? 1
DSA keypair will have 1024 bits.
ELG-E keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 2048
Requested keysize is 2048 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    “Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>”
Real name: john
Email address: john@testmail.com
Comment: No Comments
You selected this USER-ID:
    “john(No Comments) <john@testmail.com>”
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
You need a Passphrase to protect your secret key.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
++++++++++++++++++++.++++++++++++++++++++++++++++++…++++++++++.++++++++++++++++++++++++++++++.+++++++++++++++.++++++++++++++++++++++++++++++………………………………………………………>.+++++…………………………………………………………….+++++
Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy! (Need 283 more bytes)
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
++++++++++++++++++++++++++++++++++++++++++++++++++.+++++++++++++++.+++++++++++++++++++++++++++++++++++….++++++++++.+++++.+++++++++++++++++++++++++..+++++>+++++..+++++>..+++++…….>+++++………………………………………………………………………………………….+++++^^^
gpg: key DB17E9EE marked as ultimately trusted
public and secret key created and signed.
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
pub   1024D/DB17E9EE 2012-07-19
      Key fingerprint = 22E1 4A80 9899 0A27 4BD8  3200 37C4 857A DB17 E9EE
uid                  john(No Comments) <john@testmail.com>
sub   2048g/E7FFDEEF 2012-07-19
———–clap———
2.  Confirm that the above created signatures are present in the signature repository –
———–clip———-
[xxx@yyy]$ gpg –list-sigs
/home/xxx/.gnupg/pubring.gpg
———————————
pub   1024D/DB17E9EE 2012-07-19
uid                  xxx(No Comments) <john@testmail.com>
sig 3        DB17E9EE 2012-07-19  john(No Comments) <john@testmail.com>
sub   2048g/E7FFDEEF 2012-07-19
sig          DB17E9EE 2012-07-19  john(No Comments) <john@testmail.com>
———–clap———-
3. Create a file “.rpmmacros” in your home directory and add the below lines to the same ( I’ve given “john” to “%_gpg_name” as this is the real name of the signature owner that i have provided in Step 1) –
——-clip——-
%_signature gpg
%_gpg_name john
%_gpgbin /usr/bin/gpg
——-clap——-
4. Now, you’re all  ready to sign your RPM package –
——-clip——-
[xxx@yyy]$ rpm –addsign XXX-YYY-ZZZ-2.0-5.WW.i386.rpm                               // rpm name is just an example
Enter pass phrase:                   // Here provide the pass phrase as "test" because this is what I have provided 
                                     // for the signature owner "John" in Step 1
Pass phrase is good.
XXX-YYY-ZZZ-2.0-5.WW.i386.rpm:
——-clap——-
You can verify your signature on the RPM  using the command:

rpm –checksig XXX-YYY-ZZZ-2.0-5.WW.i386.rpm     // rpm name is just an example

WebSphere AppServer 6.1 MQ JMS log enabling

Static trace enabling:

1. Log on to the Administrative Console.
2. In the left panel, expand Troubleshooting. Click on “Logs and Trace”.
3. Select the application server that is to be traced. Then on the next page click on the “Diagnostic Trace” link.
4. Select the Configuration tab.
5. Select the “Enable Log” property, if already not selected.
6. Under the “Trace Output”, select the File radio button, if already not selected. Set the Maximum file size to 100 MB and Increase the Maximum number of historical files to 10.
7. To ensure you capture full data flows, select Advanced for the Trace Output Format.
8. Click on the “Change Log Detail Levels” under Additional Properties on the right side panel.
9. Under the Configuration tab, enter the following string :

*=info:JMSServer=all:Messaging=all:JMS_WASTraceAdapter=all:com.ibm.mq.*=all:jmsApi=all

10. To gather transaction and connection API trace, append the following string :

For Connection: ConnLeakLogic=all:WAS.j2c=all
For Transaction: Transaction=all

11. Click OK and Save. your configuration.  Select Synchronize changes with Nodes option.Then restart the Application server.

Dynamic trace enabling:

1. Log on to the administrative console.
2. In the left panel, expand Troubleshooting and click on Logs and Trace.
3. Select the application server to be traced, and than on the next page click the Diagnostic Trace link.
4. Select the Runtime tab (Server should be up and running for this tab to show up).
5. Under Trace Output, select File and type a File name (if you do not specify path, but just the file name, then the default location of the file is under the application server profile directory). Set the Maximum File size to 100Mb and Maximum Number of historical files to 10.
Important: Do not select Save Runtime Changes to Configuration as well if you do not want this setting to become permanent.
6. On same panel click on Change Log Detail Levels under Additional Properties on right side panel.
7. Select the Runtime tab.
8. Enter the following trace string :

*=info:JMSApi=all:JMSServer=all:Messaging=all:JMS_WASTraceAdapter=all:com.ibm.mq.*=all:jmsApi=all

9. To gather transaction and connection API trace, append the following string:

For Connection: ConnLeakLogic=all:WAS.j2c=all
For Transaction: Transaction=all

10. Click Apply and OK. Then Save your configuration.  Select Synchronize changes with Nodes option.

Using the rollup feature of Selenium

Recently someone had put forward a doubt on the usage of rollup feature in Selenium.

Rollup, in Selenium,  is a series of commands with a unique name, and optionally arguments that control the generation of the set of commands. If any one of the rolled-up commands fails, the rollup is considered to have failed. Rollups may also contain nested rollups.

Consider, I want to do below operations in a web browser –

     (a) Login to “http://www.mail.com” URL.
     (b) Type Email
     (c) Type Password
     (d) Click on “Log in”

Logically if you see, all the above 4 different activities are serving  to a single use-case – “do_login”.

Any activity (reading mail, deleting mail, sending mail etc) will need you to first login to your mailbox. So, instead of duplicating the code for “login”  across all your testcases (e.g. reading mail testcase, sending mail testcase, delete mail testcase), you can write only once the testcase code for login and then wrap-up this testcase with a name and call this code with it’s wrapped-up name across all your testcases which needs login to the mailbox as a pre-requisite. This is where the “rollup” feature of Selenium comes into picture.

Have a look at the user-extensions.js (below). You can think of this file as a re-usable library wherein I’ve defined the actual action steps i.e. logging in, typing username, typing password and signing in. I’ve then wrapped up all these actions under “do_login” rollup rule.
I haven’t hardcoded the username and password here as I wanted to read these from the testcase.
var manager = new RollupManager();

manager.addRollupRule({
 name: 'do_login'
 , description: 'log in to mail.com'
 , args: [
 {
 name: 'username'
 , description: 'username'
 }
 , {
 name: 'password'
 , description: 'password'
 }
 ], commandMatchers: [
 ]
 , getExpandedCommands: function(args) {
 var commands = [];

commands.push({
 command: 'open'
 , target: ''
 });
 commands.push({
 command: 'type'
 , target: 'login'
 , value: args.username
 });
 commands.push({
 command: 'type'
 , target: 'password'
 , value: args.password
 });
 commands.push({
 command: 'click'
 , target: 'btnLogin'
 });
 return commands;
 }
});
Now have a look at my actual testcase “rollupExample.html” (below). If you notice, here I’m just calling the rollup rule i.e. “do_login”. Along with it I’m passing the required username and password (sanjit/sanjit). Just a single line of code in my testcase and it takes care of all the login functionality!!!
Now, all you need to do is to make the Selenium core aware of your new user-extensions javascript file and then import the testcase to your selenium IDE and run. Thats all!

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”