Monday, December 5, 2011

organization

Many believe that the organization of your house reflects the level turmoil of your being. I believe this to be very true which is why tonight I clean. Along side this I also believe the same for thought. The more methodical a person is in forming opinion/strategy, the more defined the outcome and probable of being successful.

 In the software arena it is ever important to anticipate your next step as it is in every aspect of our lives has human beings. If we can't / won't anticipate where we will be standing next then how can we intend to get there - even if where we anticipate to be standing is not exactly correct ... it's the journey not the destination I suppose. Like all things in life people have the tendency to remember the last bad thing that you did versus, the more optimistic, last good thing you did .. and hopefully it was more recent.

Thursday, May 19, 2011

freemarker

Two things.

1) Find a concern across many problems that you can standardize with sufficient metadata to drive an algorithm.
2) Use freemarker to standardize the code generation and save yourself a lot of time.

I recently did this by extending the hibernate-tools suite and the hibernate3-maven-plugin to give my organization what it needs -- well, part of what it needs -- a data access layer code generator that takes it to the next level. Generics, AOP and pseudo-partial classes. This solidifies the pattern and practice and is extremely extensible not to mention it slims down the application code drastically and development timelines.

There are a ton of code generation strategies but I'm a firm believe in the power of decoupling at the interface and not binding yourself to an implementation. With that said this generation code generates an injectable/autowireable manager, dao interfaces that extend a generic definition, genericized jpa implementations that extend an implementation specific generic dao (that happens to implement the same aforementioned dao interface as well).

If you have questions or need help with such things drop me a line. I'm more than willing to help especially considering the hibernate-tools code is not well documented nor is the context information passed into freemarker.

Thursday, April 21, 2011

Loathe, Like, Love.: Loathe of the day...Ai WeiWei's Latest Predicament...

Loathe, Like, Love.: Loathe of the day...Ai WeiWei's Latest Predicament...: "Ai WeiWei's Template Grapes Chandelier, 2002 Cube Light Forever Bicycles The artist/activist. I hate to get political w..."

Tuesday, April 19, 2011

android and aspect oriented programming (aop)

When OOP appeared in the software world it was pioneering. Encapsulation! Abstraction! OOP became the next big thing and it's still huge. OOP is great; you can define an ontology and build out what the grammar of whatever your layer/application is. It's fantastic. But there are simply some things that don't really belong to an object. We'll call these cross-cutting concerns. These concerns are pervasive throughout an application (i.e. transaction registration, CRM auditing) and typically functional. Enter AOP (aspect oriented programming) brought to us some years ago by the guys at Xerox PARC. Some will say it's made things a lot easier, some would say I have no clue what is going on. AOP compliments OOP very well. Some will say that you can do the same with well defined interfaces or abstracts BUT that truly does require dead accuracy basically the first time, can cause drastic issues if refactoring is needed and simply can clutter your code. AOP is a new(er) strategy for modularization. Note: another good one is the decorator pattern.

Getting back to it. I've used many AOP technologies and am currently using AspectJ rather frequently in lower level framework development. Making some concerns declarative via an annotation, or simply flat out applied to all methods (i.e. tracing, execution auditing), for some reason makes it a lot easier to understand. Hide the magic.

Recently I've begun doing a significant amount of Android development across many products and have thought to myself Can I get AOP to work on the Dalvik VM?. Well, the answer is yes. Largely I've had a desire to do this b/c I lead a group of developers and unifying a development process always comes from the bottom up. This guarantees adherence to pattern and convention above and beyond coding standards and promotes a massive amount of re-use. This very important for making sure certain concerns are addressed in the same fashion (i.e. exception handling).

Granted AOP has taken off in certain areas and has not in others the challenge of introducing advice into Android code was a challenging one up front but not insurmountable. The reason being for this is that the first building block of Android is a Java development environment and the Java class byte code format. The next stage, after development, is the packaging of these java class files into the Dalvik Executable format (DEX). Unfortunately advice cannot be applied directly to DEX files b/c currently the Android runtime lacks a byte code generation scheme where Java supports several forms of advice introduction:

  1. compile time -- byte code manipulation.
  2. load time -- byte code manipulation. Has a slower startup time.
  3. run time -- auto-proxies of various forms (an is-a relationship) or jdk interceptors (Spring for example can work in both of these paradigms but it is fundamentally the slowest).

With that said applying advice to an Android app, due to the lack byte code generation schemes, is option 1. With this we can write java code and compile aspects directly into it and finally convert it to the DEX format to run on android devices.

One thing to note about DEX is that it unpacks all jar files and packages all dependent classes into a single zip archive, classes.dex. This could be because of several historical reasons:

  1. J2ME has proven to have issues in the past with class loaders and and a large number of classes.
  2. not having the byte code in the java format mitigates the need for the OEM to have to pay Sun / J2ME licensing fees.

A bit of history....

Let's get back to it.

I'm a firm believer in logical architecture where your libraries represent modularized concerns. With that said I also like to create aspects that sit at a lower level or at that of an API. This can be done generally via abstract pointcut definitions to allow the application to define the fully qualified pointcut definition but the same advice is applied; or, by proceeding in a declarative fashion. This is great b/c it engages the developer and removes the need for them to understand pointcut definitions.

So, considering this, let's create a Java project in maven with an aspect to be applied to another module. We'll call it android.aop. The following is a boiled down maven build script for the android.aop project:


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>some.group</groupId>
 <artifactId>android.aop</artifactId>
 <version>1.0.0</version>
 <packaging>jar</packaging>

 <dependencies>
  <dependency>
   <groupId>com.google.android</groupId>
   <artifactId>android</artifactId>
   <version>2.2.1</version>
   <scope>provided</scope>
  </dependency>
  <dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjrt</artifactId>
   <version>1.6.10</version>
   <scope>provided</scope>
   <optional>false</optional>
  </dependency>
  <dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjweaver</artifactId>
   <version>1.6.10</version>
   <scope>provided</scope>
   <optional>false</optional>
  </dependency>
  <dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjtools</artifactId>
   <version>1.6.10</version>
   <scope>provided</scope>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.3.1</version>
    <configuration>
     <source>1.5</source>
     <complianceLevel>1.5</complianceLevel>
     <showWeaveInfo>true</showWeaveInfo>
     <verbose>true</verbose>
    </configuration>
    <executions>
     <execution>
      <goals>
       <goal>compile</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
   <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
     <source>1.5</source>
     <target>1.5</target>
    </configuration>
   </plugin>
  </plugins>
 </build>
</project>


The maven-aspectj-plugin will look for aspects beneath src/main/aspect.

An android apk maven build script (boiled down of course):


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>some.other.group</groupId>
 <artifactId>android.apk</artifactId>
 <version>1.0.0</version>
 <packaging>apk</packaging> 

 <dependencies>
  <dependency>
   <groupId>com.google.android</groupId>
   <artifactId>android</artifactId>
   <version>2.2.1</version>
   <scope>provided</scope>
  </dependency>
  <dependency>
   <groupId>some.group</groupId>
   <artifactId>android.aop</artifactId>
   <version>1.0.0</version>
   <type>jar</type>
   <scope>compile</scope>
  </dependency>
  <dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjrt</artifactId>
   <version>1.6.9</version>
  </dependency>
  <dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjtools</artifactId>
   <version>1.6.10</version>
   <scope>provided</scope>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>com.jayway.maven.plugins.android.generation2</groupId>
    <artifactId>maven-android-plugin</artifactId>
    <version>2.8.4</version>
    <configuration>
     <sdk>
      <platform>2.1</platform>
     </sdk>
     <extractDuplicates>true</extractDuplicates>
     <undeployBeforeDeploy>true</undeployBeforeDeploy>
    </configuration>
    <extensions>true</extensions>
   </plugin>
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.3.1</version>
    <configuration>
     <argumentFileName>trace.lst</argumentFileName>
     <aspectLibraries>
      <aspectLibrary>
       <groupId>some.group</groupId>
       <artifactId>android.aop</artifactId>
      </aspectLibrary>
     </aspectLibraries>
     <source>1.5</source>
     <complianceLevel>1.5</complianceLevel>
     <showWeaveInfo>true</showWeaveInfo>
     <verbose>true</verbose>
    </configuration>
    <executions>
     <execution>
      <goals>
       <goal>compile</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
   <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
     <source>1.5</source>
     <target>1.5</target>
    </configuration>
   </plugin>
  </plugins>
 </build>
</project>

Now that the build rigmarole is out of the way you can focus on aspect development. For instance, a declarative approach to audit use case execution perhaps.

/**
 * An annotation to be applied to methods of which we would like to track their execution
 * (i.e) createAccount
 */
public @interface Tracked {

 // add in whatever you need to track 

}

The example skeleton aspect that handles the hitting of the method:

@Aspect
public class TrackingAspect {

 @AfterReturning(value = "execution(* *(..)) && @annotation(tracked)", argNames = "joinPoint, tracked")
 public void track(JoinPoint joinPoint, Tracked tracked) {
  // whatever your tracking logic may be. 
  // The JoinPoint injection is only added with an execution pointcut is defined.
  // the tracked is passed in as an arg on the join point
 }
}

These two classes would end up in your android.aop jar and would allow for some bit of functionality to occur within your application whenever a method decorated with the @Tracked annotation appears. These annotations don't necessarily need to have a Runtime retention policy b/c we are actually applying the advice at compile time. If the Dalvik VM supported load time weaving (had a byte code generation scheme) you could leverage a Runtime retention policy.

Another that I've found useful with various declarative advice applications is leveraging JEXL (Java expression language) to pass runtime metadata to the interwoven advice via the call stack ... but we'll leave that for another post.

At any rate, that's the high and low of it. Much thanks to Nikhil Walvekar ( published an example of aspectj method tracing in Android ) for his assistance with helping me figure out a modular build in maven.

If you have questions don't hesitate to email me.

dan

Thursday, April 14, 2011

Android and a GenericizedRequest structure

One thing that I've noticed as of late as that there Android does have a great capacity for asynchronous processing via adapters to java.lang.Thread. However, I've found that when developing domain libraries it's best to hide as much of the synchronicity from the consuming developer to
a) standardized
b) simply

By providing a synchronous and asynchronous call you provide flexibility in how the API is consumed. AND you can guarantee to lighten the load of development by the integration developer. I'll create a standardized API that exposes to execute methods that derived off of a generic class which encapsulates the AsyncTask structure for say http calls if that is what you're wanting to hide. By doing this the API becomes very light, consistent and reusable across applications.

Callback is the key for onPost AsyncTask functionality. Will allow the dev to encapsulate as a reusable anonymous inner class.
public abstract class Callback {
 
 Object caller;
 
 Context context;
 
 public Callback(Object sender, Context context) {
  this.caller = sender;
  this.context = context;
 }
 
 public Object getSender() {
  return caller;
 }
 
 public final void handle(T response, Object... params) {
  doCallback(this.caller, response, params);
 }

 /**
  * The callback template
  * 
  * @param sender
  *            the activity that sent the request
  * @param response
  *            the response of T
  * @param params
  *            the input stack
  */
 protected abstract void doCallback(Object sender, T response, Object... params);
}



GenericRequest:
public abstract class GenericRequest {

 private static final String TAG = "GenericRequest";

 protected HttpRequest requestor;

 protected String url;

 public GenericRequest() {

 }

 public GenericRequest(HttpRequest requestor, String url) {
  this.requestor = requestor;
  this.url = url;
 }

 /**
  * Will make the request in a synchronous fashion
  * 
  * @return
  * @throws Exception
  */
 public T execute() throws Exception {
  assert url != null;
  assert requestor != null;
  requestor.makeRequest(url);
  String offTheWire = requestor.getStringResponse();
  return parseResponse(offTheWire);
 }

 /**
  * Will invoke an request as an AsyncTask on a thread and the
  * {@link Callback} will be invoked at the end of the execution cycle
  * 
  * @param callback
  *            the callback functionality to be made
  * @throws Exception
  *             any exception
  */
 public void execute(Callback callback) throws Exception {
  Log.d(TAG, "executing(..)");
  if (callback != null) {
   CallingAsyncTask caller = new CallingAsyncTask(callback);

   caller.execute(url);
  }
 }

 protected abstract T parseResponse(String httpResponse);

 /**
  * An inner class to handle AsyncTasks for {@link HttpRequest} if a
  * {@link Callback} method is passed to an
  * {@link GenericRequest#execute(Callback)}
  * 
  * @author Daniel Williams
  * 
  */
 class CallingAsyncTask extends AsyncTask {

  static final String TAG = "CallingAsyncTask";

  Callback callback;

  String url;

  public CallingAsyncTask(Callback callback) {
   this.callback = callback;
  }

  /**
   * Will execute a single URL and invoke the parent's
   * {@link GenericRequest#parseResponse(String)} method.
   * 

* This method by default will return java.lang.Void as we are * leveraging the Callback to handle the return to the caller. */ @Override protected T doInBackground(String... params) { Log.d(TAG, "doInBackground"); T response = null; if (params == null || params.length > 1 || params.length == 0) throw new RuntimeException("Must handle a single URL."); else this.url = params[0]; try { Log.d(TAG, "Requesting " + params[0]); requestor.makeRequest(new HttpGet(params[0])); Log.d(TAG, "request completed."); } catch (Exception e) { Log.d(TAG, e.getMessage()); throw new RuntimeException(e.getMessage(), e); } response = parseResponse(requestor.getStringResponse()); Log.d(TAG, "doInBackground complete"); return response; } @Override protected void onPostExecute(T result) { Log.d(TAG, "onPostExecute"); callback.handle(result, url); } } }



And the API Request class:
public class Request extends GenericRequest {

 public Request() {
 }
 
 /**
  * Will by default call the parent
  * @param requestor
  * @param url
  */
 public Request(HttpRequest requestor, String url) {
  super(requestor, url);
 }

 /* (non-Javadoc)
  * @see com.nbc.cnbc.android.GenericRequest#parseResponse(java.lang.String)
  */
 @Override
 protected Response parseResponse(String httpResponse) {
      // parse your httpResponse
 }
}


By solidifying this pattern via templates, anonymous inner classes for Callbacks and encapsulated AsyncTasks your API can be easily executed as:

// synchronously
Request r = new Request(new HttpRequest(), "http://www.google.com");
Response response = r.execute();

// or Asynchronously
Request r = new Request(new HttpRequest(), "http://www.google.com");
Response response = r.execute(new Callback(this, this)( {
    @Override
    public void doCallback(Object sender, Response response, Object... params) ({
         this.context.......
         this.sender.notify();
      });

Tuesday, April 12, 2011

Android persistence framework

Lately I've been doing a large amount of development work on the Android platform and have found with as many things standardizing at a lower level is a great way to enforce a concern. One of the things I've noticed is that many people have a difficult time dealing with entity relationships as well as the sqlite database in general. So, what I did was develop a genericized DAO structure as well as introduce a dao manager that can be grown by the applicaiton.

Unfortunately this strategy has a few limitations.
1) The sqlite api in Android does not support a datatype retrieval mechanism as does JDBC
2) There are a few tweaks that still need to occur in this to support CLOB and BLOB formats
3) The foreign key / entity relationship mapping still needs some work done on it for lazy loading
3) ... and some other random things

The basic grammar is simple.

An Entity has a Dao
An Entity has an ID which is a java.lang.Long
An Entity is persistable (save and delete)
An Entity can have relationships to other entities.
An Entity can be derived and its DAO can be derived as well.

Largely this is a light weight implementation of JPA for Android to simplify database persistence and remove the need for developers to have to hand code everything.

Largely the genericized DAO is a port of an implementation I've done for several other technologies including NHibernate, Hibernate and JPA and a lot of the following annotations and enumeration types are simply there to guide the engine.

Column.java:
@Retention(RetentionPolicy.RUNTIME)  
public @interface Column {
 String name() default "";
 
 /**
  * Should return a String, Long, Integer, BLOB
  * @return
  */
 EColumnType type() default EColumnType.String;
 
 /**
  * which direction are we going in relation to the {@link Entity}
  * @return
  */
 EOperation op() default EOperation.Inflate;
}

EColumnType.java:
public enum EColumnType {

 Integer(),
 Long(),
 String(),
 Blob(),
 Double(),
 Float(),
 Short();

 EColumnType() {  
 }
}


EOperation.java:
public enum EOperation {
 
 Inflate(),
 Deflate();

 EOperation() {  
 }
}

IGenericDao.java:
public interface IGenericDao<E extends IEntity> {

    public E findById(long id) throws Exception;

    public void save(E entity) throws Exception;
    
    public void delete(E entity) throws Exception;
    
    public List findAll() throws Exception; 
}

And all of the magic really happens in the Entity and GenericDao classes. The entity for all intensive purposes is a template that provides the ability to proxy to its concrete DAO and invoke the save method.

Entity.java
public abstract class Entity implements IEntity {

 static final String TAG = "Entity";

 protected Integer m_id;

 static Map inflationMap = null;

 static Map deflationMap = null;

 static Map methodAnnotationMap = null;
 
 static Gson gson = new Gson();

 /**
  * Default constructor for the generic. Will additionally normalize all
  * input methods for the column names to upper case
  */
 public Entity() {

  // load all of the column annotations related to a method
  synchronized (this.getClass()) {
   if (inflationMap == null && deflationMap == null) {
    inflationMap = new ConcurrentHashMap();
    deflationMap = new ConcurrentHashMap();
    methodAnnotationMap = new ConcurrentHashMap();

    Method[] methods = this.getClass().getMethods();

    for (Method m : methods) {
     if (m.isAnnotationPresent(Column.class)) {
      Column c = m.getAnnotation(Column.class);

      if (c.op() == EOperation.Inflate) {
       inflationMap.put(c.name().toUpperCase(), m);
       methodAnnotationMap.put(m, c);
      }

      if (c.op() == EOperation.Deflate) {
       deflationMap.put(c.name().toUpperCase(), m);
       methodAnnotationMap.put(m, c);
      }
     }
    }
   }
  }
 }

 public Entity(Integer id) {
  this();
  m_id = id;
 }

 public Integer getId() {
  return m_id;
 }

 public void setId(Integer id) {
  m_id = id;
 }

 private java.util.Date m_lastModifiedDate;

 /**
  * lastModifiedDate is exactly that. Will have column def of
  * last_modified_date
  */
 // @Override
 public java.util.Date getLastModifiedDate() {
  return m_lastModifiedDate;
 }

 // @Override
 public void setLastModifiedDate(java.util.Date date) {
  this.m_lastModifiedDate = date;
 }

 private java.util.Date m_createDate;

 /**
  * column definition create_date
  */
 public java.util.Date getCreateDate() {
  return m_createDate;
 }

 public void setCreateDate(java.util.Date date) {
  this.m_createDate = date;
 }

 @Override
 public boolean equals(Object o) {
  if (!this.getClass().equals(o.getClass()))
   return false;
  else {
   Entity e = (Entity) o;

   if (e.getId().equals(this.getId()))
    return true;
   else
    return false;
  }
 }

 public int hashCode() {
  int result;
  result = 29 * this.getClass().hashCode() + getId().hashCode();
  return result;
 }

 @Override
 public String toString() {
  return String.format("[%s#%d]", this.getClass(), getId());
 }

 public void onLoad() {
  doOnLoad();
 }

 protected void doOnLoad() {
 }

 public void save() throws Exception {
  Log.d(TAG, String.format("Save() called for: %s", this));

  doSave();
 }

 protected void doSave() throws Exception {
 }

 public void delete() throws Exception {
  Log.d(TAG, String.format("Delete() called for: {0}", this));

  doDelete();
 }

 protected void doDelete() throws Exception {
 }

 /**
  * Will generate a set of ContentValues to be persisted into the database
  * structure. This method does this by leveraging the creation of several
  * annotation driven maps based upon {@link Column}
  * 

* This method can be overriden to not leverage the reflection driven * strategy */ public ContentValues deflate() throws Exception { ContentValues values = null; Log.d("DEFLATE", String.format("deflating %s", this.toString())); if (deflationMap != null && deflationMap.size() > 0) { values = new ContentValues(); for (String s : deflationMap.keySet()) { Method m = deflationMap.get(s); Column col = methodAnnotationMap.get(m); Log.d("DEFLATE", String.format("Column identified as %s, %s, %s", col.name(), col.type(), col.op())); Object o = null; switch (col.type()) { case Integer: o = m.invoke(this, (Object[])null); Log.d("DEFLATE", String.format("Deflation value of: %s", o.toString())); values.put(col.name(), (Integer)o); break; case String: o = m.invoke(this, (Object[])null); Log.d("DEFLATE", String.format("Deflation value of: %s", o.toString())); values.put(col.name(), (String)o); break; case Short: o = m.invoke(this, (Object[])null); Log.d("DEFLATE", String.format("Deflation value of: %s", o.toString())); values.put(col.name(), (Short)o); break; case Long: o = m.invoke(this, (Object[])null); Log.d("DEFLATE", String.format("Deflation value of: %s", o.toString())); values.put(col.name(), (Long)o); break; // case Blob: // values.put(col.name(), m.invoke(this, (Object[])null)); // break; } } } return values; } /** * Will generate a set of ContentValues to be persisted into the database * structure. This method does this by leveraging the creation of several * annotation driven maps based upon {@link Column} *

* This method can be overriden to not leverage the reflection driven * strategy */ public void inflate(android.database.Cursor c) throws Exception { int idx = -1; // to find a possible permutation of id if ((idx = c.getColumnIndex("id")) != -1 || (idx = c.getColumnIndex("ID")) != -1 || (idx = c.getColumnIndex("Id")) != -1) setId(new Integer(c.getInt(idx))); if (inflationMap == null || inflationMap.size() == 0) return; String[] names = c.getColumnNames(); for (String s : names) { Method m = null; if ((m = inflationMap.get(s.toUpperCase())) != null) { int index = c.getColumnIndex(s); setValue(m, c, index); } } } /** * Leverages the information from the {@link Column} and the * {@link EColumnType} to determine which set to pass. * * @param m * the method we are setting * @param c * The data curosr * @param idx * the column index * @throws Exception */ final void setValue(Method m, Cursor c, int idx) throws Exception { Column col = methodAnnotationMap.get(m); switch (col.type()) { case Integer: m.invoke(this, new Integer(c.getInt(idx))); break; case String: m.invoke(this, c.getString(idx)); break; case Short: m.invoke(this, new Short(c.getShort(idx))); break; case Long: m.invoke(this, new Long(c.getLong(idx))); break; case Blob: m.invoke(this, c.getBlob(idx)); break; } } }



GenericDao.java
import java.util.ArrayList;
import java.util.List;
import java.lang.reflect.*;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

@SuppressWarnings("unchecked")
public abstract class GenericDao
  implements IGenericDao {

 protected Class m_persistentClass;

 static final String TAG = "GenericDao";

 SQLiteDatabase db;

 public GenericDao(SQLiteDatabase db) {
  this.db = db;
  try {
   ParameterizedType genericSuperclass = (ParameterizedType) getClass()
     .getGenericSuperclass();
   this.m_persistentClass = (Class) genericSuperclass
     .getActualTypeArguments()[0];

  } catch (Exception e) {
  }
 }
 
 
 public SQLiteDatabase getDatabase() {
  return this.db;
 }

 public void delete(E entity) throws Exception {
  
  Log.d(TAG, String.format("Deleting a %s tfrom %s", entity.getClass().getName(), m_persistentClass.getSimpleName()));
  
  db.delete(m_persistentClass.getSimpleName(), "id = ?", new String[] { entity
    .getId().toString() });
 }

 public List findAll() throws Exception {

  List retVals = null;

  Cursor c = null;

  try {
   c = db.rawQuery("select * from " + m_persistentClass.getSimpleName(), null);

   if (c.moveToFirst()) {
    retVals = new ArrayList();
    do {
     E e = newInstance();

     e.inflate(c);

     retVals.add(e);     
    } while ( c.moveToNext() );
   }
  } finally {
   if (c != null) {
    c.close();
    c = null;
   }
  }

  return retVals;
 }

 public E findById(long id) throws Exception {
  Cursor c = null;
  E e = null;
  try {
   c = db.query(m_persistentClass.getSimpleName(), null, "id = ?",
     new String[] { Long.toString(id) }, null, null, null);

   if (c.moveToFirst()) {
    c.moveToFirst();

    e = newInstance();

    e.inflate(c);
   }
  } finally {
   if (c != null) {
    c.close();
    c = null;
   }
  }

  return e;
 }

 public void save(E entity) throws Exception {
  if (entity.getId() == null) {
   ContentValues cv = entity.deflate();
   
   Log.d(TAG, String.format("Saving a %s to %s", entity.getClass().getName(), m_persistentClass.getSimpleName()));

   long id = db.insert(m_persistentClass.getSimpleName(), null, cv);
   
   Log.d(TAG, String.format("ID returned as %s", Integer.toString((int)id)));

   entity.setId(new Integer((int)id));
  } else {
   Log.d(TAG, String.format("Updating %s", this.toString()));
      
   db.update(m_persistentClass.getSimpleName(), entity.deflate(), "id = ?", new String[]{entity.getId().toString()});
  }
 }

 /**
  * Will take in a string query and execute it
  * 
  * @param query
  *            the query to execute
  * @return a instance of E
  * @note possibly create a permutation of this method which takes in a set
  *       of objects and will infer the type to be added to the query
  */
 public E queryObject(String query) throws Exception {
  
  return queryObject(query, (Object[])null);
 }

 /**
  * Is expected to return a unique object
  * 
  * @param query
  * @param params
  * @return
  * @throws Exception
  */
 public E queryObject(String query, Object... params) throws Exception {

  E e = null;

  Cursor c = null;

  try {
   String[] vars = null;

   if (params != null) {
    vars = new String[params.length];

    for (int i = 0; i < params.length; i++) {
     vars[i] = params[i].toString();
    }
   }

   c = db.rawQuery(query, vars);
   
   if (c.moveToFirst()) {
    e = newInstance();
    e.inflate(c);
   }   
  } finally {
   if (c != null) {
    c.close();
    c = null;
   }
  }

  return e;
 }

 /**
  * Will take in a string query and execute it
  * 
  * @param query
  *            the query to execute
  * @return a list of E
  * @note possibly create a permutation of this method which takes in a set
  *       of objects and will infer the type to be added to the query
  */
 public List queryObjects(String query) throws Exception {
  return queryObjects(query, (Object[]) null);
 }

 public List queryObjects(String query, Object... params)
   throws Exception {
  List retVals = null;

  Cursor c = null;

  try {

   String[] vars = null;

   if (params != null) {
    vars = new String[params.length];

    for (int i = 0; i < params.length; i++) {
     vars[i] = params[i].toString();
    }
   }

   c = db.rawQuery(query, vars);

   if (c.moveToFirst()) {
    retVals = new ArrayList();
    
    do {
     E e = newInstance();

     e.inflate(c);

     retVals.add(e);
    } while ( c.moveToNext() );
   }
  } finally {
   if (c != null) {
    c.close();
    c = null;
   }
  }

  return retVals;
 }

 /**
  * Due to java type erasure we capture the meta data as input on the ctor to
  * factory later
  * 
  * @return
  */
 E newInstance() {
  E instance = null;
  try {
   instance = (E) m_persistentClass.newInstance();
  } catch (Exception e) {
   Log.e(TAG, e.getMessage(), e);
  }
  return instance;
 }

}

An example would be simple.

DaoManager.java:
public class DaoManager {

 Context context;

 MySQLiteOpenHelper helper;

 SomeEntityDao someEntityDao = null;

 private static DaoManager instance;

 private DaoManager(Context context) {
  this.context = context;

  helper = new MySQLiteOpenHelper(context);
 }

 public static void initialize(Context context) {
  if (instance == null)
   instance = new DaoManager(context);
 }

 public static DaoManager getInstance() {
  return instance;
 }

 public synchronized SomeEntityDao getSomeEntityDao() {
  if (watchListDao == null)
   someEntityDao = new SomeEntityDao(helper.getWritableDatabase());

  return watchListDao;
 }

 public class MySQLiteOpenHelper extends SQLiteOpenHelper {

  public MySQLiteOpenHelper(Context c) {
   super(c, "TEST", null, 2);
  }

  @Override
  public void onCreate(SQLiteDatabase db) {
   Log.d("DB", "onCreate");
   String table = "Your ddl";

   db.execSQL(table);
  }

  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
   Log.d("DB", "onUpgrade");
   db.execSQL("drop table watchlist;");

   String table = "Your ddl";

   db.execSQL(table);
  }
 }
}

SomeEntity.java:
public class SomeEntity extends Entity {
 
 public SomeEntity() {
  
 }
 
 public SomeEntity(String value, int i) {
  this.value = value;
  this.i = i;
 }

 @Override
 protected void doSave() throws Exception {
  DaoManager.getInstance().getSomeEntityDao().save(this);
 }
 
 
 @Override
 protected void doDelete() throws Exception {
  DaoManager.getInstance().getSomeEntityDao().delete(this);
 }
 
 
 String value;
 
 @Column(name="value", type=EColumnType.String, op=EOperation.Deflate)
 public String getValue() {
  return value;
 }

 @Column(name="value", type=EColumnType.String, op=EOperation.Inflate)
 public void setValue(String value) {
  this.value = value;
 }
 
 Integer i;
 @Column(name="intValue", type=EColumnType.Integer, op=EOperation.Deflate)
 public Integer getIntValue() {
  return i;
 }
 
 @Column(name="intValue", type=EColumnType.Integer, op=EOperation.Inflate)
 public void setIntValue(Integer value) {
  this.i = value;
 }
}

SomeEntityDao.java:
public class SomeEntityDao extends GenericDao {

 public SomeEntityDao(SQLiteDatabase db) {
  super(db);
  // TODO Auto-generated constructor stub
 }
}

The major advantage to this strategy is that it allows you to put your genericized persistence logic in a lower level shared library and develop a data access layer that is much more clean and extensible. Of course, with mobile (and or anything Android) not being as powerful as a server you'll want a lightweight implementation which is why the developer can additionally override the default implementation of Entity#deflate or Entity#inflate to make it less dynamic.

Wednesday, April 21, 2010

java vs .net exception model

Lately I’ve been going back and forth between java and .NET and trying to keep as many of the architectural constructs the same because of the similarities in IL representation and concepts .... plus it’s just great to have analogous ported concerns to work with.

One issue I have not been able to get past is the throwable model between the two.

Java:
<code>
public class RandomClass
{
        public void doSomething throws Exception
        {
                // do something
        }
}
</code>

.NET/C#
<code>
public class RandomClass
{
        public void DoSomething
        {
                // do something
                // note the lack of a need to define the exception stack
        }
}
</code>

This poses issues for various architectures and/or frameworks when developed in one ported to another. It’s not a huge issue b/c you can always introduce an ExceptionHandler into java as a setter on the object. But that’s not the point of this blog. The point of this blog is the seeming why this is the case.

Java’s runtime is developed in C which is a language that does not have a throwable architecture for runtime exceptions; hence, why in the JNI interface the exception isn’t thrown it’s more set and evaluated at the end of the execution of the method when returning to the Java runtime.

<code>
JNIEXPORT jvoid JNICALL example_throw(JNIEnv *env, jobject obj)
{
jclass Exception = env->FindClass("java/lang/Exception");
env->ThrowNew(Exception,”some random exception);
}
</code>

It’s after the end of the execution of the throw method that the exception is actually detected.

Conversely the .NET runtime is implemented in C++ ... which has an inherent throwable architecture. This makes sense why there doesn’t have to be metadata around what the exception hierarchy is that is being thrown.

......