Merge branch 'PojoUtilsSetters' of https://github.com/vrozov/Malhar into dt-dev
diff --git a/contrib/src/main/java/com/datatorrent/contrib/cassandra/CassandraOutputOperator.java b/contrib/src/main/java/com/datatorrent/contrib/cassandra/CassandraOutputOperator.java
index d572660..71ae073 100644
--- a/contrib/src/main/java/com/datatorrent/contrib/cassandra/CassandraOutputOperator.java
+++ b/contrib/src/main/java/com/datatorrent/contrib/cassandra/CassandraOutputOperator.java
@@ -25,8 +25,7 @@
 import com.datatorrent.lib.util.PojoUtils.GetterFloat;
 import com.datatorrent.lib.util.PojoUtils.GetterInt;
 import com.datatorrent.lib.util.PojoUtils.GetterLong;
-import com.datatorrent.lib.util.PojoUtils.GetterObject;
-import com.datatorrent.lib.util.PojoUtils.GetterString;
+import com.datatorrent.lib.util.PojoUtils.Getter;
 import java.math.BigDecimal;
 import java.util.*;
 import javax.validation.constraints.NotNull;
@@ -107,56 +106,63 @@
   {
     com.datastax.driver.core.ResultSet rs = store.getSession().execute("select * from " + store.keyspace + "." + tablename);
 
-    ColumnDefinitions rsMetaData = rs.getColumnDefinitions();
+    final ColumnDefinitions rsMetaData = rs.getColumnDefinitions();
 
-    int numberOfColumns = 0;
+    final int numberOfColumns = rsMetaData.size();
+    final Class<?> fqcn = tuple.getClass();
 
-    numberOfColumns = rsMetaData.size();
     for (int i = 0; i < numberOfColumns; i++) {
       // get the designated column's data type.
-      DataType type = rsMetaData.getType(i);
+      final DataType type = rsMetaData.getType(i);
       columnDataTypes.add(type);
+      final Object getter;
+      final String getterExpr = expressions.get(i);
+      switch (type.getName()) {
+        case ASCII:
+        case TEXT:
+        case VARCHAR:
+          getter = PojoUtils.createGetter(fqcn, getterExpr, String.class);
+          break;
+        case BOOLEAN:
+          getter = PojoUtils.createGetterBoolean(fqcn, getterExpr);
+          break;
+        case INT:
+          getter = PojoUtils.createGetterInt(fqcn, getterExpr);
+          break;
+        case BIGINT:
+        case COUNTER:
+          getter = PojoUtils.createGetterLong(fqcn, getterExpr);
+          break;
+        case FLOAT:
+          getter = PojoUtils.createGetterFloat(fqcn, getterExpr);
+          break;
+        case DOUBLE:
+          getter = PojoUtils.createGetterDouble(fqcn, getterExpr);
+          break;
+        case DECIMAL:
+          getter = PojoUtils.createGetter(fqcn, getterExpr, BigDecimal.class);
+          break;
+        case SET:
+          getter = PojoUtils.createGetter(fqcn, getterExpr, Set.class);
+          break;
+        case MAP:
+          getter = PojoUtils.createGetter(fqcn, getterExpr, Map.class);
+          break;
+        case LIST:
+          getter = PojoUtils.createGetter(fqcn, getterExpr, List.class);
+          break;
+        case TIMESTAMP:
+          getter = PojoUtils.createGetter(fqcn, getterExpr, Date.class);
+          break;
+        case UUID:
+          getter = PojoUtils.createGetter(fqcn, getterExpr, UUID.class);
+          break;
+        default:
+          getter = PojoUtils.createGetter(fqcn, getterExpr, Object.class);
+          break;
+      }
+      getters.add(getter);
     }
-    Class<?> fqcn = tuple.getClass();
-    int size = columnDataTypes.size();
-    for (int i = 0; i < size; i++) {
-      DataType type = columnDataTypes.get(i);
-      String getterExpression = PojoUtils.getSingleFieldExpression(fqcn, expressions.get(i));
-      if (type.equals(DataType.ascii()) || type.equals(DataType.text()) || type.equals(DataType.varchar())) {
-        GetterString getVarchar = PojoUtils.createGetterString(fqcn, getterExpression);
-        getters.add(getVarchar);
-      }
-      else if (type.equals(DataType.uuid())) {
-        GetterObject getObject = PojoUtils.createGetterObject(fqcn, getterExpression);
-        getters.add(getObject);
-      }
-      else if (type.equals(DataType.cboolean())) {
-        GetterBoolean getBoolean = PojoUtils.createGetterBoolean(fqcn, getterExpression);
-        getters.add(getBoolean);
-      }
-      else if (type.equals(DataType.cint())) {
-        GetterInt getInt = PojoUtils.createGetterInt(fqcn, getterExpression);
-        getters.add(getInt);
-      }
-      else if (type.equals(DataType.bigint()) || type.equals(DataType.counter())) {
-        GetterLong getLong = PojoUtils.createExpressionGetterLong(fqcn, getterExpression);
-        getters.add(getLong);
-      }
-      else if (type.equals(DataType.cfloat())) {
-        GetterFloat getFloat = PojoUtils.createGetterFloat(fqcn, getterExpression);
-        getters.add(getFloat);
-      }
-      else if (type.equals(DataType.cdouble())) {
-        GetterDouble getDouble = PojoUtils.createGetterDouble(fqcn, getterExpression);
-        getters.add(getDouble);
-      }
-      else {
-        GetterObject getObject = PojoUtils.createGetterObject(fqcn, getterExpression);
-        getters.add(getObject);
-      }
-
-    }
-
   }
 
   @Override
@@ -190,74 +196,66 @@
     if (getters.isEmpty()) {
       processFirstTuple(tuple);
     }
-    BoundStatement boundStmnt = new BoundStatement(updateCommand);
-    int size = columnDataTypes.size();
+    final BoundStatement boundStmnt = new BoundStatement(updateCommand);
+    final int size = columnDataTypes.size();
     for (int i = 0; i < size; i++) {
-      DataType type = columnDataTypes.get(i);
+      final DataType type = columnDataTypes.get(i);
       switch (type.getName()) {
         case UUID:
-          UUID id = (UUID)(((GetterObject)getters.get(i)).get(tuple));
+          final UUID id = ((Getter<Object, UUID>)getters.get(i)).get(tuple);
           boundStmnt.setUUID(i, id);
           break;
         case ASCII:
-          String ascii = ((GetterString)getters.get(i)).get(tuple);
+        case VARCHAR:
+        case TEXT:
+          final String ascii = ((Getter<Object, String>)getters.get(i)).get(tuple);
           boundStmnt.setString(i, ascii);
           break;
-        case VARCHAR:
-          String varchar = ((GetterString)getters.get(i)).get(tuple);
-          boundStmnt.setString(i, varchar);
-          break;
-        case TEXT:
-          String text = ((GetterString)getters.get(i)).get(tuple);
-          boundStmnt.setString(i, text);
-          break;
         case BOOLEAN:
-          Boolean bool = ((GetterBoolean)getters.get(i)).get(tuple);
+          final boolean bool = ((GetterBoolean)getters.get(i)).get(tuple);
           boundStmnt.setBool(i, bool);
           break;
         case INT:
-          Integer intValue = ((GetterInt)getters.get(i)).get(tuple);
+          final int intValue = ((GetterInt)getters.get(i)).get(tuple);
           boundStmnt.setInt(i, intValue);
           break;
         case BIGINT:
-          Long longValue = ((GetterLong)getters.get(i)).get(tuple);
+        case COUNTER:
+          final long longValue = ((GetterLong)getters.get(i)).get(tuple);
           boundStmnt.setLong(i, longValue);
           break;
-        case COUNTER:
-          Long counter = ((GetterLong)getters.get(i)).get(tuple);
-          boundStmnt.setLong(i, counter);
-          break;
         case FLOAT:
-          Float floatValue = ((GetterFloat)getters.get(i)).get(tuple);
+          final float floatValue = ((GetterFloat)getters.get(i)).get(tuple);
           boundStmnt.setFloat(i, floatValue);
           break;
         case DOUBLE:
-          Double doubleValue = ((GetterDouble)getters.get(i)).get(tuple);
+          final double doubleValue = ((GetterDouble)getters.get(i)).get(tuple);
           boundStmnt.setDouble(i, doubleValue);
           break;
         case DECIMAL:
-          BigDecimal decimal = (BigDecimal)((GetterObject)getters.get(i)).get(tuple);
+          final BigDecimal decimal = ((Getter<Object, BigDecimal>)getters.get(i)).get(tuple);
           boundStmnt.setDecimal(i, decimal);
           break;
         case SET:
-          @SuppressWarnings({"unchecked", "rawtypes"}) Set set = (Set)((GetterObject)getters.get(i)).get(tuple);
+          Set set = ((Getter<Object, Set>)getters.get(i)).get(tuple);
           boundStmnt.setSet(i, set);
           break;
         case MAP:
-          @SuppressWarnings({"unchecked", "rawtypes"}) Map map = (Map)((GetterObject)getters.get(i)).get(tuple);
+          final Map map = ((Getter<Object, Map>)getters.get(i)).get(tuple);
           boundStmnt.setMap(i, map);
           break;
         case LIST:
-          @SuppressWarnings({"unchecked", "rawtypes"}) List list = (List)((GetterObject)getters.get(i)).get(tuple);
+          final List list = ((Getter<Object, List>)getters.get(i)).get(tuple);
           boundStmnt.setList(i, list);
           break;
         case TIMESTAMP:
-          Date date = (Date)((GetterObject)getters.get(i)).get(tuple);
+          final Date date = ((Getter<Object, Date>)getters.get(i)).get(tuple);
           boundStmnt.setDate(i, date);
           break;
+        default:
+          throw new RuntimeException("unsupported data type " + type.getName());
       }
     }
-
     return boundStmnt;
   }
 
diff --git a/contrib/src/main/java/com/datatorrent/contrib/memsql/MemsqlOutputOperator.java b/contrib/src/main/java/com/datatorrent/contrib/memsql/MemsqlOutputOperator.java
index e91ab58..6d24496 100644
--- a/contrib/src/main/java/com/datatorrent/contrib/memsql/MemsqlOutputOperator.java
+++ b/contrib/src/main/java/com/datatorrent/contrib/memsql/MemsqlOutputOperator.java
@@ -23,9 +23,9 @@
 import com.datatorrent.lib.util.PojoUtils.GetterFloat;
 import com.datatorrent.lib.util.PojoUtils.GetterInt;
 import com.datatorrent.lib.util.PojoUtils.GetterLong;
-import com.datatorrent.lib.util.PojoUtils.GetterObject;
+import com.datatorrent.lib.util.PojoUtils.Getter;
 import com.datatorrent.lib.util.PojoUtils.GetterShort;
-import com.datatorrent.lib.util.PojoUtils.GetterString;
+
 import java.sql.*;
 import java.util.ArrayList;
 import javax.validation.constraints.NotNull;
@@ -174,64 +174,50 @@
 
   public void processFirstTuple(Object tuple)
   {
-    Class<?> fqcn = tuple.getClass();
-    int size = columnDataTypes.size();
+    final Class<?> fqcn = tuple.getClass();
+    final int size = columnDataTypes.size();
     for (int i = 0; i < size; i++) {
-      int type = columnDataTypes.get(i);
-      String getterExpression = expression.get(i);
-      if (type == Types.CHAR) {
-        GetterChar getChar = PojoUtils.createGetterChar(fqcn, getterExpression);
-        getters.add(getChar);
+      final int type = columnDataTypes.get(i);
+      final String getterExpression = expression.get(i);
+      final Object getter;
+      switch (type) {
+        case Types.CHAR:
+          getter = PojoUtils.createGetterChar(fqcn, getterExpression);
+          break;
+        case Types.VARCHAR:
+          getter = PojoUtils.createGetter(fqcn, getterExpression, String.class);
+          break;
+        case Types.BOOLEAN:
+        case Types.TINYINT:
+          getter = PojoUtils.createGetterBoolean(fqcn, getterExpression);
+          break;
+        case Types.SMALLINT:
+          getter = PojoUtils.createGetterShort(fqcn, getterExpression);
+          break;
+        case Types.INTEGER:
+          getter = PojoUtils.createGetterInt(fqcn, getterExpression);
+          break;
+        case Types.BIGINT:
+          getter = PojoUtils.createGetterLong(fqcn, getterExpression);
+          break;
+        case Types.FLOAT:
+          getter = PojoUtils.createGetterFloat(fqcn, getterExpression);
+          break;
+        case Types.DOUBLE:
+          getter = PojoUtils.createGetterDouble(fqcn, getterExpression);
+          break;
+        default:
+          /*
+            Types.DECIMAL
+            Types.DATE
+            Types.TIME
+            Types.ARRAY
+            Types.OTHER
+           */
+          getter = PojoUtils.createGetter(fqcn, getterExpression, Object.class);
+          break;
       }
-      else if (type == Types.VARCHAR) {
-        GetterString getVarchar = PojoUtils.createGetterString(fqcn, getterExpression);
-        getters.add(getVarchar);
-      }
-      else if (type == Types.BOOLEAN || type == Types.TINYINT) {
-        GetterBoolean getBoolean = PojoUtils.createGetterBoolean(fqcn, getterExpression);
-        getters.add(getBoolean);
-      }
-      else if (type == Types.SMALLINT) {
-        GetterShort getShort = PojoUtils.createGetterShort(fqcn, getterExpression);
-        getters.add(getShort);
-      }
-      else if (type == Types.INTEGER) {
-        GetterInt getInt = PojoUtils.createGetterInt(fqcn, getterExpression);
-        getters.add(getInt);
-      }
-      else if (type == Types.BIGINT) {
-        GetterLong getLong = PojoUtils.createExpressionGetterLong(fqcn, getterExpression);
-        getters.add(getLong);
-      }
-      else if (type == Types.DECIMAL) {
-        GetterObject getObject = PojoUtils.createGetterObject(fqcn, getterExpression);
-        getters.add(getObject);
-      }
-      else if (type == Types.FLOAT) {
-        GetterFloat getFloat = PojoUtils.createGetterFloat(fqcn, getterExpression);
-        getters.add(getFloat);
-      }
-      else if (type == Types.DOUBLE) {
-        GetterDouble getDouble = PojoUtils.createGetterDouble(fqcn, getterExpression);
-        getters.add(getDouble);
-      }
-      else if (type == Types.DATE) {
-        GetterObject getObject = PojoUtils.createGetterObject(fqcn, getterExpression);
-        getters.add(getObject);
-      }
-      else if (type == Types.TIME) {
-        GetterObject getObject = PojoUtils.createGetterObject(fqcn, getterExpression);
-        getters.add(getObject);
-      }
-      else if (type == Types.ARRAY) {
-        GetterObject getObject = PojoUtils.createGetterObject(fqcn, getterExpression);
-        getters.add(getObject);
-      }
-      else if (type == Types.OTHER) {
-        GetterObject getObject = PojoUtils.createGetterObject(fqcn, getterExpression);
-        getters.add(getObject);
-      }
-
+      getters.add(getter);
     }
 
   }
@@ -244,57 +230,49 @@
   }
 
   @Override
+  @SuppressWarnings("unchecked")
   protected void setStatementParameters(PreparedStatement statement, Object tuple) throws SQLException
   {
-    int size = columnDataTypes.size();
-    Object getter;
-    for (int i = 0; i < size; i++) {
-      int type = columnDataTypes.get(i);
+    final int size = columnDataTypes.size();
+    for (int i = 0; i < size; ) {
+      final int type = columnDataTypes.get(i);
       switch (type) {
         case (Types.CHAR):
-          getter = ((GetterChar)getters.get(i)).get(tuple);
+          // TODO: verify that memsql driver handles char as int
+          statement.setInt(++i, ((GetterChar<Object>) getters.get(i)).get(tuple));
           break;
         case (Types.VARCHAR):
-          getter = ((GetterString)getters.get(i)).get(tuple);
+          statement.setString(++i, ((Getter<Object, String>) getters.get(i)).get(tuple));
           break;
         case (Types.BOOLEAN):
-          getter = ((GetterBoolean)getters.get(i)).get(tuple);
+          statement.setBoolean(++i, ((GetterBoolean<Object>) getters.get(i)).get(tuple));
           break;
         case (Types.SMALLINT):
-          getter = ((GetterShort)getters.get(i)).get(tuple);
+          statement.setShort(++i, ((GetterShort<Object>) getters.get(i)).get(tuple));
           break;
         case (Types.INTEGER):
-          getter = ((GetterInt)getters.get(i)).get(tuple);
+          statement.setInt(++i, ((GetterInt<Object>) getters.get(i)).get(tuple));
           break;
         case (Types.BIGINT):
-          getter = ((GetterLong)getters.get(i)).get(tuple);
-          break;
-        case (Types.DECIMAL):
-          getter = (Number)((GetterObject)getters.get(i)).get(tuple);
+          statement.setLong (++i, ((GetterLong<Object>) getters.get(i)).get(tuple));
           break;
         case (Types.FLOAT):
-          getter = ((GetterFloat)getters.get(i)).get(tuple);
+          statement.setFloat(++i, ((GetterFloat<Object>) getters.get(i)).get(tuple));
           break;
         case (Types.DOUBLE):
-          getter = ((GetterDouble)getters.get(i)).get(tuple);
-          break;
-        case (Types.DATE):
-          getter = (Date)((GetterObject)getters.get(i)).get(tuple);
-          break;
-        case (Types.TIME):
-          getter = (Timestamp)((GetterObject)getters.get(i)).get(tuple);
-          break;
-        case (Types.ARRAY):
-          getter = (Array)((GetterObject)getters.get(i)).get(tuple);
-          break;
-        case (Types.OTHER):
-          getter = ((GetterObject)getters.get(i)).get(tuple);
+          statement.setDouble(++i, ((GetterDouble<Object>) getters.get(i)).get(tuple));
           break;
         default:
-          getter = ((GetterObject)getters.get(i)).get(tuple);
+          /*
+            Types.DECIMAL
+            Types.DATE
+            Types.TIME
+            Types.ARRAY
+            Types.OTHER
+           */
+          statement.setObject(++i, ((Getter<Object, Object>)getters.get(i)).get(tuple));
           break;
       }
-      statement.setObject(i + 1, getter);
     }
   }
 
diff --git a/library/src/main/java/com/datatorrent/lib/bucket/BucketPOJOImpl.java b/library/src/main/java/com/datatorrent/lib/bucket/BucketPOJOImpl.java
index aff632d..d9a533f 100644
--- a/library/src/main/java/com/datatorrent/lib/bucket/BucketPOJOImpl.java
+++ b/library/src/main/java/com/datatorrent/lib/bucket/BucketPOJOImpl.java
@@ -16,7 +16,8 @@
 package com.datatorrent.lib.bucket;
 
 import com.datatorrent.lib.util.PojoUtils;
-import com.datatorrent.lib.util.PojoUtils.GetterObject;
+import com.datatorrent.lib.util.PojoUtils.Getter;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -29,7 +30,7 @@
 public class BucketPOJOImpl extends AbstractBucket<Object>
 {
   private String expression;
-  private transient GetterObject getter;
+  private transient Getter<Object, Object> getter;
 
   protected BucketPOJOImpl(long bucketKey,String expression)
   {
@@ -40,10 +41,9 @@
   @Override
   protected Object getEventKey(Object event)
   {
-    if(getter==null){
+    if (getter == null) {
       Class<?> fqcn = event.getClass();
-      GetterObject getterObj = PojoUtils.createGetterObject(fqcn, expression);
-      getter = getterObj;
+      getter = PojoUtils.createGetter(fqcn, expression, Object.class);
     }
     return getter.get(event);
   }
diff --git a/library/src/main/java/com/datatorrent/lib/bucket/TimeBasedBucketManagerPOJOImpl.java b/library/src/main/java/com/datatorrent/lib/bucket/TimeBasedBucketManagerPOJOImpl.java
index b675130..ce0d401 100644
--- a/library/src/main/java/com/datatorrent/lib/bucket/TimeBasedBucketManagerPOJOImpl.java
+++ b/library/src/main/java/com/datatorrent/lib/bucket/TimeBasedBucketManagerPOJOImpl.java
@@ -81,7 +81,7 @@
   {
     if(getter==null){
     Class<?> fqcn = event.getClass();
-    GetterLong getterTime = PojoUtils.createExpressionGetterLong(fqcn,timeExpression);
+    GetterLong getterTime = PojoUtils.createGetterLong(fqcn, timeExpression);
     getter = getterTime;
     }
     return getter.get(event);
diff --git a/library/src/main/java/com/datatorrent/lib/dedup/DeduperPOJOImpl.java b/library/src/main/java/com/datatorrent/lib/dedup/DeduperPOJOImpl.java
index f0df2b0..0100725 100644
--- a/library/src/main/java/com/datatorrent/lib/dedup/DeduperPOJOImpl.java
+++ b/library/src/main/java/com/datatorrent/lib/dedup/DeduperPOJOImpl.java
@@ -19,7 +19,7 @@
 import com.datatorrent.lib.bucket.POJOBucketManager;
 import com.datatorrent.lib.bucket.TimeBasedBucketManagerPOJOImpl;
 import com.datatorrent.lib.util.PojoUtils;
-import com.datatorrent.lib.util.PojoUtils.GetterObject;
+import com.datatorrent.lib.util.PojoUtils.Getter;
 import com.google.common.base.Preconditions;
 import javax.validation.constraints.NotNull;
 import org.slf4j.Logger;
@@ -33,16 +33,16 @@
  */
 public class DeduperPOJOImpl extends AbstractDeduper<Object, Object>
 {
-  private transient GetterObject getter;
+  private transient Getter<Object, Object> getter;
 
   @Override
   public void processTuple(Object event)
   {
-     if(getter==null){
-     Class<?> fqcn = event.getClass();
-     GetterObject getterObj = PojoUtils.createGetterObject(fqcn, ((TimeBasedBucketManagerPOJOImpl)bucketManager).getKeyExpression());
-     getter = getterObj;
-     }
+    if (getter==null) {
+      Class<?> fqcn = event.getClass();
+      getter = PojoUtils.createGetter(fqcn, ((TimeBasedBucketManagerPOJOImpl) bucketManager).getKeyExpression(), Object.class);
+    }
+
     super.processTuple(event);
   }
 
diff --git a/library/src/main/java/com/datatorrent/lib/util/PojoUtils.java b/library/src/main/java/com/datatorrent/lib/util/PojoUtils.java
index f730618..a810abf 100644
--- a/library/src/main/java/com/datatorrent/lib/util/PojoUtils.java
+++ b/library/src/main/java/com/datatorrent/lib/util/PojoUtils.java
@@ -26,8 +26,12 @@
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.commons.lang3.ClassUtils;
+import org.apache.commons.lang3.StringUtils;
+
 /**
  * @since 2.1.0
  */
@@ -35,67 +39,401 @@
 {
   private static final Logger logger = LoggerFactory.getLogger(PojoUtils.class);
 
-  public static final String JAVA_DOT = ".";
-  public static final String DEFAULT_POJO_NAME = "pojo";
+  public static final String DEFAULT_EXP_OBJECT_PLACEHOLDER = "{$}";
+  public static final String DEFAULT_EXP_VAL_PLACEHOLDER = "{#}";
 
-  public static final String GET = "get";
-  public static final String IS = "is";
+  private static final String OBJECT = "object";
+  private static final String VAL = "val";
+
+  private static final String GET = "get";
+  private static final String IS = "is";
+  private static final String SET = "set";
 
   private PojoUtils()
   {
   }
 
-  public interface GetterBoolean
+  public interface GetterBoolean<T>
   {
-    public boolean get(Object obj);
+    boolean get(T obj);
   }
 
-  public interface GetterByte
+  public interface GetterByte<T>
   {
-    public byte get(Object obj);
+    byte get(T obj);
   }
 
-  public interface GetterChar
+  public interface GetterChar<T>
   {
-    public char get(Object obj);
+    char get(T obj);
   }
 
-  public interface GetterDouble
+  public interface GetterShort<T>
   {
-    public double get(Object obj);
+    short get(T obj);
   }
 
-  public interface GetterFloat
+  public interface GetterInt<T>
   {
-    public float get(Object obj);
+    int get(T obj);
   }
 
-  public interface GetterInt
+  public interface GetterLong<T>
   {
-    public int get(Object obj);
+    long get(T obj);
   }
 
-  public interface GetterLong
+  public interface GetterFloat<T>
   {
-    public long get(Object obj);
+    float get(T obj);
   }
 
-  public interface GetterObject
+  public interface GetterDouble<T>
   {
-    public Object get(Object obj);
+    double get(T obj);
   }
 
-  public interface GetterShort
+  public interface Getter<T, V>
   {
-    public short get(Object obj);
+    V get(T obj);
   }
 
-  public interface GetterString
+  public static <T> GetterBoolean<T> createGetterBoolean(Class<? extends T> pojoClass, String getterExpr)
   {
-    public String get(Object obj);
+    return createGetterBoolean(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
   }
 
-  public static String upperCaseWord(String field)
+  @SuppressWarnings("unchecked")
+  public static <T> GetterBoolean<T> createGetterBoolean(Class<? extends T> pojoClass, String getterExpr, String exprObjectPlaceholder)
+  {
+    return (GetterBoolean<T>) createGetter(pojoClass, getterExpr, exprObjectPlaceholder, boolean.class, GetterBoolean.class);
+  }
+
+  public static <T> GetterByte<T> createGetterByte(Class<? extends T> pojoClass, String getterExpr)
+  {
+    return createGetterByte(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> GetterByte<T> createGetterByte(Class<? extends T> pojoClass, String getterExpr, String exprObjectPlaceholder)
+  {
+    return (GetterByte<T>) createGetter(pojoClass, getterExpr, exprObjectPlaceholder, byte.class, GetterByte.class);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> GetterChar createGetterChar(Class<? extends T> pojoClass, String getterExpr)
+  {
+    return createGetterChar(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> GetterChar createGetterChar(Class<? extends T> pojoClass, String getterExpr, String exprObjectPlaceholder)
+  {
+    return (GetterChar<T>) createGetter(pojoClass, getterExpr, exprObjectPlaceholder, char.class, GetterChar.class);
+  }
+
+  public static <T> GetterShort<T> createGetterShort(Class<? extends T> pojoClass, String getterExpr)
+  {
+    return createGetterShort(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> GetterShort<T> createGetterShort(Class<? extends T> pojoClass, String getterExpr, String exprObjectPlaceholder)
+  {
+    return (GetterShort<T>) createGetter(pojoClass, getterExpr, exprObjectPlaceholder, short.class, GetterShort.class);
+  }
+
+  public static <T> GetterInt<T> createGetterInt(Class<? extends T> pojoClass, String getterExpr)
+  {
+    return createGetterInt(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> GetterInt<T> createGetterInt(Class<? extends T> pojoClass, String getterExpr, String exprObjectPlaceholder)
+  {
+    return (GetterInt<T>) createGetter(pojoClass, getterExpr, exprObjectPlaceholder, int.class, GetterInt.class);
+  }
+
+  public static <T> GetterLong<T> createGetterLong(Class<? extends T> pojoClass, String getterExpr)
+  {
+    return createGetterLong(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> GetterLong<T> createGetterLong(Class<? extends T> pojoClass, String getterExpr, String exprObjectPlaceholder)
+  {
+    return (GetterLong<T>) createGetter(pojoClass, getterExpr, exprObjectPlaceholder, long.class, GetterLong.class);
+  }
+
+  public static <T> GetterFloat<T> createGetterFloat(Class<? extends T> pojoClass, String getterExpr)
+  {
+    return createGetterFloat(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> GetterFloat<T> createGetterFloat(Class<? extends T> pojoClass, String getterExpr, String exprObjectPlaceholder)
+  {
+    return (GetterFloat<T>) createGetter(pojoClass, getterExpr, exprObjectPlaceholder, float.class, GetterFloat.class);
+  }
+
+  public static <T> GetterDouble<T> createGetterDouble(Class<? extends T> pojoClass, String getterExpr)
+  {
+    return createGetterDouble(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> GetterDouble<T> createGetterDouble(Class<? extends T> pojoClass, String getterExpr, String exprObjectPlaceholder)
+  {
+    return (GetterDouble<T>) createGetter(pojoClass, getterExpr, exprObjectPlaceholder, double.class, GetterDouble.class);
+  }
+
+  public static <T, V> Getter<T, V> createGetter(Class<? extends T> pojoClass, String getterExpr, Class<? extends V> exprClass)
+  {
+    return createGetter(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, exprClass);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T, V> Getter<T, V> createGetter(Class<? extends T> pojoClass, String getterExpr, String exprObjectPlaceholder, Class<? extends V> exprClass)
+  {
+    return (Getter<T, V>) createGetter(pojoClass, getterExpr, exprObjectPlaceholder, exprClass, Getter.class);
+  }
+
+  /**
+   * Setter interface for <tt>boolean</tt> primitives
+   * @param <T> class of objects that the setter applies to
+   */
+  public interface SetterBoolean<T>
+  {
+    void set(T obj, boolean booleanVal);
+  }
+
+  /**
+   * Setter interface for <tt>byte</tt> primitives
+   * @param <T> class of objects that the setter applies to
+   */
+  public interface SetterByte<T>
+  {
+    void set(T obj, byte byteVal);
+  }
+
+  /**
+   * Setter interface for <tt>char</tt> primitives
+   * @param <T> class of objects that the setter applies to
+   */
+  public interface SetterChar<T>
+  {
+    void set(T obj, char charVal);
+  }
+
+  /**
+   * Setter interface for <tt>short</tt> primitives
+   * @param <T> class of objects that the setter applies to
+   */
+  public interface SetterShort<T>
+  {
+    void set(T obj, short shortVal);
+  }
+
+  /**
+   * Setter interface for <tt>int</tt> primitives
+   * @param <T> class of objects that the setter applies to
+   */
+  public interface SetterInt<T>
+  {
+    void set(T obj, int intVal);
+  }
+
+  /**
+   * Setter interface for <tt>long</tt> primitives
+   * @param <T> class of objects that the setter applies to
+   */
+  public interface SetterLong<T>
+  {
+    void set(T obj, long longVal);
+  }
+
+  /**
+   * Setter interface for <tt>float</tt> primitives
+   * @param <T> class of objects that the setter applies to
+   */
+  public interface SetterFloat<T>
+  {
+    void set(T obj, float floatVal);
+  }
+
+  /**
+   * Setter interface for <tt>double</tt> primitives
+   * @param <T> class of objects that the setter applies to
+   */
+  public interface SetterDouble<T>
+  {
+    void set(T obj, double doubleVal);
+  }
+
+  /**
+   * Setter interface for arbitrary object
+   * @param <T> class of objects that the setter applies to
+   * @param <V> class of the rhs expression
+   */
+  public interface Setter<T, V>
+  {
+    void set(T obj, V value);
+  }
+
+  public static <T> SetterBoolean<T> createSetterBoolean(Class<? extends T> pojoClass, String setterExpr)
+  {
+    return createSetterBoolean(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> SetterBoolean<T> createSetterBoolean(Class<? extends T> pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
+  {
+    return (SetterBoolean<T>) createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, boolean.class, SetterBoolean.class);
+  }
+
+  public static <T> SetterByte<T> createSetterByte(Class<? extends T> pojoClass, String setterExpr)
+  {
+    return createSetterByte(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> SetterByte<T> createSetterByte(Class<? extends T> pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
+  {
+    return (SetterByte<T>) createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, byte.class, SetterByte.class);
+  }
+
+  public static <T> SetterChar<T> createSetterChar(Class<? extends T> pojoClass, String setterExpr)
+  {
+    return createSetterChar(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> SetterChar<T> createSetterChar(Class<? extends T> pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
+  {
+    return (SetterChar<T>) createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, char.class, SetterChar.class);
+  }
+
+  public static <T> SetterShort<T> createSetterShort(Class<? extends T> pojoClass, String setterExpr)
+  {
+    return createSetterShort(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> SetterShort<T> createSetterShort(Class<? extends T> pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
+  {
+    return (SetterShort<T>) createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, short.class, SetterShort.class);
+  }
+
+  public static <T> SetterInt<T> createSetterInt(Class<? extends T> pojoClass, String setterExpr)
+  {
+    return createSetterInt(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> SetterInt<T> createSetterInt(Class<? extends T> pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
+  {
+    return (SetterInt<T>) createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, int.class, SetterInt.class);
+  }
+
+  public static <T> SetterLong<T> createSetterLong(Class<? extends T> pojoClass, String setterExpr)
+  {
+    return createSetterLong(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> SetterLong<T> createSetterLong(Class<? extends T> pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
+  {
+    return (SetterLong<T>) createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, long.class, SetterLong.class);
+  }
+
+  public static <T> SetterFloat<T> createSetterFloat(Class<? extends T> pojoClass, String setterExpr)
+  {
+    return createSetterFloat(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> SetterFloat<T> createSetterFloat(Class<? extends T> pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
+  {
+    return (SetterFloat<T>) createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, float.class, SetterFloat.class);
+  }
+
+  public static <T> SetterDouble<T> createSetterDouble(Class<? extends T> pojoClass, String setterExpr)
+  {
+    return createSetterDouble(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> SetterDouble<T> createSetterDouble(Class<? extends T> pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
+  {
+    return (SetterDouble<T>) createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, double.class, SetterDouble.class);
+  }
+
+  public static <T, V> Setter<T, V> createSetter(Class<? extends T>pojoClass, String setterExpr, Class<? extends V> exprClass)
+  {
+    return createSetter(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER, exprClass);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T, V> Setter<T, V> createSetter(Class<? extends T>pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder, Class<? extends V> exprClass)
+  {
+    return (Setter<T, V>) createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, exprClass, Setter.class);
+  }
+
+  private static class JavaStatement {
+    private StringBuilder javaStatement;
+    private final int capacity;
+
+    private JavaStatement() {
+      javaStatement = new StringBuilder();
+      capacity = javaStatement.capacity();
+    }
+
+    private JavaStatement(int length) {
+      javaStatement = new StringBuilder(length);
+      capacity = javaStatement.capacity();
+    }
+
+    @Override
+    public String toString() {
+      return javaStatement.toString();
+    }
+
+    protected JavaStatement append(String string) {
+      javaStatement.append(string);
+      return this;
+    }
+
+    private JavaStatement appendCastToTypeExpr(Class<?> type, String expr) {
+      return append("((").append(type.getName()).append(")(").append(expr).append("))");
+    }
+
+    protected String getStatement() {
+      if (capacity < javaStatement.length() + 1) {
+        logger.debug("Java statement capacity {} was not sufficient for the statement length {}. Actual statement {}", capacity, javaStatement.length(), javaStatement);
+      }
+      return javaStatement.append(";").toString();
+    }
+  }
+
+  private static class JavaReturnStatement extends JavaStatement {
+    private JavaReturnStatement(Class<?> returnType) {
+      super();
+      append("return (").append(returnType.getName()).append(")");
+    }
+
+    private JavaReturnStatement(int length, Class<?> returnType) {
+      super(length);
+      append("return ((").append(returnType.getName()).append(")");
+    }
+
+    @Override
+    protected String getStatement() {
+      append(")");
+      return super.getStatement();
+    }
+  }
+
+  private static String upperCaseWord(String field)
   {
     Preconditions.checkArgument(!field.isEmpty(), field);
     return field.substring(0, 1).toUpperCase() + field.substring(1);
@@ -107,45 +445,64 @@
    * If the field is a public member, the field name is used else the getter function. If no matching field or getter
    * method is found, the expression is returned unmodified.
    *
-   * @param clazz
+   * @param pojoClass
    * @param fieldExpression
+   * @param castClass
    * @return
    */
-  public static String getSingleFieldExpression(Class<?> clazz, String fieldExpression)
+  private static String getSingleFieldGetterExpression(final Class<?> pojoClass, final String fieldExpression, final Class<?> castClass)
   {
+    JavaStatement code = new JavaReturnStatement(pojoClass.getName().length() + fieldExpression.length() + castClass.getName().length() + 32, castClass);
+    code.appendCastToTypeExpr(pojoClass, OBJECT).append(".");
     try {
-      Field f = clazz.getField(fieldExpression);
-      return f.getName();
-    } catch (NoSuchFieldException ex) {
-      try {
-        Method m = clazz.getMethod(GET + upperCaseWord(fieldExpression));
-        return m.getName().concat("()");
-      } catch (NoSuchMethodException nsm) {
-        try {
-          Method m = clazz.getMethod(IS + upperCaseWord(fieldExpression));
-          return m.getName().concat("()");
-        } catch (NoSuchMethodException nsm2) {
-        }
+      final Field field = pojoClass.getField(fieldExpression);
+      if (ClassUtils.isAssignable(field.getType(), castClass)) {
+        return code.append(field.getName()).getStatement();
       }
-      return fieldExpression;
-    }
-  }
-
-  public static String fieldListToGetExpression(Class<?> clazz, List<String> fields)
-  {
-    StringBuilder sb = new StringBuilder();
-
-    for (int index = 0; index < fields.size() - 1; index++) {
-      String field = fields.get(index);
-      sb.append(sb).append(getSingleFieldExpression(clazz, field)).append(JAVA_DOT);
+      logger.debug("Field {} can not be assigned to an {}. Proceeding to locate a getter method.", field, castClass);
+    } catch (NoSuchFieldException ex) {
+      logger.debug("{} does not have field {}. Proceeding to locate a getter method.", pojoClass, fieldExpression);
+    } catch (SecurityException ex) {
+      logger.debug("{} does not have field {}. Proceeding to locate a getter method.", pojoClass, fieldExpression);
     }
 
-    sb.append(getSingleFieldExpression(clazz, fields.get(fields.size() - 1)));
+    String methodName = GET + upperCaseWord(fieldExpression);
+    try {
+      Method method = pojoClass.getMethod(methodName);
+      if (ClassUtils.isAssignable(method.getReturnType(), castClass)) {
+        return code.append(methodName).append("()").getStatement();
+      }
+      logger.debug("method {} of the {} returns {} that can not be assigned to an {}. Proceeding to locate another getter method.",
+              pojoClass, methodName, method.getReturnType(), castClass);
+    } catch (NoSuchMethodException ex) {
+      logger.debug("{} does not have method {}. Proceeding to locate another getter method.",
+              pojoClass, methodName);
+    } catch (SecurityException ex) {
+      logger.debug("{} does not have method {}. Proceeding to locate another getter method.",
+              pojoClass, methodName);
+    }
 
-    return sb.toString();
+    methodName = IS + upperCaseWord(fieldExpression);
+    try {
+      Method method = pojoClass.getMethod(methodName);
+      if (ClassUtils.isAssignable(method.getReturnType(), castClass)) {
+        return code.append(methodName).append("()").getStatement();
+      }
+      logger.debug("method {} of the {} returns {} that can not be assigned to an {}. Proceeding with the original expression {}.",
+              pojoClass, methodName, method.getReturnType(), castClass, fieldExpression);
+    } catch (NoSuchMethodException ex) {
+      logger.debug("{} does not have method {}. Proceeding with the original expression {}.",
+              pojoClass, methodName, fieldExpression);
+    } catch (SecurityException ex) {
+      logger.debug("{} does not have method {}. Proceeding with the original expression {}.",
+              pojoClass, methodName, fieldExpression);
+    }
+
+    return code.append(fieldExpression).getStatement();
   }
 
-  public static Object createGetter(Class<?> pojoClass, String getterExpr, Class<?> castClass, Class<?> getterClass)
+  @SuppressWarnings("StringEquality")
+  private static <T> Object createGetter(Class<?> pojoClass, String getterExpr, String exprObjectPlaceholder, Class<?> castClass, Class<T> getterClass)
   {
     logger.debug("{} {} {} {}", pojoClass, getterExpr, castClass, getterClass);
 
@@ -154,10 +511,10 @@
     }
 
     if (getterExpr.isEmpty()) {
-      throw new IllegalArgumentException("The getter string: " + getterExpr + "\nis invalid.");
+      throw new IllegalArgumentException("The getter expression: \"" + getterExpr + "\" is invalid.");
     }
 
-    IScriptEvaluator se = null;
+    IScriptEvaluator se;
 
     try {
       se = CompilerFactoryFactory.getDefaultCompilerFactory().newScriptEvaluator();
@@ -165,64 +522,129 @@
       throw new RuntimeException(ex);
     }
 
-    try {
-      String code = "return (" + castClass.getName() + ") (((" + pojoClass.getName() + ")" + PojoUtils.DEFAULT_POJO_NAME + ")." + getterExpr + ");";
-      logger.debug("{}", code);
+    String code = StringUtils.replaceEach(getterExpr, new String[]{exprObjectPlaceholder},
+            new String[]{new JavaStatement(pojoClass.getName().length() + OBJECT.length() + 4).appendCastToTypeExpr(pojoClass, OBJECT).toString()});
+    if (code != getterExpr) {
+      code = new JavaReturnStatement(castClass.getName().length() + code.length() + 12, castClass).append(code).getStatement();
+      logger.debug("Original expression {} is a complex expression. Replacing it with {}.", getterExpr, code);
+    }
+    else {
+      code = getSingleFieldGetterExpression(pojoClass, getterExpr, castClass);
+    }
 
-      return se.createFastEvaluator(code, getterClass, new String[] { PojoUtils.DEFAULT_POJO_NAME });
+    logger.debug("code: {}", code);
+
+    try {
+      return se.createFastEvaluator(code, getterClass, new String[] {PojoUtils.OBJECT});
     } catch (CompileException ex) {
       throw new RuntimeException(ex);
     }
   }
 
-  public static GetterBoolean createGetterBoolean(Class<?> pojoClass, String getterExpr)
+  private static String getSingleFieldSetterExpression(final Class<?> pojoClass, final String fieldExpression, final Class<?> exprClass)
   {
-    return (GetterBoolean) createGetter(pojoClass, getterExpr, boolean.class, GetterBoolean.class);
+    JavaStatement code = new JavaStatement(pojoClass.getName().length() + fieldExpression.length() + exprClass.getName().length() + 16);
+    /* Construct ((<pojo class name>)pojo). */
+    code.appendCastToTypeExpr(pojoClass, OBJECT).append(".");
+    try {
+      final Field field = pojoClass.getField(fieldExpression);
+      if (ClassUtils.isAssignable(exprClass, field.getType())) {
+        /* there is public field on the class, use direct assignment. */
+        /* append <field name> = (<field type>)val; */
+        return code.append(field.getName()).append(" = ").appendCastToTypeExpr(exprClass, VAL).getStatement();
+      }
+      logger.debug("{} can not be assigned to {}. Proceeding to locate a setter method.", exprClass, field);
+    } catch (NoSuchFieldException ex) {
+      logger.debug("{} does not have field {}. Proceeding to locate a setter method.", pojoClass, fieldExpression);
+    } catch (SecurityException ex) {
+      logger.debug("{} does not have field {}. Proceeding to locate a setter method.", pojoClass, fieldExpression);
+    }
+
+    final String setMethodName = SET + upperCaseWord(fieldExpression);
+    Method bestMatchMethod = null;
+    List<Method> candidates = new ArrayList<Method>();
+    for (Method method : pojoClass.getMethods()) {
+      if (setMethodName.equals(method.getName())) {
+        Class<?>[] parameterTypes = method.getParameterTypes();
+        if (parameterTypes.length == 1) {
+          if (exprClass == parameterTypes[0]) {
+            bestMatchMethod = method;
+            break;
+          }
+          else if (org.apache.commons.lang.ClassUtils.isAssignable(exprClass, parameterTypes[0])) {
+            candidates.add(method);
+          }
+        }
+      }
+    }
+
+    if (bestMatchMethod == null) { // We did not find the exact match, use candidates to find the match
+      if (candidates.size() == 0) {
+        logger.debug("{} does not have suitable setter method {}. Returning original expression {}.",
+                pojoClass, setMethodName, fieldExpression);
+        /* We did not find any match at all, use original expression */
+        /* append = (<expr type>)val;*/
+        return code.append(fieldExpression).append(" = ").appendCastToTypeExpr(exprClass, VAL).getStatement();
+      } else {
+        // TODO: see if we can find a better match
+        bestMatchMethod = candidates.get(0);
+      }
+    }
+
+    /* We found a method that we may use for setter */
+    /* append <method name>((<expr class)val); */
+    return code.append(bestMatchMethod.getName()).append("(").appendCastToTypeExpr(exprClass, VAL).append(")").getStatement();
   }
 
-  public static GetterByte createGetterByte(Class<?> pojoClass, String getterExpr)
+  /**
+   *
+   * @param pojoClass Class object that the setter applies to
+   * @param setterExpr expression to use for setter
+   * @param exprClass Class that setter will accept as parameter
+   * @param setterClass setter interface to implement
+   * @return instance of a class that implements requested Setter interface
+   */
+  @SuppressWarnings("StringEquality")
+  private static <T> Object createSetter(Class<?> pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValPlaceholder, Class<?> exprClass, Class<T> setterClass)
   {
-    return (GetterByte) createGetter(pojoClass, getterExpr, byte.class, GetterByte.class);
-  }
+    logger.debug("{} {} {} {}", pojoClass, setterExpr, exprClass, setterClass);
 
-  public static GetterChar createGetterChar(Class<?> pojoClass, String getterExpr)
-  {
-    return (GetterChar) createGetter(pojoClass, getterExpr, char.class, GetterChar.class);
-  }
+    if (setterExpr.startsWith(".")) {
+      setterExpr = setterExpr.substring(1);
+    }
 
-  public static GetterDouble createGetterDouble(Class<?> pojoClass, String getterExpr)
-  {
-    return (GetterDouble) createGetter(pojoClass, getterExpr, double.class, GetterDouble.class);
-  }
+    if (setterExpr.isEmpty()) {
+      throw new IllegalArgumentException("The setter string: " + setterExpr + "\nis invalid.");
+    }
 
-  public static GetterFloat createGetterFloat(Class<?> pojoClass, String getterExpr)
-  {
-    return (GetterFloat) createGetter(pojoClass, getterExpr, float.class, GetterFloat.class);
-  }
+    IScriptEvaluator se;
 
-  public static GetterInt createGetterInt(Class<?> pojoClass, String getterExpr)
-  {
-    return (GetterInt) createGetter(pojoClass, getterExpr, int.class, GetterInt.class);
-  }
+    try {
+      se = CompilerFactoryFactory.getDefaultCompilerFactory().newScriptEvaluator();
+    } catch (Exception ex) {
+      throw new RuntimeException(ex);
+    }
 
-  public static GetterLong createExpressionGetterLong(Class<?> pojoClass, String getterExpr)
-  {
-    return (GetterLong) createGetter(pojoClass, getterExpr, long.class, GetterLong.class);
-  }
 
-  public static GetterShort createGetterShort(Class<?> pojoClass, String getterExpr)
-  {
-    return (GetterShort) createGetter(pojoClass, getterExpr, short.class, GetterShort.class);
-  }
+    String code = StringUtils.replaceEach(setterExpr, new String[]{exprObjectPlaceholder, exprValPlaceholder},
+            new String[]{new JavaStatement().appendCastToTypeExpr(pojoClass, OBJECT).toString(), new JavaStatement().appendCastToTypeExpr(exprClass, VAL).toString()});
+    if (code != setterExpr) {
+      code = new JavaStatement().append(code).getStatement();
+      logger.debug("Original expression {} is a complex expression. Replacing it with {}.", setterExpr, code);
+    }
+    else {
+      code = getSingleFieldSetterExpression(pojoClass, setterExpr, exprClass);
+    }
 
-  public static GetterString createGetterString(Class<?> pojoClass, String getterExpr)
-  {
-    return (GetterString) createGetter(pojoClass, getterExpr, String.class, GetterString.class);
-  }
+    try {
 
-  public static GetterObject createGetterObject(Class<?> pojoClass, String getterExpr)
-  {
-    return (GetterObject) createGetter(pojoClass, getterExpr, Object.class, GetterObject.class);
+      logger.debug("code: {}", code);
+
+      return se.createFastEvaluator(code, setterClass, new String[] { PojoUtils.OBJECT, PojoUtils.VAL});
+    } catch (CompileException ex) {
+      throw new RuntimeException(ex);
+    }
   }
 
 }
+
diff --git a/library/src/test/java/com/datatorrent/lib/util/PojoUtilsTest.java b/library/src/test/java/com/datatorrent/lib/util/PojoUtilsTest.java
index f09a1da..f925390 100644
--- a/library/src/test/java/com/datatorrent/lib/util/PojoUtilsTest.java
+++ b/library/src/test/java/com/datatorrent/lib/util/PojoUtilsTest.java
@@ -16,7 +16,28 @@
 
 package com.datatorrent.lib.util;
 
-import org.junit.Assert;
+import static com.datatorrent.lib.util.PojoUtils.createGetter;
+import static com.datatorrent.lib.util.PojoUtils.createGetterBoolean;
+import static com.datatorrent.lib.util.PojoUtils.createGetterByte;
+import static com.datatorrent.lib.util.PojoUtils.createGetterChar;
+import static com.datatorrent.lib.util.PojoUtils.createGetterDouble;
+import static com.datatorrent.lib.util.PojoUtils.createGetterFloat;
+import static com.datatorrent.lib.util.PojoUtils.createGetterInt;
+import static com.datatorrent.lib.util.PojoUtils.createGetterLong;
+import static com.datatorrent.lib.util.PojoUtils.createGetterShort;
+import static com.datatorrent.lib.util.PojoUtils.createSetter;
+import static com.datatorrent.lib.util.PojoUtils.createSetterBoolean;
+import static com.datatorrent.lib.util.PojoUtils.createSetterByte;
+import static com.datatorrent.lib.util.PojoUtils.createSetterChar;
+import static com.datatorrent.lib.util.PojoUtils.createSetterDouble;
+import static com.datatorrent.lib.util.PojoUtils.createSetterFloat;
+import static com.datatorrent.lib.util.PojoUtils.createSetterInt;
+import static com.datatorrent.lib.util.PojoUtils.createSetterLong;
+import static com.datatorrent.lib.util.PojoUtils.createSetterShort;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.fail;
+
 import org.junit.Test;
 
 import com.datatorrent.lib.util.PojoUtils.GetterBoolean;
@@ -26,86 +47,358 @@
 import com.datatorrent.lib.util.PojoUtils.GetterFloat;
 import com.datatorrent.lib.util.PojoUtils.GetterInt;
 import com.datatorrent.lib.util.PojoUtils.GetterLong;
-import com.datatorrent.lib.util.PojoUtils.GetterObject;
+import com.datatorrent.lib.util.PojoUtils.Getter;
 import com.datatorrent.lib.util.PojoUtils.GetterShort;
-import com.datatorrent.lib.util.PojoUtils.GetterString;
+import com.datatorrent.lib.util.PojoUtils.Setter;
+import com.datatorrent.lib.util.PojoUtils.SetterBoolean;
+import com.datatorrent.lib.util.PojoUtils.SetterByte;
+import com.datatorrent.lib.util.PojoUtils.SetterInt;
+import com.datatorrent.lib.util.PojoUtils.SetterLong;
+import com.datatorrent.lib.util.PojoUtils.SetterShort;
+
 import com.esotericsoftware.kryo.Kryo;
 
+
 public class PojoUtilsTest
 {
+
+  private final Class<?> fqcn = TestObjAllTypes.class;
+  private final Class<TestObjAllTypes.InnerObj> innerObjClass = TestObjAllTypes.InnerObj.class;
+  private final TestObjAllTypes testObj = new TestObjAllTypes();
+  private final TestObjAllTypes.InnerObj innerObj = testObj.innerObj;
+
   @Test
-  public void simpleTest() throws Exception
+  public void testGetters() throws Exception
   {
-    Class<?> fqcn = TestObjAllTypes.class;
-    TestObjAllTypes testObj = new TestObjAllTypes();
+    GetterBoolean<Object> getBoolean = createGetterBoolean(fqcn, "innerObj.boolVal");
+    assertEquals(testObj.innerObj.isBoolVal(), getBoolean.get(testObj));
 
-    GetterBoolean getBoolean = PojoUtils.createGetterBoolean(fqcn, "innerObj.boolVal");
-    Assert.assertEquals(testObj.innerObj.isBoolVal(), getBoolean.get(testObj));
+    GetterByte<Object> getByte = createGetterByte(fqcn, "innerObj.byteVal");
+    assertEquals(testObj.innerObj.getByteVal(), getByte.get(testObj));
 
-    GetterByte getByte = PojoUtils.createGetterByte(fqcn, "innerObj.byteVal");
-    Assert.assertEquals(testObj.innerObj.getByteVal(), getByte.get(testObj));
+    GetterChar<Object> getChar = createGetterChar(fqcn, "innerObj.charVal");
+    assertEquals(testObj.innerObj.getCharVal(), getChar.get(testObj));
 
-    GetterChar getChar = PojoUtils.createGetterChar(fqcn, "innerObj.charVal");
-    Assert.assertEquals(testObj.innerObj.getCharVal(), getChar.get(testObj));
+    GetterShort<Object> getShort = createGetterShort(fqcn, "innerObj.shortVal");
+    assertEquals(testObj.innerObj.getShortVal(), getShort.get(testObj));
 
-    GetterString getString = PojoUtils.createGetterString(fqcn, "innerObj.stringVal");
-    Assert.assertEquals(testObj.innerObj.getStringVal(), getString.get(testObj));
+    GetterInt<Object> getInt = createGetterInt(fqcn, "innerObj.intVal");
+    assertEquals(testObj.innerObj.getIntVal(), getInt.get(testObj));
 
-    GetterShort getShort = PojoUtils.createGetterShort(fqcn, "innerObj.shortVal");
-    Assert.assertEquals(testObj.innerObj.getShortVal(), getShort.get(testObj));
+    GetterLong<Object> getLong = createGetterLong(fqcn, "innerObj.longVal");
+    assertEquals(testObj.innerObj.getLongVal(), getLong.get(testObj));
 
-    GetterInt getInt = PojoUtils.createGetterInt(fqcn, "innerObj.intVal");
-    Assert.assertEquals(testObj.innerObj.getIntVal(), getInt.get(testObj));
+    GetterFloat<Object> getFloat = createGetterFloat(fqcn, "innerObj.floatVal");
+    assertEquals(testObj.innerObj.getFloatVal(), getFloat.get(testObj), 0);
 
-    GetterLong getLong = PojoUtils.createExpressionGetterLong(fqcn, "innerObj.longVal");
-    Assert.assertEquals(testObj.innerObj.getLongVal(), getLong.get(testObj));
+    GetterDouble<Object> getDouble = createGetterDouble(fqcn, "innerObj.doubleVal");
+    assertEquals(testObj.innerObj.getDoubleVal(), getDouble.get(testObj), 0);
 
-    GetterFloat getFloat = PojoUtils.createGetterFloat(fqcn, "innerObj.floatVal");
-    Assert.assertEquals(testObj.innerObj.getFloatVal(), getFloat.get(testObj), 0);
+    Getter<Object, String> getString = createGetter(fqcn, "innerObj.stringVal", String.class);
+    assertEquals(testObj.innerObj.getStringVal(), getString.get(testObj));
 
-    GetterDouble getDouble = PojoUtils.createGetterDouble(fqcn, "innerObj.doubleVal");
-    Assert.assertEquals(testObj.innerObj.getDoubleVal(), getDouble.get(testObj), 0);
+    Getter<Object, Object> getObject = createGetter(fqcn, "innerObj.objVal", Object.class);
+    assertEquals(testObj.innerObj.getObjVal(), getObject.get(testObj));
 
-    GetterObject getObject = PojoUtils.createGetterObject(fqcn, "innerObj.objVal");
-    Assert.assertEquals(testObj.innerObj.getObjVal(), getObject.get(testObj));
+  }
 
-    //Check serialization
+  @Test
+  public void testSerialization() throws Exception
+  {
+    GetterBoolean<Object> getBoolean = createGetterBoolean(fqcn, "innerObj.boolVal");
     TestUtils.clone(new Kryo(), getBoolean);
+  }
 
+  @Test
+  public void testSettersBoolean() throws Exception
+  {
+    boolean boolVal = !innerObj.boolVal;
+    createSetterBoolean(fqcn, "innerObj.boolVal").set(testObj, boolVal);
+    assertEquals(boolVal, innerObj.boolVal);
+    createSetterBoolean(innerObjClass, "boolVal").set(innerObj, !boolVal);
+    assertEquals(!boolVal, innerObj.boolVal);
+    createSetterBoolean(innerObjClass, "protectedBoolVal").set(innerObj, boolVal);
+    assertEquals(boolVal, innerObj.protectedBoolVal);
+    createSetterBoolean(innerObjClass, "privateBoolVal").set(innerObj, boolVal);
+    assertEquals(boolVal, innerObj.isPrivateBoolVal());
+  }
+
+  @Test
+  public void testSettersByte() throws Exception
+  {
+    byte byteVal = innerObj.byteVal;
+    createSetterByte(fqcn, "innerObj.byteVal").set(testObj, ++byteVal);
+    assertEquals(byteVal, innerObj.byteVal);
+    createSetterByte(innerObjClass, "byteVal").set(innerObj, ++byteVal);
+    assertEquals(byteVal, innerObj.byteVal);
+    createSetterByte(innerObjClass, "protectedByteVal").set(innerObj, ++byteVal);
+    assertEquals(byteVal, innerObj.protectedByteVal);
+    createSetterByte(innerObjClass, "privateByteVal").set(innerObj, ++byteVal);
+    assertEquals(byteVal, innerObj.getPrivateByteVal());
+  }
+  
+  @Test
+  public void testSetterChar() throws Exception
+  {
+    char charVal = innerObj.charVal;
+    createSetterChar(fqcn, "innerObj.charVal").set(testObj, ++charVal);
+    assertEquals(charVal, innerObj.charVal);
+    createSetterChar(innerObjClass, "charVal").set(innerObj, ++charVal);
+    assertEquals(charVal, innerObj.charVal);
+    createSetterChar(innerObjClass, "protectedCharVal").set(innerObj, ++charVal);
+    assertEquals(charVal, innerObj.protectedCharVal);
+    createSetterChar(innerObjClass, "privateCharVal").set(innerObj, ++charVal);
+    assertEquals(charVal, innerObj.getPrivateCharVal());
+  }
+  
+  @Test
+  public void testSetterShort() throws Exception
+  {
+    short shortVal = innerObj.shortVal;
+    createSetterShort(fqcn, "innerObj.shortVal").set(testObj, ++shortVal);
+    assertEquals(shortVal, innerObj.shortVal);
+    createSetterShort(innerObjClass, "shortVal").set(innerObj, ++shortVal);
+    assertEquals(shortVal, innerObj.shortVal);
+    createSetterShort(innerObjClass, "protectedShortVal").set(innerObj, ++shortVal);
+    assertEquals(shortVal, innerObj.protectedShortVal);
+    createSetterShort(innerObjClass, "privateShortVal").set(innerObj, ++shortVal);
+    assertEquals(shortVal, innerObj.getPrivateShortVal());
+  }
+
+  @Test
+  public void testSetterInt() throws Exception
+  {
+    int intVal = innerObj.intVal;
+    PojoUtils.createSetterInt(fqcn, "innerObj.intVal").set(testObj, ++intVal);
+    assertEquals(intVal, innerObj.intVal);
+    createSetterInt(innerObjClass, "intVal").set(innerObj, ++intVal);
+    assertEquals(intVal, innerObj.intVal);
+    createSetterInt(innerObjClass, "protectedIntVal").set(innerObj, ++intVal);
+    assertEquals(intVal, innerObj.protectedIntVal);
+    createSetterInt(innerObjClass, "privateIntVal").set(innerObj, ++intVal);
+    assertEquals(intVal, innerObj.getPrivateIntVal());
+  }
+
+  @Test
+  public void testSetterLong() throws Exception
+  {
+    long longVal = innerObj.longVal;
+    PojoUtils.createSetterLong(fqcn, "innerObj.longVal").set(testObj, ++longVal);
+    assertEquals(longVal, innerObj.longVal);
+    createSetterLong(innerObjClass, "longVal").set(innerObj, ++longVal);
+    assertEquals(longVal, innerObj.longVal);
+    createSetterLong(innerObjClass, "protectedLongVal").set(innerObj, ++longVal);
+    assertEquals(longVal, innerObj.protectedLongVal);
+    createSetterLong(innerObjClass, "privateLongVal").set(innerObj, ++longVal);
+    assertEquals(longVal, innerObj.getPrivateLongVal());
+  }
+
+  @Test
+  public void testSetterString() throws Exception
+  {
+    String string = innerObj.stringVal.concat("test");
+    createSetter(fqcn, "innerObj.stringVal", String.class).set(testObj, string);
+    assertSame(string, innerObj.stringVal);
+    createSetter(innerObjClass, "stringVal", String.class).set(innerObj, string = string.concat("more test"));
+    assertEquals(string, innerObj.stringVal);
+    createSetter(innerObjClass, "protectedStringVal", String.class).set(innerObj, string = string.concat("and more test"));
+    assertSame(string, innerObj.protectedStringVal);
+    createSetter(innerObjClass, "privateStringVal", String.class).set(innerObj, string = string.concat("and even more test"));
+    assertSame(string, innerObj.getPrivateStringVal());
+  }
+
+  @Test
+  public void testSetterFloat() throws Exception
+  {
+    float floatVal = innerObj.floatVal;
+    createSetterFloat(fqcn, "innerObj.floatVal").set(testObj, ++floatVal);
+    assertEquals(floatVal, innerObj.floatVal, 0);
+    createSetterFloat(innerObjClass, "floatVal").set(innerObj, ++floatVal);
+    assertEquals(floatVal, innerObj.floatVal, 0);
+    createSetterFloat(innerObjClass, "protectedFloatVal").set(innerObj, ++floatVal);
+    assertEquals(floatVal, innerObj.protectedFloatVal, 0);
+    createSetterFloat(innerObjClass, "privateFloatVal").set(innerObj, ++floatVal);
+    assertEquals(floatVal, innerObj.getPrivateFloatVal(), 0);
+  }
+
+  @Test
+  public void testSetterDouble() throws Exception
+  {
+    double doubleVal = innerObj.doubleVal;
+    createSetterDouble(fqcn, "innerObj.doubleVal").set(testObj, ++doubleVal);
+    assertEquals(doubleVal, innerObj.doubleVal, 0);
+    createSetterDouble(innerObjClass, "doubleVal").set(innerObj, ++doubleVal);
+    assertEquals(doubleVal, innerObj.doubleVal, 0);
+    createSetterDouble(innerObjClass, "protectedDoubleVal").set(innerObj, ++doubleVal);
+    assertEquals(doubleVal, innerObj.protectedDoubleVal, 0);
+    createSetterDouble(innerObjClass, "privateDoubleVal").set(innerObj, ++doubleVal);
+    assertEquals(doubleVal, innerObj.getPrivateDoubleVal(), 0);
+  }
+
+  @Test
+  public void testSetterObject() throws Exception
+  {
+    createSetter(fqcn, "innerObj.objVal", Object.class).set(testObj, fqcn);
+    assertSame(fqcn, innerObj.objVal);
+    createSetter(innerObjClass, "objVal", Object.class).set(innerObj, innerObjClass);
+    assertSame(innerObjClass, innerObj.objVal);
+    createSetter(innerObjClass, "protectedObjVal", Object.class).set(innerObj, innerObjClass);
+    assertSame(innerObjClass, innerObj.protectedObjVal);
+    createSetter(innerObjClass, "privateObjVal", Object.class).set(innerObj, innerObjClass);
+    assertSame(innerObjClass, innerObj.getPrivateObjVal());
   }
 
   public static class TestPojo
   {
-    public int intField = 1;
+    public static final String INT_FIELD_NAME = "intField";
+    public int intField;
+    @SuppressWarnings("unused")
+    private int privateIntField;
 
-    public int getIntVal() {
-      return 2;
-    };
+    public TestPojo(int intVal)
+    {
+      intField = intVal;
+    }
+
+    public int getIntVal()
+    {
+      return intField;
+    }
 
     public boolean isBoolVal()
     {
       return true;
-    };
+    }
+
+    @SuppressWarnings("unused")
+    public void setIntVal(int intVal)
+    {
+      intField = intVal;
+    }
+
+    @SuppressWarnings("unused")
+    public void setIntVal(Integer intVal) {
+      intField = intVal;
+    }
+
+    @SuppressWarnings("unused")
+    public void setBoolVal(boolean boolVal)
+    {
+      throw new UnsupportedOperationException("setting boolean is not supported");
+    }
+
+    @SuppressWarnings("unused")
+    private void setPrivateInt(final int intVal)
+    {
+      throw new UnsupportedOperationException("not the right method");
+    }
+
+    @SuppressWarnings("unused")
+    public void setPrivateInt(final int intVal, final int anotherIntVal)
+    {
+      throw new UnsupportedOperationException("not the right method");
+    }
 
   }
 
   @Test
   public void testGetterOrFieldExpression()
   {
-    TestPojo testObj = new TestPojo();
+    TestPojo testObj = new TestPojo(1);
 
-    String expr = PojoUtils.getSingleFieldExpression(testObj.getClass(), "intVal");
-    GetterObject getObject = PojoUtils.createGetterObject(testObj.getClass(), expr);
-    Assert.assertEquals(testObj.getIntVal(), getObject.get(testObj));
+    Class<?> testObjClass = testObj.getClass();
 
-    expr = PojoUtils.getSingleFieldExpression(testObj.getClass(), "intField");
-    getObject = PojoUtils.createGetterObject(testObj.getClass(), expr);
-    Assert.assertEquals(testObj.intField, getObject.get(testObj));
+    Getter<Object, Object> getObject = createGetter(testObjClass, "intVal", Object.class);
+    assertEquals(testObj.getIntVal(), getObject.get(testObj));
+    assertEquals(testObj.getIntVal(), createGetterInt(testObjClass, "intVal").get(testObj));
 
-    expr = PojoUtils.getSingleFieldExpression(testObj.getClass(), "boolVal");
-    getObject = PojoUtils.createGetterObject(testObj.getClass(), expr);
-    Assert.assertEquals(testObj.isBoolVal(), getObject.get(testObj));
+    getObject = createGetter(testObjClass, "intField", Object.class);
+    assertEquals(testObj.intField, getObject.get(testObj));
+    assertEquals(testObj.intField, createGetterInt(testObjClass, "intField").get(testObj));
+
+    getObject = PojoUtils.createGetter(testObjClass, "boolVal", Object.class);
+    assertEquals(testObj.isBoolVal(), getObject.get(testObj));
+    assertEquals(testObj.isBoolVal(), createGetterBoolean(testObjClass, "boolVal").get(testObj));
 
   }
 
+  @Test
+  public void testComplexGetter()
+  {
+    TestPojo testPojo = new TestPojo(1);
+    final Class<?> testPojoClass = testPojo.getClass();
+    GetterInt<Object> getterInt = createGetterInt(testPojoClass, "{$}.getIntVal() + {$}.intField");
+    assertEquals(testPojo.getIntVal() + testPojo.intField, getterInt.get(testPojo));
+  }
+
+  @Test
+  public void testComplexSetter()
+  {
+    TestPojo testPojo = new TestPojo(1);
+    Class<?> testPojoClass = testPojo.getClass();
+    SetterInt<Object> setterInt = createSetterInt(testPojoClass, "{$}.setIntVal({$}.getIntVal() + {#})");
+    setterInt.set(testPojo, 20);
+    Setter<Object, String> setterString = createSetter(testPojoClass, "{$}.setIntVal(Integer.valueOf({#}))", String.class);
+    setterString.set(testPojo, "20");
+  }
+
+  @Test
+  @SuppressWarnings("UnnecessaryBoxing")
+  public void testSetterOrFieldExpression()
+  {
+    TestPojo testPojo = new TestPojo(0);
+    final Class<?> testPojoClass = testPojo.getClass();
+    SetterInt<Object> setterInt = createSetterInt(testPojoClass, TestPojo.INT_FIELD_NAME);
+    setterInt.set(testPojo, 1);
+    assertEquals(1, testPojo.intField);
+
+    setterInt = createSetterInt(testPojoClass, "intVal");
+    setterInt.set(testPojo, 2);
+    assertEquals(2, testPojo.getIntVal());
+
+    SetterByte<Object> setterByte = createSetterByte(testPojoClass, TestPojo.INT_FIELD_NAME);
+    setterByte.set(testPojo, (byte)3);
+    assertEquals(3, testPojo.intField);
+
+    SetterShort<Object> setterShort = createSetterShort(testPojoClass, TestPojo.INT_FIELD_NAME);
+    setterShort.set(testPojo, (short)4);
+    assertEquals(4, testPojo.intField);
+
+    try {
+      @SuppressWarnings("unused")
+      SetterLong<Object> setterLong = createSetterLong(testPojoClass, TestPojo.INT_FIELD_NAME);
+      fail("long can't be assigned to the int field");
+    }
+    catch (Exception ignored) {
+    }
+
+    Setter<Object, Integer> setterInteger = createSetter(testPojoClass, TestPojo.INT_FIELD_NAME, Integer.class);
+    setterInteger.set(testPojo, Integer.valueOf(5));
+    assertEquals(5, testPojo.intField);
+
+  }
+
+  @Test (expected = UnsupportedOperationException.class)
+  public void testExceptionInSetter()
+  {
+    final Class<?> testPojoClass = TestPojo.class;
+    SetterBoolean<Object> setterBoolean = createSetterBoolean(testPojoClass, "boolVal");
+    setterBoolean.set(new TestPojo(3), false);
+  }
+
+  @Test (expected = RuntimeException.class)
+  public void testPrivateField()
+  {
+    final Class<?> testPojoClass = TestPojo.class;
+    @SuppressWarnings("unused")
+    SetterInt<Object> setterInt = createSetterInt(testPojoClass, "privateIntField");
+  }
+
+  @Test (expected = RuntimeException.class)
+  public void testWrongSetterMethod()
+  {
+    final Class<?> testPojoClass = TestPojo.class;
+    @SuppressWarnings("unused")
+    SetterInt<Object> setterInt = createSetterInt(testPojoClass, "privateInt");
+  }
 }
diff --git a/library/src/test/java/com/datatorrent/lib/util/TestObjAllTypes.java b/library/src/test/java/com/datatorrent/lib/util/TestObjAllTypes.java
index 387c9f2..478ea27 100644
--- a/library/src/test/java/com/datatorrent/lib/util/TestObjAllTypes.java
+++ b/library/src/test/java/com/datatorrent/lib/util/TestObjAllTypes.java
@@ -50,11 +50,33 @@
     public String stringVal = "hello";
     public short shortVal = 10;
     public int intVal = 11;
-    public long longVal = 15;
+    public long longVal = 15L;
     public float floatVal = 5.5f;
     public double doubleVal = 6.3;
     public Object objVal = Lists.newArrayList("bananas");
 
+    protected boolean protectedBoolVal = boolVal;
+    protected byte protectedByteVal = byteVal;
+    protected char protectedCharVal = charVal;
+    protected String protectedStringVal = stringVal;
+    protected short protectedShortVal = shortVal;
+    protected int protectedIntVal = intVal;
+    protected long protectedLongVal = longVal;
+    protected float protectedFloatVal = floatVal;
+    protected double protectedDoubleVal = doubleVal;
+    protected Object protectedObjVal = objVal;
+
+    private boolean privateBoolVal = boolVal;
+    private byte privateByteVal = byteVal;
+    private char privateCharVal = charVal;
+    private String privateStringVal = stringVal;
+    private short privateShortVal = shortVal;
+    private int privateIntVal = intVal;
+    private long privateLongVal = longVal;
+    private float privateFloatVal = floatVal;
+    private double privateDoubleVal = doubleVal;
+    private Object privateObjVal = objVal;
+
     /**
      * @return the boolVal
      */
@@ -214,5 +236,156 @@
     {
       this.objVal = objVal;
     }
+
+    public void setProtectedBoolVal(boolean protectedBoolVal)
+    {
+      this.protectedBoolVal = protectedBoolVal;
+    }
+
+    public void setProtectedByteVal(byte protectedByteVal)
+    {
+      this.protectedByteVal = protectedByteVal;
+    }
+
+    public void setProtectedCharVal(char protectedCharVal)
+    {
+      this.protectedCharVal = protectedCharVal;
+    }
+
+    public void setProtectedStringVal(String protectedStringVal)
+    {
+      this.protectedStringVal = protectedStringVal;
+    }
+
+    public void setProtectedShortVal(short protectedShortVal)
+    {
+      this.protectedShortVal = protectedShortVal;
+    }
+
+    public void setProtectedIntVal(int protectedIntVal)
+    {
+      this.protectedIntVal = protectedIntVal;
+    }
+
+    public void setProtectedLongVal(long protectedLongVal)
+    {
+      this.protectedLongVal = protectedLongVal;
+    }
+
+    public void setProtectedFloatVal(float protectedFloatVal)
+    {
+      this.protectedFloatVal = protectedFloatVal;
+    }
+
+    public void setProtectedDoubleVal(double protectedDoubleVal)
+    {
+      this.protectedDoubleVal = protectedDoubleVal;
+    }
+
+    public void setProtectedObjVal(Object protectedObjVal)
+    {
+      this.protectedObjVal = protectedObjVal;
+    }
+
+    public boolean isPrivateBoolVal()
+    {
+      return privateBoolVal;
+    }
+
+    public void setPrivateBoolVal(boolean privateBoolVal)
+    {
+      this.privateBoolVal = privateBoolVal;
+    }
+
+    public byte getPrivateByteVal()
+    {
+      return privateByteVal;
+    }
+
+    public void setPrivateByteVal(byte privateByteVal)
+    {
+      this.privateByteVal = privateByteVal;
+    }
+
+    public char getPrivateCharVal()
+    {
+      return privateCharVal;
+    }
+
+    public void setPrivateCharVal(char privateCharVal)
+    {
+      this.privateCharVal = privateCharVal;
+    }
+
+    public String getPrivateStringVal()
+    {
+      return privateStringVal;
+    }
+
+    public void setPrivateStringVal(String privateStringVal)
+    {
+      this.privateStringVal = privateStringVal;
+    }
+
+    public short getPrivateShortVal()
+    {
+      return privateShortVal;
+    }
+
+    public void setPrivateShortVal(short privateShortVal)
+    {
+      this.privateShortVal = privateShortVal;
+    }
+
+    public int getPrivateIntVal()
+    {
+      return privateIntVal;
+    }
+
+    public void setPrivateIntVal(int privateIntVal)
+    {
+      this.privateIntVal = privateIntVal;
+    }
+
+    public long getPrivateLongVal()
+    {
+      return privateLongVal;
+    }
+
+    public void setPrivateLongVal(long privateLongVal)
+    {
+      this.privateLongVal = privateLongVal;
+    }
+
+    public float getPrivateFloatVal()
+    {
+      return privateFloatVal;
+    }
+
+    public void setPrivateFloatVal(float privateFloatVal)
+    {
+      this.privateFloatVal = privateFloatVal;
+    }
+
+    public double getPrivateDoubleVal()
+    {
+      return privateDoubleVal;
+    }
+
+    public void setPrivateDoubleVal(double privateDoubleVal)
+    {
+      this.privateDoubleVal = privateDoubleVal;
+    }
+
+    public Object getPrivateObjVal()
+    {
+      return privateObjVal;
+    }
+
+    public void setPrivateObjVal(Object privateObjVal)
+    {
+      this.privateObjVal = privateObjVal;
+    }
+
   }
 }