MacJournal Post

2009 May 25
by noisyheads

Just testing MacJournal if it’s any good.

Some stuff that I can’t do:

  1. No formatting? Just rtf?
  2. How can I add links?
  3. How can I add images?

Update:
Ok, I figured out 2 and 3 somehow. But I still can’t format properly. I can’t even do a strikethrough. Fail!

Grails SoundManager Plugin Version 0.4 Released

2009 May 4
by noisyheads

Just released Grails SoundManager Plugin Version 0.4. This is a simple maintenance release to catch up with what’s going on with SoundManager2.

Funny thing is, after I released 0.3, earlier in the day, a new SoundManager2 version was released as well. Hence the two plugin versions were released on the same day. Blah :p

Beware: Controller and Service Dirt and Flush

2009 April 12
by noisyheads

From my earlier post, I’ve mentioned that I am now keeping a cleaner approach as regards GORM methods in either a controller or a service. Just when I thought I got that all figured out, (hibernate) transaction pandemonium happened to me.

Fact, each GORM call opens, if not already is, a hibernate session. So a “get” would actually give you a hibernate object that currently belongs to the persistent context. A “dirty” domain object is the result of modifying it’s properties, unless of course it is explicitly a “read-only” object.  Changes that made the object “dirty”  wouldn’t otherwise be persisted if a discard is invoked on it. The thing that might surprise most people though is that once the session is flushed somehow, for example a save(flush:true) is invoked on another domain object somewhere along the method, the “dirty” object gets saved as well, even without invoking a save() on it. This bypasses all the validation thingos that comes along with GORM.

Given that, I encountered a problem that might be triggering this session flush unexpectedly. This is when the controller action invokes a service that is transactional.

e.g, your domain:

class Book
{
  String title
  static constraints = {
    title(blank: false)
  }
}

your controller action:

def update = {
  def book = Book.get(params['id'])
  book.properties = params

  if(!book.hasErrors() && bookService.update(book)
  {
    ....
  }
  else
	...
}

and the BookService method:

def update(book)
{
  if(!book.hasErrors() && book.save())
  {
		//do something
  }
  else
  {
    throw new RuntimeException()
  }
	..
	..
}

When I set the Book.title to a blank String, indeed the RuntimeException was thrown. But! The blank title was still saved! How could that happen? The only thing that I could pin point is the fact that before the service was invoked, the book instance was already dirty, by setting params as it’s properties. And a session flush happened prior to the service call.

With the help of Burt Beckwith from the list, here’s a couple of solutions.

One is to either invoke all GORM methods from the service exclusively. I tried this, and it worked. But it’s very messy since you don’t have a handle on the domain object from within the controller. Unless of course it is returned by the service call.

Another solution which I eventually used is to pass the property changes to the service method. This, instead of doing the changes prior to the service method call. Retained the domain object retrieval from within the controller.

So your service should look something like:

def update(book, params)
{
  book.properties = params
  ...
}

The downside of course is that you are already passing Maps to your service methods. Hmm actually, dunno if that’s really a downside.

Bottom line is: Never pass a dirty domain object to a transactional service!

Here’s the issue ticket for this sucker.

GORM: Controller vs Service

2009 March 23
by noisyheads

Scaffolds, generated codes, and lots of tutorials in the web or in print usually show Grails controllers directly invoke GORM methods. You will often see a list(), a findBySomething() in there. Simple invocations, I really have no problems. Usually, I would think of controllers as really thin callers to the business layer of your app. A single call to get() in your “show” action is a call to a business method, quite simply. But chaining a lot of GORM inside your action:

def someAction = {
  def book = new Book(params["book"])
  def chapter = new Chapter(params["chapter"])
  def snippet = Snippet.findByKeyword(params.keyword)
  if(snippet) {
    chapter.addToSnippets(snippet)
  }
  book.addToChapters(chapter)
  if(book.save())
  {
    do something
  }
  else
  {
    do something else
  }
  def bookShelf = new BookShelf(params["bookShelf"])
  bookShelf.addToBooks = book
  book.bookShelf = bookShelf
  if(!bookShelf.save()) {
    etc.. etc..
  }
  ....
}

A little messy. First, that doesn’t make our controller appear like the thin business logic caller that it should be. Another is that some parts of this example need to be transactional. For this case, we’ve got three different domain models (book, chapter, bookshelf) to persist in one go. That would probably rule out the withTransaction GORM method as well. So perfect situation to make use of a Grails Service. You can wrap around all these logic inside a service method, and make sure to make the service transactional. So in your controller action, you can simply have:

def yourService

def someAction = {
  def book = new Book(params["book"])
  def chapter = new Chapter(params["chapter"])
  def bookShelf = new BookShelf(params["bookShelf"])

 yourService.bookServiceMethod(book, chapter, bookShelf, params.keyword)
}

Now YourService should have something like:

boolean transactional = true

def bookServiceMethod(book, chapter, bookShelf, snippetKeyword) {
  ..same as codes above..
}

Take note that the transaction breaks (and hence triggers rollback) when a RuntimeException is incurred during the service method call. So be smart about placing those within the method logic.

The Jump to 1.1x

2009 March 7
by noisyheads

As I blogged recently, I rebooted the noisyheads project again this month. And among the changes that were included in reenergizing this project again is to move to Grails 1.1x. The previous stable build of noisyheads was using Grails 1.0.4. I made a fresh start using Grails 1.1-beta, which was what was available during the time I started a new tree. Then switched immediately to 1.1-RC1 when it came out. Although 1.1-RC2 has been released, I am still finishing some tasks before I make the move again. Wew, really quick release process. Go Grails community! I was assuming I’m gonna finish this project just in time as 1.1 final comes out. Looks like I’m gonna release way later than that :-p

I was kinda disappointed not to see JPA support yet. I expected that for 1.1. Nice to have though, but doesn’t really matter at the moment anyway. Although I am a Maven zealot, I couldn’t care less about the Maven integration that was created. Just too different. I already made known my thoughts on that matter.

Lots of lovely improvements and changes which I have yet to fully utilize. GORM looks more powerful. I have been using the new test framework methods as I try to get at least 90% code coverage. Previously, all I cared about were integration tests. Now I’m more inclined to unit test some more.

Among the changes that bugged me includes the need to invoke the toCharArray() method on config properties. A little puzzled on this bit. I’m sure what I see is a Map toString() value being shown if I don’t explicitly grab the char array value. I saw also a deprecation message stating that the controller property “allowedMethods” should be declared now as “static.” Semantically probably cleaner, but undocumented besides the warning.

Finally, I’m kinda not digging the more universal grails plugin placement. I still like to see the bundled plugins of my app in it’s source tree. I got kinda lost looking where they went. Only to find they all are in .grails/<grails version>/.. Now there’re two places for me to look. My hidden plugin directory, and my main Grails app directory. When I wanted to check the source codes of the plugin I just installed then, it’s just right there a few millis below. I could imagine this new directory ballooning, each and every time you create a grails app. Wonder if conflicts happen if you create two or more grails app with the same name. Hmm.. Do you really monitor hidden directories? At least when I delete my grails app back then, I’m pretty sure all files are cleaned out. But then again I’m on a Mac. Nothing new about “uninstalling” stuff there.

All-in-all, change doesn’t really impact me much. I have no idea if there are new 1.1-ways that I should start doing and dump speaking in 1.0.x-parlance.

Reboot

2009 March 6
by noisyheads

Since I took a long break last December 2008, it’s only now that I’m slowly putting effort on this project again. A lot of changes have happened since then:

  1. I bought myself a MacBook Pro to develop with
  2. Moving to Git as my scm
  3. Back up source codes online to subversion host xp-dev
  4. Upgraded to Grails 1.1 RC1 (RC2 1.1 is already available btw)
  5. Moved from IntelliJ Idea to TextMate
  6. Stopped using myriads of project management shit and stick to one app: Process 3. I got it for free at MacHeist :-p

After asking some friends to test the last snapshot and a lot of self-reflecting, I decided to start from the ground up. I know. It’s the best way to fuck up a project. Or, the best way to ensure a project never gets released :-p Ok probably not starting from scratch because I will be copying over source codes that seem ok. But feature, design, all redone. So here’s to another year developing vaporware 2.0 yeeeeha!

Grails SoundManager Plugin @ Official Grails Plugin Repo

2008 November 11
by noisyheads

Didn’t take too long for that to happen \m/ My little SoundManager plugin is now available via the Grails Plugin repo.

To use, just invoke:

grails install-plugin sound-manager

to you project. Then you’re good to go.

Also released version 0.2 just a while ago. Added playlist feature with auto start option.

Grails SoundManager Plugin

2008 November 9
by noisyheads

Been contemplating a lot on whether to stick with the flash mp3 player that I had, or to rollout a javascript-based player. The benefit of the former is the ability to embed the player anywhere, even beyond your site. The latter of course is much search engine friendlier, easily integrates with other elements in you page, and you don’t need any pricy Adobe products :P

So jumped the gun. And what do you know, life aint gonna be too hard after all. Discovered Scott Schiller’s awesome Javascript library, SoundManager2. Fuckin’ phenomenal. So all I needed was to create a Grails plugin to capitalize on the API. And voila, the Grails SoundManager Plugin.

Buh-bye OpenID

2008 October 31
tags:
by noisyheads

So much for an attempt at sparking widespread OpenID use, as I ambitiously claimed earlier. After a few round of random user testing, it’s just not gonna help my case. Diminuitive yet-another-web2.0ish website can’t have more entry point barriers. Feedback from users: were confused by it, had a hard time understanding it, left the site at first glance. The last thing I want is to put a bunch of text in a page explaining to someone to input a valid URL from another site were she/he has an account on. I can see Steve Krug shaking his head. Have you ever seen a billboard with this much text? Though Plaxo probably have a good idea working for them.

I am not very optimistic in spite of the Google and Microsoft OpenID move even. Don’t get me wrong. OpenID is a great idea. And sometime in the future, I just may comeback. Maybe when the site brings in it’s first million. Blah! :p

early feedback

2008 September 26
by noisyheads

For the past few days, I’ve asked some friends to start testing what noisyheads has got so far. In my project plan, it’s at Milestone 1 (Milestone 5 should mark a public beta). And what an eye-opener it was. I’m glad I did early testing. They were able to catch some usability issues, and some feature problems. Got some great suggestions as well. Although I’ve invested a bunch of effin’ time on it, I’ve decided to redo a whole crap load of mess in the app. I’ve been rethinking my use-case diagram, and probably throw out most of it and type in new and hopefully way cooler stuff.

I should’ve done testing much earlier though. I know someone told me not to invest too much time on the underlying stuff in the architecture early on, but begin on the surface first, that which humans actually interact with. Because ultimately, that’s the stuff that matters. An arguable statement, but has some sense nonetheless.

Note to self. The Agile Way works! Should try it more often. Now if I could afford scheduling 2 week sprints instead of feature-based milestones..