Thursday, 3 May 2018

Shell Scripting Examples

Generate comma separated dates for last seven days:

# Fetch the date 7 days ago
DATE=$(date -d '7 day ago' '+%Y-%m-%d');

# Generate comma-separated string for last 7 days
for i in {6..1}; do DATE=$DATE","$(date -d "$i day ago" '+%Y-%m-%d'); done

Considering current date is 2016-04-08, DATE variable value will be as follows:

2016-04-01,2016-04-02,2016-04-03,2016-04-04,2016-04-05,2016-04-06,2016-04-07

We can use different date formats on a case to case basis. This thing comes in handy when we have to feed a date range to some reporting tool.

Generate comma separated dates for last month and from today to start of the day:





Sunday, 7 January 2018

Java - SQL Parsing

Recently I had a use case where I have to validate a SQL query. Basically I had to look at the JOINS and WHERE clauses in the query.

I thought that why to parse a SQL on my own and extract table names and where clauses from the query. Why to reinvent the wheel and write your own logic when you can re-use existing open source libraries. Keeping that in mind I started searching for a simple open source library to serve the purpose.

Surprisingly I found only a few and those were not serving the purpose then I found Apache-Calcite(https://calcite.apache.org/). Apache-Calcite is a huge project and SQL parsing is just one part of it.

I didn't find a good example though using its SQL parser and had to dig in a bit to get a working example. Following is a working example:

So this is just about extracting table names and where clauses. This SQL parser can do definitely more and can be used to extract other parts of the query as well. Of course you can dig in the java docs and API to cater your requirements. Happy Learning !!!

Sunday, 30 July 2017

Unit testing your POJO classes in Java.

Ever bothered about testing your pojo classes in java. Probably NO. We tend to ignore these pojo classes saying why should I test lame methods i.e. setter, getters, toString etc.

However these pojo classes adds to your test coverage report and if you don't have tests written for these classes you'll end up with a reduced test coverage stats for your java project.

What about delegating the testing responsibility to a framework or library which will ensure the quality of your pojo classes. Cool Huh !!!

I have got such a situation in my project and found this cool library POJO-TESTER to serve the purpose.

What about giving it a quick look around? Happy Testing !!!!




Saturday, 3 December 2016

Push messages to browser/clients with NodeJS WebSocket

Hi Folks, off late I have been trying to do a POC on pushing messages from server to all the connected clients and found that websocket can be used for it in conjunction with NodeJS. So I am putting it all over to this post.

Following are the prerequisites in order to run the setup:
  1. NodeJS Installation (We need npm to install packages) Download Link
  2. NPM Packages (websocket, http-server, finalhandler, serve-static).
NPM package installation commands:
  • npm install websocket
  • npm install http-server
  • npm install finalhandler
  • npm install serve-static
After successful installation of NodeJS and above mentioned npm packages we can start off writing the code. We need following three files hosted on a folder (All the npm package installation commands will be executed on this folder).
  1. frontend.html.
  2. frontend.js (NodeJS Frontend).
  3. backend.js (NodeJS Backend).
Following is the source code of above files:

frontend.html

frontend.js

backend.js


Following is the directory structure of project:

Sunday, 18 September 2016

Limit typing numbers in input type 'number' HTML

Recently I have started front-end development using AngularJS where I had the following requirement:
  1. Open a modal window.
  2. Paint form on the modal.
  3. Form will have a text field of type "number" with following criteria:
    1. User can put only positive numbers in the text field nothing else.
    2. User can put numbers only from 0-999.
At first above requirement seems to be very easy to implement with min and max properties of input type "number". However there is a catch that min and max restricts only the spinner (increase and decrease) but user can still type numbers which does not belong to 0-999 (Even characters).

To address first criteria we can use onkeypress event and pass it a function which will listen to 0-9 number key presses only and discard the rest:

onkeypress="return (event.charCode == 8 || event.charCode == 0) ? null : event.charCode >= 48 && event.charCode <= 57"

To address second criteria we can use oninput event and pass it a function which will clip/remove the characters after 3rd position:

oninput="this.value.length > 3 ? this.value= this.value.slice(0,3) : this.value"

Note: I have seen suggestions of an alternate approach to accomplish the above using onkeydown event however I have found that if we use onkeydown event it screws up the spinner and also allows text to be pasted and dragged having length more than 3 characters whereas oninput handles all these cases.

Following is the complete input tag:
<input type="number"
       name="sampleTextbox"
       min="0"
       max="999"
       oninput="this.value.length > 3 ? this.value= this.value.slice(0,3) : this.value"
       onkeypress="return (event.charCode == 8 || event.charCode == 0) ? null : event.charCode >= 48 && event.charCode <= 57"/>

Monday, 30 May 2016

Frequency of occurrence of Strings/Words in a list.

I had a problem where I have to keep a track of the frequency of occurrence of a given string in a record (row). I was thinking of doing this using a Map (Probably the best candidate here) where the key is the string and value is the frequency of occurrence.

But there was a catch here, what should we do on the first occurrence of the string as it won't be present in the Map. Below is the solution I came up with:

import java.util.HashMap;

public class MyHashMap {
       private HashMap<String, Integer> myHashMap;

       public MyHashMap(final HashMap<String, Integer> myHashMap) {
           this.myHashMap = myHashMap;
       }

       public void put(String key) {
           Integer integer = myHashMap.get(key);

           if (integer == null) {
                myHashMap.put(key, new Integer(1));
           } else {
                myHashMap.put(key, ++integer);
          }
        }

        @Override
        public String toString() {
            return "MyHashMap [myHashMap=" + myHashMap + "]";
         }

        public static void main(String[] args) {
             MyHashMap m = new MyHashMap(new HashMap<>());

             m.put("Steve");
             m.put("Steve");
             m.put("Simon");

             System.out.println(m);
       }
}

Output:

        MyHashMap [myHashMap={Simon=1, Steve=2}]

Above implementation works fine however you can see we had to do first occurrence handling in put method from our side which I wanted to avoid so I was looking at some other solution. No problem Java 8 Stream API is here and does this thing very smoothly in one liner.

Following is the Java 8 code snippet :

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamsDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();

list.add("Steve");
list.add("Steve");
list.add("Frank");
list.add("Tom");
list.add("Steve");

Stream<String> stream = list.stream();

Map<String, Long> collect = stream.collect(Collectors.groupingBy(e -> e, Collectors.counting()));

System.out.println(collect);
}
}

Output:

{Frank=1, Tom=1, Steve=3}

Above implementation which uses Java 8 Stream API does the trick as if we are executing a aggregate function COUNT(*) with GROUP BY. Cool !!

Sunday, 1 May 2016

Create executable jar with Maven

If you are using Maven and wants to create an executable jar file but not getting an exact solution (Google is providing too many results and nothing is straightforward :-)). So let me get this straight and there is a plugin for it which is maven-assembly-plugin.

Below is the pom.xml which makes use of maven-assembly-plugin to generate executable jar:


<?xml version="1.0" encoding="UTF-8"?>
<project
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
       http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>test-project</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <targetJdk>1.7</targetJdk>
        <project.build.sourceEncoding>UTF-8
                          </project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8
                          </project.reporting.outputEncoding>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>com.test.App</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies
                                                </descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-jar-with-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            ......
            ......
        </dependency>
    </dependencies>
</project>

Now run "Maven install" and following executable jar file will be created : test-project-0.0.1-SNAPSHOT-jar-with-dependencies.jar

Monitoring java process running under jetty using JConsole

I came across a situation recently where an application running under jetty were having some performance issues which eventually resulted in high latency. After spending quite sometime troubleshooting the problem with no conclusion we had to profile the application to see how many threads are running, how much heap is getting used etc.

To profile the application we had chosen JConsole. Now at first it seemed to be a straightforward setup (After all its just a connection to a given host and port) however it took us a while. Hence sharing the steps here which should be followed to have a hassle free setup.

Step 1:

Add following parameters inside start.ini file found in jetty distribution directory/folder:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.port=1099 # 1099 is default JMX Port.
-Djava.rmi.server.hostname=Your_Machine_IP


Step 2:

Make below changes inside (Adding a connector for remote JMX connection) etc/jetty-jmx.xml as per https://wiki.eclipse.org/Jetty/Tutorial/JMX:

<new class="org.eclipse.jetty.jmx.ConnectorServer" id="ConnectorServer">
<arg>
<new class="javax.management.remote.JMXServiceURL">
<arg type="java.lang.String">rmi</arg>
<arg type="java.lang.String">
<arg type="java.lang.Integer"><systemproperty default="1099" name="jetty.jmxrmiport"></systemproperty></arg>
<arg type="java.lang.String">/jndi/rmi://<systemproperty default="localhost" name="jetty.jmxrmihost">:<systemproperty default="1099" name="jetty.jmxrmiport">/jmxrmi</systemproperty></systemproperty></arg>
</arg></new>
</arg>
<arg>org.eclipse.jetty.jmx:name=rmiconnectorserver</arg>
<call name="start">
</call></new>


Note: Above xml configuration is already present inside etc/jetty-jmx.xml file but its commented by default. So just uncomment the xml tag.

Now we are all done. Open the JConsole application and connect to the application using below URL:

service:jmx:rmi:///jndi/rmi://Your_Machine_IP:1099/jmxrmi

Now we should be able to see the real-time application activity in terms of JConsole graphs.

Saturday, 2 January 2016

UI for Zookeeper - zk-web

I have been using Zookeeper for the configuration management of my application. There are usually various configurations stored in zookeeper and sometimes it happens that we have to check the configuration values. Using zk-cli command line utility we can accomplish this however zk-cli is a command line tool and you need to learn commands in order get the information out of it.

So I was looking for a GUI Tool which would be simple and cleaner and luckily I found one known as zk-web (https://github.com/qiuxiafei/zk-web).

All the installation instruction can be found here (https://github.com/qiuxiafei/zk-web), However while installing it I faced some issues and thought it would be worth sharing all the steps to have a hassle free installation.

Prerequisites:
  • Java ( > Java 6 update 40 )
  • Git
  • Lien

Installing git:

sudo yum install git (My machine was amazon ec2 Linux)
sudo apt-get install git (If the machine is having ubuntu Linux)

NOTE: Make sure you are running on java version higher than java 6 update 40 If not upgrade the java version.

Cloning git repository for zk-web:

git clone git://github.com/qiuxiafei/zk-web.git

Configuration File:

cd zk-web/conf/

[ec2-user@ip-xx-xxx-x-xxx conf]$ cat zk-web-conf.clj
{
:server-port 8080
:users {"admin" "hello"}
:default-node ""
}

Installing lein:

wget https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein
wget --no-check-certificate https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein

Move lein to ~/bin so that it will be available on PATH.

Grant execute permissions to lein:
cd ~/bin/
chmod 755 lein

To start zk-web run the below commands:
lein deps
lein run

Now the zk-web should be available at Your_IP:8080 URL.

Most of the time we want zk-web to run as a background process so that we can use it without the need to start it. In this scenario there is an option to generate a jar file using lein:

[ec2-user@ip-xx-xxx-x-xxx zk-web]$ cat project.clj
(defproject zk-web "0.1.0-SNAPSHOT"
     :description "FIXME: write this!"
     :dependencies [[org.clojure/clojure "1.4.0"]
       [noir "1.3.0-beta3"]
       [com.netflix.curator/curator-framework "1.1.16"]
       [com.netflix.curator/curator-test "1.1.16"]]
     :main zk-web.server)

Now using lein we have to build this clj(closure) file.
lein uberjar

This will build 2 jar files:
zk-web-0.1.0-SNAPSHOT.jar
zk-web-0.1.0-SNAPSHOT-standalone.jar

We have to use the second one which is a standalone jar. Below is command we can use to run this jar in background:
nohup java -jar target/zk-web-0.1.0-SNAPSHOT-standalone.jar &

As an alternative, we can put this command to /etc/rc.local file to start zk-web on machine reboot.

Monday, 7 December 2015

Writable redis slave

While working with redis, you may have a master redis running on a central server and all of your web application servers are running redis slaves. There may be some instances where you want to make these slaves writable for some testing purposes. Here is how we can accomplish this:

1. Load the data from master redis:
nohup /usr/bin/redis-server --port "slave port" --slaveof "Master Redis Machine IP" "Master Redis Port" > redis.out &

nohup /usr/bin/redis-server --port 7000 --slaveof 137.53.57.37 7000 > redis.out &

2. Kill the above redis process using kill command once the data is loaded.

3. Disconnect slave from master redis:
nohup /usr/bin/redis-server --port "slave port" --slaveof none "Master Redis Port" > redis.out &

nohup /usr/bin/redis-server --port 7000 --slaveof none 7000 > redis.out &

Now your slave is disconnected from master and you can write on it.

Monday, 16 November 2015

Grep/Search specific line number in linux/unix.

Today I had a situation where I had to search/grep for a specific line number in a file in linux. Here is the solution I found and thought it is worth sharing:

Uncompressed File:
cat test_file.csv | head -line_number | tail -1
cat test_file.csv | head -337930 | tail -1

Compressed File:
zcat test_file.gz | head -line_number | tail -1
zcat test_file.gz | head -337930 | tail -1

Above examples grep/search for line number 337930.

Tuesday, 3 November 2015

Webpage redirection

What happens if your visitors try to access a page that was recently renamed, deleted, or moved? By default they will get an error message, but you can change that. Instead of your visitors stumbling upon an error when trying to access such a page, you can set a redirection rule that will redirect them to a new page.

This page is about individual page redirection. For information on domain redirection check out our domain redirection tutorial.

NOTE: Redirection is very good for search engines. Search engines need to know when one of your files has changed locations to re-index your site properly.

301 and 302 redirects

There are two types of redirects - 301 and 302. These are actually HTTP status codes which specify the status of communication between the web browser and the web server.

The code samples below should be placed in the file you're redirecting from unless otherwise specified.

302 redirects

302 redirects are used when a page's location has been changed temporarily.

HTML

HTML 302 redirects work through the <meta> tag:

<meta http-equiv="refresh" content="10; url=http://www.site.com/newpage.html" />

In the content attribute, the number is the amount of seconds before redirecting to the new page specified by url.

Javascript

Javascript 302 redirects work through the window.location property:

<script type="text/javascript">
window.location="http://www.yahoo.com";
</script>

Set the window.location property equal to the URL you want to redirect to. Include this Javascript code in the head section of an HTML document. The redirect should occur right away.

PHP

PHP 302 redirects work through the header function:

<?php header("Location: http://www.site.com/newpage.html"); ?>

Inside the header() function, put Location: followed by the URL to redirect to.

.htaccess

Put this in your .htaccess file:

redirect 302 /oldfile.html http://www.yoursite.com/newfile.html

/oldfile.html is the location of the file you're redirecting from and http://www.yoursite.com/newfile.html is the location of the file you're redirecting to.

301 redirects

301 redirects are used when a page's location has been changed permanently.

PHP

PHP redirects are 302 redirects by default, but by putting the HTTP/1.1 301 code at the top, we create a PHP 301 redirect:

<?php
header("HTTP/1.1 301 Moved Permanently");
header("Location: http://www.site.com/newpage.html");
?>


NOTE: When you use a PHP redirect make sure that the redirect code is the only thing on the page that you are redirecting from.

.htaccess

Put this in your .htaccess file:

redirect 301 /oldfile.html http://www.yoursite.com/newfile.html

/oldfile.html is the location of the file you're redirecting from and http://www.yoursite.com/newfile.html is the location of the file you're redirecting to.

Saturday, 17 October 2015

Imitating domain names in linux.

Sometimes we may have to simulate different domains in our local machine. For example If you want to use domain "awesome.com" in place of localhost you can do the following:

You must be having below entry in your /etc/hosts file:

  127.0.0.1 localhost

Change this entry as given below:

  127.0.0.1 awesome.com

And you are done. Hit "awesome.com" from your browser and the request will come to your localhost. Similarly you can do multiple entries in /etc/hosts to simulate multiple domains.

Thursday, 17 September 2015

isNumeric in Java.

Once in while in java we might have to check If a passed string to method is a valid numerical value. Below are some utility methods to accomplish this:

    Using java.text.NumberFormat.


    public static boolean isNumeric(final String str) {
        try {
            Double.parseDouble(str);
        } catch (final NumberFormatException | NullPointerException e) {
            return false;
        }

        return true;
    }

    JUnit Test Case:


        Assert.assertEquals(false, yourClass.isNumeric(null));
        Assert.assertEquals(false, yourClass.isNumeric(""));
        Assert.assertEquals(true, yourClass.isNumeric("2.74"));
        Assert.assertEquals(true, yourClass.isNumeric("2.745435E3"));
        Assert.assertEquals(true, yourClass.isNumeric("0"));
        Assert.assertEquals(true, yourClass.isNumeric("0.0f"));
        Assert.assertEquals(false, yourClass.isNumeric("NaN"));       


    Using Double.parseDouble.


     public static boolean isNumeric(final String string) {
        try {
            NumberFormat.getInstance().parse(string);
        } catch (ParseException | NullPointerException e) {
            return false;
        }

        return true;
    }

    JUnit Test Case:


        Assert.assertEquals(false, yourClass.isNumeric(null));
        Assert.assertEquals(false, yourClass.isNumeric(""));
        Assert.assertEquals(true, yourClass.isNumeric("2.74"));
        Assert.assertEquals(true, yourClass.isNumeric("2.745435E3"));
        Assert.assertEquals(true, yourClass.isNumeric("0"));
        Assert.assertEquals(true, yourClass.isNumeric("0.0f"));
        Assert.assertEquals(true, yourClass.isNumeric("NaN"));


As you guys might have noticed that I have an assert statement for both the methods which checks the method against string "NaN". The thing which makes this more interesting is that the method which uses NumberFormat returns false for this string while the method which uses Double.parseDouble(string) returns true.

You might say that the method which uses NumberFormat is correct because "NaN" is technically just a mere string value. Below is the description of how java treats "NaN" while doing floating-point operations :

"NaN" stands for "not a number". "Nan" is produced if a  floating point operation has some input parameters that cause the operation to produce some undefined result. For example, 0.0 divided
by 0.0 is arithmetically undefined. Taking the square root of a negative number is also undefined.


That's all for now folks stay tuned for new posts !!!!!!!!

 
 
 



Saturday, 5 September 2015

Jetty - Enabling request logs

Whenever you start jetty using jetty.sh shell script located inside jetty's bin folder, the jetty will start with the below logs enabled defined inside /opt/jetty/start.ini file (defined using xml files) by default:

etc/jetty.xml
etc/jetty-annotations.xml
etc/jetty-deploy.xml
etc/jetty-webapps.xml
etc/jetty-contexts.xml
etc/jetty-testrealm.xml

Below is the snapshot of the /opt/jetty/start.ini file to show complete set of configuration files:

#===========================================================
# Configuration files.
# For a full list of available configuration files do
#   java -jar start.jar --help
#-----------------------------------------------------------
#etc/jetty-jmx.xml
etc/jetty.xml
etc/jetty-annotations.xml
# etc/jetty-ssl.xml
# etc/jetty-requestlog.xml
etc/jetty-deploy.xml
#etc/jetty-overlay.xml
etc/jetty-webapps.xml
etc/jetty-contexts.xml
etc/jetty-testrealm.xml
#===========================================================

As highlighted in the above configuration the request log xml file is commented by default. We just have to uncomment the same and restart jetty to enable request logs and you should be able to see the request logs generated in the below directory:

/opt/jetty/logs

$ ls -lt
total 48
-rw-rw-r-- 1 jetty jetty  165 Aug 21 13:54 2015_08_21.request.log

Thursday, 4 June 2015

AspectJ Weaving - Finally Working !!!!!



After almost banging my head on the desk I finally get this working and thought of sharing the same in order to have a smooth run for anyone looking at it for the first time.

Before explaining the sample project I would like to set the plot that why I wanted to use AspectJ at the first place. I wanted to log a method's execution time in java. Though I would have done it a simple way by recording the difference between start time and end time of the method I chose AspectJ for not polluting the method body with the execution time logic.

In this tutorial I am not going to explain what is AspectJ? As I wanted to focus more on a working example. I have created a sample MAVEN project consists of the following java files:

SampleTarget.java:
This class contains a method fact for which we have to record the execution time.

 package com.piyush.aspect.tutorial;

/**
 * Class on which advice will be applied
 */
public class SampleTarget {
    public static void main(String[] args) {
        // Calling fact method on which 'around' advice will be applied
        new SampleTarget().fact(5);
    }

    public void fact(int num) {
        int c, fact = 1;
        if ( num < 0 )
           System.out.println("Number should be non-negative.");
        else
        {
           for ( c = 1 ; c <= num ; c++ )
              fact = fact * c;
           System.out.println("Factorial of "+num+" is = "+fact);
        }
    }
} 


SampleAspect.java: This class contains the advice implementation which has to be applied to the SampleTarget fact method.

package com.piyush.aspect.tutorial;

import org.aspectj.lang.ProceedingJoinPoint;
/**
 * A sample class annotated with @Aspect and implementing around advice
 */
@Aspect
public class SampleAspect {
    @Around("execution (* com.piyush.aspect.tutorial.SampleTarget.fact*(..))")
    public void advice(ProceedingJoinPoint joinPoint) throws Throwable {
        final long startTime = System.nanoTime();

        joinPoint.proceed();
        System.out.println("Elapsed time: ="+ (System.nanoTime() - startTime));
    }
}


Above things were not that difficult and can be found easily over the various blogs or tutorials. The key thing which has to be setup right is the pom.xml. Following is the pom.xml file which can be used without any modifications:

<?xml version="1.0" encoding="UTF-8"?>
<project
    <modelVersion>4.0.0</modelVersion>
    <groupId>SampleProject</groupId>
    <artifactId>SampleProject</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <targetJdk>1.7</targetJdk>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.12</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.12</version>
        </dependency>
    </dependencies>
    <build>
        <sourceDirectory>src</sourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.5</version>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>1.6.12</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <complianceLevel>1.6</complianceLevel>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>com.piyush.aspect.tutorial.SampleTarget</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Above pom.xml contains 3 dependencies aspectjrt, aspectjweaver and aspectjtools. It also contains aspectj maven plugin and maven execution plugin to execute SampleTarget.java having main method.

Now we have to run this project and see if the advice is applied to the fact method or not. Following command can be used to run the project from command line (make sure you are in the root directory of the project):

Command : mvn clean install OR mvn install

Following output should be displayed after running the project:

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building Unnamed - SampleProject:SampleProject:jar:0.0.1-SNAPSHOT
[INFO]    task-segment: [clean, install]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean {execution: default-clean}]
[INFO] Deleting /home/piyusht/workspace/rtb/MyAspect/target
[INFO] [resources:resources {execution: default-resources}]
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Compiling 3 source files to /home/piyusht/workspace/rtb/MyAspect/target/classes
[WARNING] POM for 'org.apache.maven.wagon:wagon-provider-api:pom:1.0-beta-6:runtime' is invalid.
Its dependencies (if any) will NOT be available to the current build.
[INFO] [aspectj:compile {execution: default}]
[INFO] [resources:testResources {execution: default-testResources}]
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/piyusht/workspace/rtb/MyAspect/src/test/resources
[INFO] [compiler:testCompile {execution: default-testCompile}]
[INFO] No sources to compile
[WARNING] POM for 'org.apache.maven:maven-toolchain:pom:2.0.9:runtime' is invalid.
Its dependencies (if any) will NOT be available to the current build.
[INFO] [surefire:test {execution: default-test}]
[INFO] No tests to run.
[INFO] Surefire report directory: /home/piyusht/workspace/rtb/MyAspect/target/surefire-reports
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
[INFO] [jar:jar {execution: default-jar}]
[INFO] Building jar: /home/piyusht/workspace/rtb/MyAspect/target/SampleProject-0.0.1-SNAPSHOT.jar
[INFO] Preparing exec:java
[WARNING] Removing: java from forked lifecycle, to prevent recursive invocation.
[INFO] No goals needed for project - skipping
[INFO] [exec:java {execution: default}]
Factorial of 5 is = 120
Elapsed time: =119435
[INFO] [install:install {execution: default-install}]
[INFO] Installing /home/piyusht/workspace/rtb/MyAspect/target/SampleProject-0.0.1-SNAPSHOT.jar to /home/piyusht/.m2/repository/SampleProject/SampleProject/0.0.1-SNAPSHOT/SampleProject-0.0.1-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Wed Jun 03 18:09:31 IST 2015
[INFO] Final Memory: 31M/244M
[INFO] ------------------------------------------------------------------------

das Ende !!!! Nope it is not garbage, its THE END in german. Although it has nothing to do with this post, mentioned just to put THE END in a different way :-)

Hope it helps. Please share your feedback and questions If any.

Sunday, 9 November 2014

Strengthen your test suite - Mutation Testing

Hey Guys, I found this interesting thing sometime back and was wondering how can somebody be not using this.

So we must be encountered the following situations while Unit Testing our code:
  • Hey there are some more scenarios against which we have to test the method !!!
  • Hey I did not take this scenario into account while unit testing and this results in a production issue.
  • Hey I had 100% code coverage, how can a bug will come?
Myth here is : 100% Code Coverage does not mean 100% Test Scenarios are covered.

The answer to all the above or to avoid such conditions is to use Mutation Testing. A cool testing technique to validate and enhance your test suite.
There are several Mutation Testing frameworks present right now however the most simple and active framework named PIT is a good choice.

Following are some other framework for Mutation Testing:
  • Jester Source-based mutation testing tool for Java
  • Judy Mutation testing tool for Java
  • Jumble Bytecode-based mutation testing tool for Java

Links to go through:

Tuesday, 4 November 2014

Hadoop Single Node Setup & Map-Reduce

This time I would like to share something big and here I come with the "BigData". Though I won't talk much on BigData, I will explain the Single node setup for hadoop and a map reduce java program running on it.

Following are the pre-requisites of running a Single node hadoop:
  • Java 6 or higher.
  • Apache Hadoop 2.5.1 (Download Link)
  • SSH Server.
  • Password less SSH login for localhost.
  • Make/Edit ~/.bashrc file.
First 2 steps are pretty simple and can be accomplished with ease. At this point I assume that you have downloaded/installed java and hadoop.

Note: Hadoop installation is merely a copy and paste task, so once after downloading the tar file for hadoop, unpack the same and put it to the following directory: /usr/local/hadoop
Command: sudo cp –rf ~/Downloads/hadoop-2.5.1/* /usr/local/hadoop
Add your user as owner to the hadoop directory i.e. /usr/local/hadoop as below:
Command: sudo chown <username> /usr/local/hadoop

SSH Server:
Install the SSH Server using the below command:
Command: sudo apt-get install openssh-server openssh-client

Password less SSH login for localhost:
To get rid of input the password login to localhost, we have to execute the following commands:

        1. Delete the SSH directory:
rm -rf ~/.ssh
2. Generate the SSH key:
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
3. Register the generated key as authorized:
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
4. Login to localhost:
ssh localhost (Should not ask for password)

Make/Edit ~/.bashrc file:

This is one of the important part of this setup, so insert the below entries into the .bashrc file if you have .bashrc file otherwise create .bashrc file by yourself and insert the entries:

JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
PATH=$PATH:$JAVA_HOME/bin
JRE_HOME=/usr/lib/jvm/java-7-openjdk-amd64
PATH=$PATH:$JRE_HOME/bin
HADOOP_INSTALL=/usr/local/hadoop/
PATH=$PATH:$HADOOP_INSTALL/bin
PATH=$PATH:/sbin
export HADOOP_CLASSPATH=$JAVA_HOME/lib/tools.jar
export JAVA_HOME
export JRE_HOME
export PATH

Above entries are to set the important environment variables. Once after you are done with .bashrc file creation/modification close your terminal window and start a new one as changes may not reflect in the same terminal window.

Note: As we can see in the above entries there is an environment variable HADOOP_INSTALL, don’t confuse with it, it is same as the HADOOP_HOME however that is deprecated now so use HADOOP_INSTALL in place of HADOOP_HOME.


Okay !!! Now we are done with the pre-requisites so let’s make some configuration changes necessary for the hadoop single node setup to work:

1. Move to the directory which has all the configuration files in the hadoop installation directory i.e. /usr/local/hadoop/etc/hadoop

2. Set the JAVA_HOME variable inside file hadoop-env.sh:

export JAVA_HOME=${JAVA_HOME}
OR
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64

3. Add following lines in the core-site.xml:
<property>
    <name>fs.default.name</name>
    <value>hdfs://localhost:9000</value>
</property>
<property>
    <name>hadoop.tmp.dir</name>
    <value>/usr/local/hadoop/tmp</value>
</property>
As we can see here the value for hadoop.tmp.dir is /usr/local/hadoop/tmp, we have to create tmp directory before running hadoop scripts.

4. Add following lines in the hdfs-site.xml:
<property>
    <name>dfs.replication</name>
    <value>1</value>
</property>
<property>
    <name>dfs.namenode.name.dir</name>
    <value>/var/hadoop/namenode</value>
</property>
<property>
    <name>dfs.datanode.data.dir</name>
    <value>/var/hadoop/datanode</value>
</property>
Here we are defining the name node and data node directories; these should also be created before we run/start the hadoop. Also we have to add our username as the owner of these directories. Below are the commands for the same:

sudo mkdir /var/hadoop/namenode
sudo mkdir /var/hadoop/datanode
sudo chown <username> /var/hadoop

5. There will be a mapred-site.xml.template file inside /usr/local/hadoop/etc/hadoop so we have to move the file as mapred-site.xml:
sudo mv etc/hadoop/mapred-site.xml.template etc/hadoop/mapred-site.xml

Then add below entries in the same:
<property>
    <name>mapred.job.tracker</name>
    <value>localhost:9001</value>
</property>
Now we are done with the configurations files.


HDFS Steps:


Now we’ve to format the name node : (we are at the /usr/local/hadoop/)
hadoop namenode –format

To check if the name node is formatting is successful check for the below message:
/var/hadoop/namenode had been successfully formatted. (In our case)

After this start all the necessary services using below command:

sbin/start-all.sh
<username>@mysystem-desktop /usr/local/hadoop $ sbin/start-all.sh
This script is Deprecated. Instead use start-dfs.sh and start-yarn.sh
Starting namenodes on [localhost]
localhost: starting namenode, logging to /usr/local/hadoop/logs/hadoop-<username>-namenode-xxx-desktop.out
localhost: starting datanode, logging to /usr/local/hadoop/logs/hadoop-<username>-datanode-xxx-desktop.out
Starting secondary namenodes [0.0.0.0]
0.0.0.0: starting secondarynamenode, logging to /usr/local/hadoop/logs/hadoop-<username>-secondarynamenode-xxx-desktop.out
starting yarn daemons
starting resourcemanager, logging to /usr/local/hadoop/logs/yarn-<username>-resourcemanager-xxx-desktop.out
localhost: starting nodemanager, logging to /usr/local/hadoop/logs/yarn-<username>-nodemanager-xxx-desktop.out

You can check about the running processes using jps command as below:

<username>@mysystem-desktop /usr/local/hadoop $ jps
3316 SecondaryNameNode
3506 ResourceManager
3160 DataNode
3932 Jps
3607 NodeManager
3060 NameNode

This will tell us about the running services and components. All the components listed above should be running if not there is some issue.

Once all the processes are started you can view the name node setup with the help of below URL: NameNode - http://localhost:50070/. Here you can get all the information about the directories, datanode etc.


Setup for Map-Reduce:

To run the Map-Reduce example we first have to make the input directory where we will store our input files on which map-reduce program will run.

1. Make the HDFS directories required to execute MapReduce jobs:
$ bin/hdfs dfs -mkdir -p /user/<username>/input
2. Copy the input files into the distributed filesystem: (This is not exactly the input file but the configuration files)
$ bin/hdfs dfs -put etc/hadoop input
3. Map Reduce Dictionary example: Map-Reduce Example, we are using the example from the link mentioned before, where the whole procedure is divided in below steps:

1. Go to the below links and download the dictionary files for Italian, French ans Spanish:
2. Merge all the three files into one file with the below:
cat French.txt >> fulldictionary.txt
cat Italian.txt >> fulldictionary.txt
cat Spanish.txt >> fulldictionary.txt
3. Copy this file i.e. fulldictionary.txt to hadoop file system input directory with the below command: (assuming you are in the path: /usr/local/hadoop)
bin/hdfs dfs -copyFromLocal ~/<your_path>/fulldictionary.txt input
4. In this example Map-Reduce Example there is one Dictionary.java file having map-reduce logic in it, which you have to compile, make jar and run the jar using below commands:
Compilation:
javac -classpath $HADOOP_INSTALL/share/hadoop/common/hadoop-common-2.5.1.jar:$HADOOP_INSTALL/share/hadoop/mapreduce/hadoop-mapreduce-client-core-2.5.1.jar:$HADOOP_INSTALL/share/hadoop/common/lib/commons-cli-1.2.jar Dictionary.java
JAR Creation:
jar -cvf dc.jar Dict*.class
JAR Execution:
hadoop jar dc.jar Dictionary input output
 Note: Before compiling the Dictionary.java file make the below changes in it:
FileOutputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
Instead of hard-coding the path for Input and Output take it from command line arguments as shown above.
Once you are done with JAR Execution, check the output directory in hdfs for result. Please note that, do not make output directory by yourself, output directory will be created by the map-reduce job itself else you will get an error saying output directory already exists.

Viola !!! The End. Hope this tutorial will be helpful for the beginners.














Wednesday, 29 October 2014

Google Protobuf - Get it working on Linux


Note: This article is posted while keeping in mind that the reader has already gone through the Proto file syntax i.e. what variable are used data types etc, last but not the least what protobuf is? If answer to this question is NO, Please visit: https://developers.google.com/protocol-buffers/

Getting Goggle Protobuf working is quite a heck so to make it easy I thought it would be worth sharing a quick read:

Steps to configure a sample maven java project in eclipse using protobuf in LINUX:
1. Install the protobuf compiler as below:
sudo apt-get install protobuf-compiler

2. Maven dependency that needs to be inserted into the pom.xml
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.6.0</version>
</dependency>

3. First of all we have to create a .proto file and then compile it using the protobuf compiler which results in .java class:
Syntax:  
protoc --java_out=<path where you want your respective java files to be created> <the actual .proto file's path>
Example: 
protoc --java_out=src/com/piyush/demo src/com/piyush/demo/addressbook.proto
protoc --java_out=src/ src/com/piyush/demo/my_object.proto

4. Earlier step can be automated using "maven-antrun-plugin", however get this running is quite a heck so please refer the below thread for this:
Links:
We can use maven-antrun-plugin in following ways:
  • For Single proto file compilation:
<echo>Generate</echo>
<exec executable="protoc">
<arg value="--java_out=src/" />
<arg value="src/com/piyush/demo/addressbook.proto" />
</exec>
  • For Multiple proto files compilation:
        <tasks>
                <echo>Generate</echo>
                    <path id="proto.path">
                        <fileset dir="src/com/piyush/demo/proto">
                            <include name="**/*.proto" />
                            </fileset>
                       </path>
                        <pathconvert pathsep=" " property="proto.files" refid="proto.path" />
                        <exec executable="protoc" failonerror="true">
                            <arg value="--java_out=src/" />
                            <arg value="-I${project.basedir}/src/com/piyush/demo/proto" />
                            <arg line="${proto.files}" />
                        </exec>
        </tasks>


Tips & Tricks:
1. Message name should be in camel case.

2. Beware that the name of the message and java_outer_classname should not be same in the proto file. For Example below proto file won't compile:
option java_package = "com.xyz.zrtb.simulator.protos";
option java_outer_classname = "A";
message a {
   optional string id = 1;
   optional string name = 2;
   repeated string cat = 4;
   optional string domain = 3;
}
Below will compile fine:
option java_package = "com.xyz.zrtb.simulator.protos";
option java_outer_classname = "OuterA";
message A {
   optional string id = 1;
   optional string name = 2;
   repeated string cat = 4;
   optional string domain = 3;
}


3. Importing proto file in one another is quite a heck and so it is good if you get it right at the very first place:
Import relies on the on the parameter '--proto_path' so If you've a package com.abc.pqr.model and defined '--proto_path' as below:
--proto_path=${project.basedir}/src/main/java/com/abc/pqr/model
THEN you can import just by writing xxx.proto However If you've defined '--proto_path' as below:
--proto_path=${project.basedir}/
THEN you can import by writing src/main/java/com/abc/pqr/model/xxx.proto and many such combinations.

4. The maven-antrun-plugin is problematic and can be a blocker, so below is the ready to use pom.xml configuration:
<build>
     <pluginManagement>
         <plugins>
            <!-- force a dependency on JDK 5.0 -->
            <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-compiler-plugin</artifactId>
               <configuration>
                  <source>1.7</source>
                  <target>1.7</target>
               </configuration>
            </plugin>
            <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build
          itself. -->
            <plugin>
               <groupId>org.eclipse.m2e</groupId>
               <artifactId>lifecycle-mapping</artifactId>
               <version>1.0.0</version>
               <configuration>
                  <lifecycleMappingMetadata>
                     <pluginExecutions>
                        <pluginExecution>
                           <pluginExecutionFilter>
                              <groupId>org.apache.maven.plugins</groupId>
                              <artifactId>maven-antrun-plugin</artifactId>
                              <versionRange>[1.7,)</versionRange>
                              <goals>
                                 <goal>run</goal>
                              </goals>
                           </pluginExecutionFilter>
                           <action>
                              <ignore />
                           </action>
                        </pluginExecution>
                     </pluginExecutions>
                  </lifecycleMappingMetadata>
               </configuration>
            </plugin>
         </plugins>
        <pluginManagement>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.7</version>
            <executions>
               <execution>
                  <id>generate-sources</id>
                  <phase>generate-sources</phase>
                  <configuration>
                     <target>
                        <echo>Generate</echo>
                        <path id="proto.path">
                           <fileset dir="src/main/java/com/piyush/zrtb/simulator/proto">
                              <include name="**/*.proto" />
                           </fileset>
                        </path>
                        <pathconvert pathsep=" " property="proto.files" refid="proto.path" />
                        <exec executable="protoc" failonerror="true">
                           <arg value="--java_out=src/main/java" />
                           <arg value="-I${project.basedir}/src/main/java/" />
                           <arg line="${proto.files}" />
                        </exec>
                     </target>
                     <sourceRoot>src/main/java</sourceRoot>
                  </configuration>
                  <goals>
                     <goal>run</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
      </plugins>
      <extensions />
   </build>

Links to go through:
  • https://code.google.com/p/protoclipse/
  • http://www.siafoo.net/user/stou/blog/2010/01/29/Protocol-Buffers-and-Eclipse
  • http://www.masterzen.fr/2011/12/25/protobuf-maven-m2e-and-eclipse-are-on-a-boat/
  • http://techtraits.com/noproto/
  • http://xmeblog.blogspot.in/2013/12/sending-protobuf-serialized-data-using.html
  • http://sleeplessinslc.blogspot.in/2010/03/restful-representation-with-google.html
  • http://tutorials.jenkov.com/maven/maven-tutorial.html
  • https://developers.google.com/protocol-buffers/docs/proto#generating

Friday, 21 February 2014

To start off with my first words here, I would like to share a quote which I always found significant and worth following in life:

"There is nothing noble about being superior to some other person, true nobility lies in about being superior to your former self".