SlideShare a Scribd company logo
1 of 66
By: Saurabh Dixit
 Grails is a full stack framework and attempts
to solve as many pieces of the web
development puzzle through the core
technology and its associated plugins.
 Need not to worry about XML configuration
files
 Creating controller classes:
 Creating Services:
 Command Objects in grails:
 In Grails, command objects are like domain
classes, but don’t persist data.
 They are very useful when you need to
group request parameters in a single object.
 First thing you‘ll need to do is describe your
command object. It is fine to do in the same
file that contains controller that will use it.
 If command will be used by more than one
controller, describe it in controllers or in
groovy source directory.
 DeclaringCommand Objects:
▪ Command object classes are defined just like any other class.
@Validateable
class PasswordChangeCommand {
String username
String actualPassword
String newPassword
String repNewPassword
static constraints = {
newPassword(nullable: false, blank: false)
repNewPassword(nullable: false, blank: false, validator: {String
repNewPassword, obj ->
String newPassword = obj.properties['newPassword']
if( !(newPassword == repNewPassword) ) {
return 'PasswordChangeCommand.newPasswordMismatch' //key of the i18 message
} else {
return true
}
})
}
}
def checkRegisterCommand = { PasswordChangeCommand
command->
if ( command.validate() ) {
println("Command validated")
redirect action: 'index'
}
else {
println("Command validation failed")
flash.message = command.errors.allErrors.collect { error ->
error.field
}.join(", ")
redirect action: 'index'
}
}
<g:form action="checkRegisterCommand">
username: <g:textField name="username"/>
actualPassword: <g:textField name="actualPassword"/>
newPassword: <g:textField name="newPassword"/>
repNewPassword: <g:textField name="repNewPassword"/>
<g:submitButton name="checkRegisterCommand" />
</g:form>
 As this example shows, since the command
object class is marked withValidateable you
can define constraints in command objects
just like in domain classes.
 Another way to make a command object
class validateable is to define it in the same
source file as the controller which is using the
class as a command object.
 If a command object class is not defined in
the same source file as a controller which
uses the class as a command object and the
class is not marked withValidateable, the
class will not be made validateable.
 It is not required that command object
classes be validateable.
 Command objects can participate in dependency
injection.This is useful if your command object has some
custom validation logic which uses a Grails service:
@grails.validation.Validateable
class LoginCommand {
def loginService
String username
String password
static constraints = {
username validator: { val, obj ->
obj.loginService.canLogin(obj.username, obj.password)
}
}
}
 Sharing Constraints Between Classes:
 A common pattern in Grails is to use command
objects for validating user-submitted data and
then copy the properties of the command object
to the relevant domain classes.
 This often means that your command objects and
domain classes share properties and their
constraints.
 You could manually copy and paste the
constraints between the two, but that's a very
error-prone approach. Instead, make use of Grails'
global constraints and import mechanism.
 Global Constraints:
 In addition to defining constraints in domain
classes, command objects and other validateable
classes, you can also define them in grails-
app/conf/Config.groovy:
grails.gorm.default.constraints = {
'*'(nullable: true, size: 1..20)
myShared(nullable: false, blank: false)
}
 These constraints are not attached to any particular
classes, but they can be easily referenced from any
validateable class:
class User {
...
static constraints = {
login shared: "myShared"
}
}
 Note:
▪ the use of the shared argument, whose value is the name of one of the constraints
defined in grails.gorm.default.constraints.
▪ Despite the name of the configuration setting, you can reference these shared
constraints from any validateable class, such as command objects. The '*' constraint
is a special case: it means that the associated constraints ('nullable' and 'size' in the
above example) will be applied to all properties in all validateable classes. These
defaults can be overridden by the constraints declared in a validateable class.
 Importing Constraints:
 Grails 2 introduced an alternative approach to
sharing constraints that allows you to import a set
of constraints from one class into another.
 Let's say you have a domain class like so:
class User {
String firstName
String lastName
String passwordHash
static constraints = {
firstName blank: false, nullable: false
lastName blank: false, nullable: false
passwordHash blank: false, nullable: false
}
}
 You then want to create a command object,
UserCommand, that shares some of the
properties of the domain class and the
corresponding constraints.You can do this
with the importFrom() method:
class UserCommand {
String firstName
String lastName
String password
String confirmPassword
static constraints = {
importFrom User
password blank: false, nullable: false
confirmPassword blank: false, nullable: false
}
}
 This will import all the constraints from the User
domain class and apply them to UserCommand.
 The import will ignore any constraints in the source
class (User) that don't have corresponding properties
in the importing class (UserCommand).
 In the above example, only the 'firstName'
and 'lastName' constraints will be imported
into UserCommand because those are the
only properties shared by the two classes.
 If you want more control over which
constraints are imported, use the include and
exclude arguments.
 So for example, if you only wanted to import
the 'lastName' constraint you would use:
…
static constraints = {
importFrom User, include: ["lastName"]
…
}
 or if you wanted all constraints that ended with
'Name':
…
static constraints = {
importFrom User, include: [/.*Name/]
…
}
 Exploring scopes:
 You’ve seen how controller actions can return a
map that gets passed through to the view, and
you’ve seen the flash object also passing data
from controller to view.
 This passing of information, and the lifetime of
the variables that you pass, is known as variable
scope.
 Grails supports different scopes to store
information in, and each of them lasts a
different length of time.When you passed data
in a map from a controller to a view,
you were implicitly making use of request scope.
 But Grails lets you reference the different scopes
explicitly so you can store data for as long as you
need it.
 In particular, Grails offers you four special
map-like storage scopes that you can
reference by name in every controller action.
 Grails supports four storage contexts for
passing content between controllers and
forms Scope variable Survival time for entries
in this scope:
 request: Survive until the target GSP finishes
rendering flash: Survive to the next page, and
the one after that
 session: Survive until the current user closes
the browser
 servletContext: Survive until the application
is restarted (this map is shared by all users)
 REQUEST SCOPE:
▪ Request scope is great when you want to store data that is
shared only between your controller and the view (normally a
GSP page).
 FLASH SCOPE: Basically single redirect
▪ Entries in the flash map survive one (and only one) redirect,
after which they’re removed.
 SESSION SCOPE:
▪ The next longest lived scope is session scope. Objects that
you place in session scope remain until the user closes their
browser.
▪ Internally, servers use a session cookie called JSESSIONID to
map a user to their session, and the cookie expires when they
close their browser (or when the server times out the session
due to inactivity).
 Session gotchas:the mystery of the
detached object
 If you’re storing a domain object in the session
(such as the logged-in User object), the object will
become detached from your Hibernate session.
That means you won’t be able to access any
uninitialized lazy-loaded relationships the object
holds.
 For example, you won’t be able to call
session.user.following.each {}.
 To reattach the object (so you can walk its
object graph of relationships, for instance),
 use the attach() method that is available on
all domain classes.
 For our User example, it would look like this:
def user = session.user
if (!user.isAttached()) {
user.attach()
}
user.following.each { nextFollowing -> /* do stuff */ }
 SERVLETCONTEXT (APPLICATION) SCOPE:
 The final scope available is servletContext scope,
sometimes called application scope.
 This map is shared across your whole application, and
it’s handy for storing state that’s not dependent on
any particular user (such as the number of logins since
the application was started).
 Throughout the documentation so far the
convention used for URLs has been the
default of /controller/action/id.
 However, this convention is not hard wired
into Grails and is in fact controlled by a URL
Mappings class located at grailsapp/
conf/UrlMappings.groovy.
 The UrlMappings class contains a single
property called mappings that has been
assigned a block of code:
class UrlMappings {
static mappings = {
}
}
 Mapping to Controllers and Actions:
To create a simple mapping simply use a
relative URL as the method name and specify
named parameters for the controller and
action to map to:
"/product"(controller: "product", action: "list")
 In this case we've mapped the URL /product to
the list action of the ProductController. Omit the
action definition to map to the default action of
the controller:
"/product"(controller: "product")
 An alternative syntax is to assign the controller
and action to use within a block passed to the
method:
"/product" {
controller = "product"
action = "list"
}
 Which syntax you use is largely dependent on
personal preference.
 To rewrite one URI onto another explicit URI
(rather than a controller/action pair) do
something like this:
"/hello"(uri: "/hello.dispatch")
 Rewriting specific URIs is often useful when
integrating with other frameworks.
 SimpleVariables
 The previous section demonstrated how to map
simple URLs with concrete "tokens".
 In URL mapping speak tokens are the sequence of
characters between each slash, '/'.
 A concrete token is one which is well defined such
as as /product. However, in many circumstances
you don't know what the value of a particular
token will be until runtime.
 In this case you can use variable placeholders
within the URL for example:
static mappings = {
"/product/$id"(controller: "product")
}
 In this case by embedding a $id variable as
the second token Grails will automatically
map the second token into a parameter
(available via the params object) called id.
 For example given the URL /product/MacBook,
the following code will render "MacBook" to the
response:
class ProductController {
def index() { render params.id }
}
 In this case by embedding a $id variable as the
second token Grails will automatically map the
second token into a parameter (available via the
params object) called id.
 For example given the URL
/product/MacBook,
the following code will render "MacBook" to
the response:
class ProductController {
def index() { render params.id }
}
 You can of course construct more complexexamples
of mappings.
 For example the traditional blog URL format could
be mapped as follows:
static mappings = {
"/$blog/$year/$month/$day/$id"(controller: "blog", action: "show")
}
 The above mapping would let you do things like:
/graemerocher/2007/01/10/my_funky_blog_entry
 The individual tokens in the URL would again be
mapped into the params object with values
available for year, month, day, id and so on.
 OptionalVariables:
 Another characteristic of the default mapping is
the ability to append a ? at the end of a variable to
make it an optional token.
 In a further example this technique could be
applied to the blog URL mapping to have more
flexible linking:
static mappings = {
"/$blog/$year?/$month?/$day?/$id?"(controller:"blog",
action:"show")
}
 With this mapping all of these URLs would
match with only the relevant parameters
being populated in the params object:
/graemerocher/2007/01/10/my_funky_blog_entry
/graemerocher/2007/01/10
/graemerocher/2007/01
/graemerocher/2007
/graemerocher
 ArbitraryVariables:
You can also pass arbitrary parameters from the URL mapping
into the controller by just setting
them in the block passed to the mapping:
"/holiday/win" {
id = "Marrakech"
year = 2007
}
 This variables will be available within the
params object passed to the controller.
 You can resolve a URL to a view without a
controller or action involved.
For example to map the root URL / to a GSP
at the location grails-app/views/index.gsp
you could use:
static mappings = {
"/"(view: "/index") // map the root URL
}
 Alternatively if you need a view that is
specific to a given controller you could use:
static mappings = {
"/help"(controller: "site", view: "help") // to a view for a
controller
}
 Grails also lets you map HTTP response codes
to controllers, actions or views. Just use a
method name that matches the response
code you are interested in:
static mappings = {
"403"(controller: "errors", action: "forbidden")
"404"(controller: "errors", action: "notFound")
"500"(controller: "errors", action: "serverError")
}
 Or you can specify custom error pages:
static mappings = {
"403"(view: "/errors/forbidden")
"404"(view: "/errors/notFound")
"500"(view: "/errors/serverError")
}
 Declarative Error Handling:
 In addition you can configure handlers for individual
exceptions:
static mappings = {
"403"(view: "/errors/forbidden")
"404"(view: "/errors/notFound")
"500"(controller: "errors", action: "illegalArgument",
exception: IllegalArgumentException)
"500"(controller: "errors", action: "nullPointer",
exception: NullPointerException)
"500"(controller: "errors", action: "customException",
exception: MyException)
"500"(view: "/errors/serverError")
}
 With this configuration, an
IllegalArgumentException will be handled by the
illegalArgument action in ErrorsController,
 a NullPointerException will be handled by the
nullPointer action, and a MyException will be
handled by the customException action.
 Other exceptions will be handled by the catch-all
rule and use the
/errors/serverError view.
 You can access the exception from your custom error
handing view or controller action using the request's
exception attribute like so:
class ErrorController {
def handleError() {
def exception = request.exception
// perform desired processing to handle the exception
}
}
 If your error-handling controller action throws an
exception as well, you'll end up with a
StackOverflowException.
 Grails' URL mappings mechanism also supports
wildcard mappings. For example consider the
following mapping:
static mappings = {
"/images/*.jpg"(controller: "image")
}
 This mapping will match all paths to images
such as /image/logo.jpg.
 Of course you can achieve the same effect with a
variable:
static mappings = {
"/images/$name.jpg"(controller: "image")
}
 However, you can also use double wildcards
to match more than one level below:
static mappings = {
"/images/**.jpg"(controller: "image")
}
 In this cases the mapping will match
/image/logo.jpg as well as
/image/other/logo.jpg.
 Even better you can use a double wildcard
variable:
static mappings = {
// will match /image/logo.jpg and /image/other/logo.jpg
"/images/$name**.jpg"(controller: "image")
}
 In this case it will store the path matched by
the wildcard inside a name parameter
obtainable from the params object:
def name = params.name
println name // prints "logo" or "other/logo"
 URL Mappings also support named mappings, that is
mappings which have a name associated with them.
 The name may be used to refer to a specific mapping
when links are generated.
 The syntax for defining a named mapping is as
follows:
static mappings = {
name <mapping name>: <url pattern> {
// …
}
}
 For example:
static mappings = {
name personList: "/showPeople" {
controller = 'person'
action = 'list'
}
name accountDetails: "/details/$acctNumber" {
controller = 'product'
action = 'accountDetails'
}
}
 The mapping may be referenced in a link tag in a
GSP.
<g:link mapping="personList">List People</g:link>
 That would result in:
<a href="/showPeople">List People</a>
 Parameters may be specified using the params
attribute.
<g:link mapping="accountDetails“params="[acctNumber:'8675309']">
Show Account
</g:link>
 That would result in:
<a href="/details/8675309">ShowAccount</a>
 Alternatively you may reference a named
mapping using the link namespace.
<link:personList>List People</link:personList>
 That would result in:
<a href="/showPeople">List People</a>
 The link namespace approach allows
parameters to be specified as attributes.
<link:accountDetails acctNumber="8675309">Show Account</link:accountDetails>
 That would result in:
<a href="/details/8675309">ShowAccount</a>
 To specify attributes that should be applied to
the generated href, specify a Map value to
the attrs attribute.
 These attributes will be applied directly to the
href, not passed through to be used as
request parameters.
<link:accountDetails attrs="[class: 'fancy']" acctNumber="8675309">
ShowAccount
</link:accountDetails>
 That would result in:
<a href="/details/8675309" class="fancy">ShowAccount</a>
 Customizing URL Formats:
 The default URL Mapping mechanism supports
camel case names in the URLs.The default URL
for accessing an action named addNumbers in a
controller named MathHelperController would be
something like /mathHelper/addNumbers.
 Grails allows for the customization of this pattern
and provides an implementation which replaces
the camel case convention with a hyphenated
convention that would support URLs like /math-
helper/add-numbers.
 To enable hyphenated URLs assign a value of
"hyphenated" to the grails.web.url.converter
property in grails-app/conf/Config.groovy.
// grails-app/conf/Config.groovy
grails.web.url.converter = 'hyphenated'
 Namespaced Controllers:
 An application is not allowed to define multiple
controllers with the same name, even if they are
defined in separate packages.
 For example an application may not contain
com.accounting.ReportingController and
com.humanresources.ReportingController.
 However it is allowed for an application to use a
plugin which provides a controller with the same
name as a controller provided by the application
as long as the controllers are in separate
packages.
 For example, an application may include a
controller named
com.accounting.ReportingController
 and the application may use a plugin which
provides a controller named
com.humanresources.ReportingController.
 The only issue with that is the URL mapping for
the controller provided by the plugin needs to be
explicit in specifying that the mapping applies to
the ReportingController which is provided by the
plugin.
static mappings = {
"/accountingReports" {
controller = "reporting"
}
"/humanResourceReports" {
controller = "reporting"
plugin = "humanResources"
}
}
 With that mapping in place, a request to
/accountingReports will be handled by the
ReportingController which is defined in the
application.
 A request to /humanResourceReports will be
handled by the ReportingController which is
provided by the humanResources plugin
 There could be any number of
ReportingController controllers provided by
any number of plugins but no plugin may
provide more than one ReportingController
even if they are defined in separate packages.
 Assigning a value to the plugin variable in the
mapping is only required if there are multiple
controllers with the same name available at
runtime provided by the application and/or
plugins.
 If the humanResources plugin provides a
ReportingController and there is no other
ReportingController available at runtime, the
following mapping would work.
static mappings = {
"/humanResourceReports" {
controller = "reporting"
}
Grails basics

More Related Content

What's hot

React, Redux, ES2015 by Max Petruck
React, Redux, ES2015   by Max PetruckReact, Redux, ES2015   by Max Petruck
React, Redux, ES2015 by Max PetruckMaksym Petruk
 
Introduction to React JS for beginners
Introduction to React JS for beginners Introduction to React JS for beginners
Introduction to React JS for beginners Varun Raj
 
Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at...
 Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at... Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at...
Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at...Big Data Spain
 
Executing Sql Commands
Executing Sql CommandsExecuting Sql Commands
Executing Sql Commandsleminhvuong
 
Database connect
Database connectDatabase connect
Database connectYoga Raja
 
Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...
Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...
Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...Codemotion
 
React Lifecycle and Reconciliation
React Lifecycle and ReconciliationReact Lifecycle and Reconciliation
React Lifecycle and ReconciliationZhihao Li
 
React Native: JS MVC Meetup #15
React Native: JS MVC Meetup #15React Native: JS MVC Meetup #15
React Native: JS MVC Meetup #15Rob Gietema
 
CS101- Introduction to Computing- Lecture 32
CS101- Introduction to Computing- Lecture 32CS101- Introduction to Computing- Lecture 32
CS101- Introduction to Computing- Lecture 32Bilal Ahmed
 
Java Servlet
Java ServletJava Servlet
Java ServletYoga Raja
 
Java rmi example program with code
Java rmi example program with codeJava rmi example program with code
Java rmi example program with codekamal kotecha
 
ASP.NET Session 11 12
ASP.NET Session 11 12ASP.NET Session 11 12
ASP.NET Session 11 12Sisir Ghosh
 
Redux training
Redux trainingRedux training
Redux trainingdasersoft
 
Chain of Responsibility Pattern
Chain of Responsibility PatternChain of Responsibility Pattern
Chain of Responsibility PatternHüseyin Ergin
 
Workshop 20: ReactJS Part II Flux Pattern & Redux
Workshop 20: ReactJS Part II Flux Pattern & ReduxWorkshop 20: ReactJS Part II Flux Pattern & Redux
Workshop 20: ReactJS Part II Flux Pattern & ReduxVisual Engineering
 
React Development with the MERN Stack
React Development with the MERN StackReact Development with the MERN Stack
React Development with the MERN StackTroy Miles
 
GraniteDS 360|Flex DC
GraniteDS 360|Flex DCGraniteDS 360|Flex DC
GraniteDS 360|Flex DCwdrai
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJSAbul Hasan
 

What's hot (20)

React, Redux, ES2015 by Max Petruck
React, Redux, ES2015   by Max PetruckReact, Redux, ES2015   by Max Petruck
React, Redux, ES2015 by Max Petruck
 
Introduction to React JS for beginners
Introduction to React JS for beginners Introduction to React JS for beginners
Introduction to React JS for beginners
 
Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at...
 Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at... Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at...
Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at...
 
Executing Sql Commands
Executing Sql CommandsExecuting Sql Commands
Executing Sql Commands
 
Database connect
Database connectDatabase connect
Database connect
 
Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...
Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...
Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...
 
React Lifecycle and Reconciliation
React Lifecycle and ReconciliationReact Lifecycle and Reconciliation
React Lifecycle and Reconciliation
 
React Native: JS MVC Meetup #15
React Native: JS MVC Meetup #15React Native: JS MVC Meetup #15
React Native: JS MVC Meetup #15
 
CS101- Introduction to Computing- Lecture 32
CS101- Introduction to Computing- Lecture 32CS101- Introduction to Computing- Lecture 32
CS101- Introduction to Computing- Lecture 32
 
Java Servlet
Java ServletJava Servlet
Java Servlet
 
Java rmi example program with code
Java rmi example program with codeJava rmi example program with code
Java rmi example program with code
 
ASP.NET Session 11 12
ASP.NET Session 11 12ASP.NET Session 11 12
ASP.NET Session 11 12
 
Solid scala
Solid scalaSolid scala
Solid scala
 
Redux training
Redux trainingRedux training
Redux training
 
Chain of Responsibility Pattern
Chain of Responsibility PatternChain of Responsibility Pattern
Chain of Responsibility Pattern
 
Workshop 20: ReactJS Part II Flux Pattern & Redux
Workshop 20: ReactJS Part II Flux Pattern & ReduxWorkshop 20: ReactJS Part II Flux Pattern & Redux
Workshop 20: ReactJS Part II Flux Pattern & Redux
 
React Development with the MERN Stack
React Development with the MERN StackReact Development with the MERN Stack
React Development with the MERN Stack
 
GraniteDS 360|Flex DC
GraniteDS 360|Flex DCGraniteDS 360|Flex DC
GraniteDS 360|Flex DC
 
Java jdbc
Java jdbcJava jdbc
Java jdbc
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJS
 

Similar to Grails basics

intoduction to Grails Framework
intoduction to Grails Frameworkintoduction to Grails Framework
intoduction to Grails FrameworkHarshdeep Kaur
 
4 pillars of OOPS CONCEPT
4 pillars of OOPS CONCEPT4 pillars of OOPS CONCEPT
4 pillars of OOPS CONCEPTAjay Chimmani
 
My 70-480 HTML5 certification learning
My 70-480 HTML5 certification learningMy 70-480 HTML5 certification learning
My 70-480 HTML5 certification learningSyed Irtaza Ali
 
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
Grails 0.3-SNAPSHOT Presentation WJAX 2006 EnglishGrails 0.3-SNAPSHOT Presentation WJAX 2006 English
Grails 0.3-SNAPSHOT Presentation WJAX 2006 EnglishSven Haiges
 
GR8Conf 2011: Adopting Grails
GR8Conf 2011: Adopting GrailsGR8Conf 2011: Adopting Grails
GR8Conf 2011: Adopting GrailsGR8Conf
 
Adopting Grails - GR8Conf Europe
Adopting Grails - GR8Conf EuropeAdopting Grails - GR8Conf Europe
Adopting Grails - GR8Conf EuropeKlausBaumecker
 
Cocoa and MVC in ios, iOS Training Ahmedbad , iOS classes Ahmedabad
Cocoa and MVC in ios, iOS Training Ahmedbad , iOS classes Ahmedabad Cocoa and MVC in ios, iOS Training Ahmedbad , iOS classes Ahmedabad
Cocoa and MVC in ios, iOS Training Ahmedbad , iOS classes Ahmedabad NicheTech Com. Solutions Pvt. Ltd.
 
Deploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPCDeploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPCGR8Conf
 
Horizontal scaling with Galaxy
Horizontal scaling with GalaxyHorizontal scaling with Galaxy
Horizontal scaling with GalaxyEnis Afgan
 
MCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISP
MCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISPMCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISP
MCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISPAli Shah
 
systemverilog-interview-questions.docx
systemverilog-interview-questions.docxsystemverilog-interview-questions.docx
systemverilog-interview-questions.docxssuser1c8ca21
 
ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010
ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010
ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010vchircu
 

Similar to Grails basics (20)

Introduction To Grails
Introduction To GrailsIntroduction To Grails
Introduction To Grails
 
Grails basics part2
Grails basics  part2Grails basics  part2
Grails basics part2
 
intoduction to Grails Framework
intoduction to Grails Frameworkintoduction to Grails Framework
intoduction to Grails Framework
 
4 pillars of OOPS CONCEPT
4 pillars of OOPS CONCEPT4 pillars of OOPS CONCEPT
4 pillars of OOPS CONCEPT
 
Adobe Flex4
Adobe Flex4 Adobe Flex4
Adobe Flex4
 
My 70-480 HTML5 certification learning
My 70-480 HTML5 certification learningMy 70-480 HTML5 certification learning
My 70-480 HTML5 certification learning
 
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
Grails 0.3-SNAPSHOT Presentation WJAX 2006 EnglishGrails 0.3-SNAPSHOT Presentation WJAX 2006 English
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
 
G pars
G parsG pars
G pars
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
 
Grails Controllers
Grails ControllersGrails Controllers
Grails Controllers
 
GR8Conf 2011: Adopting Grails
GR8Conf 2011: Adopting GrailsGR8Conf 2011: Adopting Grails
GR8Conf 2011: Adopting Grails
 
Adopting Grails - GR8Conf Europe
Adopting Grails - GR8Conf EuropeAdopting Grails - GR8Conf Europe
Adopting Grails - GR8Conf Europe
 
Controller
ControllerController
Controller
 
Cocoa and MVC in ios, iOS Training Ahmedbad , iOS classes Ahmedabad
Cocoa and MVC in ios, iOS Training Ahmedbad , iOS classes Ahmedabad Cocoa and MVC in ios, iOS Training Ahmedbad , iOS classes Ahmedabad
Cocoa and MVC in ios, iOS Training Ahmedbad , iOS classes Ahmedabad
 
Grails Advanced
Grails Advanced Grails Advanced
Grails Advanced
 
Deploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPCDeploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPC
 
Horizontal scaling with Galaxy
Horizontal scaling with GalaxyHorizontal scaling with Galaxy
Horizontal scaling with Galaxy
 
MCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISP
MCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISPMCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISP
MCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISP
 
systemverilog-interview-questions.docx
systemverilog-interview-questions.docxsystemverilog-interview-questions.docx
systemverilog-interview-questions.docx
 
ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010
ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010
ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010
 

Recently uploaded

Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 

Recently uploaded (20)

Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 

Grails basics

  • 2.  Grails is a full stack framework and attempts to solve as many pieces of the web development puzzle through the core technology and its associated plugins.  Need not to worry about XML configuration files
  • 5.  Command Objects in grails:  In Grails, command objects are like domain classes, but don’t persist data.  They are very useful when you need to group request parameters in a single object.
  • 6.  First thing you‘ll need to do is describe your command object. It is fine to do in the same file that contains controller that will use it.  If command will be used by more than one controller, describe it in controllers or in groovy source directory.
  • 7.  DeclaringCommand Objects: ▪ Command object classes are defined just like any other class. @Validateable class PasswordChangeCommand { String username String actualPassword String newPassword String repNewPassword static constraints = { newPassword(nullable: false, blank: false) repNewPassword(nullable: false, blank: false, validator: {String repNewPassword, obj -> String newPassword = obj.properties['newPassword'] if( !(newPassword == repNewPassword) ) { return 'PasswordChangeCommand.newPasswordMismatch' //key of the i18 message } else { return true } }) } }
  • 8. def checkRegisterCommand = { PasswordChangeCommand command-> if ( command.validate() ) { println("Command validated") redirect action: 'index' } else { println("Command validation failed") flash.message = command.errors.allErrors.collect { error -> error.field }.join(", ") redirect action: 'index' } }
  • 9. <g:form action="checkRegisterCommand"> username: <g:textField name="username"/> actualPassword: <g:textField name="actualPassword"/> newPassword: <g:textField name="newPassword"/> repNewPassword: <g:textField name="repNewPassword"/> <g:submitButton name="checkRegisterCommand" /> </g:form>
  • 10.  As this example shows, since the command object class is marked withValidateable you can define constraints in command objects just like in domain classes.  Another way to make a command object class validateable is to define it in the same source file as the controller which is using the class as a command object.
  • 11.  If a command object class is not defined in the same source file as a controller which uses the class as a command object and the class is not marked withValidateable, the class will not be made validateable.  It is not required that command object classes be validateable.
  • 12.  Command objects can participate in dependency injection.This is useful if your command object has some custom validation logic which uses a Grails service: @grails.validation.Validateable class LoginCommand { def loginService String username String password static constraints = { username validator: { val, obj -> obj.loginService.canLogin(obj.username, obj.password) } } }
  • 13.  Sharing Constraints Between Classes:  A common pattern in Grails is to use command objects for validating user-submitted data and then copy the properties of the command object to the relevant domain classes.  This often means that your command objects and domain classes share properties and their constraints.  You could manually copy and paste the constraints between the two, but that's a very error-prone approach. Instead, make use of Grails' global constraints and import mechanism.
  • 14.  Global Constraints:  In addition to defining constraints in domain classes, command objects and other validateable classes, you can also define them in grails- app/conf/Config.groovy: grails.gorm.default.constraints = { '*'(nullable: true, size: 1..20) myShared(nullable: false, blank: false) }
  • 15.  These constraints are not attached to any particular classes, but they can be easily referenced from any validateable class: class User { ... static constraints = { login shared: "myShared" } }  Note: ▪ the use of the shared argument, whose value is the name of one of the constraints defined in grails.gorm.default.constraints. ▪ Despite the name of the configuration setting, you can reference these shared constraints from any validateable class, such as command objects. The '*' constraint is a special case: it means that the associated constraints ('nullable' and 'size' in the above example) will be applied to all properties in all validateable classes. These defaults can be overridden by the constraints declared in a validateable class.
  • 16.  Importing Constraints:  Grails 2 introduced an alternative approach to sharing constraints that allows you to import a set of constraints from one class into another.  Let's say you have a domain class like so: class User { String firstName String lastName String passwordHash static constraints = { firstName blank: false, nullable: false lastName blank: false, nullable: false passwordHash blank: false, nullable: false } }
  • 17.  You then want to create a command object, UserCommand, that shares some of the properties of the domain class and the corresponding constraints.You can do this with the importFrom() method:
  • 18. class UserCommand { String firstName String lastName String password String confirmPassword static constraints = { importFrom User password blank: false, nullable: false confirmPassword blank: false, nullable: false } }  This will import all the constraints from the User domain class and apply them to UserCommand.  The import will ignore any constraints in the source class (User) that don't have corresponding properties in the importing class (UserCommand).
  • 19.  In the above example, only the 'firstName' and 'lastName' constraints will be imported into UserCommand because those are the only properties shared by the two classes.  If you want more control over which constraints are imported, use the include and exclude arguments.
  • 20.  So for example, if you only wanted to import the 'lastName' constraint you would use: … static constraints = { importFrom User, include: ["lastName"] … }  or if you wanted all constraints that ended with 'Name': … static constraints = { importFrom User, include: [/.*Name/] … }
  • 21.  Exploring scopes:  You’ve seen how controller actions can return a map that gets passed through to the view, and you’ve seen the flash object also passing data from controller to view.  This passing of information, and the lifetime of the variables that you pass, is known as variable scope.
  • 22.  Grails supports different scopes to store information in, and each of them lasts a different length of time.When you passed data in a map from a controller to a view, you were implicitly making use of request scope.  But Grails lets you reference the different scopes explicitly so you can store data for as long as you need it.
  • 23.  In particular, Grails offers you four special map-like storage scopes that you can reference by name in every controller action.  Grails supports four storage contexts for passing content between controllers and forms Scope variable Survival time for entries in this scope:
  • 24.  request: Survive until the target GSP finishes rendering flash: Survive to the next page, and the one after that  session: Survive until the current user closes the browser  servletContext: Survive until the application is restarted (this map is shared by all users)
  • 25.  REQUEST SCOPE: ▪ Request scope is great when you want to store data that is shared only between your controller and the view (normally a GSP page).  FLASH SCOPE: Basically single redirect ▪ Entries in the flash map survive one (and only one) redirect, after which they’re removed.  SESSION SCOPE: ▪ The next longest lived scope is session scope. Objects that you place in session scope remain until the user closes their browser. ▪ Internally, servers use a session cookie called JSESSIONID to map a user to their session, and the cookie expires when they close their browser (or when the server times out the session due to inactivity).
  • 26.  Session gotchas:the mystery of the detached object  If you’re storing a domain object in the session (such as the logged-in User object), the object will become detached from your Hibernate session. That means you won’t be able to access any uninitialized lazy-loaded relationships the object holds.
  • 27.  For example, you won’t be able to call session.user.following.each {}.  To reattach the object (so you can walk its object graph of relationships, for instance),  use the attach() method that is available on all domain classes.
  • 28.  For our User example, it would look like this: def user = session.user if (!user.isAttached()) { user.attach() } user.following.each { nextFollowing -> /* do stuff */ }  SERVLETCONTEXT (APPLICATION) SCOPE:  The final scope available is servletContext scope, sometimes called application scope.  This map is shared across your whole application, and it’s handy for storing state that’s not dependent on any particular user (such as the number of logins since the application was started).
  • 29.  Throughout the documentation so far the convention used for URLs has been the default of /controller/action/id.  However, this convention is not hard wired into Grails and is in fact controlled by a URL Mappings class located at grailsapp/ conf/UrlMappings.groovy.
  • 30.  The UrlMappings class contains a single property called mappings that has been assigned a block of code: class UrlMappings { static mappings = { } }
  • 31.  Mapping to Controllers and Actions: To create a simple mapping simply use a relative URL as the method name and specify named parameters for the controller and action to map to: "/product"(controller: "product", action: "list")
  • 32.  In this case we've mapped the URL /product to the list action of the ProductController. Omit the action definition to map to the default action of the controller: "/product"(controller: "product")  An alternative syntax is to assign the controller and action to use within a block passed to the method: "/product" { controller = "product" action = "list" }
  • 33.  Which syntax you use is largely dependent on personal preference.  To rewrite one URI onto another explicit URI (rather than a controller/action pair) do something like this: "/hello"(uri: "/hello.dispatch")  Rewriting specific URIs is often useful when integrating with other frameworks.
  • 34.  SimpleVariables  The previous section demonstrated how to map simple URLs with concrete "tokens".  In URL mapping speak tokens are the sequence of characters between each slash, '/'.  A concrete token is one which is well defined such as as /product. However, in many circumstances you don't know what the value of a particular token will be until runtime.
  • 35.  In this case you can use variable placeholders within the URL for example: static mappings = { "/product/$id"(controller: "product") }  In this case by embedding a $id variable as the second token Grails will automatically map the second token into a parameter (available via the params object) called id.
  • 36.  For example given the URL /product/MacBook, the following code will render "MacBook" to the response: class ProductController { def index() { render params.id } }  In this case by embedding a $id variable as the second token Grails will automatically map the second token into a parameter (available via the params object) called id.
  • 37.  For example given the URL /product/MacBook, the following code will render "MacBook" to the response: class ProductController { def index() { render params.id } }
  • 38.  You can of course construct more complexexamples of mappings.  For example the traditional blog URL format could be mapped as follows: static mappings = { "/$blog/$year/$month/$day/$id"(controller: "blog", action: "show") }  The above mapping would let you do things like: /graemerocher/2007/01/10/my_funky_blog_entry  The individual tokens in the URL would again be mapped into the params object with values available for year, month, day, id and so on.
  • 39.  OptionalVariables:  Another characteristic of the default mapping is the ability to append a ? at the end of a variable to make it an optional token.  In a further example this technique could be applied to the blog URL mapping to have more flexible linking: static mappings = { "/$blog/$year?/$month?/$day?/$id?"(controller:"blog", action:"show") }
  • 40.  With this mapping all of these URLs would match with only the relevant parameters being populated in the params object: /graemerocher/2007/01/10/my_funky_blog_entry /graemerocher/2007/01/10 /graemerocher/2007/01 /graemerocher/2007 /graemerocher
  • 41.  ArbitraryVariables: You can also pass arbitrary parameters from the URL mapping into the controller by just setting them in the block passed to the mapping: "/holiday/win" { id = "Marrakech" year = 2007 }  This variables will be available within the params object passed to the controller.
  • 42.  You can resolve a URL to a view without a controller or action involved. For example to map the root URL / to a GSP at the location grails-app/views/index.gsp you could use: static mappings = { "/"(view: "/index") // map the root URL }
  • 43.  Alternatively if you need a view that is specific to a given controller you could use: static mappings = { "/help"(controller: "site", view: "help") // to a view for a controller }
  • 44.  Grails also lets you map HTTP response codes to controllers, actions or views. Just use a method name that matches the response code you are interested in: static mappings = { "403"(controller: "errors", action: "forbidden") "404"(controller: "errors", action: "notFound") "500"(controller: "errors", action: "serverError") }
  • 45.  Or you can specify custom error pages: static mappings = { "403"(view: "/errors/forbidden") "404"(view: "/errors/notFound") "500"(view: "/errors/serverError") }
  • 46.  Declarative Error Handling:  In addition you can configure handlers for individual exceptions: static mappings = { "403"(view: "/errors/forbidden") "404"(view: "/errors/notFound") "500"(controller: "errors", action: "illegalArgument", exception: IllegalArgumentException) "500"(controller: "errors", action: "nullPointer", exception: NullPointerException) "500"(controller: "errors", action: "customException", exception: MyException) "500"(view: "/errors/serverError") }
  • 47.  With this configuration, an IllegalArgumentException will be handled by the illegalArgument action in ErrorsController,  a NullPointerException will be handled by the nullPointer action, and a MyException will be handled by the customException action.  Other exceptions will be handled by the catch-all rule and use the /errors/serverError view.
  • 48.  You can access the exception from your custom error handing view or controller action using the request's exception attribute like so: class ErrorController { def handleError() { def exception = request.exception // perform desired processing to handle the exception } }  If your error-handling controller action throws an exception as well, you'll end up with a StackOverflowException.
  • 49.  Grails' URL mappings mechanism also supports wildcard mappings. For example consider the following mapping: static mappings = { "/images/*.jpg"(controller: "image") }  This mapping will match all paths to images such as /image/logo.jpg.  Of course you can achieve the same effect with a variable: static mappings = { "/images/$name.jpg"(controller: "image") }
  • 50.  However, you can also use double wildcards to match more than one level below: static mappings = { "/images/**.jpg"(controller: "image") }  In this cases the mapping will match /image/logo.jpg as well as /image/other/logo.jpg.
  • 51.  Even better you can use a double wildcard variable: static mappings = { // will match /image/logo.jpg and /image/other/logo.jpg "/images/$name**.jpg"(controller: "image") }  In this case it will store the path matched by the wildcard inside a name parameter obtainable from the params object: def name = params.name println name // prints "logo" or "other/logo"
  • 52.  URL Mappings also support named mappings, that is mappings which have a name associated with them.  The name may be used to refer to a specific mapping when links are generated.  The syntax for defining a named mapping is as follows: static mappings = { name <mapping name>: <url pattern> { // … } }
  • 53.  For example: static mappings = { name personList: "/showPeople" { controller = 'person' action = 'list' } name accountDetails: "/details/$acctNumber" { controller = 'product' action = 'accountDetails' } }
  • 54.  The mapping may be referenced in a link tag in a GSP. <g:link mapping="personList">List People</g:link>  That would result in: <a href="/showPeople">List People</a>  Parameters may be specified using the params attribute. <g:link mapping="accountDetails“params="[acctNumber:'8675309']"> Show Account </g:link>
  • 55.  That would result in: <a href="/details/8675309">ShowAccount</a>  Alternatively you may reference a named mapping using the link namespace. <link:personList>List People</link:personList>  That would result in: <a href="/showPeople">List People</a>  The link namespace approach allows parameters to be specified as attributes. <link:accountDetails acctNumber="8675309">Show Account</link:accountDetails>
  • 56.  That would result in: <a href="/details/8675309">ShowAccount</a>  To specify attributes that should be applied to the generated href, specify a Map value to the attrs attribute.
  • 57.  These attributes will be applied directly to the href, not passed through to be used as request parameters. <link:accountDetails attrs="[class: 'fancy']" acctNumber="8675309"> ShowAccount </link:accountDetails>  That would result in: <a href="/details/8675309" class="fancy">ShowAccount</a>
  • 58.  Customizing URL Formats:  The default URL Mapping mechanism supports camel case names in the URLs.The default URL for accessing an action named addNumbers in a controller named MathHelperController would be something like /mathHelper/addNumbers.  Grails allows for the customization of this pattern and provides an implementation which replaces the camel case convention with a hyphenated convention that would support URLs like /math- helper/add-numbers.
  • 59.  To enable hyphenated URLs assign a value of "hyphenated" to the grails.web.url.converter property in grails-app/conf/Config.groovy. // grails-app/conf/Config.groovy grails.web.url.converter = 'hyphenated'
  • 60.  Namespaced Controllers:  An application is not allowed to define multiple controllers with the same name, even if they are defined in separate packages.  For example an application may not contain com.accounting.ReportingController and com.humanresources.ReportingController.
  • 61.  However it is allowed for an application to use a plugin which provides a controller with the same name as a controller provided by the application as long as the controllers are in separate packages.  For example, an application may include a controller named com.accounting.ReportingController  and the application may use a plugin which provides a controller named com.humanresources.ReportingController.
  • 62.  The only issue with that is the URL mapping for the controller provided by the plugin needs to be explicit in specifying that the mapping applies to the ReportingController which is provided by the plugin. static mappings = { "/accountingReports" { controller = "reporting" } "/humanResourceReports" { controller = "reporting" plugin = "humanResources" } }
  • 63.  With that mapping in place, a request to /accountingReports will be handled by the ReportingController which is defined in the application.  A request to /humanResourceReports will be handled by the ReportingController which is provided by the humanResources plugin
  • 64.  There could be any number of ReportingController controllers provided by any number of plugins but no plugin may provide more than one ReportingController even if they are defined in separate packages.  Assigning a value to the plugin variable in the mapping is only required if there are multiple controllers with the same name available at runtime provided by the application and/or plugins.
  • 65.  If the humanResources plugin provides a ReportingController and there is no other ReportingController available at runtime, the following mapping would work. static mappings = { "/humanResourceReports" { controller = "reporting" }