Two ways to model One-to-Many in GORM

There are two subtly different, but distinct ways to model a One-to-Many relationship in GORM, each with some rather interesting implications.




Method One:
   1:class Book{
2: String title
3: static belongsTo = Author
4:}
5:
6:class Author {
7: String name
8: static hasMany = [books: Book]
9:}

This method results in the schema:


Furthermore, the following applys:
  1. An additional "link" table (author_book) will be created in the database.
  2. A books property will be available on Author
  3. There is no direct way of querying the reverse of the relationship. i.e. no straightforward way to lookup an Author if you're holding a Book object.(See this post for a solution)

Method Two:
   1:class Book{
2: String title
3: static belongsTo = Author
4: Author author
5:}
6:
7:class Author {
8: String name
9: static hasMany = [books: Book]
10:}
Note: The addition of "author" property at line 4 above.

This method results in the schema:



Furthermore:
  1. An additional column called author_id will be created on the Book table in the database
  2. No "link" table will be created in the database
  3. It is possible to query both the forward and reverse relationship by refering to the Books.author and Author.books properties respectively
FIN.


Read more...

GORM Criteria Query for One-to-Many

In Grails, GORM has some very nice features, not the least of which are Dynamic Finders. It's quite easy to sometimes overlook a really powerful and elegant alternative to dynamic finders in the form of Criteria. In this article I will cover one specific case in which there exists no dynamic finder for a specific use case, but for which a simple, elegant Criteria will do.


Consider the following one-to-many relationship in which One Author has many Books.

   1:class Book{
2: String title
3: static belongsTo = Author
4:}
5:
6:class Author {
7: String name
8: static hasMany = [books: Book]
9:}
The problem: Assuming we are holding a Book object, how do we find the associated Author for that book ? Here's how:
   1:def book = Book.findByTitle('Definitive Guide to Grails')
2:
3:def criteria = Author.createCriteria()
4:
5:def author = criteria {
6: books{
7: eq('id',book.id)
8: }
9:}
The often overlooked "trick" to the above criteria, is the fact that we can use the "books" property on Author in our Criteria to match against (line 6 above).

References:





Read more...

Grails Ajax File Upload ProgressBar

Grails has the basic infrastructure in place to support AJAX-based file upload progress bars on your pages. In this article I will show you how to leverage the ExtJS Javascript library along with the Apache Commons File Upload library to achieve a nice user-friendly file upload progress bar in your Grails project. You can download a working Grails demo application at the end of this article in the Resources section.

Below is a screenshot of the demo application in action.


Background
File upload handling is, as everything else in Grails stacked on top of the Spring Framework. The Spring Framework in turn has delegated the job of managing streaming uploads to the Apache Commons File Upload library.
Commons File Upload takes care of very important server-side memory-management by allowing you to "stream" your uploads to disk instead of them being kept and handled entirely in memory. Read more about this at the Commons File Upload site.

In this article we will need to complete the following steps in order to achieve a working client-side progressbar:
  1. Implement a custom ProgressListener
  2. Subclass Spring's CommonsMultipartResolver
  3. Inject our custom ProgressListener and CommonsMultipartResolver classes into Spring via "conf/spring/resources.xml"
  4. Create an action in a controller which can be polled for upload progress info from client-side javascript
  5. Write appropriate client-side Javascript to poll the server for progress info

Prerequisites:
  • At the time of writing, Grails 1.0.1 ships with version 1.1.x of Apache commons-fileupload. Visit http://commons.apache.org/fileupload/ and get at least version 1.2
  • For the purposes of this tutorial I will be using ExtJS version 2.x (http://extjs.com/download), which comes with a nifty ready-built javascript progressbar.

Implement a custom ProgressListener
The commons file upload API allows us to register a class which implements the org.apache.commons.fileupload.ProgressListener interface. Once registered, this will allow us to receive progress updates as multipart data is being streamed to the server. Below is a code snippet from AjaxProgressListener.groovy (see Resources at bottom of article)

6:class AjaxProgressListener implements ProgressListener {
7:
8:
.
.
22: void update(long pBytesRead, long pContentLength, int pItems){
23:
24: session.setAttribute("progressMap", ["bytesRead": pBytesRead, "length" : pContentLength, "items" : pItems])
25: println("DEBUG UPLOAD: ${pBytesRead} : ${pContentLength} : ${pItems}")
26:
27: if (pBytesRead == pContentLength){
28: session.setAttribute("progressStatus", STATUS_DONE)
29: }
30:
31: }
32:}
As you can see in the above code snippet on line 24, we place the progress information into our session. We will need access to this information in our controller for retrieving progress information via javascript.

Subclassing Spring's MultipartResolver

Grails injects a "multipartResolver" property into our applicationContext. This property is actually an instance of Spring's CommonsMultipartResolver. CommonsMultipartResolver actually wraps the commons FileUpload class. However it does not expose the FileUpload functionality allowing us to register a progress listener.
In order to get our custom ProgressListener registered, we have to subclass CommonsMultipartResolver, and expose getter/setter methods for ProgressListener registration see lines 18 to 26 and our overridden factory method on line 47) in the
   1:package com.adeptiva.commons.upload
2:
3:import org.springframework.web.multipart.commons.CommonsMultipartResolver
.
.
11:import javax.servlet.http.HttpServletRequest
12:
13:class AjaxMultipartResolver extends CommonsMultipartResolver{
14:
15: private ProgressListener pListener
16: private HttpServletRequest request
17:
18: public void setProgressListener(ProgressListener p){
19: this.pListener = p
20: }
21:
22: public ProgressListener getProgressListener(){
23:
24: return this.pListener
25:
26: }
27:
28:
.
.
46:
47: protected FileUpload newFileUpload(FileItemFactory fileItemFactory) {
48:
49: FileUpload fu = super.newFileUpload(fileItemFactory)
50:
51: if (this.pListener != null){
52: this.pListener.session = this.request.session
53: fu.setProgressListener(this.pListener)
54: }
55:
56: this.pListener?.updateStatus(AjaxProgressListener.STATUS_UPLOADING)
57:
58: return fu
59: }
60:
61:}


Injecting our AjaxMultipartResolver into Grails/Spring
Now that we have our own implementation of the Spring CommonsMultipartResolver, it's time to take advantage of dependency injection to ensure that Grails uses our AjaxMultipartResolver. We modify our "conf/spring/resources.xml" as follows:
   1:<bean id="multipartResolver" class="com.adeptiva.commons.upload.AjaxMultipartResolver">
2: <property name="maxInMemorySize">
3:
4: <value>10240</value>
5: </property>
6: <property name="maxUploadSize">
7:
8: <value>1024000000</value>
9: </property>
10: <property name="progressListener">
11: <ref bean="progressListener"/>
12: </property>
13: </bean>
14:
15:<bean id="progressListener" class="com.adeptiva.commons.upload.AjaxProgressListener"/>
16:

Progress Information
The action which retrieves progress information is rather simple, and beyond doing some minor error checking is only responsible for constructing a JSON response (using builders of course).

   1:    def uploadInfo = {
2:
3: def progressMap = session.getAttribute("progressMap")
4: def progressStatus = session.getAttribute("progressStatus")
.
.
22: render(builder:'json'){
23: bytesRead(progressMap['bytesRead'] )
24: totalSize(progressMap['length'] )
25: status(progressStatus)
26: }
27: }

Our .gsp and Javascript
Between the .gsp and javascript files there remains only a few items to take care of:
  • Perform a form submission containing our file input via Javascript. This prevents the browser from navigating away from the current page after upload is complete.
  • Start an asynchronous task which polls the server for upload progress, updating our progressbar on each return.
The above is rather straightforward, and should be self-explanatory based on the supplied source code (js/application.js and views/home/index.gsp respectively) (see Resources section).

Resources:
You can download the full project demonstrating the above from HERE.

References:
File Uploading section from the Grails User Guide.
Apache Commons File Upload website


FIN.

Read more...

Grails Custom Exception Handling

Updated On: 2 Jul 2008 - Tested on Grails 1.0.1
Grails allows you to perform custom , fine-grained Exception handling for error conditions in your controllers. As per usual, you can take advantage of this feature by making use of Grails' nifty Dependency Injection features. In this case, we will depend on the GrailsExceptionResolver class being injected into /conf/BootStrap.groovy as "exceptionHandler".

Note: This article shows you a fine-grained alternative to the "500 Internal Server" catch-all which is generated by default in /conf/UrlMappings.groovy

The important changes are in the below bit of code on lines 3, and 7 to 9 of my BootStrap.groovy file:

   1:class BootStrap {
2:
3: def exceptionHandler
4:
5: def init = { servletContext ->
6:
7: exceptionHandler.exceptionMappings =
8: [ 'NoSuchFlowExecutionException' :'/my/doIt',
9: 'java.lang.Exception' : '/error']
10:
11: }
12:
13: def destroy = { }
14:}

In the above code snippet we set the exceptionHandler's exceptionMappings property to a Map containing the name of the exception we wish to handle, mapped to the URI we wish to handle our error condition.
Line 9 above is very important. This is our "catchall" for all other java.lang.Exceptions to be handled by Grails' internal error handler. It is worth noting that leaving out "java.lang" will have the incorrect bevaviour. Taken from the javadoc for GrailsExceptionResolver's setExceptionMappings() method:


NB: Consider carefully how specific the pattern is, and whether to include package information (which isn't mandatory). For example, "Exception" will match nearly anything, and will probably hide other rules. "java.lang.Exception" would be correct if "Exception" was meant to define a rule for all checked exceptions. With more unusual exception names such as "BaseBusinessException" there's no need to use a FQN.


NOTE: In the above code the URI maps onto our urlMappings, therefore
  • '/my/doIt' - invokes doIt closure on MyController
  • '/error' - skips straight to /views/error.gsp

Lastly, in order for all the above to work, we must remove the default "500" error handler from your /conf/UrlMappings.groovy as follows (line 8):
   1:class UrlMappings {
2: static mappings = {
3: "/$controller/$action?/$id?"{
4: constraints {
5: // apply constraints here
6: }
7: }
8:// "500"(view: null)
9: }
10:}
References:


Read more...