dependency inject Grails Webflow - grails

Is it possible to inject a Spring bean into a Grails webflow? I tried the following
class CheckoutController {
ShoppingService shoppingService
def checkoutFlow = {
start {
action {
// This attempt to access the service doesn't work
flow.addresses = shoppingService.getOrder()
}
}
}
}
I can access shoppingService from a regular controller action, but I can't access it from an action of the webflow (see above).

add the following to your controller:
def transient shoppingService

There are issues with dependency injection with webflows in controllers that contain traditional actions plus webflows. It worked for me if the traditional action executed first.
see:
GRAILS-7095
GRAILS-4141
Webflows also break notions of defaultAction in mixed controllers. I have found the first webflow wins and becomes the default action.
separately using transient keeps your service from be serialized between flow states. (e.g. don't have to implement serializable)

At first I thought what you listed was pseudocode but I made a sample app using your example and got the NPE as well. I think it may be your flow structure that is the problem. action blocks should go within a flow state. Your flow definition should look something like:
class CheckoutController {
ShoppingService shoppingService
def checkoutFlow = {
start {
action {
flow.addresses = shoppingService.getOrder()
if(flow.addresses) {
showForm()
}
else {
showError()
}
}
on("showForm").to "showForm"
on("showError").to "showError"
}
showError {
...
}
//etc.
}
}
You can definitely use injected services in your web flows. I am guessing that the problem lies in your flow structure.

Related

Applying a Grails filter to login URL

In my Grails 2.5.X app I'm using the Spring Security REST plugin and have configured the login URL like so in Config.groovy
grails.plugin.springsecurity.rest.login.endpointUrl = '/internal/login'
I need to apply a filter to this URL and am attempting to do this with
class GrailsFilters {
def filters = {
login(uri: '/internal/login') {
before = {
// implementation omitted
}
after = { Map model ->
// implementation omitted
}
}
}
}
But for some odd reason the filter never gets called. Is there something special about the login endpoint which means it can't be filtered?
Yes, there is something special about it. It uses a servlet filter (chain there of) which have a higher priority than the Grails filter you are trying to use.
If you need to intercept the call you'll need to create your own filter in the Spring Security filter chain. The documentation has an entire section that goes into the details.

Override Grails redirect method

I'm carrying the locale of my Grails application in the URL, such as
http://myapp.com/LANG/controller/action/id.
Therefore, I adjusted the URLMappings.groovy with the language attribute. Since I would like to save work and don't apply the lang parameter at every link, I have overridden the g:link taglib with the language from params.lang. This works pretty good.
When I do a redirect from a controller, such as
redirect(action: "logout")
I'd like to append the params.lang automatically instead of writing every time
redirect(action: "logout", params: [lang: params.lang])
I found the thread grails override redirect controller method, but I'm unsure how to proceed. Where does this code take part?
How can I override the redirect() method and add the params.lang-attribute?
Please advice, thank you very much.
The easiest way to do this in your application would be to use a bit of meta programming and the BootStrap.groovy for your Grails application. The following is just a simple example of what that might look like:
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes
class BootStrap {
def init = { servletContext ->
def ctx = servletContext.getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT)
def app = ctx.getBean("grailsApplication")
app.controllerClasses.each() { controllerClass ->
def oldRedirect = controllerClass.metaClass.pickMethod("redirect", [Map] as Class[])
controllerClass.metaClass.redirect = { Map args ->
// new pre-redirect logic
if (!args['params']) args['params'] = [:] // just in case redirect was called without any parameters
args['params']['whatever'] = 'something' // add something into the parameters map
oldRedirect.invoke delegate, args
// new post-redirect logic
}
}
}
def destroy = {
}
}
The above example just wraps the implementation for redirect on all controllers within your Grails application and injects a new parameter called whatever with the value of something.
The above was tested (quickly) using Grails 2.4.2.

Grails execute service method after bootstrap completes

Just a quick one to see whether it is possible to run a block of code after the bootstrap's init() has completed?
Hows the best way to go about it?
I have some external systems I need to connect to, and I want to show an 'index' page saying 'Connecting to sub systems' or something similar whilst this block completes, and then once its done the application works as normal.
Am I right in thinking you cant access a page until after bootstrap? Is there a simple way to restrict people accessing other parts of the system whilst this service runs? Does this seem feasible?
Cheers for any help!
Based on your requirement as you also pointed out bootstrap is not your friend. you need a view and controller for your screen and a service for your connection logic to external systems. You also need a flag or a method for sanity check of the communication within the scope of application or session. Then I would suggest to create a filter and check if you have the connections, if not redirect them to the controller that will connect it.
Sudo:
class ConnectionFilters {
def filters = {
loginCheck(controller: '*', action: '*') {
before = {
if (!session.connection ) {
redirect(controller:'connection',action: 'connect')
return false
}
}
}
}
}
class controller {
def connectionService
def connect (){
try {
connectionService.connectTo('systemx')
connectionService.connectTo('systemy')
connectionService.connectTo('systemz')
}
catch(e){
session.connection = false
redirect view:'error'
}
session.connection = true
}
}
class ConnectionService {
def connectTo(systemname){
....
}
}

How to dynamically generate urls used by grails.plugins.springsecurity?

This is not one of the simple questions.. So let me explain it in detail...
The background:
In my grails application I have this mapping:
class UrlMappings {
static mappings = {
"/$storeId/$controller/$action?/$id?"
...
}
}
This means that all url's my application will process has preceding url parameter "storeId". All controllers will use this parameter to render content and perform other actions...
Also I have controller with annotation
#Secured(['IS_AUTHENTICATED_REMEMBERED'])
class SomeController {
def index = {
// ...
}
}
Let's say user is trying to access this page:
/555/some/index
If this is unauthenticated user, security-plugin will redirect him to the
/login/auth
The issue is:
When spring-security will redirect to this page, user will see 404. This happens because login controller will handle only urls like
/555/login/auth
The question is:
What should I do to dynamically build this url?
p.s.
It turns out that:
There is config param for
spring-security, called
"auth.loginFormUrl". But this is just
static text. And I need to build this
url based on what url influenced this
redirection
The redirection is done (I'm not 100%
sure) in org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint#commence.
But how to override it?
Typically that's a static value, but it's called from LoginUrlAuthenticationEntryPoint.getLoginFormUrl(), so you could subclass that and do a dynamic calculation of the url in an overridden method. The plugin already subclasses it with org.codehaus.groovy.grails.plugins.springsecurity.AjaxAwareAuthenticationEntryPoint so you should extend that.
To register your implementation instead of the plugins, add a bean override in grails-app/conf/spring/resources.groovy:
import com.yourcompany.yourapp.YourAuthenticationEntryPoint
beans = {
authenticationEntryPoint(YourAuthenticationEntryPoint) {
loginFormUrl = '/login/auth' // has to be specified even though it's ignored
ajaxLoginFormUrl = '/login/authAjax'
portMapper = ref('portMapper')
portResolver = ref('portResolver')
}
}
You don't have direct access to the request in this method, but it's available in a thread-local - call org.codehaus.groovy.grails.plugins.springsecurity.SecurityRequestHolder.getRequest().

Grails webflow url rewriting

Want to make the URLs SEO friendly when using grails webflow. It is quite limiting with the convention grails uses and hard to go around the way it's built.
For example, i have a flow called fooProcess in the controller called FooController, when i trigger the flow i would like the display: /foo/bar/test, instead of /foo/fooProcess?excecution=e1s2
class FooController {
def fooProcessFlow {
showFoo {
}
}
}
I tried using redirect and specify the uri but that's not supported, grails complains that the page isn't found
fooProcessFlow {
showFoo {
redirect(uri:"/foo/bar/test")
}
}
grails/foo/fooProcess.dispatch/externalRedirect:/foo/bar/test
Also, a redirect is an end state in a flow, if I only want to render the page, i have to use the render method and specify the view name or structure my views according to webflow convention.
fooProcessFlow {
showFoo {
render(view:"/foo/bar/test")
on "add".to "add"
}
}
The url will be in this case
/foo/fooProcessProcess?execution=e6s1
Anyone dealt with this case before ?
Did anyone use UrlRweriteFilter with webflows in grails
http://code.google.com/p/urlrewritefilter/
ken
You can use URLMappings Grails Plugin
See: http://grails.org/doc/latest/ref/Plug-ins/URL%20mappings.html
Edit this file: grails-app/conf/UrlMappings.groovy
Putting something like this inside:
class UrlMappings {
static mappings = {
"/foo/bar/test" (controller: "foo", action: "fooProcessFlow")
"/$controller/$action?/$ids?"{
constraints {
}
}
}
}

Resources