Newsletter sign-up
View all newsletters

Sign up for our Enterprise Java Newsletter

Enterprise Java

Reflection vs. code generation

Avoid runtime reflection when marshaling data

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Data marshaling (pulling data from an outside source and loading it into a Java object) can utilize the benefits of reflection to create a reusable solution. The problem is simple enough: load data from a file into an object's fields. Now, what if the target Java classes for the data change on a weekly basis? A straightforward solution still works, but you must continually maintain the loading procedures to reflect any changes. To further complicate the situation, the same problem may crosscut the system's breadth. Anyone who has dealt with a large system using XML has encountered this problem. Coding a load procedure is often tedious and subject to frequent updates and rewrites due to changes to the source data or the target Java class. A solution using reflection, which I'll describe here, often requires less coding, and updates itself when changes are made to the target Java class.

Originally, I intended to demonstrate a solution using reflection during runtime for data marshaling. Initially a dynamic, reflection-based program was far more attractive than a simpler approach. Over time, the novelty faded to reveal the complexity and risk of runtime reflection. This article charts this evolution from runtime reflection to active code generation.

From simplicity to complexity

My first solution used a loading class to load the objects' data from a flat file. My source code contained several dozen calls for the next token of a StringTokenizer object. After several refactorings (see Martin Fowler's Refactoring), my coding logic became straightforward, nearly systematic. The class structure dictated code. My initial solutions showed me that I needed only to account for three basic objects:

  1. Strings
  2. Objects
  3. Arrays of objects


You could map the class's objects to generalized code blocks, as shown in the following table:

Objects mapped to generalized code blocks

Field type Code block
String
fileIterator.nextString();
Object[]
Vector collector = new Vector();
while(fileIterator.hasMoreDataForArray()){ 
   Object data = initializeObject(fileIterator)collector.add(data);
}
Object[] objArray = new Object[collector.size()];
collector.copyInto(objArray);
Object
initializeObject(fileIterator);


Having coded the solution several times, I knew the solution and the code structure before I wrote any of the code. The difficulty arose from the classes' changing landscape. The class names, compositions, and structures could change at any moment, and any change could force a rewrite. Given these changes, the structure and loading process still remained the same; I still knew the code structure and composition before I wrote the code. I needed a way to translate the coding processes in my head into a reproducible, automated form. Since I am an efficient (i.e., lazy) programmer, I quickly tired of writing nearly identical code. Reflection came to my rescue.

Marshaling usually requires source and target data maps. Maps can take the shape of a schema, DTD (document type definition), file format, and so on. In this case, reflection interprets an object's class definition as the target map for our mapping process. Reflection can duplicate the code's functionality during runtime. So during a required rewrite, I replaced the load procedure with reflection in the same amount of time it would have taken me to do the rewrite.

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comment
Login
Forgot your account info?
Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources