8.3.13 Namespaced Controllers
If an application defines multiple controllers with the same namein different packages, the controllers must be defined in anamespace. The way to define a namespace for a controller is todefine a static property named namespace
in the controller andassign a String to the property that represents the namespace.
grails-app/controllers/com/app/reporting/AdminController.groovy
package com.app.reporting
class AdminController {
static namespace = 'reports'
// ...
}
grails-app/controllers/com/app/security/AdminController.groovy
package com.app.security
class AdminController {
static namespace = 'users'
// ...
}
When defining url mappings which should be associated with a namespacedcontroller, the namespace
variable needs to be part of the URL mapping.
grails-app/controllers/UrlMappings.groovy
class UrlMappings {
static mappings = {
'/userAdmin' {
controller = 'admin'
namespace = 'users'
}
'/reportAdmin' {
controller = 'admin'
namespace = 'reports'
}
"/$namespace/$controller/$action?"()
}
}
Reverse URL mappings also require that the namespace
be specified.
<g:link controller="admin" namespace="reports">Click For Report Admin</g:link>
<g:link controller="admin" namespace="users">Click For User Admin</g:link>
When resolving a URL mapping (forward or reverse) to a namespaced controller,a mapping will only match if the namespace
has been provided. Ifthe application provides several controllers with the same name in differentpackages, at most 1 of them may be defined without a namespace
property. Ifthere are multiple controllers with the same name that do not define anamespace
property, the framework will not know how to distinguish betweenthem for forward or reverse mapping resolutions.
It is allowed for an application to use a plugin which provides a controllerwith the same name as a controller provided by the application and for neitherof the controllers to define a namespace
property as long as thecontrollers are in separate packages. For example, an applicationmay include a controller named com.accounting.ReportingController
and the application may use a plugin which provides a controllernamed com.humanresources.ReportingController
. The only issuewith that is the URL mapping for the controller provided by theplugin needs to be explicit in specifying that the mapping appliesto the ReportingController
which is provided by the plugin.
See the following example.
static mappings = {
"/accountingReports" {
controller = "reporting"
}
"/humanResourceReports" {
controller = "reporting"
plugin = "humanResources"
}
}
With that mapping in place, a request to /accountingReports
willbe handled by the ReportingController
which is defined in theapplication. A request to /humanResourceReports
will be handledby the ReportingController
which is provided by the humanResources
plugin.
There could be any number of ReportingController
controllers providedby any number of plugins but no plugin may provide more than oneReportingController
even if they are defined in separate packages.
Assigning a value to the plugin
variable in the mapping is onlyrequired if there are multiple controllers with the same nameavailable at runtime provided by the application and/or plugins.If the humanResources
plugin provides a ReportingController
andthere is no other ReportingController
available at runtime, thefollowing mapping would work.
static mappings = {
"/humanResourceReports" {
controller = "reporting"
}
}
It is best practice to be explicit about the fact that the controlleris being provided by a plugin.