Home > General, Java > Auto Object Population via Reflection

Auto Object Population via Reflection

Using reflection in the right place can some what simplify certain tasks, in this case the population of Custom classes (data objects). I have supplied below an example of a Class being auto-populated using ResultSet data from a JDBC request (of course it could really be any type of 2D data object).

If a public class variable is declared in the implementation of IModelObject (in this case the implementation is the RemoteConfig class) if the variable name is matched against a column name in the JDBC ResultSet then the value is assigned to the class variable. The great thing is if the variable is not defined in the class then it will quite simply never be populated…obviously as it doesn’t exist :)

In the example below only; String, int and boolean types are supported.

Basic interface class to keep thing reasonably generic

package Model.Objects;

import java.sql.ResultSet;

public interface IModelObject{
	
	public void populate(ResultSet rs);
	
	public String objToString();
	
	public void setDebug(boolean debug);
	
	public boolean getDebug();

}

Implementation of IModelObject which is the Class (data access object) to be auto-populated, (variables; var1, var2, var3, var4 will attempt to be auto-populated)

package Model.Objects;

import java.lang.reflect.*;
import java.sql.ResultSet;
import java.sql.SQLException;

@SuppressWarnings("unused")
public class RemoteConfig implements IModelObject{
	
	// Public variables ONLY are auto-populated using reflection

	public String var1;
	
	public int var2;
	
	public String var3;
	
	public boolean var4;
	
	private ResultSet resultSet;
	
	private static final String REFLECTION_TYPE_INT = "int";
	
	private static final String REFLECTION_TYPE_INTEGER = "Integer";
	
	private static final String REFLECTION_TYPE_STRING = "String";
	
	private static final String REFLECTION_TYPE_BOOLEAN = "boolean";
	
	private boolean debug = false;
	
	public RemoteConfig(){
		// Default constructor
	}
	
	public RemoteConfig(ResultSet rs){
		this.resultSet = rs;
		populate(rs);
	}
	
	public RemoteConfig(ResultSet rs,boolean debug){
		this.resultSet = rs;
		this.setDebug(debug);
		populate(rs);
	}
	
	public void populate(ResultSet rs){
		// NOTE: getFields only returns public variables (which is what we want)
		// if you need all declared variables the use getDeclaredFields
		for(int i=0;i< this.getClass().getFields().length;i++){
			try {
				String varName = this.getClass().getDeclaredFields()[i].getName();
				Field field = this.getClass().getDeclaredField(varName);
				
				try{
					populateClassVarByName(field);
				} 
				catch (IllegalArgumentException e) {
					e.printStackTrace();
				} 
			} 
			catch (SecurityException e) {
				e.printStackTrace();
			}
			catch (NoSuchFieldException e) {
				e.printStackTrace();
			}
		}
		if (debug){
			System.out.print(objToString());
		}
	}
	
	private void populateClassVarByName(Field field){
		try{
			if (field.getType().getSimpleName().equals(REFLECTION_TYPE_INT) || 
				field.getType().getSimpleName().equals(REFLECTION_TYPE_INTEGER)){
			
				try {
					field.set(this,resultSet.getInt(field.getName()));
				} 
				catch (IllegalArgumentException e){
					e.printStackTrace();
				} 
				catch (IllegalAccessException e){
					e.printStackTrace();
				}
			}
			else if (field.getType().getSimpleName().equals(REFLECTION_TYPE_STRING)){
				try{
					field.set(this,resultSet.getString(field.getName()));
				}
				catch (IllegalArgumentException e){
					e.printStackTrace();
				}
				catch (IllegalAccessException e){
					e.printStackTrace();
				}
			}
			else if (field.getType().getSimpleName().equals(REFLECTION_TYPE_BOOLEAN)){
				try{
					if (resultSet.getString(field.getName()).equals("1")){
						field.set(this,true);
					}
					else if (resultSet.getString(field.getName()).equals("0")){
						field.set(this,false);
					}
					else{
						field.set(this,resultSet.getBoolean(field.getName()));
					}
				}
				catch (IllegalArgumentException e){
					e.printStackTrace();
				}
				catch (IllegalAccessException e){
					e.printStackTrace();
				}
			}
			
		} 
		catch (SQLException e){
			System.out.print("\n" + e.toString() + "\n");
		}
	}
	
	public String objToString(){
		String toStringResult = "\n---------" + this.getClass().getName() + "---------\n";
		
		for(int i=0;i< this.getClass().getDeclaredFields().length;i++){
			String varName = this.getClass().getDeclaredFields()[i].getName();
			try{
				Field field = this.getClass().getDeclaredField(varName);
				try {
					toStringResult += varName + ":" + field.get(this) + " (" + field.getType().getSimpleName() + ")\n";
				}
				catch (IllegalArgumentException e) {
					e.printStackTrace();
				} 
				catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			} 
			catch (SecurityException e) {
				e.printStackTrace();
			} 
			catch (NoSuchFieldException e) {
				e.printStackTrace();
			}
		}
		toStringResult += "---------\n";
		
		return toStringResult;
	}
	
	public void setDebug(boolean debug){
		this.debug = debug;
	}
	
	public boolean getDebug(){
		return debug;
	}
}

Basic usage


/**
 * Get you your ResultSet via JDBC and pass it in
 */

RemoteConfig remoteConfig = new RemoteConfig(myResultSet,debug);
  1. September 26th, 2009 at 00:30 | #1

    As you showed, reflection can be really useful. But code using this API usually is hard to read. There is a project that attempts to solve this problem. http://projetos.vidageek.net/mirror/

    Anyway, good post.

  1. No trackbacks yet.
*