0: Update with NetBeans IDE6.5 [Update Dec 24]
Recently I played this with NetBeans IDE6.5. Seems this one better than Eclipse, you just download the latest Netbeans package (250 M - huge). And Netbeans already have grails plugin. And you can simple click run button to make grails project run. Worth to have a try - I guess I will stay in Netbeans for a while in grails project.
/**Here is the extjs side code:
* Copyright (c) 2005 - 2008 FeyaSoft Corp. All Rights Reserved.
*/
import grails.converters.*
import com.feyasoft.myActivity.domain.account.*
/**
* @author Fenqiang Zhuang
* @Dec 1, 2008
*
* This file is used to define the account controller action
* This will provides the service for UI level.
* Most important actions are list, save, update, delete
*/
class AccountController {
// the delete, save and update actions only accept POST requests - maybe not necessary
def allowedMethods = [delete:'POST', update:'POST', create:'POST']
/**
* Mapping url: http://localhost:8080/fileMgr/account/list
*
* This will lost of accounts in the system based on search result.
* Return result will be in JSON format.
*
*/
def list = {
// log information
log.info(params: params)
if(!params.max) params.max = 20
// get a list of result based on params.
def accounts = Account.list(params)
// return a bunch of json data with metadata.
def json = [
metaData: [
totalProperty: 'totalCount',
root: 'results',
id: 'id',
fields: [
[name: "id", type: "int"],
[name: "firstname"],
[name: "lastname"],
[name: "username"],
[name: "email"]
]
],
totalCount: accounts.size,
results: accounts
]
render json as JSON
}
/**
* * Mapping url: http://localhost:8080/fileMgr/account/save
*
* create account method - get passed parameter from extjs and call save() function
* If everything ok, it will return success message for form.
*/
def create = {
def account = new Account(params)
// default error msg
def json = [failure : "true", errorInfo : "Internal Error, please try again"]
// check whether something wrong in save
if(!account.hasErrors()) {
// check username already exist or not
if (Account.findAllByUsername(account.username).size()>0) {
json = [failure : "true", errorInfo: "This username already existed, please choose another one"]
} else if (account.save()) {
json = [success : "true", info : "You have success creat this account"]
} else {
def errors = "Error is: "
account.errors.allErrors.each {
errors = errors + it
}
json = [failure : "true", errorInfo: errors]
}
}
// return json data
render json as JSON
}
/**
* This will load existing account information based on id from UI.
* Return back a json string.
*
* JSON like this:
*
* {"success":"true","data":[{"id":4,"class":"Account","createDate":new Date(1227909694000),
* "email":"","firstname":"jj","lastModifiedDate":new Date(1227909694000),"lastname":"j",
* "password":"kkkk","username":"llkl"}]}
*/
def load = {
def account = Account.get(params.id)
if(account) {
def json = [success: "true", data: [account]]
render json as JSON
} else {
// default error msg
def json = [failure : "true", errorInfo : "Internal Error, please try again"]
render json as JSON
}
}
/**
* This will update the passed parameter from UI level
* Called by the Edit.js file.
*/
def update = {
def account = Account.get( params.id )
// default error msg
def json = [failure : "true", errorInfo : "Internal Error, please try again"]
if(account) {
account.properties = params
if(!account.hasErrors()) {
if (account.save()){
json = [success : "true", info : "You have success update this account"]
} else {
def errors = "Error is: "
account.errors.allErrors.each {
errors = errors + it
}
json = [failure : "true", errorInfo: errors]
}
}
}
// return json data
render json as JSON
}
/**
* Delete this related account by id - passed by
*/
def delete = {
def json = [failure : "true", errorInfo : "Internal Error, please try again"]
// check whether del parameter is passed - if yes, delete first
if (params.delData != null) {
def jsonArray = JSON.parse(params.delData)
jsonArray.each {
log.info("start to delete account with id: ${it.id}")
def delAccount = Account.get(new Long("${it.id}"))
if (delAccount) {
delAccount.delete()
json = [success : "true", info : "You have success delete this account"]
}
}
}
render json as JSON
}
}
feyaSoft.account.List = function() {
Ext.QuickTips.init();
// define default rowsPerPage = 10;
var myPageSize = 20;
var accountCM = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),
{id: 'id', header: "Identify", dataIndex: 'id', width: 150, hidden: true},
{header: "First Name", dataIndex: 'firstname',width: 150},
{header: "Last Name", dataIndex: 'lastname',width: 150},
{header: "Username", dataIndex: 'username',width: 150},
{header: "Email", dataIndex: 'email',width: 150}
]);
accountCM.defaultSortable = false;
/************************************************************
* connect to backend - grid - core part
* create the Data Store
* connect with backend and list the result in page
* through JSON format
************************************************************/
this.dataStore = new Ext.data.JsonStore({
url: 'account/list',
remoteSort: true,
fields: [] // initialized from json metadata
});
this.dataStore.setDefaultSort('lastname', 'ASC');
/************************************************************
* Define menubar now in here
* add and delete functions
************************************************************/
var menubar = [{
text:'Add New Account',
tooltip:'Add a new account information',
iconCls:'addItem',
handler: function(){
// add new user now - call another JS class
new feyaSoft.account.Create();
}
},'-',{
text:'Archive',
tooltip:'Archive the selected items',
iconCls:'remove',
handler: function(){
//new feyaSoft.util.DeleteItem({panel: 'listAccount-panel'});
}
}];
var pagingbar = new Ext.ux.PagingToolbar({
pageSize: myPageSize,
store: this.dataStore,
displayInfo: true,
displayMsg: 'Displaying items {0} - {1} of {2}',
emptyMsg: "not result to display"
});
/************************************************************
* define grid panel now
* For more detail parameters, you can find from extjs API
************************************************************/
feyaSoft.account.List.superclass.constructor.call(this, {
id: 'list-account-panel',
ds: this.dataStore,
cm: accountCM,
viewConfig: {forceFit:true},
tbar: menubar,
bbar: pagingbar,
height:400,
width:800,
frame: true,
autoScroll:true
});
// trigger the data store load
this.dataStore.load({params:{start:0, limit:myPageSize}});
};
Ext.extend(feyaSoft.account.List, Ext.grid.GridPanel, {
// reload datasource
reload : function () {
this.dataStore.load();
},
remove : function (row) {
this.dataStore.remove(row);
},
deleteData : function (jsonData) {
this.dataStore.load({params:{start:0, delData:jsonData}});
}
});
Some hints maybe help for your to use Grails:
1: Get latest version Grail 1.0.4 and setup GRAIL_HOME in your ENV: http://grails.org/
2: Create a grails project through Eclipse.
3: Update
You do not need create tables - using dbCreate="create" for first time and grails will create DB table for us (you do need create database name). Go to:
grails-app/conf/DataSource.groovy file, you need update:
dataSource {
pooled = true
driverClassName = "com.mysql.jdbc.Driver"
username = "root"
password = "XXXXXX"
}
development {
dataSource {
dbCreate = "update" // one of 'create', 'create-drop', 'update' - first time, please use 'create'
url = "jdbc:mysql://localhost:3306/demo?tcpKeepAlive=true&useUnicode=true&characterEncoding=UTF8"
}
}
4: Run
come to the project folder: cd yourProjectFolder // using cmd
> grails clean <--- sometimes compiled code are not cleaned and behavior weird - clean will help
You can also run this through ant in Eclipse. However, I do not know how to stop Jetty under Eclipse (Finally I kill it through Ctrl + Alt + del and find task manager - kill all of Java running thread.).









