I want to call a subflow where the controller is not known. It is passed in parameters to beginFlow and I save that in flow scope. Inside goToForm I'd like to call use the controller that is saved in flow.theController.
def beginFlow = {
enter {
action {
if (params?.redirectTo != null) {
String flow.theController = params.redirectTo
}
if ( flow.theController() ) {
success()
}
}
on("success").to("beginPage")
}
beginPage {
on('next').to('goToForm')
}
goToForm {
// I'd like this:
// subflow(controller: flow.theController, action:'start'
// this subflow works, but won't work for all cases
subflow(controller: 'AZ_A4', action:'start')
on('done').to('showResults')
on('notDone').to('beginPage')
}
showResults {
redirect(action: 'results')
}
}
As discussed on the user list, it appears that this isn't possible directly, as the subflow name has to be known at the time when the flow structure is being built (at application startup). But since the flow definition DSL is Groovy code you can do something like this:
beginPage {
on('next').to('selectSubflow')
}
selectSubflow {
action {
return "subflow_${flow.theController}"()
}
for(subController in listOfControllers) {
on("subflow_${subController}").to("subflow_${subController}")
}
}
for(subController in listOfControllers) {
"subflow_${subController}" {
subflow(controller:subController, action:'start')
on('done').to('showResults')
on('notDone').to('beginPage')
}
}
The listOfControllers could be a static somewhere, or you could possibly do something like this at the top of the flow definition
def beginFlow = {
def listOfControllers = grailsApplication.controllerClasses.findAll {
it.flows.containsKey('start')
}.collect { it.logicalPropertyName }
enter {
// ...
to enumerate all the controllers in the application that define a startFlow. You might need a def grailsApplication in your class, I always forget which places in Grails have it available by default and which don't...
Related
I have a fairly large criteria closure in my Grails application, and I would like to reuse part of it in several places in my application. Rather than duplicating the section I need to reuse, I'd like to define this as a separate closure and reference it wherever it is needed, but I am struggling a bit with the syntax.
This is a simplified / cut down version, but essentially my criteria looks something like this:
def criteriaClosure = {
and {
// filtering criteria that I'd like to reuse in lots of places
or {
names.each { name ->
sqlRestriction(getFilteringSql(name), [someId])
}
}
if (isOrganisationChild(childDefaultGrailsDomainClass)) {
sqlRestriction(getFilteringSql(domain), [someArg])
}
// filtering criteria that's specific to this particular method
sqlRestriction(getSomeOtherSql(), [someOtherArg])
}
}
def criteria = domain.createCriteria()
def paginatedList = criteria.list([offset: offset, max: max], criteriaClosure)
I've tried defining the part of the closure I want to reuse as a variable, and referencing it in my criteria closure, however the restrictions it defines don't seem to be applied.
def reusableClosure = {
and {
or {
names.each { name ->
sqlRestriction(getFilteringSql(name), [someId])
}
}
if (isOrganisationChild(childDefaultGrailsDomainClass)) {
sqlRestriction(getFilteringSql(domain), [someArg])
}
}
}
def criteriaClosure = {
and {
reusableClosure() //this doesn't seem to work
sqlRestriction(getSomeOtherSql(), [someOtherArg])
}
}
I'm sure this must be a pretty straightforward thing to do, so apologies if it's a daft question. Any ideas?
I think you have to pass the delegate down to the reusableClosure, ie:
def criteriaClosure = {
and {
reusableClosure.delegate = delegate
reusableClosure()
sqlRestriction(getSomeOtherSql(), [someOtherArg])
}
}
I have a Grails project and I need to send/save table data. I have a controller(doesn't have views) with following code.
class JsonController {
def getCompany = {
for (String s in request.getHeaderNames()) {
println request.getHeader(s)
}
println Company.list()
render Company.list() as XML
}
def getEmployees = {
for (String s in request.getHeaderNames()) {
println request.getHeader(s)
}
render Employees.list() as XML
}
def getManagers = {
for (String s in request.getHeaderNames()) {
println request.getHeader(s)
}
render Managers.list() as XML
}
}
Now I need to call/run these functions on clicking an link and send the output thru email or save to a folder. How can I do this?
Thankyou
Note: the following code requires the mail plugin
I would move your JsonController to a service, which I renamed to XMLService, since that is what you are returning. Then, inject the XMLService in whatever artefacts you want to use it in, such as another service or controller.
import grails.converters.XML;
class XMLService {
def getCompanies = {
return Company.list() as XML
}
def getEmployees = {
return Employees.list() as XML
}
def getManagers = {
return Managers.list() as XML
}
}
Then, in a controller or service. This example uses a service:
class MyMailingService {
def mailService //<-- included from the Mail plugin
def xmlService
void sendEmployeeList(){
mailService.sendMail {
to "fred#g2one.com","ginger#g2one.com"
subject "Hello to mutliple recipients"
body xmlService.getEmployees()
}
}
}
And for storing files, something like the following. Note, that this does not have to be service, but for demonstration purposes, it was easier.
class MyStorageService {
def xmlService
void storeEmployeeList(){
//It was a little unclear how you wanted to store the file, so be careful because this this does not include checks you would want to implement in production (e.g. checks for existing files, possible runtime exceptions, etc).
def f= new File('employees.txt') //see http://docs.codehaus.org/display/GROOVY/JN2015-Files
f << xmlService.getEmployees()
}
}
Noticed you have had answers for email text file - this is how to to store to XML file
where rowid will be the definition for each xml row
def file=""${System.properties['catalina.base']}/file.xml"
try {
new File(file).withWriter { writer ->
def xml = new MarkupBuilder( writer )
def Users = Registeration.list()
xml.mkp.xmlDeclaration(version: "1.0", encoding: "utf-8")
xml.rowid {
Employees.each { employee ->
xml.registeration(id: employee.id) {
username(employee.username)
//somethingelse(employee.somethingelse)
}
}
}
}
} catch (Exception e) {
result=e.printStackTrace()
}
if (result!=null) {
result="all done stored in "+file
}else{
result="Something has gone wrong with "+file
}
I often write something like:
def myAction{ MyActionCommand cmd ->
if( cmd.hasErrors() ){
return render(status:HttpServletResponse.SC_BAD_REQUEST );
}else{
// actual action logic
}
So, I'd like to extract that common pattern into some reusable location. Filter looks like good candidate, but I can't find the way to get command object from the filter. Tryed something like this (in filters closure):
formValidation( controller:'*', action:'*' ){
before = { cmd ->
if( cmd.hasErrors() ){
response.sendError( HttpServletResponse.SC_BAD_REQUEST );
return false;
}else{
return true;
}
}
}
Intersted in grails 1.3.7 compatible solution. Is it possible at all?
No, it isn't possible to do what you are asking. Command Objects are not full framework artifacts like Controller, Service, etc, and so they do not get their validation logic added to them, unless they are a parameter to a Controller action. To that end a Command Object in a filter wouldn't have a .validate() or .hasErrors() method to check against.
As another option you could use the #Validateable annotation:
http://grails.org/doc/latest/guide/7.%20Validation.html#7.5%20Validation%20Non%20Domain%20and%20Command%20Object%20Classes
Move your Command Object to src/groovy as a regular Groovy class and annotate it with #Validateable. Then in your filter you can do:
def validObj = new MyValidateable(params)
if (!validObj.validate()) {
response.sendError( HttpServletResponse.SC_BAD_REQUEST );
return false;
} else {
return true;
}
Make sure you add the package name of your validateable class to the grails.validateable.packages List in Config.groovy.
What about creating a service like this:
class AutoValidateService {
def onValid(def cmd, Closure onValid) {
if( cmd.hasErrors() ){
return render(status:HttpServletResponse.SC_BAD_REQUEST );
}else{
onValid()
}
}
}
The use it like so:
class FooController {
AutoValidateService autoValidateService
def myAction{ MyActionCommand cmd ->
autoValidateService.onValid(cmd) {
// do something
}
}
}
Normally for a Grails domain or command class, you declare your constraints and the framework adds a validate() method that checks whether each of these constraints is valid for the current instance e.g.
class Adult {
String name
Integer age
void preValidate() {
// Implementation omitted
}
static constraints = {
name(blank: false)
age(min: 18)
}
}
def p = new Person(name: 'bob', age: 21)
p.validate()
In my case I want to make sure that preValidate is always executed before the class is validated. I could achieve this by adding a method
def customValidate() {
preValidate()
validate()
}
But then everyone who uses this class needs to remember to call customValidate instead of validate. I can't do this either
def validate() {
preValidate()
super.validate()
}
Because validate is not a method of the parent class (it's added by metaprogramming). Is there another way to achieve my goal?
You should be able to accomplish this by using your own version of validate on the metaclass, when your domain/command class has a preValidate() method. Something similar to the below code in your BootStrap.groovy could work for you:
class BootStrap {
def grailsApplication // Set via dependency injection
def init = { servletContext ->
for (artefactClass in grailsApplication.allArtefacts) {
def origValidate = artefactClass.metaClass.getMetaMethod('validate', [] as Class[])
if (!origValidate) {
continue
}
def preValidateMethod = artefactClass.metaClass.getMetaMethod('preValidate', [] as Class[])
if (!preValidateMethod) {
continue
}
artefactClass.metaClass.validate = {
preValidateMethod.invoke(delegate)
origValidate.invoke(delegate)
}
}
}
def destroy = {
}
}
You may be able to accomplish your goal using the beforeValidate() event. It's described in the 1.3.6 Release Notes.
Grails noob here...
How do I get the state name inside a Grails webflow state? I'm prototyping a mobile app using Grails WebFlow and jQueryMobile. Because it's a mobile app comprised primarily of lists, I manage the back events using a stack like this:
class myController {
def myFlow {
start {
action {
flow.states = []
[ ... ]
}
on("success").to "state0"
}
state0 {
on("back").to "home"
on("event") {
flow.states << "state0"
}.to "state1"
}
state1 {
on("back").to { flow.states.pop() }
on("event") {
flow.states << "state1"
}.to "state2"
}
state2 {
on("back").to { flow.states.pop() }
}
home {
redirect( ... )
}
}
}
This works, but I'd like to replace the hard coded state name strings in lines like flow.states << "state#" with an expression if there's a way to do it.
EDIT: I'll accept answers that explain why this can't be done.
Try using the RequestContext and/or the FlowExecutionContext? e.g. flowExecutionContext.currentState.id