Wednesday, June 16, 2010

AuDAO goes open-source

As of the AuDAO v1.5, the project is fully open sourced.

The project is hosted at http://code.google.com/p/audao/.

The offical pages including built documentation, examples and a free online DAO generator are still located at audao.spoledge.com.

Wednesday, May 5, 2010

Version 1.4 - Standalone Version for Free!

AuDAO 1.4 is out and the main change is that the standalone tool can be freely downloaded and used!

This is the first step of moving AuDAO project towards open-source projects. The standalone binary version does not contain any limitations of the input XML source nor the number of entities to be generated.

To start using the standalone version just go to the download page. The documentation concerning the standalone tool is here.

Monday, March 29, 2010

Version 1.3 - GWT+GAE - RPC Optimizations

AuDAO allows you to generate Data Transfer Objects (DTOs), which are actuallly POJOs. Also from the beginning of AuDAO these DTO's could be used in Google Web Toolkit (GWT) enabled projects or transfering data between server's and client's code.

Since AuDAO 1.2 we fully support Google App Engine (GAE) types like GeoPt or Key. But it is not enough to support transfering such DTO's - containing these types - between the server and the client.

Fortunately AuDAO 1.3 comes with two features which enable to transfer DTO's containing GAE types - GeoPt, Key, User and others - between the server and the client:

  • generating custom field serializers for GWT

  • basic emulation of the GAE types for GWT (client side code)


GWT Custom Field Serializers

If you use GWT RPC mechanism to transfer data between server and client parts, then GWT serializes and deserializes the Java and JavaScript objects for you automatically. It is similar as standard Java object serialization works.

But it is also possible to write your own (de)serializers. If your DTO class name is com.foo.MyDto, then the (de)serializer class name will be com.foo.MyDto_CustomFieldSerializer. The (de)serializer has several static methods for serializing and deserializing which GWT uses on both the server and the client sides.

The question is why or when to write your own (de)serializer class ? The answer is simple: by writing you own (de)serializer you can compress the data sent between the server and the client. You can save more data if your DTO class contains nested non primitive non-standard fields - like GAE's types: GeoPt or Key. If you know which data you want to send/receive, then you do not need to send also the meta-information like the fully qualified class names or the field names.

Now AuDAO comes with feature of generating these custom (de)serializer classes. Just check the checkbox in the online web generator or enable it by the audao-dto-gwt-serializer option in the standalone version.

My test DTO which contained one long type, one int type, one String type (up to 10 chars length) and one GeoPt had size 270 bytes and after using (de)serializer generated by AuDAO it was only 153 bytes - which means saving of about 44% of network data !

Basic Emulation of the GAE Types

The custom field serializer would not work for GAE types if did not show the source to GWT. GWT needs source to translate it to the JavaScript. GAE itself does not provide sources and even if it do so, we could not use them for GWT due to their complexity and GWT/JavaScript unsupported features.

So as a part of the AuDAO project, we created a basic emulation of these GAE types which you may be interested in - e.g. GeoPt, Key, User and others.

Please be aware of the purpose of these source files - they were created only to support serialization of the GAE types between server and the client. They cannot be used on the server side in any manner - please do not put the compiled classes into your server's classpath - they could conflict with the classes contained in the GAE SDK's jars.

The emulation source files you can find on the AuDAO download page.

Friday, February 26, 2010

Version 1.2 - Full Support of GAE Types

AuDAO now supports all Google App Engine types including Lists. Although Lists appeared in the version 1.1, it was only a limited solution. Now Lists can contain all types as normal single properties including the new types - GAE core types like Key, Geopt or User.

Let's look how it is easy to work with generated classes:
CREATE:
  OfficeDao dao = DaoFactory.createOfficeDao();

Office off = new Office();
off.setLocation( new GeoPt( latitude, longitude ));
off.setManager( new User( managerMail, "gmail.com" ));
off.setOnSite( Arrays.asList( off.getManager(), myself ));

dao.insert( off );

FIND (and also COUNT and DELETE):
  // location = geopt
dao.findByLocation( new GeoPt( latitude, longitude ));
...
// location IN (loc1, loc2, loc3)
dao.findByLocations( Arrays.asList( loc1, loc2, loc3 ));
...
// manager = user
dao.findByManager( new User( managerMail, "gmail.com" ));
...
// onSite IN (john, jack, myself)
dao.findBySomeOnSite( Arrays.asList( john, jack, myself ));
...
// onSite = manager AND onSite = myself
dao.findByAllOnSite( Arrays.asList( manager, myself ));

The last finder is one of the most interesting one - it automatically expands simple equality condition into several conditions concatenated by "AND" operator.

And all these DTO and DAO classes can be generated automatically from a source config XML file which can have less than 100 lines and 2KB of size! Learn more...

Well, if you need to create conditions dynamically, the DAO can be generated to allow it as well. GQL queries are supported:
  // find the office where the manager is on-site
// 0=offset, 1=maxRecords
dao.findDynamic("manager=USER(:1) AND onSite=USER(:1)", 0, 1, managerEmail);

You can create dynamic queries on keys as well:
  dao.findDynamic("__key__ IN :1", Arrays.asList( id1, id2, id3 ));

More information about GQL Parser you can find at here.

Happy generating !

Tuesday, February 2, 2010

Version 1.0 is out !

Yesterday we launched version 1.0 at http://audao.spoledge.com

And what is it ?

AuDAO is a tool for Java developers.

AuDAO let's you to generate Data Access Objects (DAO) layer for Java. So instead of using directly JDBC, JDO or other database access APIs, you can easily call abstract DAO layer methods like findByPrimaryKey(), insert(), update() or delete().

Simple Example ?

Certainly. First you must configure a source file to tell AuDAO how the DAO layer should look like. The source file is a well-formed XML (see also XSD):
<?xml version="1.0" encoding="utf-8"?>
<database xmlns="http://www.spoledge.com/audao" version="1.0">
<tables>
<table name="users">
<columns>
<column name="user_id">
<type>long</type>
<auto/>
<pk/>
</column>
<column name="user_name">
<type max-length="32">String</type>
<not-null/>
</column>
<column name="full_name">
<type max-length="128">String</type>
</column>
<column name="created_date">
<type>Date</type>
<auto/>
<not-null/>
</column>
<column name="last_login_date">
<type>Timestamp</type>
<auto/>
<not-null/>
<edit/>
</column>
</columns>
<indexes>
<index name="inx_user_name">
<unique/>
<columns>
<column name="user_name"/>
</columns>
</index>
</indexes>
<methods>
<count>
<all/>
</count>
<find>
<pk/>
</find>
<find>
<index name="inx_user_name"/>
</find>
<find name="latestLoggedIn">
<condition>
<query><![CDATA[last_login_date > ?]]></query>
<query dbtype="gae"><![CDATA[lastLoginDate > :1]]></query>
<params>
<column name="last_login_date"/>
</params>
</condition>
</find>
<delete>
<dynamic/>
</delete>
</methods>
</table>
</tables>
</database>


Then you use AuDAO tool to generate DAO layer - source Java files. You can either user the online generator or purchase a standalone version.

The generated DAO layer contains Data Transfer Object (DTO) - class User.java, abstract DAO interface UserDao.java and its hidden implementation UserDaoImpl.java. It also contains DaoFactory.java class which helps you to instantiate the DAO class.

The implementation classes vary by the target database type (Oracle, MySQL or Google App Engine), but the DTO and abstract DAO interface is still the same:

public long insert( User dto ) throws DaoException;
public void update( long userId, User dto) throws DaoException;
public int countAll();
public User findByPrimaryKey( long userId );
public User findByUserName( String userName );
public User[] findLatestLoggedIn( java.sql.Timestamp lastLoginDate )
public int deleteDynamic( String condition, Object... params )


How the generated DAO layer is used ?

To instantiate DAO interface just call DaoFactory methods. DaoFactory finds the right implementation class for you:
UserDao dao = DaoFactory.createUsedDao();

After that you can insert new records:
User dto = new User();
dto.setUserName("vaclav");
dto.setFullName("Vaclav Bartacek");
long userId = dao.insert( dto );

count or find one or more records:
int total = dao.countAll();
User user1 = dao.findByPrimaryKey( userId );
User user2 = dao.findByUserName( "vaclav" );
User[] lastHourUsers = dao.findByLatestLoggedIn( new Timestamp(System.currentTimeMillis()-3600000);

update records:
User dto2 = new User();
dto2.setLastLoginDate(new Timestamp(System.currentTimeMillis());
dao.update( userId, dto2 );

delete records (not logged within 90 days):
int totalDeleted = dao.deleteDynamic( "last_login_date < ?", new Timestamp(System.currentTimeMillis()-3600000L*24*90));


You can see that no JDBC or other database API calls are visible to you. The abstract layer allows you to develop for multiple database platforms.