Grails 2.2.0 renders wrong page - grails

I have a grails 2.2.0 application. I have created a global filter and that has some check. if the check fails then it renders a static view file using render view: viewFileName ending the flow else it returns true saying app can continue.
At login action, the action renders a login view calling render view: loginFileName but it displays the viewFileName instead. Note that filter pass has already passed by now and the check in it has passed too.
This issue seems similar to earlier post
Grails "respond" renders the wrong view when launched from .war file
but the difference is that there are two index view files of same name but in different controller but here we have filter rendering a view if some condition passes which gets displayed even if that condition fails.
To makes sure that this is an issue, i removed that render view: viewFileName in filter with render "< div>....< /div >" and then it worked all well i.e. action displayed the right page and not the static page.
I can post more detail if required. I cannot rely on that page that is in string to render as that will not be long term.
Here are the two classes with issue
class MainController {
def login() {
def param = getHeaderParameters()
render view: "login", model: param
}
}
class MainFilters {
private final String mainControllerName = "main"
private final String startPage = "start"
def GrailsConventionGroovyPageLocator groovyPageLocator
def filters = {
all(controller: '*', action: '*') {
before = {
if (AdminUtils.isStart(request)) {
println "rending start page...."
final fileView = "/$mainControllerName/$startPage"
render view: fileView
}
}
}
}

When you render a page and not redirecting it, your action will be called after the before check, if you not return false. For your scenario you don't want your action to be called so you need to return false after that.
def filters = {
all(controller: '*', action: '*') {
before = {
if (AdminUtils.isStart(request)) {
println "rending start page...."
final fileView = "/$mainControllerName/$startPage"
render view: fileView
return false
}
}
}
}

Related

Preventing redirecting from the start

I'm experience some auto redirecting at the page when it first loaded.
These are my codes:
def editUser = {
if(params.account_expired != null )
{
String updateQuery = "UPDATE user SET expired='"+params.account_expired+"'"
def update = sql.executeUpdate(updateQuery)
redirect (action: listUser)
[update:update]
}
else
{
}
}
so what happen is, when the page got loaded, it auto redirect back to listuser page. This is actually an edituser page and I want it to stay there until the user clicks a button. And then redirect to listuser. Any idea guys?
It's common to use POST method to send update, and GET to show form (as it suggested by W3C, and used in Grails by default). So you can use:
def editUser = {
if (request.method == 'GET') {
render(view: 'editUser')
} else if (request.method == 'POST') {
//.... current code
}
}
by default Grails creates POST form, when you're using <g:form tag, but if you're using plain HTML tags, you should specify POST method as:
<form method="POST">
</form>
That's exactly what your code is supposed to do, because you have this executed:
redirect (action: listUser)
If you want it stay in editUser page, you should remove it. Then
[Query1:Query1]
will render editUser.gsp with this parameter passed.

Render GSP in filter is not working

I'm trying to render a .GSP view inside the view folder from my filter. The following code show that:
def filters = {
all(controller:'*', action:'*') {
afterView = { Exception e ->
if (controllerName) {
//some code here
if (annotation!=null) {
switch(response.format){
case 'all':
if(!response.containsHeader("AC_MSG")|| !response.containsHeader("AC_STATUS")){
render(view: "/internalerror", model: [controller: controllerName,action:currentAction,
message:"Response doesn't contain required headers AC_MSG or AC_STATUS. Either add the required headers or use json format.",
example:"Add the following response headers: AC_MSG:response message , AC_STATUS: false or true"
])
return false
}
break
default:
render status: 406
break
}
}
}
}
}
}
The problem is that this page didn't get rendered even the code is executed. The page is on the view directory directly. What I did wrong?
Thanks,
I don't think a filter can render a gsp, but controllers can.
A perfect example of what you want to do is available in the docs: filters
Basically you create an action inside a controller that renders the page, and the filter just redirects to the action.
case 'all':
if(!response.containsHeader("AC_MSG")|| !response.containsHeader("AC_STATUS")) {
redirect(controller: "someController", action:"someAction")
return false
}
Make ErrorController.groovy and implement action with this render view and params.
In filter use only redirect. Remove 'return false' statement also.

Grails 2.1.1: Redirect to /index.gsp not working with Filter defined

I have a Grails 2.1.1 application which runs fine, at least until I try to define a filter for all Controller to redirect to the index.gsp if user is not set in the session variable...
what ever I try, I'm not able to redirect to "/index", nor render "/index" when starting the server - if I remove the filter and redirect to "/index" from my AuthenticationController on false parameters, all works like charm...
so, here's what I have so far:
class AuthenticationFilters {
all(controller:'*', action'*') {
before = {
def user = (User) session.getValue("user")
if(user == null || !user.loginState) {
redirect(controller: 'authentication', action: 'index')
return false
}
}
}
}
class AuthenticationController {
def authenticationService
def index = {
render(view: '/index')
}
def login(LoginCommand cmd) {
if(cmd.hasErrors()) {
redirect(action: index)
return
}
}
....
}
now, if I comment out the all Filters definition, everything works well. I got the page (index.gsp) shown on start up and if the LoginCommand has errors, I'm redirected to the index.gsp page without any problems.
if I now comment in the all Filters definition, I get a 404.
I tried:
Grails: Redirect to index.gsp that is not in any controller
Upgrade to Grails 2.0: /index.gsp not found
Grails: what are the main issues (and his solutions) when deploying in weblogic?
but I didn't had any luck...
I'm developing on Intellij IDEA 11.1.4 Premium (evaluation)
EDIT: I tried to get the User object from the session property in my AuthenticationFilters class, surrounded by a try/catch block and now facing the problem that obviously the session property is not available? why?
try {
def user = (User) session.getValue("user")
if((user == null || !user.loginState)) {
...
}
} catch(Exception e) {
println("... couldn't get user from session! ${e.getMessage()}")
}
console output:
... couldn't get user from session! No such property: session for class: grailstest001.AuthenticationFilters
any suggestions on this?
So, just to add my experience here to close this question as solved and for further usage for other users:
to check if the user is entering the page for the first time, you could easily do this by checking for the controllerName field. It should be null or "" (empty String) if the user was not referred to the site by any controller.
Also, I'm not using any Database within my application for authentication because all of this issuses are backended by an API. So I created a UserService.groovy class which is acting as a SessionScopedBean and I store all my user related infos within this class.
So, your filter definition could look like:
class MyFilters {
def filters = {
before = {
if(!controllerName || controllerName.equals("")) {
redirect(controller:'home',action:'index')
}
if(!applicationContext.userService?.getUser() || !applicationContext.userService?.getUser.isLoggedIn) {
redirect(controller:'auth',action:'login')
}
}
}
}
Otherwise, if you don't want to redirect the user which 'freshly' entered your page from within your Filters.groovy class, you could use the UrlMappings.groovy class to do so. Just map your / (root) index to the page you want:
class UrlMappings {
static mappings = {
"/"(controller:'mycontroller',action:'myaction') // change it to your liking
"/$controller/$action?/$id?" {
constraints {
// apply constraints here
}
}
"500"(view:'/error')
}
}
I think your filter syntax may be incorrect - try
Class AuthenticationFilters {
def filters = { // <--- added this
all(controller:'*', action'*') {
before = {
def user = (User) session.getValue("user")
if(user == null || !user.loginState) {
redirect(controller: 'authentication', action: 'index')
return false
}
}
}
} // <-- added
}

How to render a specific view according a flow param in grails flow?

I need to change the gsp to render dynamically according certain params. the thing is: in the render action I get
org.codehaus.groovy.grails.commons.metaclass.PropertyExpression#680dc2a instead of the params I passed.
promoFlow = {
start {
action {
flow.inputPage = "landing1/input/${params.land}"
flow.pinPage = "landing1/pin/${params.land}"
flow.finishPage = "landing1/finish/${params.land}"
...
success()
...
}on('success'){
...
}.to 'preview'
}
preview {
render(view: flow.inputPage )
on('next') {...}.to 'pin'
}
Paul if you are using Grails2 why not add a parameter to the action method instead of accessing the params directly, eg:
def myAction(String land) {
...
flow.inputPage = "landing1/input/${land}"
...
}

In Grails, how do I return to the calling current view from a controller?

Below is a very simple controller with a "search" action that is fired from g:submitButton in a gsp file. My question is, instead of redirecting to the "index" action and view, how do I return to the view that contained the submit button that called this controller's search action?
class DefaultSearchController {
def searchableService
def index = {
}
def search = {
def query = params.query
if(!query){
redirect(action:"index", params:params)
}
try{
def searchResults = searchableService.searchEvery( query )
redirect(action:"index", searchResults)
}
catch( e ){
params.errors = "${e.toString()}"
redirect(action: "index", params:params)
}
}
}
If the search action is going to be called from various places, I would pass in a parameter to it telling search controller where to redirect to or which view to render the search results with.
cheers
Lee

Resources