Grails UrlMapping 404 - grails

I have this:
static mappings = {
"/a/b/$id/stuff"(controller: "stuff", action "action1" )
"/a/b/$id/stuff/$stuffId"(controller: "stuff", action "action2" )
"/a/b/$id/stuff/$stuffId/c"(controller: "stuff", action "action3" )
}
I can hit action1 and action2, but I can't hit action3, as it returns a 404.
What's going on?

def method(){
}
will not work.
def method = {
}
WILL work.

have you checked the code of your view? I guess if it can't compile, you'll get a 404.
At least, that's what I experienced.

Related

UrlMapping to Index is not working

I am trying to get my Index which in my case is just localhost:8080 to go to a different page. This code is not working and I'm just going to the index page instead of rendering "this worked"
My UrlMappings file looks like this:
package appworld
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?(.$format)?"{
constraints {
// apply constraints here
}
}
"/" {
controller = "Home"
action = "isUserLoggedIn"
}
"500"(view:'/error')
"404"(view:'/notFound')
}
}
The method in HomeController.groovy looks like:
def isUserLoggedIn() {
println("We made it from index")
render "this worked"
}
It looks like your syntax is off. Try:
"/"(controller:"home", action:"isUserLoggedIn")

Grails: How do I map a 404 with /**

I've tried to create a custom 404 url mapping for URL's that are not found:
"/test" {
controller="test"
}
"404" {
controller="application"
action="send404"
}
"500" {
controller="application"
action="send500"
}
But for some reason, the controller and action are never called. I get the default container 404 page. So, instead I tried:
"/test" {
controller="test"
}
"/**" {
controller="application"
action="send404"
}
"500" {
controller="application"
action="send500"
}
Which seems to work fine, except that it also seems to call the send404 action on every request. For example, if I hit /test, I see the test page, but I also get the log statement I made in the send404() action.
Ideas appreciated...
Have you tried killing whitespace in your declaration, as outlined in this answer?
"404"(controller:'application', action:'send404')
There is also an open issue GRAILS-4232 about this topic.
In grails, there is an ErrorController, the one that render stacktrace on 500, etc.
class UrlMappings {
static mappings {
"403" (controller: "error", action: "forbidden")
"404" (controller: "error", action: "notFound")
"500" (controller: "error", action: "internalError")
}
}
And then, you can render(controller:"error", action"notFound") in another controller to stay RESTful. Or it will automagically render the notFound action of the error controller.
More details here : http://groovy.dzone.com/articles/grails-exception-handling-http
Perhaps it's favicon.ico that's being requested by the browser on each request that's causing this to happen.
// Route 404 to this action to see!
def send404() {
log.error("404 Page Not Found! " + request.forwardURI)
response.status = 404;
render(view:"/application/not-found.gsp")
}

Grails UrlMapping Redirect to keep DRY

I am working with Grails 2.1.1 and would like to add a handful of customized URLs that map to Controller Actions.
I can do that, but the original mapping still works.
For example, I created a mapping add-property-to-directory in my UrlMappings as follows:
class UrlMappings {
static mappings = {
"/add-property-to-directory"(controller: "property", action: "create")
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/"(view:"/index")
"500"(view:'/error')
}
}
Now, I can hit /mysite/add-property-to-directory and it will execute PropertyController.create, as I would expect.
However, I can still hit /mysite/property/create, and it will execute the same PropertyController.create method.
In the spirit of DRY, I would like to do a 301 Redirect from /mysite/property/create to /mysite/add-property-to-directory.
I could not find a way to do this in UrlMappings.groovy. Does anyone know of a way I can accomplish this in Grails?
Thank you very much!
UPDATE
Here is the solution that I implemented, based on Tom's answer:
UrlMappings.groovy
class UrlMappings {
static mappings = {
"/add-property-to-directory"(controller: "property", action: "create")
"/property/create" {
controller = "redirect"
destination = "/add-property-to-directory"
}
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/"(view:"/index")
"500"(view:'/error')
}
}
RedirectController.groovy
class RedirectController {
def index() {
redirect(url: params.destination, permanent: true)
}
}
It is possible to achieve this:
"/$controller/$action?/$id?" (
controller: 'myRedirectControlller', action: 'myRedirectAction', params:[ controller: $controller, action: $action, id: $id ]
)
"/user/list" ( controller:'user', action:'list' )
and in the action you get the values normallny in params:
log.trace 'myRedirectController.myRedirectAction: ' + params.controller + ', ' + params.action + ', ' + params.id
As of Grails 2.3, it is possible to do redirects directly in the UrlMappings, without the need for a redirect controller. So in case you ever upgrade, you can redirect in UrlMappings like so, as per the documentation:
"/property/create"(redirect: '/add-property-to-directory')
Request parameters that were part of the original request will be included in the redirect.
In recent Grails version (currently 5.x) you need to pass a Map into the redirect: property:
"/viewBooks"(redirect: [uri: '/add-property-to-directory'])
https://docs.grails.org/latest/guide/theWebLayer.html#redirectMappings

Grails: Can't figure out why I'm getting a 404

I'm using Grails 1.3.6. I have this file ...
grails-app/views/home/design/index.gsp
Here is what is defined in my HomeController. Sadly, whenever I visit, "http://localhost:port/context-path/design/", I get a 404 error. The server starts normally and there are no errors in the logs. What can I do to get my page instead of the 404?
def index = {
def folder = params.folder;
def page = params.page;
if (page) {
try {
def contents = IOService.getFileContents(folder, page)
response.setContentType("application/json")
response << contents
} catch (FileNotFoundException e) {
response.status = 404;
} // try
} else {
render(view: "/home/${folder}/index")
} // if
}
My URLMappings file consists of ...
static mappings = {
"/$folder?/$page"{
controller = "home"
action = "index"
}
"/"(view:"/index")
"500"(view:'/error')
}
Thanks, - Dave
If you want to be able to access
/context-path/home/design
Your action needs to be named design, i.e.
class HomeController {
def design = {
}
}
The Grails convention is always /context-path/controllerName/actionName (unless you have it mapped differently in grails-app/conf/URLMappings.groovy).
Your example's a bit unclear which path you're trying to access. To address both:
If you want /context-path/design, you need a DesignController with an index action (because if no action is supplied in the URL, Grails looks for the index action).
If you want /context-path/home/design, you need a HomeController with a design action.
Edit:
In the comments, you express the want to be able to have /context-path/design map to the HomeController index action. You can do this with grails-app/conf/URLMappings.groovy:
"/design"(controller: 'home', action: 'index')
Since it seems you have two distinct actions, I would set things up a bit differently:
def indexWithPage = {
def folder = params.folder;
def page = params.page;
try {
def contents = IOService.getFileContents(folder, page)
response.setContentType("application/json")
response << contents
} catch (FileNotFoundException e) {
e.printStackTrace();
response.status = 404;
} // try
}
def index
def folder = params.folder;
render(view: "/home/${folder}/index")
}
with a URLMaping of:
static mappings = {
"/$folder/$page"{
controller = "home"
action = "indexWithPage"
}
"/$folder"{
controller = "home"
action = "index"
}
"/"(view:"/index")
"500"(view:'/error')
}
I also threw a e.printStackTrace(); in there to help us determine whether you're getting YOUR 404 or the action is truely not being called.

Confusion about URLMapping

I'm running Grails 1.3.6. I have this in my URLMappings.groovy file ...
static mappings = {
"/$folder?/$page?"{
controller = "Home"
action = "index"
}
"/"(view:"/index")
"500"(view:'/error')
}
and this is my HomeController ...
class HomeController {
def IOService
def index = {
def folder = params.folder;
def page = params.page;
def contents = IOService.getFileContents(folder, page)
response.setContentType("application/json")
response.text = contents
}
}
however, when I visit my URL "/context-path/folder1/page1", I'm getting an Apache Tomcat 404 error (complaining about "/context-path/folder1"). I'm new to Grails but can't figure this out. How can I adjust my mappings to make this work?
Thanks, - Dave
I'm not sure if controller/action definitions are case-insensitive. I've always used lowercase names. Try changing
controller = "Home"
to
controller = 'home'

Resources