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

  1. package com.app.reporting
  2. class AdminController {
  3. static namespace = 'reports'
  4. // ...
  5. }

grails-app/controllers/com/app/security/AdminController.groovy

  1. package com.app.security
  2. class AdminController {
  3. static namespace = 'users'
  4. // ...
  5. }

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

  1. class UrlMappings {
  2. static mappings = {
  3. '/userAdmin' {
  4. controller = 'admin'
  5. namespace = 'users'
  6. }
  7. '/reportAdmin' {
  8. controller = 'admin'
  9. namespace = 'reports'
  10. }
  11. "/$namespace/$controller/$action?"()
  12. }
  13. }

Reverse URL mappings also require that the namespace be specified.

  1. <g:link controller="admin" namespace="reports">Click For Report Admin</g:link>
  2. <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.ReportingControllerand 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.

  1. static mappings = {
  2. "/accountingReports" {
  3. controller = "reporting"
  4. }
  5. "/humanResourceReports" {
  6. controller = "reporting"
  7. plugin = "humanResources"
  8. }
  9. }

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 humanResourcesplugin.

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.

  1. static mappings = {
  2. "/humanResourceReports" {
  3. controller = "reporting"
  4. }
  5. }

It is best practice to be explicit about the fact that the controlleris being provided by a plugin.