Google

Oct 31, 2013

How to write immutable Java classes? -- Core Java Best Practices -- Part 2

This is an extension to Java OO Interview Questions and Answers where demonstrated a simple example as to how to design good OO classes, but those classes were not using the best practices defined in Core Java Best Practices -- Part 1. The following questions were raised.


1) Why does the Employee class need to be mutable?
2) Why aren't the roles defensively copied?
3) Why would the Employee need to know how to add and remove roles?
4) Waiter and Manager are placed in a collection but don't override hashcode and equals. That will cause the contains method on a List to not behave as expected.
5) You check if the role is null then throw an IllegalArgumentException, that should instead be a NullPointerException.
6) The code that checks for null roles being added is duplicated, thus defeating the DRY principle.


Here are the classes with the best practices.

Step 1: Immutable Employee class

package com.mycompany.app15;

import groovy.transform.Immutable;

import java.util.Collection;
import java.util.Collections;

@Immutable
public class Employee
{
    
    private final String name;
    private final Collection<Role> roles;
    
    public Employee(String name, Collection<Role> roles)
    {
        this.name = name;
        this.roles = roles;
        
    }
    
    public String getName()
    {
        return name;
    }
    
    public Collection<Role> getRoles()
    {
        return Collections.unmodifiableCollection(roles); //returns immutable collection
    }
    
}

Step 2: Role interface same as before.

package com.mycompany.app15;

public interface Role
{
    public String getName();
    
    public void perform();
}


Step 3: The Immutable Manager and Waiter classes. They also have the equals( ) and  hashCode( ) methods added as they are add to a collection.

package com.mycompany.app15;

import groovy.transform.Immutable;

@Immutable
public final class Waiter implements Role
{
    
    private final String roleName;
    
    public Waiter(String roleName)
    {
        this.roleName = roleName;
    }
    
    @Override
    public String getName()
    {
        return this.roleName;
    }
    
    @Override
    public void perform()
    {
        System.out.println(roleName);
    }
    
    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((roleName == null) ? 0 : roleName.hashCode());
        return result;
    }
    
    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Waiter other = (Waiter) obj;
        if (roleName == null)
        {
            if (other.roleName != null)
                return false;
        }
        else if (!roleName.equals(other.roleName))
            return false;
        return true;
    }
    
    @Override
    public String toString()
    {
        return "Waiter [roleName=" + roleName + "]";
    }
    
}




package com.mycompany.app15;

import groovy.transform.Immutable;

@Immutable
public final class Manager implements Role
{
    
    private final String roleName;
    
    public Manager(String roleName)
    {
        this.roleName = roleName;
    }
    
    @Override
    public String getName()
    {
        return this.roleName;
    }
    
    @Override
    public void perform()
    {
        System.out.println(roleName);
    }
    
    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((roleName == null) ? 0 : roleName.hashCode());
        return result;
    }
    
    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Manager other = (Manager) obj;
        if (roleName == null)
        {
            if (other.roleName != null)
                return false;
        }
        else if (!roleName.equals(other.roleName))
            return false;
        return true;
    }
    
    @Override
    public String toString()
    {
        return "Manager [roleName=" + roleName + "]";
    }
    
}


Step 3: Finally, the modified  Restaurant class.

package com.mycompany.app15;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class Restaurant
{
    
    public static void main(String[] args)
    {
        
        Role waiter = new Waiter("waiter");
        Role manager = new Manager("manager");
        
        List<Role> roles = new ArrayList<Role>();
        roles.add(waiter);
        roles.add(manager);
        
        Employee emp1 = new Employee("Bob", roles);
        
        List<Role> roles2 = new ArrayList<Role>();
        roles2.add(waiter);
        
        Employee emp2 = new Employee("Jane", roles2);
        
        System.out.println(emp1.getName() + " has roles ");
        Collection<Role> rolesRetrieved = emp1.getRoles();
        for (Role role : rolesRetrieved)
        {
            role.perform();
        }
        
        System.out.println(emp2.getName() + " has roles ");
        rolesRetrieved = emp2.getRoles();
        for (Role role : rolesRetrieved)
        {
            role.perform();
        }
        
        //can't add new roles now as getRoles return unmodifiable collection
        emp1.getRoles().add(waiter); //java.lang.UnsupportedOperationException is thrown
        
    }
}




Q. Can you still make any further improvements?
A. Yes, use log4j instead of System.out.println().

Labels: ,

Oct 30, 2013

5 strategies I used to drive traffic to my blog/website on software development

  • Are you planning to write a Software development book via a POD publisher and don't know how to promote it?
  • Are you having trouble driving traffic to your blog on software development even though you have great content?
  • Are you planning to become a freelance developer and going to create a blog to promote your skills and experience to find work continuously. 
The focus is on converting

visitors --> audience/customer --> better "Google Author Ranking" --> better SEO ranking


Here are some free and paid strategies to drive traffic to promote your skills, services, products, and books.

Strategy #1: From my personal experience and hearing from the so called the digital marketing experts, the best strategy for getting massive traffic has nothing to do with Google or search engine optimization. The single best strategy is all about building relationships with your visitors. You build relationships with your visitors by finding other high traffic sites in your niche that has spent years building their audience. You need to visit these niche sites to promote your site/blog. Don't spam. Work within those sites' rules. The key focus must be to add value to those sites by helping their visitors and audiences. If you are a Java developer, sites like "javacodegeeks.com" is a good example to publish articles.

Example #1:

Frequenting industry specific forums and sites like dzone.com, javaranch.com, infoq.com, etc to publish quality articles on software development and helping others solve their problems and dilemmas. If your readers find your articles and suggestions to be useful, they will show interest in learning more about you and your work by clicking on the links you provide to your website/blog in your signature.

Example 2#:

These high traffic sites do promote their products, services and books. Become a customer of those products and do a thorough product review and post it on your website/blog.  Notify the product owner of the review and they may link to it or tweet about it.


Strategy #2: You need to convert your visitors into audience. The best way to achieve this is to write unique content that adds value to your visitors. Know what your readers want. When I wrote my blog on "Java Job Interview Questions and Answers", it was a quite unique topic. There were thousands of sites on Java tutorials, but not many on Java job interview preparation. I made it even more unique by providing lots of diagrams, examples, and code snippets in my answers compared to other sites, which just provided only 2 line answers. Still my blog provides a more comprehensive questions and answers for Java developers. You can also provide free eBooks, and get your visitors to subscribe to your network via email, Facebook, Google+, LinkedIn, RSS feeds, etc. This will enable you to expand your network and build relationships.


Strategy #3: Using Google adwords. This is not free and you need to pay for each click. This strategy is handy if you already have a product or book that you sell via your website or blog. You can afford to drive some traffic by placing advertisements via google search.


Example #1: Initially, I placed adwords advertisements to promote my book entitled "Java/J2EE Job Interview Companion" to drive traffic to my site. I reasearched on the google adwords tool to pick key words that are a) relevant to my book, b) has reasonable search volume and c) has less competition (means low cost per click). So, picked the key words "Java Interview" and Java Interview Questions. It did work for me and sold around 25,000+ copies. I don't use adwords anymore as my blog has a decent traffic to promote my work.


Strategy 4#: Know your visitors and audience and provide relevant contents. I have basic and advanced Java related blog posts, and the posts that get higher traffic are "posts on "Basic Java" stuff and not advanced stuff. This shows that my audiences are basically beginner to intermediate level. So, I tend to write more posts targeting beginner to intermediate  level. It is also imperative to sign up for Google analytics to see where your traffic is coming from.  For example, countries, operating systems, mobile versus browsers, organic search versus other sites, etc. It is also imperative to analyze the "bounce rate" on google analytics. This indicates the rate at which people bounce out of your site. Aim to keep this rate to under 80%. Also, try to increase the "Avg. Visit Duration". 


-->
Strategy #5: Organize your content so that people can easiliy navigate to your site. Your content must be short and sweet without any fluff. Your first half of the content must attract your reader to read further. Have links to your top 10 most popular blog posts easily visible to your visitors. Provide search functionality and tag cloud so that your visitors can search by category. For example, if you are a Java developer, have tags like "Spring security", "Spring configuration",  "Hibernate", "Core Java", "Jasper Reports", etc.


The above five strategies will increase your conversion rate from

visitors --> audience/customer --> better "Google Author Ranking" --> better SEO ranking


The bottom-line is building relationships with your fellow professionals. This will become very handy if you are planning to sell your products/books/services or working hard towards becoming a freelance Software (Java ) developer. Why not do both?
 

Labels: , , ,

Oct 29, 2013

My 5 top blogging mistakes as a Software(Java) developer

Mistake #1: Wrote blog posts for adsense and SEO robots. The tell tale sign is checking my adsense income and keyword ranking every hour or so.

Lessons learned: Write blog posts for people. Not for adsense or not for SEO robots. If one of your reasons to write blog is to monetize your site, then you need traffic. The only way to drive traffic is by writing quality content for human. Your blog must add value to your readers, and consequently your readers will frequent your blog by bookmarking your home page and subscribing to it. So, blogging is all about unique content, unique content, unique content. Even if the content is not that unique, it needs to be written in a unique style for human. I have 150+ blog posts on my site, but only 15 blog posts contribute to 80% of the traffic. For many bloggers, 1 or 2 great blog posts become the life changing ones. So, shift your focus from frequently checking your adsense income or spending hours on the internet for great blogging tips to writing quality content.


Mistake #2: Splashed my blog posts with advertisements. Wasted lots of time hoping someone will click on those advertisements and searching for that secret tip that will increase my adsense income. The secret tip is not to make the mistakes #1 and #2. Just keep writing unique content and see where it takes you. Think of cliches like "quality over quantity" and "less is more"

Lessons learned: Having lots of advertisements will not only irritate your readers, but also your users will become immuned to the advertisements and will learn how to not click them. Some users will never bother coming back again. I am a firm believer in 80/20 principle. Only 20% of your blog posts will contribute to 80% of your traffic. So, place only 1 or 2 advertisements in those high traffic pages without irritating your readers. Relying only on adsense income is like putting all your eggs in one basket. Your key purpose of blogging is to create a brand for yourself so that you can

  • find development work as a freelancer through your networked resources. Create a link to your blog from your resume and professional profiles like LinkedIn.com to establish yourself  as a talented freelancer. It is a great promotional tool to sell your services. This is what going to bring you the main portion of your income. For many, the adsense income is going to be not more than a small pocket money.
  • sell your books and products via your blog.
  • sell others' books or products.
  • provide training or consulting services.
  • provide guest speaking or blogging.

All these need traffic, traffic, and more traffic.

Google uses "Authors' Ranking" for its SEO rankings, hence key to get good  "Authors' Ranking" is by writing quality content and connecting with people. Writing software is all about building relationships with your clients. Same is true for blogging. Writing blogs is all about building relationships with you readers and discovering new opporunities. In on of my freelance assignemnts as a Java developer, my hiring manager was one of the readers of my books. 

Mistake #3: Not putting myself on my readers' shoes. Initially started writing my blogs as a repository of my knowledge. As a freelance software developer, I wanted to maintain a journal of my experience. Software development is very vast, and it really pays to maintain a journal so that it will become handy in my future assignements. I might work on a framework A, and never work on it again for about 1-2 years. I did not pay much attention as to my readers will understand or not.

Lessons learned: Learnt to write blog posts with good diagrams and code snippets to make it easier for my readers. Also, started to track each blog posts' popularity via google analytics and number of comments posted. Good thought provoking blog posts will result in feedback via user comments.  


Mistake #4: Did not pay much attention to my blog titles. Bland titles will not   encourage readers to read your blog posts. Recently, I saw some impressive titles like 
  • How my Dog learned Polymorphism?
  • Serious About Your Software Career? Leave your job
Lessons learned:  Many people judge a book by its cover. Quantifying your title does make a difference. For example:

Instead of: Job Interview Questions and Answers
use: 150+ Job Interview Questions and Answers.

Instead of: Blogging mistakes
use: 10 Blogging mistakes you must avoid.


Mistake #5: Subconsciously repeating the mistakes #1 to #4 and lacking patience. It is a human tendendency to keep making the same mistakes and seeking instant gratification. It took me a good 2 years to get around 65,000 unique vistors per month to my Java career training blog.  

Lesson learned: Repeatedly train the subconscious mind to not make those mistakes again. For example, spend less time on searching for those great adsense revenue making tips, and spend some quality time with your other passions. Spend more time thinking and researching for some quality content for your next blog post. Start blogging early and give yourself enough time to grow and learn from your mistakes. 



Labels: , ,

Oct 28, 2013

Java Tree structure interview questions and coding questions -- Part 2



In the previous post entitled  Java Tree structure interview questions and coding questions -- Part 1, we looked at a very simple Tree structure. In this example, let's look at a more complex tree structure with generics.

Q. Write classes for a Tripple tree structue as shown below? The Leaf contains the data, and the Node contains Leaves. Both the Leaf and Node are treated as a Tree. This is the power of composite design pattern. The example has 3 levels.


Step 1: Define the Tree interface.

package com.mycompany.flatten;

public interface Tree<T>
{

}

Step 2: Define the Leaf tree class that holds the data.

package com.mycompany.flatten;

public class Leaf<T> implements Tree<T>
{
    public static <T> Tree<T> leaf(T value)
    {
        return new Leaf<T>(value);
    }
    
    private final T data;
    
    public Leaf(T t)
    {
        this.data = t;
    }
    
    @Override
    public String toString()
    {
        return "Leaf [data=" + data + "]";
    }
    
}

Step 3: The Node tree class that holds other Leaves.

package com.mycompany.flatten;

public class Node<T> implements Tree<T>
{
    
    public static <T> Tree<T> tree(T left, T middle, T right)
    {
        return new Node<T>(Leaf.leaf(left), Leaf.leaf(middle), Leaf.leaf(right));
    }
    
    private final Triple<Tree<T>> branches;
    
    public Node(Tree<T> left, Tree<T> middle, Tree<T> right)
    {
        this.branches = new Triple<Tree<T>>(left, middle, right);
    }
    
    
    @Override
    public String toString()
    {
        return "Node {branches=" + branches + "}";
    }
    
}


Step 4: Finally, a test class that constructs the above tree structure.

package com.mycompany.flatten;

public class SpecialTreeTest
{
    
    public static void main(String[] args)
    {
        
        Tree<String> leafB21 = Leaf.leaf("B21");
        Tree<String> leafB22 = Leaf.leaf("B22");
        Tree<String> leafB23 = Leaf.leaf("B23");
        
        //takes all 3 args as "Leaf<String>" and returns "Tree<Leaf<String>>"
        Tree<Tree<String>> level3 = Node.tree(leafB21, leafB22, leafB23); // all leaves
        
        Tree<String> leafB1 = Leaf.leaf("B1");
        Tree<String> leafB3 = Leaf.leaf("B3");
        
        //takes  3 args as "Leaf<String>", "Tree<Leaf<String>>", and  "Leaf<String>" 
        Tree<Tree<? extends Object>> level2 = Node.tree(leafB1, level3, leafB3);
        
        
        Tree<Tree<? extends Object>> level1 = Node.tree(Leaf.leaf("A"), level2, Leaf.leaf("C"));
        
        System.out.println(level1); //level1 is the root

        
    }
    
}


Step 5: Finally, the output is:

Node {branches=Triple [l=Leaf [data=Leaf [data=A]], m=Leaf [data=Node {branches=Triple [l=Leaf [data=Leaf [data=B1]], m=Leaf [data=Node {branches=Triple [l=Leaf [data=Leaf [data=B21]], m=Leaf [data=Leaf [data=B22]], r=Leaf [data=Leaf [data=B23]]]}], r=Leaf [data=Leaf [data=B3]]]}], r=Leaf [data=Leaf [data=C]]]}

You may also like:

Labels: , ,

Oct 27, 2013

Top 5 career mistakes that I made as a Java developer

I learned a lot from the mistakes I made in my career as a Java software developer. Here are my top five mistakes, and hope you share yours with fellow developers.

  • Mistake #1: Naively believing that I could easily find a job with my M. Eng. degree led to being unemployed for about 16 months. I under estimated the power of hands-on experience and much needed job hunting skills. I wish I had taken on unpaid internships or volunteer work.  In many situations the cliche is Experience, Experience, Experience. Here are more tips on how to get some experience on your CV
  • Mistake #2: When I was interviewed for my first IT job, I was asked how I would go about working with a person who is difficult to work with. Only after taking up the job, I realized that I had to work with a such person, and my lack of soft skills and immaturity resulted in leaving the job just after 5 months. I learned the lesson that just being a techie is not enough to open more doors. 


    • I think of it as this -- If I am paid $50k as a Java developer, then $25k is for my technical skills, and the remaining $25K is to put up with things. In other words for being a team player, having good interpersonal skills, and right attitude.

  • Mistake #3: Squandered great job opportunities due to lack of good resume writing and interviewing skills. I also let others around me decide what is best for me in terms of my career path. For example, letting the recruitment agents decide what is best for me, how much I should get paid, and what frameworks and technologies I should learn next.


    • An interview is a two way street. As a prospective employer is assessing your suitability, you are assessing the suitability of the position to see if it is inline with your career goals. So, failing to ask the right questions can land you in a dilemma as you want to accept an offer or not. How would you go about choosing from multiple job offers?
  • Mistake #4: Fear of change, false understanding of job security, and fear of job interviews made me get into a comfort zone. Didn't realize that the real job security stems from having the right and up to date skills until the software house I was working for closed down. 


    • Nowadays I make it a point to learn at least 1 new thing a week. With so many quality resources around you, why have excuses to learn.
     
  • Mistake #5: As everyone does, from time to time stagnated at my job without enough work or challenging tasks. Didn't realize that what other avenues I could have explored as a software engineer to open more doors in and outside work. Most good software engineers are self-taught and there are plenty of things to learn and myriad of free and paid resources to learn from. There are a number of paths to take, and some paths are less traveled than the others. The big picture diagram in this section will inspire you as to what you can do as a software engineer.




    Click on the diagram below to see what options you have as a Java developer or software engineer in general.

    As a software engineer, there are many avenues to look at depending on your interests, strengths, and career goals as shown in the ensuing diagram. With these avenues, you can not only open more doors to fast track your career by acquiring much needed experience in technical and non-technical areas, but also can open doors to new active and passive income streams.




    Everyone makes mistakes, but the important thing is to learn from your mistakes. Feel free to share your mistakes and how you rectified it.



    Do something out of the norm to succeed in your career. When everyone is preparing for certfication, then doing the certification is not the norm. Seeking unpaid opensource or voluntary work opportunities is out of the norm. Be passionately committed about what you do, and see where it takes you.  This also mean that you need to be patient and keep at your goal. For example, many technical bloggers lose motivation after a few months as they did not get enough traffic. I had to work on my blog for at least 2 years to get a decent traffic.

Labels:

Oct 26, 2013

Find subarray of an array - coding

Q. Can you write code to find starting position of a sub array in an array? if not found, return -1 as the position.

For example, find
  • [-3, 7] in [5, 9, -3, 7, 8] --> 2
  • [7, 8, 9] in   [5, 9, -3, 7, 8] --> -1
  • [5] in   [5, 9, -3, 7, 8] --> 0
A. This can be approached a number of different ways. I will discuss 3 approaches.

Define the interface first


 
package findarray;

public interface FindArray {
    abstract int findArray(int[] array, int[] subArray) ;
}


Approach 1: Make use of the Collections.indexOfSubList method as per don't reinvent the wheel principle.

 
package findarray;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class FindArrayImpl1 implements FindArray
{
    
    @Override
    public int findArray(int[] array, int[] subArray)
    {
        if (array == null || subArray == null || subArray.length > array.length)
        {
            return -1;
        }
        
        //convert primitive int to Integer and then use the Collections API 
        return Collections.indexOfSubList(convertArrayToList(array), convertArrayToList(subArray));
    }
    
    /**
     * convert int[] to List<Integer>
     */
    public List<Integer> convertArrayToList(int[] input)
    {
        if (input == null)
        {
            return null;
        }
        List<Integer> output = new ArrayList<Integer>(input.length);
        for (int i = 0; i < input.length; i++)
        {
            output.add(Integer.valueOf(input[i]));
        }
        
        return output;
        
    }
    
    public static void main(String[] args)
    {
        int[] array =
        {
            5, 9, -3, 7, 8
        };
        
        int[] subArray1 =
        {
            -3, 7
        };
        
        //should return 2
        System.out.println(new FindArrayImpl1().findArray(array, subArray1));
        
        int[] subArray2 =
        {
            7, 8, 9
        };
        
        //should return -1
        System.out.println(new FindArrayImpl1().findArray(array, subArray2));
        
        int[] subArray3 =
        {
            5
        };
        
        //should return 0
        System.out.println(new FindArrayImpl1().findArray(array, subArray3));
        
    }
}

Approach 2: Write your own logic. The interviewer might be wanting to test your logic processing ability.

 
package findarray;

public class FindArrayImpl2 implements FindArray
{
    
    @Override
    public int findArray(int[] array, int[] subArray)
    {
        if (array == null || subArray == null || subArray.length > array.length)
        {
            return -1;
        }
        
        int index = -1; // assume not found
        
        for (int i = 0; i < array.length; i++)
        {
            // Check if the next element of array is same as the first element of subarray
            if (array[i] == subArray[0])
            {
                //check subsequent elements of subarray against the subsequent elements of array
                for (int j = 0; j < subArray.length; j++)
                {
                    //if found, set the index
                    if (i + j < array.length && subArray[j] == array[i + j])
                    {
                        index = i;
                    }
                    else
                    {
                        index = -1;
                        break;
                    }
                }
            }
        }
        
        return index;
        
    }
    
    public static void main(String[] args)
    {
        int[] array =
        {
            5, 9, -3, 7, 8
        };
        
        int[] subArray1 =
        {
            -3, 7
        };
        
        //should return 2
        System.out.println(new FindArrayImpl2().findArray(array, subArray1));
        
        int[] subArray2 =
        {
            7, 8, 9
        };
        
        //should return -1
        System.out.println(new FindArrayImpl2().findArray(array, subArray2));
        
        int[] subArray3 =
        {
            5
        };
        
        //should return 0
        System.out.println(new FindArrayImpl2().findArray(array, subArray3));
        
    }  
}


Approach 3: Using the StringBuilder class.

 
package findarray;

public class FindArrayImpl3 implements FindArray
{
    
    @Override
    public int findArray(int[] array, int[] subArray)
    {
        if (array == null || subArray == null || subArray.length > array.length)
        {
            return -1;
        }
        
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < array.length; i++)
        {
            sb.append(array[i]);
        }
        
        StringBuilder sbSub = new StringBuilder();
        for (int i = 0; i < subArray.length; i++)
        {
            sbSub.append(subArray[i]);
        }
        
        int index = sb.toString().indexOf(sbSub.toString());
        if (index >= 0)
        {
            return index;
        }
        else
        {
            return -1;
        }
    }
    
    public static void main(String[] args)
    {
        int[] array =
        {
            5, 9, -3, 7, 8
        };
        
        int[] subArray1 =
        {
            -3, 7
        };
        
        //should return 2
        System.out.println(new FindArrayImpl3().findArray(array, subArray1));
        
        int[] subArray2 =
        {
            7, 8, 9
        };
        
        //should return -1
        System.out.println(new FindArrayImpl3().findArray(array, subArray2));
        
        int[] subArray3 =
        {
            5
        };
        
        //should return 0
        System.out.println(new FindArrayImpl3().findArray(array, subArray3));
        
    }
}

The output for all 3 approaches:

 
2
-1
0


Feel free to show us other creative and better approaches.

Labels:

Oct 25, 2013

Java Tree structure interview questions and coding questions -- Part 1

Core Java Coding Questions and Answers for beginner to intermediate level

Q1 Q2 Q3 Q4 Q5 Q6

Java does not have a Tree class but you can define one. In my 10+ years as a Java developer, I have rarely used a Tree structure,  but when I do use it I find it to be a bit more complicated than working with other data structure. I have also experienced and noticed that developer interview pre screening coding tests including Tree related coding questions. Especially the software houses. I guess this could be due to 2 reasons.
So, here is a  series of Java Tree related developer questions and answers.

Q. Can you create a Tree class that can work with different types like String, File, Person, etc and supports the follwing methods
  • Tree add(T data) -- adds a child node to the parent node. 
  • void remove (T data) -- removes a child node to the parent node. 
  • Tree getRoot( ) -- returns the root of the tree.
  • boolean contains(T data) -- searches the tree for a given type

A. This is a very basic question. The tree class should be parametrized with generics. Let's say this is T that can be substituted during compile-time for String, File, Person, etc. Let's use both iteration and recursion.
The tree structure needs both the parent and children to traverse top to bottom and bottom to top. Since it is a n-ary tree, that is a parent can have n number of children, we will use an ArrayList to store child nodes. 



Now, the Java code to represent the above diagram as simple as possible with the relevany methods.




package com.mycompany.app.tree;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Tree<T>
{
    private T data;
    private Tree<T> parent;
    private List<Tree<T>> children;
    
    public Tree(T data)
    {
        this.data = data;
        children = new ArrayList<Tree<T>>();
    }
    
    /**
     * Adds a new child node to the parent node returns the added Child
     */
    public Tree<T> addChild(T childData)
    {
        Tree<T> childNode = new Tree<T>(childData);
        childNode.parent = this;
        this.children.add(childNode);
        return childNode;
    }
    
    /**
     * Removes a child node from a parent.
     */
    public void removeChild(T childData)
    {
        Tree<T> childNode = new Tree<T>(childData);
        this.children.remove(childNode);
    }
    
    /**
     * Returns the parent
     */
    public Tree<T> getParent()
    {
        return this.parent;
    }
    
    /**
     * Returns the parent
     */
    public Tree<T> getRoot()
    {
        if (this == null)
        {
            return this;
        }
        
        Tree<T> parentTmp = this.parent;
        Tree<T> root = this;
        
        //iteration
        while (parentTmp != null)
        {
            parentTmp = root.parent;
            if (parentTmp != null)
            {
                root = parentTmp;
            }
            
        }
        
        return root;
    }
    
    /**
     * Searches the tree for a given type
     */
    public boolean contains(T data)
    {
        
        if (this == null)
        {
            return false;
        }
        
        if (this.data.equals(data))
        {
            return true;
        }
        
        List<Tree<T>> children2 = this.children;
        Iterator<Tree<T>> iterator = children2.iterator();
        while (children2 != null && iterator.hasNext())
        {
            Tree<T> next = iterator.next();
            if (next != null)
            {
                next.contains(data); //recursion
            }
            
        }
        
        return false;
    }
    
    @Override
    public String toString()
    {
        StringBuilder output = new StringBuilder("[");
        helpToString(this, output, 0);
        output.append("]");
        return output.toString();
    }
    
    private void helpToString(Tree<T> tree, StringBuilder output, int level)
    {
        if (tree == null)
            return; // Tree is empty, so leave.
            
        output.append(getSpaces(level) + tree.data);
        
        List<Tree<T>> children2 = tree.children;
        ++level; //increment the level
        
        Iterator<Tree<T>> iterator = children2.iterator();
        while (children2 != null && iterator.hasNext())
        {
            Tree<T> next = iterator.next();
            if (next != null)
            {
                helpToString(next, output, level); //recursion
            }
            
        }
        
    }
    
    private String getSpaces(int level)
    {
        StringBuilder sb = new StringBuilder("\n");
        for (int i = 0; i < level; i++)
        {
            sb.append("--");
        }
        
        return sb.toString();
    }
    
}

Finally, the test class with the main method to keep it simple.

package com.mycompany.app.tree;

public class TreeTest
{
    public static void main(String[] args)
    {
        Tree<String> root = new Tree<String>("A");
        root.addChild("B");
        Tree<String> childC = root.addChild("C");
        root.addChild("D");
        
        Tree<String> childC1 = childC.addChild("C1");
        
        System.out.println("root = " + childC.getRoot());                 // toString() method is invoked
        System.out.println("Contains C = " + childC.contains("C"));
        System.out.println("Contains D = " + childC.contains("D"));
        
        System.out.println("root = " + childC1.getParent());              // toString() method is invoked
        
    }
}

The printed output is:

root = [
A
--B
--C
----C1
--D]
Contains C = true
Contains D = false
root = [
C
--C1]

More Java developer questions and answers on Tree data structure.

Labels: ,

Oct 23, 2013

Drools with Decision tables (Excel spreadsheet) tutorial

This is an extension to Drools tutorial with Maven. This externalize the rules criteria to an Excel spreadsheet license.xls. This means the age condition is supplied in the xls file under src/main/resources/drools/license.xls.

Step 1: Maven pom.xml file dependencies. Add dependencies including the decision tables.


 
<dependency>
 <groupId>org.drools</groupId>
 <artifactId>drools-core</artifactId>
 <version>5.5.0.Final</version>
</dependency>
<dependency>
 <groupId>org.drools</groupId>
 <artifactId>drools-compiler</artifactId>
 <version>5.5.0.Final</version>
</dependency>
<dependency>
 <groupId>org.drools</groupId>
 <artifactId>drools-decisiontables</artifactId>
 <version>5.5.0.Final</version>
</dependency>

Step 2: The license.xls file where rule name and age criteria are defined.



Step 3: The template file drools/license.drt under src/main/resources

 
template header
rules
age

package com.mycompany.app.drools;

import com.mycompany.app.drools.ApplicantForm;
import com.mycompany.app.drools.Applicant;
import com.mycompany.app.drools.ApplicantDao;
import com.mycompany.app.drools.ApplicantDaoImpl;

global ApplicantDao applicantDao;

template "license-rules"

  
rule "@{rules}_@{row.rowNumber}"
when
   $a : ApplicantForm();
   $applicant: Applicant( age < @{age} ) from applicantDao.findApplicant($a.getApplicantId());
then
   $a.setEligible( false );
end

end template

As you can see, @{age} and @{rules} were determined from the excel spreadsheet. The @{row.rownNumber} is excel spreadsheet row number.
Step 4: The Applicant.java, ApplicationForm.java, ApplicantDao.java, and ApplicantDaoImpl.java are same as before, but moved to a different package com.mycompany.app.drools.

Step 5: Finally, the test class ApplicantLicenseTest class that bootstraps with the xls and drt files.

 
package com.mycompany.app.drools;

import java.io.IOException;
import java.util.Iterator;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.decisiontable.ExternalSpreadsheetCompiler;
import org.drools.io.ResourceFactory;
import org.drools.io.impl.ByteArrayResource;
import org.drools.runtime.StatefulKnowledgeSession;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mvel2.optimizers.OptimizerFactory;

public class ApplicantLicenseTest
{
    
    private KnowledgeBase kbase;
    
    @Before
    public void setup() throws IOException
    {
        OptimizerFactory.setDefaultOptimizer("reflective");
        
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        loadKnowledgeBase("drools/license.xls", "drools/license.drt",
                "license", 2, 1, kbuilder);
        
        kbase = KnowledgeBaseFactory.newKnowledgeBase();
        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
        
    }
    
    private void loadKnowledgeBase(String aXlsName, String aDrlName,
            String aWorksheetName, int aStartRow, int aStartCol, KnowledgeBuilder aKbuilder) throws IOException
    {
        ExternalSpreadsheetCompiler sc = new ExternalSpreadsheetCompiler();
        
        String drlstr = sc.compile(ResourceFactory.newClassPathResource(aXlsName).getInputStream(),
                aWorksheetName,
                ResourceFactory.newClassPathResource(aDrlName).getInputStream(), aStartRow, aStartCol);
        
        System.out.println(drlstr);
        
        aKbuilder.add(new ByteArrayResource(drlstr.getBytes()), ResourceType.DRL);
        
        Iterator<KnowledgeBuilderError> errors = aKbuilder.getErrors().iterator();
        if (errors.hasNext())
        {
            StringBuilder errorMsg = new StringBuilder("Error compiling rules:");
            while (errors.hasNext())
            {
                errorMsg.append("\t" + errors.next().getMessage());
            }
            
            System.out.println(errorMsg.toString());
        }
    }
    
    @Test
    public void testApplicantLicense()
    {
        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        kbase.newStatefulKnowledgeSession();
        
        ApplicantForm applicant1 = new ApplicantForm();
        applicant1.setApplicantId(1);
        
        ApplicantForm applicant2 = new ApplicantForm();
        applicant2.setApplicantId(2);
        
        ksession.setGlobal("applicantDao", new ApplicantDaoImpl()); // assign the global dao
        
        ksession.insert(applicant1);
        ksession.insert(applicant2);
        ksession.fireAllRules();
        
        ksession.dispose();
        
        Assert.assertTrue(applicant1.isEligible() == false);//John is not eligible
        Assert.assertTrue(applicant2.isEligible() == true); //Peter is eligible
    }
    
}

Step 6: The output:

 
package com.mycompany.app.drools;
import com.mycompany.app.drools.ApplicantForm;
import com.mycompany.app.drools.Applicant;
import com.mycompany.app.drools.ApplicantDao;
import com.mycompany.app.drools.ApplicantDaoImpl;
global ApplicantDao applicantDao;

rule "License criteria_1"
when
   $a : ApplicantForm();
   $applicant: Applicant( age < 18 ) from applicantDao.findApplicant($a.getApplicantId());
then
   $a.setEligible( false );
end



fetched applicant: name=John, age=16
fetched applicant: name=Peter, age=20



Labels:

Java Tree finding the Lowest Common Ancestor (LCA)

This extends Java Preorder Tree Traversal : recursive and iterative flattening of tree. This is also a very popular coding interview question.

Q. Find out the LCA (i.e. Lowest Common Ancestor) for nodes a and b where a = 3 and b = 4 as shown below?



A. The Node a has ancestors : 2 and 1.  The Node b has ancestors 2 and 1. The Lowest Common Ancestor is Node with value 2. Let's look at the code for this.


Step 1: Define the TreeNode class as did before but define the "parent" attribute so that each node knows not only who the children are, but also who the parent is as well.


 
package com.mycompany.app14;

public class TreeNode
{
    
    private int value;
    //children
    private TreeNode left;
    private TreeNode right;
    //parent
    private TreeNode parent;
    
    public TreeNode(int value, TreeNode left, TreeNode right)
    {
        super();
        this.value = value;
        this.left = left;
        this.right = right;
    }
    
    public int getValue()
    {
        return value;
    }
    
    public void setValue(int value)
    {
        this.value = value;
    }
    
    public TreeNode getLeft()
    {
        return left;
    }
    
    public void setLeft(TreeNode left)
    {
        this.left = left;
    }
    
    public TreeNode getRight()
    {
        return right;
    }
    
    public void setRight(TreeNode right)
    {
        this.right = right;
    }
    
    public TreeNode getParent()
    {
        return parent;
    }
    
    public void setParent(TreeNode parent)
    {
        this.parent = parent;
    }
    
    @Override
    public String toString()
    {
        return "TreeNode [value=" + value + ", left=" + left + ", right=" + right + "]";
    }  
}


Step 2: The test class that constructs the tree structure and then calculates the LCA. Uses a Deque class, which is a LIFO structure.

 
package com.mycompany.app14;

import java.util.ArrayDeque;
import java.util.Deque;

public class TestFindCommonAncestor
{
    
    public static void main(String[] args)
    {
        TreeNode root = createOneTo6PreOrderTree();
        
        //Find the common ancestor for two given nodes a and b.
        
        //root node value is 1, node a is 3, and node b is 4
        //so, find the Least Common Ancestor for nodes representing values 3 and 4
        TreeNode commonNode = findLowestCommonAncestor(root.getLeft().getLeft(), root.getLeft().getRight());
        System.out.println(commonNode);
        
    }
    
    private static TreeNode createOneTo6PreOrderTree()
    {
        TreeNode leaf3 = new TreeNode(3, null, null);
        TreeNode leaf4 = new TreeNode(4, null, null);
        TreeNode leaf6 = new TreeNode(6, null, null);
        
        TreeNode node5 = new TreeNode(5, leaf6, null);
        TreeNode node2 = new TreeNode(2, leaf3, leaf4);
        
        TreeNode root1 = new TreeNode(1, node2, node5);
        
        //set parents
        leaf3.setParent(node2);
        leaf4.setParent(node2);
        
        leaf6.setParent(node5);
        
        node2.setParent(root1);
        node5.setParent(root1);
        
        return root1;
    }
    
    /**
     * @param a
     * @param b
     * @return
     */
    public static TreeNode findLowestCommonAncestor(TreeNode a, TreeNode b)
    {
        TreeNode oldNode = null;
        
        //find the parent nodes of a: should have 1, 2, and 3 for a = 3 
        Deque<TreeNode> parentNodesA = new ArrayDeque<TreeNode>();
        while (a != null)
        {
            parentNodesA.push(a);
            a = a.getParent();
        }
        
        //find the parent nodes of b: should have 1, 2 and 4 for b = 4
        Deque<TreeNode> parentNodesB = new ArrayDeque<TreeNode>();
        while (b != null)
        {
            parentNodesB.push(b);
            b = b.getParent();
        }
        
        //initially a and b will be null
        while (a == b && !parentNodesA.isEmpty() && !parentNodesB.isEmpty())
        {
            oldNode = a;
            a = parentNodesA.pop();
            b = parentNodesB.pop();
        }
        
        // a will be 3 and b will be 4 and oldNode will be 2
        if (a == b)
        {
            return a;                        // One node is descended from the other
        }
        else
        {
            return oldNode;                 // Neither is descended from the other
        }
        
    }
}



Step 3: Output

 
TreeNode [value=2, left=TreeNode [value=3, left=null, right=null], right=TreeNode [value=4, left=null, right=null]]

Labels: ,

Oct 22, 2013

jBehave Tutorial

This extends the previous tutorials
To appreciate jBehave, let's look at a better example here. This example is about a science formula

  Speed = distance / Time.

So,

  • given  distance and time, calculate speed
  • given speed and time, calculate distance
  • given speed and distance, calculate time.

Step 1: The story file in plain english. speed.story under src/main/resources/jBehave folder.


Narrative: As a student, I want to practice speed formula where speed = distance / time

scenario: calculate speed from distance and time

Given distance = 10.0
Given time = 2.5
When calculate speed
Then verify speed = 4.0


scenario: calculate distance from speed and time

Given speed = 4.0
Given time = 2.5
When calculate distance
Then verify distance = 10.00

scenario: calculate time from speed and distance

Given speed = 4.0
Given distance = 10.0
When calculate time
Then verify time = 2.50


Step 2: Mapping the story to Java step class. The steps are fine grained so that they can be mixed and matched depending on th scenario.

package com.mycompany.jbehave2;

import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Named;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;
import org.jbehave.core.steps.Steps;
import org.springframework.util.Assert;

public class SpeedVelocityFormulaSteps extends Steps
{
    
    SpeedVelocityFormaula svf = new SpeedVelocityFormulaImpl();
    
    private double speed;
    private double distance;
    private double time;
    
    private double resultSpeed;
    private double resultDistance;
    private double resultTime;
    
    @Given("speed = $speed")
    public void speedInput(@Named("speed") double speed)
    {
        this.speed = speed;
    }
    
    @Given("distance = $distance")
    public void distanceInput(@Named("distance") double distance)
    {
        this.distance = distance;
    }
    
    @Given("time = $time")
    public void timeInput(@Named("time") double time)
    {
        this.time = time;
    }
    
    @When("calculate speed")
    public void calcSpeed()
    {
        Assert.notNull(distance);
        Assert.notNull(time);
        
        resultSpeed = svf.calculateSpeed(this.distance, this.time);
    }
    
    @When("calculate distance")
    public void calcDistance()
    {
        Assert.notNull(speed);
        Assert.notNull(time);
        
        resultDistance = svf.calculateDistance(this.speed, this.time);
    }
    
    @When("calculate time")
    public void calcTime()
    {
        Assert.notNull(speed);
        Assert.notNull(distance);
        
        resultTime = svf.calculateTime(this.speed, this.distance);
    }
    
    @Then("verify speed = $speedSupplied")
    public void verifySpeed(double speedSupplied)
    {
        Assert.notNull(distance);
        Assert.notNull(time);
        
        junit.framework.Assert.assertEquals(speedSupplied, resultSpeed);
    }
    
    @Then("verify distance = $distanceSupplied")
    public void verifyDistance(double distanceSupplied)
    {
        Assert.notNull(this.speed);
        Assert.notNull(time);
        
        junit.framework.Assert.assertEquals(distanceSupplied, resultDistance);
    }
    
    @Then("verify time = $timeSupplied")
    public void verifyTime(double timeSupplied)
    {
        Assert.notNull(speed);
        Assert.notNull(distance);
        
        junit.framework.Assert.assertEquals(timeSupplied, resultTime);
    }
    
}

Step 3: The actual interface that performs the calculations.

package com.mycompany.jbehave2;

public interface SpeedVelocityFormaula
{
    abstract double calculateSpeed(double distance, double time);
    
    abstract double calculateDistance(double speed, double time);
    
    abstract double calculateTime(double speed, double distance);
}

Step 4: The implementation. This is the class under test.


package com.mycompany.jbehave2;

public class SpeedVelocityFormulaImpl implements SpeedVelocityFormaula
{  
    public double calculateSpeed(double distance, double time)
    {
        return distance / time; // s = d/t
    }
    
    public double calculateDistance(double speed, double time)
    {
        return speed * time; //speed * time
    }
    
    public double calculateTime(double speed, double distance)
    {
        return distance / speed;  //distance/speed
    }
    
}


Step 5: Finally the jUnit test class

package com.mycompany.jbehave2;

import de.codecentric.jbehave.junit.monitoring.JUnitReportingRunner;

import java.util.Arrays;
import java.util.List;

import org.jbehave.core.junit.JUnitStories;
import org.jbehave.core.steps.InjectableStepsFactory;
import org.jbehave.core.steps.InstanceStepsFactory;
import org.junit.runner.RunWith;

@RunWith(JUnitReportingRunner.class)
public class JBehaveUnitTest extends JUnitStories
{
    
    public JBehaveUnitTest()
    {
        super();
    }
    
    public InjectableStepsFactory stepsFactory()
    {
        return new InstanceStepsFactory(configuration(), new SpeedVelocityFormulaSteps());
    }
    
    @Override
    protected List<String> storyPaths()
    {
        return Arrays.asList("jbehave/speed.story");
    }
    
}

Step 6: Run th unit test.



Labels: ,

Oct 21, 2013

How to become a Java freelancer?

Anyone can become a freelancer, but the hardest part of becoming a freelancer is finding work. You just can't go to a freelance site like Elance.com or Odesk.com and expect to pull jobs that will give you a steady income. Those are low-dollar markets for some countries as you will be competing against people around the world. Hence, this post is based on working for a single client locally on a longer term basis like 3 months to 24 months. So, to find jobs continously

You need to "talk the talk" in your job interviews to get hired as a Java freelancer, and "walk the walk" at your freelance Java work to impress your client and consequently get repeated extensions. It can also be a challenge for Java freelancers who want to break into the finance sector as it pays slightly better rates.


So, you need to develop certain skills that distinguishes you both technically and non-technically from your competition. These are not hard and fast steps, but general guidelines from my experience. Some achieve it quicker whilst others take longer. It depends on the individual and the nature of the market (i.e. demand versus supply).


Step 1: Develop the experience and skills required to become a freelancer.
  • At least 2-3 years hands-on experience with Java, Enterprise Java, XML, SQL, regex, JSON and sought-after frameworks like Spring and Hibernate. Check the local advertisements to see what the prospective employers are looking for. Good to have 2 to 3 projects completed through the full SDLC.
  • Get a good handle on the 16 key areas to solve real business problems and to better market your skills at the job interviews and on the job. I am yet to work for an organization that did not have performance issues, concurrency issues, security vulnerabilities, and memory leaks. So learn how to create and analyze thread dumps, use visual VM to analyze memory leaks and performance issues, etc. You also need to know the big picture of the baseline architecture. you had worked on.
  • You can be a front-end developer (i.e. focusing mainly on GUI development), back end developer (i.e. writing web services to retrieve data from the database and other systems) integrating various systems, or do both, but you tend to have more strength either on front-end or back-end development. I do both, but stronger on the back end development.
  • Have good marketing skills -- 1. Good resume writing 2. Good interview preparation by brushing up on the fundamentals. I use my own resources to brush up just 6 weeks before my current contract is about to expire. I need to compete with other talented freelancers and contractors. Preparation not only breeds confidence, but also ability to sell myself more on work related accomplishments on the 16 key areas and sought-after frameworks.
  • Good networking skills. Build your network via LinkedIn.com and regular catch ups with your former bosses and colleagues. You will be under less scrutiny when you find your next contract via your previous contacts and earn a bit more by cutting out the middleman the "consulting agency" or the "recruiter".


How to become a software architect?
Many Java developers aspire a career as an architect. Can you just study to become a software architect? Will becoming an architect adversely impact your freealancing career as there are more developer jobs than architect jobs? The key is to become a hands-on solution architect. Have 2 resumes. One as Java architect and the other as Java developer.


Step 2:  Register yourself with the recruitment agencies and online freelance sites

  • Send your CV or resume to consulting or recruitment agencies so that they have your  details in their databases. Big clients prefer to deal with consulting or recruitment agencies as they do not directly want to keep in touch with hundreds of freelancers and negotiate rates. Also, if you prematurely leave a client for unforeseen reasons, then the consultancy or recruitment agency can quickly find a replacement.
  • Join the relevant professional bodies like Java forums and LinkedIn.com to advertise your availability. 
  • As only 30% to 40% of the real vacancies are advertised,  build your network to find your future contracts via your contacts. Make it a point to regularly catch-up with your former colleagues and bosses. Build a good rapport with a handful of consultancy or recruitment agencies so that they can proactively look for work on your behalf to create a "win/win" outcome for both. I have done this very successfully. 





Note: If you want to work on multiple assignments on a shorter term, then register yourself with sites like odesk.com, freelancer.com, elance.com, guru.com and bid for jobs. I have not done this myself as I prefer working for a single client on a longer term basis. 

Step 3: Decide whether you want to start your own company or go via an umbrella company.

  •  As you need to have professional indemnity and liability insurance you have to either organize it yourself if you are registering yourself as a company or use an umbrella company set up to look after these for you. You become a pay as you go employee of that umbrella company. These umbrella companies can look after your insurance and other administrative needs. You need to pay the umbrella company 3% to 5% of your pay for the service they provide. Consult an accountant and talk to fellow freelancers in your jurisdiction to see what works best for you. Each approach has its pros and cons. I go via an umbrella company as I will have no administrative work to worry about.

Step 4: Carefully asses the position(s) or offer(s) on the table

Freelancers or contractors are hired for 3 main reasons.
  1. To get them to do the boring work that other permanent staff  don't want to take on.
  2. To get the project over the line. In other words meet the deadline. 
  3. To bring in expertise that are lacked within the current team. 
So, it is imperative to learn more about the position at the job interview to ensure what you are getting into. Ask about the technologies and frameworks used, mission criticality of the project  - e.g. how many registered users?, how many servers on the clusters, the development team size, number of other systems to be integrated with? (e.g. CRM system, Data warehouse system, CMS system, etc) and so on.

You would ideally want points 2 and 3 to be the reason where you can acquire more skills and experience.

When you are asked for your contracting rates, provide a range like $650.00 to $750.0 a day as you don't want to price yourself out of the market and at the same time miss out on great opportunities. After your job interview, you will be in a better position to negotiate further once you have sold your capabilities to your prospective employer.

Step 5: Enjoy your career as a freelancer and continue to improve on step 1, 2 and 4 with more experience and exposure.

  • Endeavor  to build specialized skills in Java to increase your rates and reduce your competition. So, build niche skills by having Java + [something].  In 2004/2005, if you know Java + Spring framework + Hibernate you would have been in hot demand. But now there are thousands of developers with these skills sets. So, when you are lucky enough to pick from multiple contract or freelancing offers, choose the one that is more conducive to acquiring niche skills. Here are some examples from my experience -- A BPM  tool like IBM Lombardi, a SOA tool like web Methods, experience with highly scalable trading application using FIX protocol, a BI (Business Intelligence) tool like IBM Cognos, in memory Data grid like Oracle coherence, BigData (e.g. Hadoop)etc. In short, good system integration skills. Most applications built today are distributed. Learning Apache Camel will be handy as well.
  • If you fancy web development, invest your time in learning HTML5, CSS3, JavaScript, and JavaScript based frameworks like Angular JS, Backbone, etc. Single page RIA (Rich Internet Application) type applications are very popular using ajax calls to back end RESTful services. These frameworks use MVW (Model View Whatever) design patterns.
  • Continuously update your resume and online profiles with newly acquired skills and experience. Also, get your consultancy and recruitment agencies to update their databases.


You will gain more confidence as you go through the above steps. Freelancing  is not everyone's cup of tea, but can give professional freedom and better income streams for some.   The pros and cons of freelancing and other questions and answers are discussed in the post entitled "why work as a Java freelancer?". Some may prefer doing it for a short while and then settle down with a company to grow within that organization. Some love to do it, but fearful of or too complacent in the current role to take the first step. First step is always the hardest. Freelancing or not, more and more organizations are becoming leaner and meaner to make profit for their stake holders, and staying relevant with the technologies/frameworks without being too complacent about your current role is your only job security as a software developer. This blog has lots of technical know hows and career making tips to stay relavant.

I thoroughly enjoy my career as a freelance Java developer. In addition to monetary benefits, it also helped me fast-track my career without feeling stagnated and work with very talented Java developers.

Hope to hear your experience as a freelancer, especially for multiple clients via odesk.com, elance.com, etc.

Disclaimer: This is a general discussion only. It is imperative that you consult your accountant for relevant business structure and tax laws in your jurisdiction.

You may also like:

Labels: ,

Oct 20, 2013

Why become a Java freelancer?

Q. Why a contractor or freelancer is paid more than permanent developers?
A.
  • cost to a company for a permanent employee with benefits can be 1.5 to 2.5 times the amount they see in their pay check 
  • As a compensation for short term or temporary nature of the assignment.  Freelancers or contractors can be easily hired and fired.
  • To attract specialized and wide range of skills. Companies can hire contractors for 3 reasons.  Aim for reason number 3 described in the next answer.
Q. Why do organizations hire freelancers or contractors?
A. For 3 main reasons outlined below.

1. to get someone to do some dirty or non-interesting work that  their permanent staff is not too keen to perform.  

2. to get some additional work force on a temporary basis to get the project over the line as it is not always possible to predict workload.

3. to get expertise, which lacks in the current team. For example, get a Java developer with drools experience, etc. So, as a contractor or freelancer, if you have Java experience with some niche skills like a commercial BPM framework like IBM Websphere Lombardi, Business Intelligence (BI) software like IBM Cognos or in-memory data grid like Oracle Coherence. In the third scenario, you can call yourself more a "consultant" than a contractor.
    When you get multiple job offers to choose from, favor offers that provide Java/JEE + a sought-after commercial product experience like  a BPM (e.g. Pegasystems), SOA (Oracle Service Bus), Business Intelligence (IBM Cognos BI),  BigData (e.g. Hadoop), etc as these skills and experience cannot be self-taught like Spring or Hibernate. Specialized skills are more sought-after.

    Q. How many years of experience do you need before becoming a freelancer or a contractor?
    A. Generally 2 to 5 years.

    Q. Why work as a freelancer?
    A.
    • Better pay.  Usually, 1.5 to 2 times the permanent staff. So, you can take some time off to travel or work on your passive income generating ideas.
    • Gives you more freedom, and opportunity to acquire wider range of skills. You will have better control of your career direction by carefully choosing your contracts. Ask the right questions at your job interviews.
    • Don't have to get involved with the company politics. Do your job well, and build your network to find your future contracts directly without having to go through the job agencies.
    • Gets you out of your comfort zone to explore other opportunities and acquire new skills. 
    • Overall gives you the professional (and  possibly financial) freedom.

    Q. What are the disadvantages or risks of working as a freelancer or contractor?
    A.
    • Job security risk as your income can be unstable, especially in a difficult job market. This is more true for freelancers than contractors. This is where working on your passive income generating ideas become handy. I tend to start looking for new contracts around 6 weeks prior to my current contract expires.
    • You may have to do additional paperwork as part of insurance (e.g. professional indemnity insurance) and tax requirements. You will also be under different type of scrutiny when you apply for loans as you will have to provide evidence that you have a steady income. I go through an umbrella company as their employee for a nominal fee of 3% of my rate. This not only frees me from any administrative tasks to concentrate more on what I enjoy doing, but also makes it easier to apply for loans.
    • Freelancers also run the risk of not getting paid. This is not much of a problem for the contractors unless they work for a start up or a company that is in a brink of receivership.  Do your research on the company. 
    • You also don't have the benefits like health benefits, sick pay, holiday pay, etc. But, this can be compensated in your regular rate.
    • You need to regularly prepare for your job interviews.

    Q. Is there a difference between a Java contractor and a Java freelancer?
    A. Even though these terms are used interchangeably, there is a subtle difference.

    A contractor:  generally works for one client on an exclusive basis for a longer term say 3 to 12 months. Contractual agreements may prohibit you to work for other clients. You will get paid on an hourly or daily rate, and rates are generally 1.5 to 2 times the equivalent permanent role.You normally work at the client's location. You can find contract jobs through recruitment agencies, job advertisements or your network. This tends to have more security and steady income than a freelancer.

    A freelancer: generally works for multiple clients on a project by project basis for shorter period. You normally work at your location and visit the client office as needed. You will have to find your work on your own. You could even have overseas clients. There are popular websites like the ones listed below to bid for work. Handy to gain some extra income while gaining much needed hands-on experience.
    You can’t just jump on a freelance website and expect to pull jobs that will give you a good steady income. These are low-dollar markets as you will be competing with people around the world. Especially with people who are prepared to do the job for very low wages to gain much needed hands-on experience or to supplement their more permanent incomes. If your main focus is to gain more practical experience, then this is not a bad avenue.




    A volunteer: sole purpose is to gain much needed hands-on experience with a nominal pay or no pay. Good for beginners, and smaller businesses, charities, and community groups are more likely  to offer volunteer jobs.


    Freelancing means professional freedom, but it also means instability and the risk of failure. But if you risk your stability for something more in tune with your professional goals than a traditional job, you have the opportunity to build your name and reputation and reap more rewards.  You are the best person to decide what is best for you.

    "If you do not take risks, you will never accomplish anything."

    I have been working as a Java freelancer since 2003 and always found jobs one after another. I have shared my experience as to how you can become a freelancer (or a contractor) and what you can do to mitigate the risk. I use the term freelancer to be more of a contractor to work between 3 to 12 months for the same client.

    Disclaimer: This is a general discussion only. It is imperative that you consult your accountant for relevant business structure and tax laws in your jurisdiction.

    How to earn more as a Java developer?
    Always look beyond salary or rate when considering your options. Don't base your happiness on money alone. Job satisfaction and opportunity to grow further are equally important. Firstly, find something that you really enjoy doing., then see what happens ............

    Important: This was written as a general discussion only. The terminologies may  differ in other countries. Check the tax laws and contractual agreements carefully in your jurisdiction.


    You may also like:

    Labels: ,

    Oct 18, 2013

    Spring Java based configuration using @Configuration and @Bean


    Traditionally, Spring allows the developer to manage bean dependencies using XML based configuration through the use of application context XML file. This file is external to the application and it holds definition of beans and its dependencies for that application. There is an alternative way to define bean and its dependencies. Its called as Java based configuration.Unlike XML, Java based configuration enables you to manage beans programatically. This can be acheived through use of various annotations.
    This is acheived using @Configuration and @Bean annotations as demonstrated in real life example as shown in posts
    In this post, let's look at a typical Java configuration based dependency management.


    package com.myapp.bdd.stories;
    
    import com.myapp.*;
    
    import org.powermock.api.mockito.PowerMockito;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.context.annotation.Import;
    import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
    
    
    @Configuration
    //packages and components to scan and includ
    @ComponentScan(
            basePackages =
            {
                "com.myapp.calculation.bdd",
                "com.myapp.refdata",
                "com.myapp.dm.dao"
            
            },
            useDefaultFilters = false,
      //interfaces
            includeFilters =
            {           
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyApp.class),
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyAppDroolsHelper.class),
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = TransactionService.class),
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = TransactionValidator.class),
              
                @ComponentScan.Filter(type = FilterType.ANNOTATION, value = org.springframework.stereotype.Repository.class)
            })
    //import other config classes  
    @Import(
    {
        StepsConfig.class,
        DataSourceConfig.class,
        JmsConfig.class,
        PropertiesConfig.class
    })
    public class StoryConfig
    {
        
     
     //creates a partially mocked transaction service class
     
        @Bean(name = "txnService")
        public TransactionService getTransactionService()
        {
            return PowerMockito.spy(new TransactionService());
        }
        
    }
    

    As shown the components can be scanned by assignable type or annotation.

    Here is another example. Pay attention to the annotations used.

     
    package com.myapp.config;
    
    import com.myapp.deadlock.DeadlockRetryAspect;
    
    @Component
    @Import(
    {
        JmsConfig.class, 
        ExceptionConfig.class
    })
    @EnableJpaRepositories(basePackageClasses =
    {
        Report.class, 
     Transaction.class
    })
    @ComponentScan(basePackageClasses =
    {
        Classifier.class,
        AccountServiceImpl.class,
        TaxDaoImpl.class,
    }, useDefaultFilters = false, includeFilters =
    {
       
        @Filter(type = FilterType.ASSIGNABLE_TYPE, value = TaxService.class),
        @Filter(type = FilterType.ASSIGNABLE_TYPE, value = Classifier.class),
        @Filter(type = FilterType.ASSIGNABLE_TYPE, value = TaxDao.class),
      
        
        //All the repositories
        @Filter(type = FilterType.ANNOTATION, value = Repository.class),
        
     
    })
    @Configuration
    @PropertySource(
    {
        "classpath:reporting/report.properties", 
        "classpath:tax/tax.properties",
        "classpath:exception/exception.properties"
    })
    public class AccountingConfig
    {
    }
    
    


    You can bootsrap the above class as shown below

        
    public static void main(String[] args) {
      ApplicationContext ctx = new AnnotationConfigApplicationContext();
      ctx.register(StoryConfig.class)
    }
    




        
    public static void main(String[] args) {
      ApplicationContext ctx = new AnnotationConfigApplicationContext();
      ctx.register(AccountingConfig.class)
    }
    
    


    There are plenty of things you can do with Java configuration. The advantage is its type safety and downside is ofcourse you have to re-compile the application if you make any changes to the configuration in your Java class. So, it is worth knowing both Java and XML way of configuring your spring beans. So, don't be baffled if both approiaches are used in the next project you work on. There are more practical examples here.

    Labels:

    Oct 17, 2013

    Ehcache a beginner level tutorial

    Q. Why would you cache objects in your Java application?
    A. Caching can boost performance by offloading your database, and simplifying scalability.

    Q. Have you used any cahing framework in Java?
    A. Yes. Ehcache is the most widely-used Java-based cache because it’s robust, proven, and full-featured. Ehcache scales from in-process, with one or more nodes, all the way to mixed in-process/out-of-process configurations with terabyte-sized caches. For applications needing a coherent distributed cache, Ehcache uses the open source Terracotta Sever Array. In Hibernate you can configure Ehcache as your second-level cache.

    Here is a simple tutorial.

    Step 1: Maven pom.xml file to show dependency.


    <dependency>
     <groupId<net.sf.ehcache</groupId>
     <artifactId<ehcache-core</artifactId>
     <version<2.5.2</version>
    </dependency>
    


    Step 2: Define the ehcache config file ehcache.xml under src/main/resources/ehcache folder.

    <?xml version="1.0" encoding="UTF-8"?>
        
    <ehcache name="EmployeeCache">
    
          <defaultCache
              maxElementsInMemory="10000"
              eternal="false"
              timeToIdleSeconds="120"
              timeToLiveSeconds="120"
              overflowToDisk="true"
              diskSpoolBufferSizeMB="30"
              maxElementsOnDisk="10000000"
              diskPersistent="false"
              diskExpiryThreadIntervalSeconds="120"
              memoryStoreEvictionPolicy="LRU"/>
        
          <cache name="employees"
                 maxElementsInMemory="100"
                 maxElementsOnDisk="0"
                 eternal="false"
                 timeToIdleSeconds="120"
                 timeToLiveSeconds="0"
                 memoryStoreEvictionPolicy="LFU">
          </cache>
        
    </ehcache>
    
    
    
    
    Step 3: Define the model class Employee that needs to be Serializable.

    package com.mycompany.app.ehcache;
    
    import java.io.Serializable;
    
    public class Employee implements Serializable
    {
        private Integer emplId;
        private String firstName;
        private String lastname;
        
        public Employee(Integer emplId, String firstName, String lastname)
        {
            super();
            this.emplId = emplId;
            this.firstName = firstName;
            this.lastname = lastname;
        }
        
        public Integer getEmplId()
        {
            return emplId;
        }
        
        public void setEmplId(Integer emplId)
        {
            this.emplId = emplId;
        }
        
        public String getFirstName()
        {
            return firstName;
        }
        
        public void setFirstName(String firstName)
        {
            this.firstName = firstName;
        }
        
        public String getLastname()
        {
            return lastname;
        }
        
        public void setLastname(String lastname)
        {
            this.lastname = lastname;
        }
        
        @Override
        public String toString()
        {
            return "Employee [firstName=" + firstName + ", lastname=" + lastname + "]";
        }
        
    }
    

    Step 4: The next step is to define a SimpleEHCache class.

    package com.mycompany.app.ehcache;
    
    import java.io.InputStream;
    
    import net.sf.ehcache.CacheManager;
    import net.sf.ehcache.Ehcache;
    import net.sf.ehcache.Element;
    
    public class SimpleEHCache
    {
        /**
         * The CacheManager provides us access to individual Cache instances
         */
        private static final CacheManager cacheManager;
        
        static
        {
            
            ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
            InputStream resourceAsStream = contextClassLoader.getResourceAsStream("ehcache/ehcache.xml");
            cacheManager = CacheManager.create(resourceAsStream);
        }
        
        /**
         * A cache that we're designating to hold Employee instances
         */
        private Ehcache employeeCache;
        
        public SimpleEHCache()
        {
            // Load our employees cache:
            employeeCache = cacheManager.getEhcache("employees");
        }
        
        /**
         * Adds a new Employee to the Cache
         */
        public void addEmployee(Integer id, Employee employee)
        {
            // Create an EHCache Element to hold the Employee
            Element element = new Element(id, employee);
            
            // Add the element to the cache
            employeeCache.put(element);
        }
        
        /**
         * Retrieves a Employee from the cache
         */
        public Employee getEmployee(Integer id)
        {
            // Retrieve the element that contains the requested Employee
            Element element = employeeCache.get(id);
            if (element != null)
            {
                
                return (Employee) element.getValue();
            }
            
            return null;
        }
    }
    


    Step 5: Finally, the unit test class.

    package com.mycompany.app.ehcache;
    
    import org.junit.Assert;
    import org.junit.Before;
    import org.junit.Test;
    
    public class SimpleEHCacheTest
    {
        private SimpleEHCache simpleEHCacheExample;
        
        @Before
        public void setUp()
        {
            // Create a sample SimpleEHCacheExample object
            simpleEHCacheExample = new SimpleEHCache();
            
            // Add a few employees
            simpleEHCacheExample.addEmployee(1, new Employee(1, "John", "Sander"));
            simpleEHCacheExample.addEmployee(2, new Employee(2, "Peter", "Sander"));
            simpleEHCacheExample.addEmployee(3, new Employee(3, "Emma", "Sander"));
        }
        
        @Test
        public void testRetrieve()
        {
            Employee employee = simpleEHCacheExample.getEmployee(1);
            Assert.assertNotNull("The employee was not found in the cache", employee);
            Assert.assertEquals("Did not find the correct employee", "John", employee.getFirstName());
        }
        
        @Test
        public void testRetrieveNotFound()
        {
            Employee employee = simpleEHCacheExample.getEmployee(5);
            Assert.assertNull("I did not expect find the employee in the cache but it was there", employee);
        }   
    }
    


    Labels: