Tuesday, 10 November 2009

Grails on GAE and persistence

Introduction
In my last post we created very simple Grails project and deployed it on Google Application Engine. Now we will try to extend it to use Google Datastore for persistence.

Configuration
Create a project in the same way as in previous post but ensure you will choose JPA as a persistence provider. Another option is JDO but I simply don't know this technology;)
Next step will be to install gorm-jpa plugin for Grails:
grails install-plugin gorm-jpa

Application goals
We will create very simple one page application to manage list of books. On the top there will be a list of book items. At the bottom there will a form to store new ones.



Implementation
We should create class for our domain object - grails-app\domain\test\Book.groovy:
package test

import javax.persistence.*;

@Entity
class Book implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id

String title

static constraints = {
id visible:false
}
}
We need also web controller that will be responsible for 3 web actions:
  • index - main action listing all books
  • save - adding new book
  • remove - removing book
Add following code to grails-app\controllers\BookController.groovy:
import test.*

class BookController {
def index = {
[books : Book.list( params )]
}

def save = {
Book b=new Book(params)
b.save()
redirect(action : index)
}

def remove = {
Book b=Book.get(params.id)
b.delete()
redirect(action : index)
}
}
Finally add GSP page (grails-app\views\book\index.gsp) that will present data and invoke particular actions of our controller:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="layout" content="main" />
<title></title>
</head>
<body>
<h1>Books:</h1>
<table>
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th></th>
</tr>
</thead>

<g:each in="${books}" status="i" var="book">
<tr>
<td>${book.id}</td>
<td>${book.title}</td>
<td><g:link action="remove" id="${book.id}">remove</g:link> </td>
</tr>
</g:each>
</table>
<h1>New:</h1>
<g:form action="save">
<table>
<tr>
<td>Title</td>
<td><g:textField name="title" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" /></td>
</tr>
</table>
</g:form>
</body>
</html>
Deploy the application just as we did it in last post. Point the browser to /book resource of your web app. You should see our page running.

Now, you can also browse datastore on GAE account pages:

2 comments:

  1. Very useful posts, thankyou, this has got me started with GAE.

    ReplyDelete
  2. i think it won't work with on-to-many relationships when id type is long. you'd need to do the following

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
    String id

    regards,
    wojciech (your new colleague)

    ReplyDelete