EoD SQL Applied – Part 5 / 5 (GWT Applications)

The Dreaded “Not Serializable” Problem

GWT turns all of your Java code into JavaScript, but it also obfuscates everything. With this in mind, it makes serialization a bit more complex than usual. GWT generates a serializer and deserializer for each class that could be transported across the wire to an RPC service. The difficulty comes in knowing which types had code generated, and which didn’t. GWT solves this problem for itself with the Serialization Policy file, where the compiler lists all of the classes that the client code will know how to deserialize.

This however leads to another problem: what happens when something unexpected gets in the way. Hibernate is the most used, and thus most complained about when it comes to Serialization problems. Hibernate turns any Collection object into a special “lazy” implementation that will only load your data when you ask for it. All very fine and well for a server bound application, but a GWT application needs all that data up front for serialization. When GWT comes to sending that List<Message> to the client, it chokes. It knows how to serialize an ArrayList, and LinkedList (since you worked with them on the client side), but a Hibernate List or PersistentCollection is a totally unknown type, so it’s not in the Serialization Policy, so the server side throws an Exception at you.

So how does EoD SQL help with these problems? Read on to find out! 😉

Loosing the Lazy Loading

EoD SQL  (unlike most OR mapping layers) makes no attempt to understand the internal relationships between you objects. The reason for this is that EoD SQL is technically dialect neutral, it doesn’t actually care what you put into you @Select annotation so long as it can create a PreparedStatement and populate it with parameters. This frees you to take maximum advantage of database extensions, or weird SQL dialects. It also means that EoD SQL will never generate any SQL code for you: what you type is what gets executed.

Within a GWT application, you don’t have a way to block until a method is complete, and thus lazy-loading data becomes a chore, since you need to work with a lot of callbacks (a nice way of abstracting lazy-like-loading is posted on my blog). This means that most of the object model given to GWT needs to be (at least partly) eager-loaded.

So because EoD SQL doesn’t do any lazy-loading, it “forces” you into thinking about how much data and what data you will be sending to the client. It takes a little getting used to, but over time you will find your code much clearer to read and running much faster (since less data comes from the database, fewer queries are run and the JavaScript has less data to deal with).

Arrays instead of Collections

The first trick to working with GWT is: when you need more than one object fetched from the database (which is most of the time), return an array instead of a Collection:

public interface MessageQuery extends BaseQuery {

/*
* This is not a great way to do things in EoD SQL 2.0 when dealing with GWT.
* This method will return an ArrayList of Message objects, however the List implementation could
* possibly be changed in the future (not likely). Further the ArrayList is populated using the basic
* List.add(Object) method. The ArrayList will re-copy it's internal array over-and-over again as
* the ResultSet is scanned.
*
* So while this method will work with GWT, it's really not recommended.
*/
@Select("SELECT * FROM messages WHERE parent_id = ?1 ORDER BY date DESC LIMIT ?3 OFFSET ?2")
List&lt;Message&gt; selectChildMessagesAsList(int parentId, int start, int count);

/*
* This won't work at all with GWT. The DataSet may offer lazy-loading
* and some other wonderful tricks, but since the client code has no idea
* how to deal with a DataSet it's useless here. I thought I'd put it in for completeness.
*/
@Select("SELECT * FROM messages WHERE parent_id = ?1 ORDER BY date DESC LIMIT ?3 OFFSET ?2")
DataSet&lt;Message&gt; selectChildMessagesAsDataSet(int parentId, int start, int count);

/*
* This is the way to do it! Using only arrays for Serialization has a side effect
* on the GWT side of things: less JavaScript code for your clients to download.
* GWT understands how to deserialize arrays, and doesn't need to include
* Serialization code for different List implementations.
*/
@Select("SELECT * FROM messages WHERE parent_id = ?1 ORDER BY date DESC LIMIT ?3 OFFSET ?2")
Message[] selectChildMessagesAsArray(int parentId, int start, int count);

}

Now for the big question: why are arrays “so much better” than a List of some sort? EoD SQL takes fairly extreme measures to keep the performance of an Array as fast as possible. For the most part (that is: on most JDBC drivers) the array will be pre-sized and fetched backwards. This sounds very strange, but it is generally a lot faster than trying to work forwards and re-growing the array whenever it runs out of space (and then down-sizing it at the end). EoD SQL will run forwards if the JDBC driver requires it, but for the most part it runs backwards.

This technique will not only improve performance, JavaScript size, and simplicity of the code (arrays are just easier in most cases); it’ll also reduce the amount of memory your server uses (since the array is pre-sized and never copied).

Finally: because the type is declared as an array, you know exactly what Serialization code GWT is going to generate.

Looking to the Future (EoD SQL 2.1)

In EoD SQL 2.0 you can declare Collection objects as return types, but only as their interfaces (as you saw in the above code example). EoD SQL 2.1 has a new feature which allows you to declare concrete implementations as return types. This is the preferred method of declaration for GWT (since again: it minimizes the amount of JavaScript generated). A few nice little examples:

public interface MessageQuery extends BaseQuery {

@Select("SELECT * FROM messages WHERE parent_id = ?1 ORDER BY date DESC LIMIT ?3 OFFSET ?2")
ArrayList&lt;Message&gt; selectMessages(int parentId, int start, int count);

@Select("SELECT title, date, author FROM messages WHERE parent_id IS NULL ORDER BY date")
MyCollectionImplementation&lt;Message&gt; selectTopLevelMessages();

}

The big difference between 2.0s handling of Collection objects, and 2.1 is that 2.1 will allow the Collection implementation (including those declared as their interfaces) to optimize their fetching of the data internally (if they are able). Thus returning a List or ArrayList will no longer cause the resize-resize-resize effect (or shouldn’t anyways). Collections will be given the same treatment as arrays in 2.1.

Conclusion

So we’ve looked at four different situations where EoD SQL works really well.

The concept to take away from this (I feel) is that: with EoD SQL you are in total control of how the code is going to behave.

If you need lazy-loading and scrolling data (like in our Swing example), you can use a DataSet; to minimize memory a DataIterator; and when lazy-loading can’t be used because of other constraints Collections and Arrays are available. Whatever the situation: EoD SQL is going to make life that little bit easier for you, without you giving up control of what goes on behind the scene.

Advertisements

5 Responses to “EoD SQL Applied – Part 5 / 5 (GWT Applications)”

  1. archenroot Says:

    I am new to GWT and want to make UI components interacting with database (in our case Oracle). We decided we will allow any access to database only via parametrized stored procedures, because there more than interface based on GWT which will interacts with database and we want to define something like database interface to make it clear from the beginning and to be sure mistake in java or whatever code will not corrupt our data. So, am I write if I expect that instead of following code>

    public interface MessageQuery extends BaseQuery {
    @Select(“SELECT * FROM messages WHERE parent_id = ?1 ORDER BY date DESC LIMIT ?3 OFFSET ?2”)
    ArrayList<Message> selectMessages(int parentId, int start, int count);
    …..
    }

    I can also use somethink like this? >

    public interface MessageQuery extends BaseQuery {
    @Select(“EXECUTE fetchData (‘?1’)”)
    ArrayList<Message> selectMessages(int parentId);
    …..
    }

    • Jason Says:

      EoD SQL Includes a special annotation for calling stored procs: @Call. So instead of @Select(“EXECUTE fetchData (‘?1′)”) you would use: @Call(“EXECUTE fetchData (?1)”).

      Bare in mind that the JDBC driver will quote and escape an input string for you.

  2. archenroot Says:

    Well,

    I am still in learning phase deep in documentation of GWT, EoD SQL, Hibernate, SmartGWT…blabla :-)))

    I think in my case EoD SQL will be chosen for use with SmartGWT. But still I didn’t find much documentation or let me say I still don’t understand these things well 🙂 so some complete packaged project with GWT Form/Grid/etc and EoD SQL in eclipse (if you use eclipse) would really help to understand.

    Anyway thank you for info about possibility of using stored procedures with EoD SQL.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: