Archives for September 2008
Carbonado and Griffon
As it stands now, Griffon doesn't yet support GORM. In pre-Griffon apps, I got around this by using Groovy's SQL datasets and some light raw SQL. Since Griffon is all about simplification, I decided to see if any object-relational mappers work with little modification. Carbonado is one that does.
Carbonado is a Java ORM, initially developed by Amazon that is now an Apache project. It has much of the stardard ORM fare but also supports Berkeley DB. One of the reasons I chose it for this small scall demo was the fact that it doesn't require configuration files. Domain objects are annotated interfaces whose concrete implementations are generated at run-time. Very Groovy-like.
Here's my StoredMessage domain object:
import com.amazon.carbonado.PrimaryKey;
import com.amazon.carbonado.Storable;
@PrimaryKey("ID")
public interface StoredMessage extends Storable {
long getID();
void setID(long id);
String getMessage();
void setMessage(String message);
}
Coming back to the Griffon structure for a moment, StoredMessage.groovy found its home in /src/main/groovy.
The model for this example is very short with only a String property:
import groovy.beans.Bindable
class CarbonadoDemoModel {
@Bindable message
}
The view is equally brief, changing the label to be bound the model:
application(title:'CarbonadoDemo', size:[150,75],
location:[50,50], locationByPlatform:true) {
label(text:bind(source:model, sourceProperty:'message'))
}
Startup.groovy is where the real heavy lifting is done(ie loading the repository, writing/reading from it, and binding to the model).
import java.io.File;
import com.amazon.carbonado.Repository;
import com.amazon.carbonado.RepositoryException;
import com.amazon.carbonado.Storage;
import org.apache.derby.jdbc.EmbeddedDataSource
import com.amazon.carbonado.repo.sleepycat.BDBRepositoryBuilder
def rootModel = app.models.root
try {
// Need to build access to a Repository instance. In this
// case, we're building access to a Repository that stores
// data in Berkeley DB.
BDBRepositoryBuilder builder = new BDBRepositoryBuilder();
// All Repositories require a name to be configured.
builder.setProduct("JE");
builder.setName("test");
builder.setEnvironmentHome("testRepo");
builder.setTransactionWriteNoSync(true);
// Now build the Repository instance.
Repository repo = builder.build();
// Access Storage for a specific type of Storable.
Storage<storedmessage> storage = repo.storageFor(StoredMessage.class);
/*
//Insert message.
StoredMessage message = storage.prepare();
message.setID(1);
message.setMessage("Hello Carbonado!")
message.insert()
*/
// Get message from repository
StoredMessage message = storage.prepare();
message.setID(1);
message.load()
rootModel.message = message.getMessage()
} catch (Exception e) {
e.printStackTrace()
}
Until GORM is there, Carbonado seems like a good solution for small to medium scale applications that are too big to do raw SQL and too small to deal with the multiple config files Hibernate needs.
Download the source here.
Porting a Groovy app to Griffon
Just before launch, I started porting the Groovy port of jFlubber to Griffon. I would have included some screenshots but it looks the same. I’ll be delving into the code a bit so take and minute to download the old and new versions. On the changes:
Resources
The original app lived in one mess of a directory along with the images. Images now live in the resources directory and are properly separated from the code.
Helper classes
Also in the main src directory were two helper classes to encapsulate some Java Timer capabilities(GroovyTimerTask and UpdateTimeTask). Though Griffon will be able to locate them in the view directory, they are not in and of themselves views. It’s more appropriate for them to be outside the Griffon MVC architecture in src/main/groovy.
MVC
By far, this was the area that benefited the most from the port. What began as a big clusterf—k all in one file has evolved to a nice separation of MVC. Thanks to @Bindable and changing from a concrete class as a view to a view clousure, I was able to eliminate some useless instance variable move what needed to referenced from the view to the model.
import groovy.beans.Bindable
import org.jdesktop.swingx.*
import org.jdesktop.swingx.painter.*
class GriffonFlubberModel {
@Bindable String timeText = ’0:00’
@Bindable String flubText = ’’
@Bindable TextPainter timeLabel
@Bindable Timer timer
@Bindable long startTime = 0L
@Bindable int labelNo = 0
}
Likewise most of the helper functions for the view moved to the controller.
Awakening the Griffon
Griffon, inspired by the mythical creature, is a Swing application framework for Groovy.
Griffon is the fruit of almost a year’s long effort by the Groovy Swing team and an attempt to take the best of rapid application development, as indicated by its Grails-like structure, the über-sexiness of Groovy, and the pleothra of components for Swing.
Griffon aims to reduce the typical confusion that occurs with traditional Swing development. Due to the MVC structure of Griffon, you never have to go searching for files or be confused on how to start that new project. Everything begins with:
griffon create-app <APP_NAME>
The builder infrastructure enables seamless integration of different widget libraries. Want to mix traditional Swing, JIDE, and SwingX? No problem.
Griffon’s built-in scripts include targets for desktop, webstart, and applets. To not leave our Mac friends in the cold, the baseline requirement is Java 5 or higher. We thought it was very important for all platforms to have equal access on release day.
In this release, we have included three sample applications:
- Greet, a Groovy Twitter client featured in the JavaOne Script Bowl,
- GrailsSnoop, a Grails documentation browser, and
- WidgetsKitchenSink, a WIP showing components in the included widget sets.
Griffon is Swing simplified.
Download Griffon here and run through the Quickstart.
For the folks on Debian, I’ll be rolling a deb soon. If there are any Windows or Mac folks who want to package the framework on those platforms, email the griffon-user list or tweet Danno, Andres, or myself so we can coordinate efforts.
Much thanks to those that have been poking and prodding the framework, kicking its tires and such. Continue to do so.