Sunday, December 25, 2011

Struts2 json plugin - Action class public method names with "get" prefix.

I recently figured out this, what I am going to explain you, and it can make a huge impact for an application. I am using struts 2 JSON plugin for an AJAX invocations to action class methods and to send a JSON response. Struts 2 JSON plugin serializes all the bean properties when sending a JSON response to the browser. Sometime, you may not know that, While serialization process, it invokes all the public method which are having “get” prefix in their method names. If we really don’t know about this, it can make a significant impact to our application’s performance and generates exceptions which are hard to figure out. I will explain how this can impact for an application. Look into the following two methods which are defined in ‘DepartmentAction’ class. Those tow method returns JSON response to the browser.

public String getAllEmployees() throws Exception {
    List<Employee> employees = departmentService.getDepartmentEmployees();
    setEmployees(employees);
    return JSON;
}
public String getActiveDepartmentsByLocationId() throws Exception { 
    List<Department> departmetns = departmentService.getActiveDepartmentsByLocationId(locationId);
    setDepartments(departmetns); 
    return JSON;
} 
Normally, When you want to get the list of departments for a given location id, you will invoke the method ‘getActiveDepartmentsByLocationId’ method with an AJAX request. When the function returns the JSON response, it serializes action class bean properties which causes to invoke "getAllEmployees" method also. That means, it invoke the relevant service method from “getAllEmployees” method also. But you only need to get the list of departments for a given location id. Can you guess the impact for the application?

If you put a break point in “getAllEmployees” method while invoking “getActiveDepartmentsByLocationId” method, You will understand this behavior. Normally, developers are used to give “get” prefix for action class methods. If you use struts2 JSON plugin, make sure not to use “get” prefix for public method names which are resulting JSON response. You can use “find” prefix instead.

Thursday, December 8, 2011

Java sorting function with Generics and Reflection

Fed up with writing sorting function every time??. This post will be a great relief for you.I am going to explain, How to write a java class which can be used to sort any type of java object collection in any field in any order. Thanks for introducing java 5 Generics and Reflection in Java.

/**
 * 
 */
package com.shims.support;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @author Semika Siriwardana
 *
 */
public class SHIMSSoringSupport<T> {

 private List<T> objectList;
 private String sortField = null;
 private String sortOrder = null;
 private static final String ASC = "asc";
 /**
  * @param 
  * 
  *   objectList 
  *    The list to be sorted
  * @param sortField
  *    The field name in which list to be sorted
  * 
  * @param sortOrder
  *    Sorting order.Either assending or decending. 
  */
 public SHIMSSoringSupport(List<T> objectList, String sortField,
   String sortOrder) {
   super();
   this.objectList = objectList;
   this.sortField = sortField;
   this.sortOrder = sortOrder;
 }
 
 /**
  * Perform soring
  * @param aClass
  * @throws Exception
  */
 public void sort(final Class aClass) throws Exception {
  
    final String _sortField = this.sortField;
    final String _sortOrder = this.sortOrder;
  
    Collections.sort(this.objectList, new Comparator<T>() {

    @Override
    public int compare(T o1, T o2) {
    
    try {
        Field sortField = aClass.getDeclaredField(_sortField);
        sortField.setAccessible(true);
     
        Object val1 = sortField.get(o1); 
        Object val2 = sortField.get(o2);
     
        if (val1 instanceof String && val2 instanceof String) {                                            
           if (ASC.equals(_sortOrder)){ //String field
               return ((String) val1).compareTo((String)val2);
           } else {
               return ((String) val2).compareTo((String)val1);
           }
        } else { //Numeric field  
           Number num1 = (Number)val1;
           Number num2 = (Number)val2;
      
           if (ASC.equals(_sortOrder)) {
               if (num1.floatValue() > num2.floatValue())  {
                  return 1;
               } else {
                  return -1;
               }
           } else {
                if (num2.floatValue() > num1.floatValue())  {
                    return 1;
                } else {
                    return -1;
                }
           }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } 
    return 0;
   }
  });
 }
}


Next, I will explain how to use above class to sort a list of objects. As You can see in the code, when instantiating class instance, You have to pass three constructor arguments into it.

objectList  - List of objects that are needed to get sorted.
sortField   - The field in which, You want to sort the collection.
sortOrder - The sorting order.This should be either 'asc' or 'desc'.

Following code shows, How to instantiate a class instance and invoke the sorting.

Think, You have a list of 'Employee' objects to sort.

List<Employee> empList = employeService.getAllEmployees(); 
   
SHIMSSoringSupport<Employee> soringSpt 
     = new SHIMSSoringSupport<Employee>(empList, "name", "asc");
soringSpt.sort(Employee.class);

The above code will sort the employee list by it's 'name' field in ascending order.
Share

Widgets