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! 😉 Read the rest of this entry »

Advertisements

EoD SQL Applied – Part 4 / 5 (JavaScript)

JavaScript vs. Web Applications

So far in this series we’ve discussed using DataSets for Swing applications and DataIterators for web-applications. Why would I now bring in JavaScript as something outside of “web-application”? JavaScript applications have very different requirements to a normal web-application. Where a normal web-application has little ability to do things like preload data (like the next page), a JavaScript application may (for example) download the entire data-set and then display it in pages. This next section is about binding to JSON for JavaScript applications.

First thing to remember here is that an EoD SQL DataSet is a List and thus compatible with the Collections API. For this example we’re going to be working with the outstanding GSON API from our friends at Google. Our objective here is to minimize the amount of time spent between the Database and pushing the data to the client. Because GSON doesn’t appear to support Iterable object out-of-the-box, we’re going to start off using a DataSet.
Read the rest of this entry »

Why TraceMonkey is maybe the wrong way

With Firefox 3.5 finally out the door and in use I thought it was time to write something about it that’s been bugging me for a while. TraceMonkey (the new FF JavaScript engine) employs a semi-Hotspot approach to JavaScript compilation. Although the approach is quite different under-the-hood, the basic principal is the same: interpret the code until you know what to optimize. This makes abundant sense to me: why go through the expense of native compiling a method that only ever gets run once? However: there is a hidden expense to doing things this way: your compilation unit is often much smaller. Smaller compilation-units means more compiled code that needs to go back and forth to interpreted code. It also means you can’t optimize as heavily (although that optimization has it’s own massive expense).

Where am I heading with this? I think the TraceMonkey approach adds huge value to a language like Java where an application consists of hundreds and / or thousands of classes (both those in the application and all of it’s dependent APIs), in this case: you’re loading time would be abysmal if you pre-loaded all the possibly used code and native compiled it on start-up. However in the JavaScript world we are limited by the connection, and JavaScript applications (even really huge ones like those written with GWT) are relatively small. In this case it makes more sense to me to either compile everything up front; or run everything interpreted and run a massive compilation in the background (hot-swapping the implementations when you’re finished the compile).

It’s just a thought. Maybe FF should adopt v8 and see what happens?

GWT’s new Event Model – Handlers in GWT 1.6

Theres a lot of concern and worry around the “new event model” in GWT 1.6: throwing out Listeners (a well know and used Java construct) and replacing them with Handlers (a GWT team invention). Let me put your mind at rest, Handlers will make your GWT life much easier.

So what are the differences between Listeners and Handlers?

Listeners Handlers
Have one Listener per event source (ie: “mouse”, “keyboard”, etc) Have one Handler per event type (ie: “mouse press”, “mouse down”, “mouse up”)
Are uncategorized, and the Widget is responsible for sinking / un-sinking the DOM events Are categorized into 2 types: DOM and Logical, adding a DOM Handler to any Widget deferrers to Widget.addDomHandler which sinks events as required
Each Widget uses a ListenerCollection for each class of Listener added All Handlers are stored with a HandlerManager which also manages dispatching any type of event (including new ones you create yourself)
Listeners are removed with the pattern Button .removeClickListener(listener); Adding a Handler returns a HandlerRegistration object, removing a Handler is done by calling HandlerRegistration .removeHandler();
GWT Listeners accept a parameter for each bit of relative event information (ie: sender, mouse x, mouse y) Handlers (more like normal Java Event Listeners) are passed an Event object with all the Event details as their only parameter

So what do Handlers actually buy you in code?

Possibly the most important thing to notice is they take up a lot less space when compiled to GWT. This in mainly due to the fact that their management is centralized in HandlerManager instead of requiring a separate ListenerCollection for each Listener type, and that an implementation only needs a single method overridden (instead of having to listen for events you’re not interested in).

Another point to take note of is that all DOM related Event objects extend from DomEvent. Why is this important? Because DomEvent includes the methods:

  • preventDefault()
  • stopPropagation()
  • getNativeEvent()

I find the last (getNativeEvent()) to be the most useful, it works much the same as Event.getCurrentEvent() and returns a NativeEvent (the new parent class to Event). The advantage of this mechanism over Event.getCurrentEvent() is that you have all the access to the underlying event information (mouse button, modifiers, etc) but attached directly to the dispatched event.

Summary

Handlers are a good step forward for GWT, and make abundant sense in a Web environment where code size is very important. They also make it much easier to add you own events since you no longer need to manage your own Listener registration / deregistration cycle or firing of the events to all of the registered Listeners (HandlerManager does it all for you). I think there will be some interesting new patterns emerging with regards to managing events on generated structures (built based on data fetched from the server for example).

I’m looking forward to seeing what comes of these changes.

Easy GWT Database Binding with EoD SQL

Connecting Java to a Database effectively can be a lot of work at the best of times. Sure JDBC does make life easy for us, but theres still turning to ResultSet into nice Java Objects. When you throw GWT into the mix, what was a lot of work becomes a bit of a nightmare (especially when you’re trying to work with JPA or Hibernate). Fortunately EoD SQL comes to the rescue!

For those of you who are either new to my blog or new to EoD SQL, go check-out this little snippet of code over on the EoD SQL homepage. You can think of EoD SQL as a very lightweight Hibernate. It’s also the perfect way to connect you GWT application to your database. Unlike Hibernate and JPA, EoD SQL requires no modification or work-arounds to get it to work perfectly with GWT.

You do need to keep to 2 very simple rules however:

  1. Your Query interfaces may not return DataSet or DataIterator objects (since they require a working JDBC Connection)
  2. You will still need an RPC Servlet between GWT and EoD SQL

That said, there are strong upsides to these “limitations”:

Instead of returning a DataSet or DataIterator: have your Query interfaces return single objects, or arrays of objects. Arrays are heavily optimized by EoD SQL and since your application is actually running in a browser somewhere, you want to provide it with the entire ResultSet (and not lazy-load the data, which is where the default Hibernate and JPA models fall over).

Instead of exposing your database methods directly to the client: you should place the functionality behind a RemoveServiceServlet anyways! Why? Because it gives you a good chance to verify that the user is allowed to take the given action on the database. If, for example, you wrote a forum application, and you had an admin-only “deleteForum” method that you exposed. If the RPC Servlet just deleted the forum and returned, anyone who got hold of the URL and knew anything about GWT RPC could delete every forum in the database. Not really something you want to allow.

Summary
EoD SQL works with GWT without any modifications. This is mostly due to the fact that EoD SQL is designed to be a “what you see is what you get” API. The fact that it doesn’t manage parent-child relationships automatically is also advantages in that it forces you to think about what data is going to be needed on the client side. Bare in mind that GWT by it’s very nature runs in a limited environment on the client, sending and receiving complex object graphs is never a good idea. It’s better to lazy-load child relationships when there is a strong chance the child data will not be needed.

I may consider an eod4gwt API which includes a special RPC Servlet implementation for handling EoD SQL requests (which would allow you to put the @Select and @Update annotations in your RemoteService interface). There would need to be a demand for it though 😉

An automated JSON Encoder and Decoder for Java

I posed a little while ago that I’d implemented a JSON Encoding that worked a bit like Java Serialization. It works as such in that you don’t need to encode the objects by hand. As long as you follow some basic rules, the code will automagically turn your Java objects into JSON, and the JSON back into Java objects again. Well, I finally got my act together and the implementation is below. Consider this Public Domain code now! If it doesn’t work for you, it’s not my problem (that said, I’d like to know if it doesn’t work).

Before The implementation, heres a few things to know about it:

  1. It solves the Date problem in such a way that it’s transparent to the JavaScript code!
    1. Dates are encoded as “new Date(UTCTime)”
    2. They are decoded against a collection of date-formats (listed at the top of the JSONDecoder class)
  2. The encoding and decoding work against Reader and Writer objects, and thus have declared IOExceptions
    1. They expect to be closely tied to the Reader and Writer provided by the Servlet Container
  3. They both conform to the Java Beans specs, so if it’s not a bean property, it’s ignored
  4. The decoder can handle both the abstract Collection types and concrete types
    1. public void setUserList(List<User> users)
    2. public void setUserList(ArrayList<User> users)
    3. The Collections must have a solid type declared as their content (in the generic)
  5. Map objects are encoded as JavaScript objects
    1. Map keys must therefore be Strings
    2. The Map keys should be valid JavaScript identifiers

If you are going to use this code, I would appreciate a comment here (just to let me know).

Read the rest of this entry »

Using PropertyChangeListeners to ease GWT Async Calls

A while back I blogged a simple set of classes to make Property Binding easier in GWT, it’s also tied to GWT’s RPC system. I did not, however, provide an example of how this worked. The GWT list sees a lot of questions around asynchronous behavior, so heres an nice little example of how the Property pattern can be used to simplify RPC:

public class MyModule implements ModuleEntryPoint, PropertyChangeListener {
	private final Property<User> user = new Property<User>("user");

	private final TextBox username = new TextBox();

	private final Label firstName = new Label();

	private final Label lastName = new Label();

	private final Label dateOfBirth = new Label();

	public void onModuleLoad() {
		// we need to listen for change events on the "user" Property
		user.addPropertyChangeListener(this);

		// make a GUI to search and display the User data with
		final Grid grid = new Grid(4, 3);

		grid.setWidget(0, 0, new Label("User Name: "));
		grid.setWidget(0, 1, username);
		grid.setWidget(0, 2, new Button("Load", new ClickListener() {
			public void onClick(final Widget sender) {
				// we need an instance of our pretend RPC service Async interface
				final UserManagerAsync manager = GWT.create(UserManager.class);
				// we ask it to find the user by the name typed into the TextBox
				// and we pass the AsyncCallback as the "user" Property object
				manager.findUser(username.getText(), user);
			}
		});

		grid.setWidget(1, 0, new Label("First Name: "));
		grid.setWidget(1, 1, firstName);
		grid.setWidget(2, 0, new Label("Last Name: "));
		grid.setWidget(2, 1, lastName);
		grid.setWidget(3, 0, new Label("Birth Date: "));
		grid.setWidget(3, 1, dateOfBirth);

		RootPanel.get().add(grid);
	}

	public void propertyChanged(final SourcesPropertyChangeEvents source, final String propertyName,
			final Object oldValue, final Object newValue) {

		if(propertyName.equals("user")) {
			// if the service returned null (no User found) we clear the labels
			if(newValue == null) {
				firstName.setText("");
				lastName.setText("");
				dateOfBirth.setText("");
			} else {
				// otherwise fetch the new User object and fill in the labels
				final User u = user.get();
				firstName.setText(u.getFirstName());
				lastName.setText(u.getLastName());
				dateOfBirth.setText(u.getDateOfBirth().toString());
			}
		}
	}
}

To understand this code better you should look at the original post where I detailed the supporting
classes (PropertyChangeListener, Property, etc.).