Thursday, October 30, 2008
Division operator in Groovy
And if you want to obtain an integer you should invoke the method intdiv:6.intdiv(2) then the result is an integer:3
Friday, September 19, 2008
An ant example for how to Validate XML
<tns:root xmlns:tns="http://www.example.org/Simple" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/Simple Simple.xsd ">
This is an user test
<tns:user role="admin">
<tns:name>tnsname1</tns:name>
<tns:age>18</tns:age>
<tns:gender>Male</tns:gender>
<tns:password>sfds3555</tns:password>
<tns:title/>
</tns:user>
<tns:user role="admin">
<tns:name>tnsname1</tns:name>
<tns:age>18</tns:age>
<tns:gender>Male</tns:gender>
<tns:password>sfds3555</tns:password>
<tns:title/>
</tns:user>
<tns:cost>0.22</tns:cost>
<tns:cost>0</tns:cost>
</tns:root>
A XSD Schema file for example.
targetNamespace="http://www.example.org/Simple" xmlns:tns="http://www.example.org/Simple"
elementFormDefault="qualified">
<xs:complexType name="user" mixed="true">
<xs:sequence>
<xs:element name="name" type="xs:string" default="Eric001" />
<xs:element name="age" type="tns:age" default="30" />
<xs:element name="gender" type="tns:gender" default="Male" />
<xs:element name="password" type="tns:password" />
<xs:any maxOccurs="unbounded"></xs:any>
</xs:sequence>
<xs:attribute name="role" type="xs:string"/>
</xs:complexType>
<xs:simpleType name="gender">
<xs:restriction base="xs:string">
<xs:enumeration value="Male" />
<xs:enumeration value="Female" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="age">
<xs:restriction base="xs:integer">
<xs:minInclusive value="1" />
<xs:maxInclusive value="120" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="letter">
<xs:restriction base="xs:string">
<xs:pattern value="[A-Za-z0-9]"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="password">
<xs:restriction base="xs:string">
<xs:pattern value="(([0-9]+[a-zA-Z]+)|([a-zA-Z]+[0-9]+))"></xs:pattern>
<xs:minLength value="5" />
<xs:maxLength value="8" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="amount">
<xs:restriction base="xs:decimal">
<xs:totalDigits value="2"></xs:totalDigits>
</xs:restriction>
</xs:simpleType>
<xs:element name="root">
<xs:complexType mixed="true">
<xs:sequence>
<xs:any maxOccurs="unbounded"></xs:any>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="user" type="tns:user" >
</xs:element>
<xs:element name="cost" type="tns:amount" />
<xs:element name="title"></xs:element>
</xs:schema>
Following is the XML file:
<?xml version="1.0" encoding="UTF-8"?>
<tns:root xmlns:tns="http://www.example.org/Simple" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/Simple Simple.xsd ">
This is an user test
<tns:user role="admin">
<tns:name>tnsname1</tns:name>
<tns:age>18</tns:age>
<tns:gender>Male</tns:gender>
<tns:password>sfds3555</tns:password>
<tns:title/>
</tns:user>
<tns:user role="admin">
<tns:name>tnsname1</tns:name>
<tns:age>18</tns:age>
<tns:gender>Male</tns:gender>
<tns:password>sfds3555</tns:password>
<tns:title/>
</tns:user>
<tns:cost>0.22</tns:cost>
<tns:cost>0</tns:cost>
</tns:root>
Wednesday, September 17, 2008
Add bookmark on docbook PDF
<!--
- target: build-pdf
- description: Iterates through a directory and transforms
- .xml files into .fo files which can then be turned into DocBook XML
- files.
-->
<target name="build-pdf" depends="depends"
description="Generates PDF files from DocBook XML">
<xslt style="${fo.stylesheet}" extension=".fo"
basedir="${basedir}/src" destdir="${target.dir}/fo">
<classpath refid="xalan.classpath" />
<include name="**/*.xml" />
<exclude name="**/*chapter*.xml"/>
</xslt>
<property name="fop.home" value="${basedir}/lib/fop-0.95"/>
<taskdef name="fop" classname="org.apache.fop.tools.anttasks.Fop">
<classpath>
<fileset dir="${fop.home}/lib">
<include name="*.jar"/>
</fileset>
<fileset dir="${fop.home}/build">
<include name="fop.jar" />
</fileset>
</classpath>
</taskdef>
<fop format="application/pdf"
outdir="${target.dir}/pdf" basedir="${target.dir}/fo">
<fileset dir="${target.dir}/fo">
<include name="*.fo"/>
</fileset>
</fop>
</target>
following is my dobook segment:
<sect1>
<title>Section 1 title</title>
<para>
<sect2>
<title>section 2 title</title>
<para>
description...
</para>
<sect3>
<para>witing something...</para>
<sect3>
</sect2>
</sect1>
Now the question is;
1)I want to display the label of section.
2)I want to display the bookmark in PDF.
The final solution is change the param.xml file.
1)to display the label of section:
change following line
<xsl:param name="section.autolabel" select="0">
to this line
<xsl:param name="section.autolabel" select="1">
2)to display the bookmark in PDF.
change following line
<xsl:param name="fop1.extensions" select="0">
to this line
<xsl:param name="fop1.extensions" select="1">
Note:don't change following line otherwise you will get an exception like:
No element mapping definition found for (Namespace URI: "http://xml.apache.org/fop/extensions", Local Name: "destination")
<xsl:param name="fop.extensions" select="0">
Friday, September 12, 2008
How to change the locale in Grails.
<span>
<g:link controller="${params.controller}" action="${params.action}" params="[lang:'en']" class="menuButton">English</g:link>
</span>
<span>
<g:link controller="${params.controller}" action="${params.action}" params="[lang:'de']" class="menuButton">German</g:link>
</span>
then you will have a change language in every page.or another way you can put this code in your layout.gsp file directly.
Error starting Sun's native2ascii: In Grails
Then try this method:
Copying %Java_Home%/lib/tools.jar to %Java_Home%/jre/lib/ext/tools.jar fixed this problem.
(a better approach is to set up JRE path to the directory JDK)
How to implement i18n message in controller
Thursday, September 11, 2008
Notes on Grails Internationalization (i18n)
When using Grails for web app development, it's desirable to place all text in messages.properties files. When you do this, you can easily change the text to another language, and that makes internationalization easier. You still have to deal with other issues such as date formats and currency, but at least the text is easy to modify that way.
Once you have all your properties files created, you can make change languages by passing in the lang parameter and setting it to the language of your choice. For instance, if you want to list out some values, you can call the "list" action and pass it the Spanish language as a parameter.
<g:link action="list" params="[lang:'es']">
Note: Once you pass this parameter to any page, your app will now be in that language until you change it.
So, in order to facilitate this, you need to create the necessary files and reference the properties in your code. For example, create a messages.properties file and add text such as "Search" for your home page.
home.search=Search
Now, you can create a messages_es.properties that contains your Spanish translations:
home.search=Buscar
So, once you have all the text defined in your messages.properties file(s), (one for each language you are translating to) all you then need to do is reference that particular property in your code. Grails picks that up and inserts the appropriate property for you. Here are some tips on doing that in your code.
In the GSP page, if you want to reference the file in just plain text, use the g:message tag:
<g:message code="home.search" default="Search"/>
This tells Grails to find the property "home.search" in the properties file, and insert that value here. If it cannot find "home.search" in your properties file, it will insert whatever is in the default parameter.
When using the sortableColumn GSP tag, use the "titleKey" parameter to set the property as follows:
<g:sortableColumn property="title" titleKey="certification.title"/>
To set the text of a button, you can pass in a variable from the controller. I've used the flash scope to pass data back to the view, but you can use another object if you want to and return it. First, grab the value from the flash scope in the GSP page as follows:
<input type="submit" value="${flash.search}"/>
Next, in the controller action, just set the flash.search parameter before you return:
flash.search = message(code: 'home.search')
Now, the action in the controller will grab the message and throw it into the flash.search variable. You simply read that variable in the GSP page and it's all good. There's probably a better way of reading that parameter directly in the GSP page, and when I find it, I'll post an update.
Log4j configuration in Grails
development {
log4j {
appender.access="org.apache.log4j.ConsoleAppender"
appender.'access.layout'="org.apache.log4j.PatternLayout"
appender.access.layout.ConversionPattern==%d %p %x [%c] %m%n //you must put the quote around "access.layout.ConversionPattern"
logger
{
grails.'app.controller.UserController'='warn,access'
}
}
}
following statement is copy from Grails official site,it explain why we should do it like that
A couple things to keep in mind while modifying Config.groovy:
1) Unlike the flat format used by log4j, the Grails config format is hierarchical, so if you write:
grails.app.controller.YourController="debug,stdout"
grails="info,stdout"
grails.'app.controller.YourController'="debug,stdout"
grails="info,stdout"
grails.app="info,stdout"
grails.app.controller="debug,stdout"
Reversing the lines will eliminate the error (but the definition of grails.app will override the definition of grails.app.controller):
grails.app.controller="debug,stdout"
grails.app="info,stdout"
But After I fix it,it sitll can not doesn't work.then I google again and again.finally,
I found there are something error in default generate from Grails.
we should change following line
logger
{
grails.'app.controller.UserController'='warn,access'
}
logger.
logger.grails.'app.controller.UserController'='warn,access'
now it's work well done.
Deprecated constraints in Grails domain class
length
maxLength
minLength
instead of:
size
maxSize
minSize.
Just for remember
Wednesday, September 10, 2008
Premature end of file in Grails
Tuesday, September 9, 2008
How to define a closure by method
Safe dereferencing with the ?. operator
How the Grails Link element work
<g:link action="show" id="${currentBook.id}">${currentBook.name}</g:link>
<g:link controller="book">Book Home</g:link>
<g:link controller="book" action="list">Book List</g:link>
<g:link url="[action:'list',controller:'book']">Book List</g:link>
<g:link action="list" params="[sort:'title',order:'asc',author:currentBook.author]">
Book List
</g:link>
Monday, September 8, 2008
Single or double quotes
Another method for redirection in index.gsp
Sunday, September 7, 2008
How to redirect url from index.gsp?
Wednesday, March 19, 2008
Test in Grails
>>grails create unit-test
then Grails will ask you which Domain you want to test.for example type project
Then Grials will generate a class in directory: gwork\gira\workspace\test\integration
Write some code like this
class ProjectTests extends GroovyTestCase {
void testSort() {
def sortByAttribute={property ->
Project.findAll().sort{it."$property"}.title
}
def titles=sortByAttribute("title")
assert titles
assert titles.size()==3
assert titles[0]=="App1"
}
void setUp(){
new Project(title:'App1',description:'This is a test',createDate:new Date()).save()
new Project(title:'App2',description:'This is a test',createDate:new Date()).save()
new Project(title:'App3',description:'This is a test',createDate:new Date()).save()
}
void tearDown(){
Project.list()*.delete()
}
}
Then run command:
>>grails run-test
You will get the test reult.
Dynamic scaffod in Grails
• grails generate-views: Generates views for the specified domain class
• grails generate-controller: Generates a controller for the specified domain class
• grails generate-all: Generates both a controller and associated views
Hpw to change the default context of Grails server
>>grails run-app
I found the context of Grails server is still sparrow.Oh,how to change it.I found there is application.properties file in my project directory,I edit it like this
app.name=gria
Then the server's context change to gria.
Tuesday, March 18, 2008
The inList conatraint must follow blank constraint
priority(inList:["High","Low"])
then,when you open the page to edit or create this domain,you will find that the property can't be select by a HTML select box.So,you must follow another constraint blank and set it false.like this:
priority(inList:["High","Low"],blank:false)
Is it a bug?
Monday, March 17, 2008
Constraint in Grails
Name | Example | Description |
blank | title(blank:false) | Set to false if a string value cannot be blank |
email(email:true) | Set to true if the value must be an email address | |
inList | sex(inList:['Man','Woman']) | Value must be contain within the given list |
length | title(length:1..50) | Use a range value to restrict the length of string or range |
min | age(min:new Date() | Set the minimun value |
minLength | title(minLength:5) | Set the minimum length of a string or array property |
minSize | children(minSize:10) | Set the minimum size of a collection or number property |
matches | name(matches:/[a-zA-Z]/) | Matches the supplied regular expression |
max | age(max:new Date() | Set the maximum value |
maxLength | title(maxLength:5) | Set the maximum length of a string or array property |
maxSize | children(maxSize:10) | Set the maximum size of a collection or number property |
notEqual | name(notEqual:'Eric') | Must not equal the special value |
nullable | name | Set to false if property value cannot be null |
range | age(range:30..60) | Must occur within the special range |
size | children(size:5..15) | Use a range to restrict the size of a collection or number |
unique | name(unique:true) | Set to true if the property must be unique |
url | url(url:true) | Set to true if a string value is a url address |
HQL in Grail
/**find method*/
//following method will return a project object whose attribute is 'App1'
def project=Project.find('from Project p where p.title=?',['App1'])
/**findAll method*/
//following method will return all of project objects.
def projectList=Project.findAll('from Project')
//Grails also provide a elegant IN operator
def plist=Project.findAll('from Project')
def ilist=Issue.findAll("from Issue as b where b.project in (:p)", [p:plist])
/**executeQuery method*/
def plist=Project.executeQuery("select distinct p.title from Project p")
//it is possible to perform more-advanced queries using joins, aggregate functions, and subqueries.
And also we can some limit for query result number,for example:
def plist=Project.executeQuery("select distinct p.title from Project p",[max:10,offset:5])
)
Sunday, March 16, 2008
Dynamic Finders in Grails
This figure from the book:the definitive guid to grails.
Now I list the available Dynamic Finder method and example:
Expression Arguments Example
Between 2 Project.findByCreateDateBetween(today-10,today)
Equals 1 Project.findByTitleEquals('App1')
GreaterThan 1 Project.findByCreateDateGreaterThan(lastmonth)
GreaterThanOrEqual 1 Project.findByCreateDateGreaterThanOrEqual(lastmon)
IsNull 1 Project.findByTitleIsNull()
IsNotNull 1 Project.findByTitleIsNotNull()
LessThan 1 Project.findByCreateDateLessThan(lastmonth)
LessThanOrEqual 1 Project.findByCreateDateLessThanOrEqual(lastmonth)
Like 1 Project.findByTitleLike('App1%')
NotEqual 1 Project.findByTitleNotEqual('App1')
All of findBy* method only return that fisrt be found object.
There are two cousins method findAllBy* and countBy*.
findAllBy* :return a list that is matched the query logic
countBy* :return a number that is matched result total.
Data operator CRUD in Grails
/**Create data*/
//create a project
def project1=new Project(title:'Project1',description:'Hello world!',createDate:new Date())
//now we have the project object.we will save it.
project1.save()
//as you can see ,we never define the method save().but we can use it,because Grails auto //generate it in runtime for us.when we call this method,the project information will be saved in database table,it's cool.
//Now we'll define issue object
def issue1=new Issue(summary:'Issue1',description:'This is a issue',createDate:new Date(),project:project1)
//we created the issue object,but the different in this place.we have a parameter project:project1 ,because the project and issue has a one-many relationship,so we need point there whcih Project that this Issue belong to.
/**read*/
after we create the object information.we usually need get these data.how to do that?the answer is get(id) and exists(id) method.
//get Project by ID
def p1=Project.get(1)//we will use id parameter get a project,which id is 1
def boolean=Project.exist(1)//the exists method will return ture if it's exists.
The exists method, reads better and is arguably more performant than get method.
if(Project.get(1)){
def p=Project.get(1) //bad performant,because you called twice get method
}
if(Project.exists(1)){
def p=Project.get(1) //better performant
}
/**update Object*/
//update object is easy
def p=Project.get(1)
p.title='New title'
p.save()
/**delete Object*/
def p=Project.get(1)
p.delete()
/**sort,listing,and counting*/
GORM provides a list method, which takes a number of named arguments such as max, offset,
sort, and order to customize the results, the definitions of which are listed here:
• max: The maximum number of instances to return
• offset: The offset relative to 0 of the first result to return
• sort: The property name to sort by
• order: The order of the results, either asc or desc for ascending and descending order respectively
//demonstrate
//get all objecta
def allProject=Project.list()
//get top 10 objects
def topten=Project.list(max:10)
//sort objects
def sortingProject=Project.list(max:10,sort:'createDate')
//sort and order
def sortingProject2=Project.list(max:10,sort:'createDate',order:'desc')
//order by column name
def allBycreateDate=Project.listOrderByCreateDate()
Note:the listByCreateDate is auto generate by Grails.it's a role,that means listOrderBy+property'name
Friday, March 14, 2008
How to create the Domain-class of Grails--Sparrow begin
But before the beginning of our process,let me introduce the requirement of our Sparrow.For facilitate,I will illustrate the requirement by a UML diagram.
As you can see, our project will include three functions.
1)create a project.
2)create issues for this project.
3)create issues type for existing issues.
Following is the Domain Class Model :
Now,let's begin.In Grails,it use the Hibernate for ROM ,but as the same time Grails extend the Hibernate,we call this extension "GOM".It's also based on "Convention Role",so we only need create a POJO class by Groovy language.In our project there are three domain class we'll create.Grail provide us a easy to used tool.To do this,just open the command line.type:
>>grails create-domain-class
then enter the class name ,for example :project.
Grails will auto generate a class with capitalize letter.like this:
class Project {
static hasMany=[issues:Issue]//one project can has many issues
String title
String description
Date createDate
}
Note:the hasMany is a key word of Grails,that means one project can has many issues.so Issue class will have a belongsTo attribute.like this:
class Issue {
static belongsTo=Project
Project project
String summary
String description
Date createDate
}Because of we have create our database(postgreSql).now we run our application.
>>grails run-app
You'll see that grails auto create the database table for these two domain class.
As you can see Grails auto create two field "id" and "version".it's a convention,also id is a default key and it's request.And also,may be you have saw that the property field "createDate" in database table is create_date,because the createDate field has a capitalize letter "D",so it replace by "_d".yes it's also a convention.
Wednesday, March 12, 2008
How to config Grails's datasource
• DB2 7.1, 7.2, 8.1
• HSQLDB
• HypersonicSQL 1.61, 1.7.0, 1.7.2, 1.8
• Microsoft SQL Server 2000
• MySQL 3.23, 4.0, 4.1, 5.0
• Oracle 8i, 9i, 10g
• PostgreSQL 7.1.2, 7.2, 7.3, 7.4, 8.0, 8.1
• SAP DB 7.3
• Sybase 12.5 (JConnect 5.5)
• Timesten 5.1
Let me assume that we use postgresql.Then we should download the JDBC driver from postgresql homepage,and copy it into the directoty lib($App_home$/lib).Then edit the file DataSource.groovy in directory conf.like this(I add some comments for every section):
dataSource {
pooled = true //which allows you to configure whether to use a connection pool or not
driverClassName = "org.postgresql.Driver" //the database driver class name
username = "postgres" //database name
password = "123456" //database password
}
//It is the configurate for hibernate,you can change it fit your want.
hibernate {
cache.use_second_level_cache=true
cache.use_query_cache=true
cache.provider_class='org.hibernate.cache.EhCacheProvider'
}
// environment specific settings,there are three database for our application.
//sparrow_dev:for development phase.
//sparrow_test:for test phase.
//sparrow_pro:for product phase.
environments {
development {
dataSource {
dbCreate = "update" // one of 'create', 'create-drop','update'
url = "jdbc:postgresql://127.0.0.1:5432/sparrow_dev"
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:postgresql://127.0.0.1:5432/sparrow_test"
}
}
production {
dataSource {
dbCreate = "update"
url = "jdbc:postgresql://127.0.0.1:5432/sparrow_pro"
}
}
}
Now,you can run you application under a database model.congratulation.
Monday, March 10, 2008
What the Grails application directory contains?
grails-app:This directory containing core Grails artifacts
+conf: Contains configuration elements,such as DataSource.groovy,UrlMappings.groovy
+controllers :Controllers that handle requests
+domain:Contains domain object class.
+i18n:Contains internationalization message bundles.
+services:Services that encapsulate business logic
+taglib:Dynamic tag libraries
+views:Groovy server page or JSP.
+layouts:the GSP or JSP layouts powered by sitemesh.
grails-test:application unit tests.
hibernate:optional Hibernate configuration.
lib:java lib jar archives
spring:optional Spring configuration.
src:Include other Groovy or Java sources.
+java:Further Java sources for compilation.
+groovy:Further Groovy sources for compilation.
web-app:web application resources (CSS, JavaScript, etc.)
How to change the default servlet version of Grails
1)passs argument -Dservlet.version,for example:
>>grails -Dservlet.version=2.5 run-app
2)Or we can directly edit the Init.groovy file in directory Grails_Home/scripts.find the key "servletVersion" and change its default value from 2.4 to others what you want,for example:
servletVersion = System.getProperty("servlet.version") ? System.getProperty("servlet.version") : "2.5"
How to display database comments of table's columns
select * from user_col_comments where table_name='table name'
as same principle.we can show the table's comments:
select * from user_tab_comments where table_name='table name'
How to change the default port number of Grails server
1) when you do run-app,add command -Dserver.port=9090.for example
>>grails -Dserver.port=9090 run-app
2) if you want to change the port to 9090 as default value,then Edit the file GRAILS_HOME/scripts/Init.groovy and change the phrase 8080 to another port number like 9090 .
A good IDE for develop dynamic language.
We decide to find a easy to use and free license IDE for our team.After a several of days,we found a good tools open komodo .It's support a lot of existing dynamic language.such as python,ruby,lisp and several of dynamic language such as django. etc....Also it's support customizable feature ,such as customize command,customize menu etc.. We'll use this IDE in our Sparrow application.
Sunday, March 9, 2008
The Controllers in Grails framework
So let's create our first controller for our Sparrow.let's assume we want a page to say hello for everyone who access our app.The requirement is simple,it's just print a "hello world "(Yes,always hello world).It's easy to do this in Grails.We need a controllers,type following command:
>>cd sparrow
>>grails create-controller
Grails will ask you what's controller name.pls type hello
After a minute,Grails will create a HelloController.groovy in path /sparrow/grails-app/controllers/
then open it and find the index method.Note every methods in this groovy file are action .the index method is the default behavior when you navigate following url:http://127.0.0.1:8080/sparrow/hello/
We will modify this method like this :
def index = {
render "Hello World!"
}
When you navigate http://127.0.0.1:8080/sparrow/hello/
you'll see a page with "Hello World!" string.Note this file is a standard groovy file.index method is a default method as I said at above.the render also a keyword.We can assume it like Response object's write method in Java servelt.
If you want define other action in hello controller.just define a new method in the file HelloController.groovy.for example.I want to show a good bye information.Just add following method :
def saygoodbye={
render "Good Bye!"
}
then navigate to following url: http://127.0.0.1:8080/sparrow/hello/saygoodbye.
Note:in this url,
the http://127.0.0.1:8080/ is domain and port.
the saprrow is context path.
the hello is controler name.
the saygoodbye is action name.
In future section we'll discuss it detail.
My friend get a new job
In the end, I wish she have a good luck beginning.God bless her.
Getting start with Grails for our Sparrow app
As you can see,our app's name is Sparrow,then how to create it,follow me.
open your command line.type
>>make dir learnapp
>>cd learnapp
>>grails create-app
after this,grails will ask your what's name your project.we'll tyep
>>sparrow
then grails will generate all of you need to start an application.Note,Grails is a role framework.so you will see somes like domain,controllors,tlb folder etc.in the future,we'll create relative file to fit our application.for now,we only need a blamk frame,but it's a runable application.we'll start our first grails app.type following command:
>>cd sparrow
>>grails run-app
You will see some run time information in console.then open your favorite browser then type:
http://127.0.0.1:8080/sparrow/
you will see a welcom page like this:
Grails used Jetty as its default servlet container.In the future,may be you want to move it to other containers such as tomcat .or some appservers such as JBoss.You can just type grails war .Grails will generate a war file for you,then you can make your own deployment in others environment.
Now.through only a few commmand you create a runable application.It's really cool.In the following section,we'll discuss how to add our first domain model project.we'll add some useful feature for our application and introduce what grails's domain model is as same time.
Grails Command-Line Help
>grails
help:
Usage: grails [target]
Targets:
"create-app" - Create a new grails app
"create-controller" - Create a new controller
"create-service" - Create a new service
"create-domain-class" - Create a new domain class
"create-taglib" - Create a new tag library class
"create-test-suite" - Create a new test suite
"create-job" - Create a quartz scheduled job
"generate-controller" - Generates a controller from a domain class
"generate-views" - Generates the views from a domain class
"generate-all" - Generates all artifacts from a domain class
"test-app" - Run current app's unit tests
"run-app" - Run the application locally and wait
"create-webtest" - Create the functional test layout
"run-webtest" - Run the functional tests for a running app
"shell" - Opens the Grails interactive command line shell
"console" - Opens the Grails interactive swing console
"war" - Create a deployable Web Application Archive (WAR)
While you run these command.you will note at this point that Grails uses the Apache Ant.
Domain model for Sparrow
Today we create the domain model for Sparrow system.For now,it's only a draft version.
Also you can find the soure file from here
Start new project Sparrow
Friday, March 7, 2008
Lock step iteration in Python
>>a=(1,2,3)
>>b=(4,5,6)
>>for i in map(None,a,b): print i
The result is :
(1, 4)
(2, 5)
(3, 6)
Wow.It's cool ,right.now assume the length of each list is different.for example,we set them like this
>>a=(1,2,3)
>>b=(4,5,6,7,8)
The result is:
(1, 4)
(2, 5)
(3, 6)
(None, 7)
(None, 8)
As you can see,now we have two extra small list with the element None.Yes,Python auto append a None type in last list,because it is the first parameter in the map function.Until now,it looks good ,right ?we only write one line code ,then map function do two times loop.But it's not elegant.because :
- It is non-obvious to programmers without a functional
programming background.
- The use of the magic `None' first argument is non-obvious.
- It has arbitrary, often unintended, and inflexible semantics
when the lists are not of the same length: the shorter sequences
are padded with `None'.
Fortunately,we have another function,zip.yes it's good to use.let me give a example:
>>a=(1,2,3)
>>b=(4,5,6,7,8)
>>zip(a,b)
The result is:
(1, 4)
(2, 5)
(3, 6)
Yes,as you can see,no other two redundant list.it's more clearly.of course,if you think that
other twos is useful,you can also use the map function.But now we have another choose.