Google

Sep 17, 2013

Google Guava library handy methods to write your Comparators for sorting

Sorting objects in a collection key in presenting those objects in GUI or report like PDF, etc. In Java you use a Comparator interface or the Comparable interface to define the custom sorting logic. I hava covered this in a number of following blog posts.
 Recently, I had the opportunity to work with a number of Google Guava libraries and its comparator  came handy to write a more concise code to get the same thing done. Working with Java Collection using Gauva was covered with examples.

Step 1: The Guava library dependency in pom.xml file.

<!--  Google GUAVA -->
<dependency>
 <groupId>com.google.guava</groupId>
 <artifactId>guava</artifactId>
  <version>13.0.1</version>
</dependency>


Step 2: Here is a sample ReportKey value object class that uses Apache common librarie's utility methods for equals( ), hashCode( ), toString( ), and compareTo( ) methods. Implementing the Comparable interface and providing the compareTo method provides natural ordering for the ReportKey class. It is also a best pracrice to define your key class as an immutable object. Defensive copying is used to make it immutable.

package com.myapp.reporting;

import java.util.Date;

import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.springframework.util.Assert;

public class ReportKey implements Comparable<ReportKey>
{    
    private String clientId;
    private Date valuationDate;
    
    public ReportKey()
    {
    }
    
    private ReportKey(String clientId, Date valuationDate)
    {
        this.clientId = clientId;
        this.valuationDate = new Date(valuationDate.getTime()); // defensive
                                                                // copy
    }
    
    public static ReportKey newInstance(String clientId, Date valuationDate)
    {
        Assert.notNull(clientId);
        Assert.notNull(valuationDate);
        return new ReportKey(clientId, valuationDate);
    }
    
    public String getClientId()
    {
        return clientId;
    }
    
    public Date getValuationDate()
    {
        return new Date(valuationDate.getTime()); // defensive copy
    }
    
    @Override
    public int hashCode()
    {
        return new HashCodeBuilder().append(clientId).append(valuationDate).toHashCode();
    }
    
    @Override
    public boolean equals(final Object obj)
    {
        if (obj instanceof ReportKey)
        {
            final ReportKey other = (ReportKey) obj;
            return new EqualsBuilder().append(clientId, other.clientId).append(valuationDate, other.valuationDate)
                    .isEquals();
        }
        return false;
    }
    
    @Override
    public String toString()
    {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
    
    @Override
    public int compareTo(ReportKey reportKey)
    {
        return new CompareToBuilder().append(this.clientId, reportKey.clientId)
                .append(this.valuationDate, reportKey.valuationDate).toComparison();
    }
}



Step 3: The above natual ordering sorts by clientId and valuationDate in ascending order. What if you ant to sort it by clientId in ascending order and by valuationDate in descending order? Here is sample anonymous class using Google's Gauva library.

List<ReportKey> reportKeys = (List<ReportKey>) reportService.find();
Collections.sort(reportKeys, new Comparator<ReportKey>()
{
    @Override
    public int compare(ReportKey o1, ReportKey o2)
    {
        return ComparisonChain.start()
                .compare(o1.getClientId(), o2.getClientId())
                .compare(o1.getValuationDate(), o2.getValuationDate(), Ordering.natural().reverse())
                .result();
    }
});


Labels:

Aug 14, 2013

Google Gauva library to work with the collection objects.

The Guava project contains several of Google's core libraries that we rely on in our Java-based projects: collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, and so forth. This blog post deals with the Collection utilities using Functional programming. As of Java 7, functional programming in Java can only be approximated through awkward and verbose use of anonymous classes. This is expected to change in Java 8, Please be aware that excessive use of Guava's functional programming idioms can lead to verbose, confusing, unreadable, and inefficient code. Hre is a sample code to demonstrate partitioning, transforming, and filtering.


Step 1: The Guava library dependency in pom.xml file.


<!--  Google GUAVA -->
<dependency>
 <groupId>com.google.guava</groupId>
 <artifactId>guava</artifactId>
  <version>13.0.1</version>
</dependency>


Step 2: Sample code using the Gauva library.

package com.mycompany.app11;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class GuavaMain
{
    public static void main(String[] args)
    {
        GuavaMain main = new GuavaMain();
        List<Employee> initialData = main.prepareData();
        
        //Split into batches
        Iterable<List<Employee>> batchedData = main.partitionData(initialData);
        System.out.println("Batching -- 2 batches of employees: " + batchedData);
        
        //transform the above batches of employees to extract their names
        Iterable<Set<String>> transformedData = main.transformData(batchedData);
        System.out.println("Transforming -- " + transformedData);
        
        //concat and filter with a predicate       
        Set<String> filteredData = main.filterData(transformedData);
        System.out.println("Filtering -- " + filteredData);
        
    }
    
    private List<Employee> prepareData()
    {
        //create 4 employees
        Employee john = new Employee(22, "John");
        Employee peter = new Employee(23, "Peter");
        Employee sam = new Employee(24, "Sam");
        Employee eric = new Employee(25, "Eric");
        
        List<Employee> employees = new ArrayList<Employee>();
        employees.add(john);
        employees.add(peter);
        employees.add(sam);
        employees.add(eric);
        
        return employees;
    }
    
    /**
     * Say we want to process in batches of 2 employees
     */
    public Iterable<List<Employee>> partitionData(List<Employee> departments)
    {
        //using Gauva library's partition method
        return Iterables.partition(departments, 2);// batches of 2 employees.
    }
    
    /**
     * Say we want to transform batched employees to extract their names
     */
    public Iterable<Set<String>> transformData(Iterable<List<Employee>> batchedData)
    {
        //define an anonymous function
        Function<List<Employee>, Set<String>> extractNamesFunction = new Function<List<Employee>, Set<String>>()
        {
            public Set<String> apply(List<Employee> batch)
            {
                final Set<String> names = new HashSet<String>(batch.size());
                for (Employee employee : batch)
                {
                    names.add(employee.getName());
                }
                return names;
            }
            
        };
        
        //using Gauva library's transform method
        Iterable<Set<String>> transformedData = Iterables.transform(batchedData, extractNamesFunction);
        
        return transformedData;
    }
    
    /**
     * Say we want to filter data so that names shorter than 3 characters are
     * filtered out
     */
    public Set<String> filterData(Iterable<Set<String>> transformedData)
    {
        //using Gauva library's concat method
        Iterable<String> concatenatedData = Iterables.concat(transformedData);
        
        //Define a predicate for filtering data as an anonymous function
        Predicate<String> longerThanThreeCharacters = new Predicate<String>()
        {
            public boolean apply(String input)
            {
                return input.length() > 3;
            }
        };
        
        //filter
        FluentIterable<String> filteredData = FluentIterable.from(concatenatedData).filter(longerThanThreeCharacters);
        
        return filteredData.toImmutableSet();
    }
    
}




package com.mycompany.app11;

public class Employee
{
    private Integer id;
    private String name;
    
    public Employee(Integer id, String name)
    {
        super();
        this.id = id;
        this.name = name;
    }
    
    public Integer getId()
    {
        return id;
    }
    
    public void setId(Integer id)
    {
        this.id = id;
    }
    
    public String getName()
    {
        return name;
    }
    
    public void setName(String name)
    {
        this.name = name;
    }
    
    @Override
    public String toString()
    {
        return "Person [id=" + id + ", name=" + name + "]";
    }
    
}

The Employee POJO:

Step 3: Finally, the output:

Batching -- 2 batches of employees: [[Person [id=22, name=John], Person [id=23, name=Peter]], [Person [id=24, name=Sam], Person [id=25, name=Eric]]]
Transforming -- [[Peter, John], [Sam, Eric]]
Filtering -- [Peter, John, Eric]


Reference: Guava Collection Utilities

Labels: ,

Apr 4, 2013

Top 3 Core Java Third Party librararies that you use frequently in your Java projects

Q. Can you list a few third party libraries and useful methods that you frequently use in you core Java and enterprise Java development?
A. Firstly, the Apache Commons library has a number of utility methods to simplify your development with a number of proven APIs with utility methods.

Firstly, the toString(  ), equals( .. ), and hashCode( ... ) methods are very frequently used in your domain or value object classes. Here are a few handy Apache commons library methods.


import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

public Class Customer {

    private String name;

    //...getters and setters

    @Override
    public int hashCode()
    {
        return HashCodeBuilder.reflectionHashCode(this);
    }
    
    @Override
    public boolean equals(Object obj)
    {
        return EqualsBuilder.reflectionEquals(this, obj);
    }
    
    @Override
    public String toString()
    {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
 
 
    //...


The FileUtils class has a number of handy file processing methods.

import org.apache.commons.io.FileUtils;

public Class FileUtils {

    //....
    try
        {
            FileUtils.touch(lockFile);
        }
        catch (IOException e)
        {
            logger.error("Error creating a lock file: " + lockFile.getAbsolutePath(), e);
            throw new MyCustomException(e);
        }

    //....


    public void moveFile(File srcFile, File destFile) throws IOException
    {
        FileUtils.moveFile(srcFile, destFile);
    }
 
}


The StringUtils is handy for checking if a given String is blank or empty.

import org.apache.commons.lang.StringUtils;

//....

    if (StringUtils.isEmpty(feedFileMeta.getFilePath())) {
        feedFileMeta.setFilePath(defaultFilePath);
    }


The Apache commons package has so many handy methods.

import org.apache.commons.codec.binary.Base64;

public class ApacheLibBase64Example{

    public static void main(String args[]) throws IOException {
        String origStr = "original String before encoding";

        //encoding  byte array into base 64
        byte[] encoded = Base64.encodeBase64(origStr.getBytes());     
      
        System.out.println("Original String: " + origStr );
        System.out.println("Base64 Encoded String : " + new String(encoded));
      
        //decoding byte array into base64
        byte[] decoded = Base64.decodeBase64(encoded);      
        System.out.println("Base 64 Decoded  String : " + new String(decoded));

    }
}


Package org.springframework.util  has a number of handy utility classes like Assert, ClassUtils, CollectionUtils, FileCopyUtils, FileSystemUtils, ObjectUtils, StringUtils, TYpeUtils (Java 5 Generics support) and ReflectionUtils to name a few.  The Assert utility class that assists in validating arguments. Useful for identifying programmer errors early and clearly at run time. For example,

Assert.notNull(clazz, "The class must not be null");
Assert.isTrue(i > 0, "The value must be greater than zero");


The google Guava library provides a number of precondition checking utilities with the Preconditions class.

checkArgument(i >= 0, "Argument was %s but expected nonnegative", i);
checkArgument(i < j, "Expected i < j, but %s > %s", i, j);
checkNotNull(objA);


Here is an example using the Preconditions class:

@Controller
...
public void order(ProductInfo data) {
    //required in the controller to handle errors and send a sensible error back to the client
    Preconditions.checkArgument(StringUtils.hasText(data.getName()), "Empty name parameter."); //validation
    productService.order(data);
}



public class ProductInfoValidator implements Validator {

    /**
    * This Validator validates just ProductInfo  instances
    */
    public boolean supports(Class clazz) {
        return ProductInfo.class.equals(clazz);
    }

    public void validate(Object obj, Errors e) {
        ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
        ProductInfo p = (ProductInfo) obj;
        if (p.getSku() < 0) {
            e.rejectValue("sku", "negativevalue");
        } else if (p.getSku() > 9999) {
            e.rejectValue("sku", "sku.out.of.range");
        }
    }
}


The Service layer needs to apply validation to promote defensive programming. The design by contract states that your methods should check for pre and post conditions and fail fast if the contract is not met.

@Service
...
public void order(ProductInfo data) {
    //fail fast and defensive programming. aka assertions and design by contract 
    Preconditions.checkArgument(StringUtils.hasText(data.getName()), "Empty name parameter.");
    productDao.order(data);
}

If you have a requirement to work a lot with the Java collections, and performance and memory usage are of utmost importance, then look at the following libraries to work with the collections.
  1. The Trove library provides high speed regular and primitive collections for Java. 
  2. PCJ (Primitive Collections for Java)
  3. Guava (from google)

In a nut shell, the Apache commons from Apache, Spring utils from Spring, and  Guava libraries from Google should make you more productive without having to reinvent the wheel. If you have heavy usage of data structures, then Trove becomes very handy. So, before you roll out your own utility methods, check if they are already provided by these libraries.


Q. What libraries or frameworks do you use to marshaling and unmarshaling  Javas POJOs to CSV, XML, EXCEL, and PDF?
A.  There are a number of libraries available.

BeanIO is an open source Java framework for reading and writing Java beans or plain old java objects (POJO's) from a flat file or stream. BeanIO is ideally suited for batch processing, and currently supports XML, CSV, delimited and fixed length file formats. It is also handy for writing automated tests using Apache Camel where test instructions can be written on a flat file and read via BeanIO. It can also be used to produce CSV and XML download files.

The Maven users can define

    <!-- BeanIO dependency -->
    <dependency>
      <groupId>org.beanio</groupId>
      <artifactId>beanio</artifactId>
      <version>2.0.0</version>
    </dependency>

    <!-- StAX dependencies for JDK 1.5 users -->
    <dependency>
      <groupId>javax.xml</groupId>
      <artifactId>jsr173</artifactId>
      <version>1.0</version>
    </dependency>
    <dependency>
      <groupId>com.sun.xml.stream</groupId>
      <artifactId>sjsxp</artifactId>
      <version>1.0.2</version>
    </dependency>  


OpenCSV is an alternative for working with CSV files.

Apache POI, JXLS and JExcelApi are handy for working with Excel files in Java.

To create XML, use JAXB, Stax, JiBX, JDOM, XStream, etc. 

To create PDF documents you can use a number of options listed below.
  1. iText and JasperReports.
  2. Apache PDFBox.
  3. BFO.
  4. Converting to XML and then using XSLT to XSL-FO and then render with Apache FOP.

Labels: , ,