i have this grails webflow
def currencyDescriptionFlow = {
start {
action {
flow.messageCommand = new MessageCommand()
flow.currencyId = params.id
flow.languageList = Language.findAll([sort: 'codeDescription', order: 'asc'])
}
on('success').to('description')
}
description{
action{
flow.DescriptionMessageList = Message.findAllByKey(flow.currencyId + '_Currency')
}
on('add').to('addSubmit')
on('finish').to('currencyShow')
}
addSubmit{
action {
MessageCommand cmd ->
flow.messageCommand = cmd
if (!flow.messageCommand.validate()){
error()
}
}
on('error').to('description')
on('success').to('description')
}
saveMessage{
action{
def str = flow.currencyId + '_Currency'
messageSevice.descriptionMultiLanguage(str, params.description, params.Language)
}
on('error').to('description')
on('success').to('description')
}
currencyShow{
redirect(controller:'currency', action: "show", id: flow.currencyId)
}
}
when i click the link to redirect to this page, ann error occurs
Error 500: No transition was matched on the event(s) signaled by the [1] action(s)
that executed in this action state 'description' of flow 'message/currencyDescription';
transitions must be defined to handle action result outcomes -- possible flow
configuration error? Note: the eventIds signaled were: 'array<String>
['success']', while the supported set of transitional criteria for this action
state is 'array<TransitionCriteria>[add, finish]'
Servlet: grails
URI: /adm-appserver-manager/grails/message/currencyDescription.dispatch
Exception Message: No transition was matched on the event(s) signaled by the [1]
action(s) that executed in this action state 'description' of flow 'message/currencyDescription';
transitions must be defined to handle action result outcomes -- possible flow
configuration error? Note: the eventIds signaled were: 'array<String>
['success']', while the supported set of transitional criteria for this action state
is 'array<TransitionCriteria>[add, finish]'
Caused by: No transition was matched on the event(s) signaled by the [1] action(s)
that executed in this action state 'description' of flow 'message/currencyDescription';
transitions must be defined to handle action result outcomes -- possible flow
configuration error? Note: the eventIds signaled were: 'array<String>['success']',
while the supported set of transitional criteria for this action state is
'array<TransitionCriteria>[add, finish]'
Class: Unknown
At Line: [-1]
Code Snippet:
Note:
where language is a table in the database
MessageCommand is command object
messageService is a service
descriptionMultiLanguage method in message service for saving message
i try this way of writing code in another action and controoler and it works without any error.
by debugging this code i found the error on (
on('add').to('addSubmit')
on('finish').to('currencyShow')
)
when i remove these 2 lines , no problem found
def currencyDescriptionFlow = {
start {
action {
flow.messageCommand = new MessageCommand()
flow.currencyId = params.id
flow.languageList = Language.findAll([sort: 'codeDescription', order: 'asc'])
flow.DescriptionMessageList = Message.findAllByKey(flow.currencyId + '_Currency')
}
on('success').to('description')
}
description{
on('add').to('addSubmit')
on('finish').to('currencyShow')
}
addSubmit{
action {
MessageCommand cmd ->
flow.messageCommand = cmd
if (!flow.messageCommand.validate()){
error()
}
flow.message = null
}
on('error').to('description')
on('success').to('saveMessage')
}
saveMessage{
action{
Message messageInstance = new Message(language:flow.messageCommand.language,value:flow.messageCommand.value,key:flow.currencyId + '_Currency')
if (!messageInstance.save(flush:true)){
flow.message = "${message(code: 'error.adding.description')}"
error()
}
flow.DescriptionMessageList = Message.findAllByKey(flow.currencyId + '_Currency')
}
on('error').to('description')
on('success').to('description')
}
currencyShow{
redirect(controller:'currency', action: "show", id: flow.currencyId)
}
}
Related
I am very new to Groovy and this is an old application where the author is no longer with our organization. None of the previous questions that look similar offered any help. The application needs to send a simple message to the user to warn they are missing an entry before they con continue on.
I have made no fewer than 20 changes from flash.message to confirm. Flash causes the application to jump all the way to the user login function. This confirm is giving a crash message: Error 500: Executing action [submitrequest] of controller [SdrmController] caused exception: Runtime error executing action
def submitrequest = {
def testChecker
testChecker = [params.fullExpName].flatten().findAll { it != null }
log.info('testChecker.size = ' + testChecker.size)
if (testChecker.size > 0) {
if (!confirm('Submitting can not be undone, are you sure?')) return
} else {
if (!confirm('You have to pick an expedition. Please return to your Request and pick at least one expedition.')) return
} else {
return
}
}
// rest of long time working code here
}
Expected Result is a simple message to screen tell the user to pick an "Expedition" from a list and then the code returns to the same point so the user can make the change then hit the submit again.
Then full message:
No signature of method: SdrmController.confirm() is applicable for argument types: (java.lang.String) values: [You have to pick an expedition. Please return to your Request and pick at least one expedition.] Possible solutions: notify(), render(java.lang.String)
-- flash.message worked for our situation.
`legChecker = [params.programLeg].flatten().findAll{it!=null}
if(requestInstance.futurePast == "future" && expChecker.size<1) {
flash.message = " you must select a future expedition "
render(view: 'stepstart', model: [....])
return
}`
I am trying to setup a simple API. I have a Controller all other API controllers are extending, and I have attached a dispatch listener like so. I created a test that will always fail. Set the status code to 401, and return a message. However, it's still calling the main Controller method and not abandoning the request from the preDispatch method. Can I build a proper response here and force ZF2 not to continue executing the requested route? I tried just adding an exit() statement, but the client side receives an incomplete response.
protected function attachDefaultListeners()
{
parent::attachDefaultListeners();
$events = $this->getEventManager();
$this->events->attach('dispatch', array($this, 'preDispatch'), 100);
$this->events->attach('dispatch', array($this, 'postDispatch'), -100);
}
public function preDispatch (MvcEvent $e)
{
$this->dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default');
// TODO: Check user and token from DB
if (Cookie::isCookieSet())
{
$cookie = Cookie::readCookie();
if (empty($cookie->user))
{
$this->getResponse()->setStatusCode(401);
return new JsonModel(array('auth' => false, 'msg' => 'Try again'));
}
// Cookie not set, if we are authenticating, continue; otherwise return a failure
} else {
}
}
You need to return a response object to short circuit the process, not a ViewModel:
Try something like this:
$response = $this->getResponse();
$response->setStatusCode(401);
$response->setContent(array('auth' => false, 'msg' => 'Try again'));
return $response;
I have a simple controller with an action for a long running task and an action for checking a status of the long task:
class AsyncController {
def index() { }
def longTerm() {
session.longTerm = 0
session.longTermDone = false
task {
for (int i; i < 10; i++ ) {
try {
sleep(3000) //NOT WORKING
println " TASK: sessionID ${session.id} value ${session.longTerm++}"
//sleep(3000) //WORKING
} catch (e) {
println(e.class.name)
}
}
session.longTermDone = true
}
render(text: [] as JSON, status: 200)
}
def longTermStatus() {
println "STATUS: sessionID ${session.id} value ${session.longTerm}"
render(text: [successCount: session.longTerm, done: session.longTermDone] as JSON, status: 200)
}
}
In the longTerm action there is a problem with HttpSession.
If the first line of code in the task closure is doing something with HttpSession the rest of the code is working fine. But if the first line is doing something else I get NullPointerException when I try to access session.id
Working code example is at https://github.com/machacekjan/StackOverflowAsyncRequest
Does anyone know why Grails behaves this way?
The issue here appears to be that you're performing the render() outside of the tasks block. If you move render() inside the tasks block, the NullPointerException disappears.
I think this is because the render() finishes the request and you bypass the Servlet 3 Async support. You need to return a promise from the action, which task() does .
Unfortunately, render() doesn't seem to work with the async stuff in Grails 2.3.7 or 2.3.10. But that's a separate issue.
Below is my Geb Page, Spec and Error. I am not sure where and what the issue is. When I remove the below from the ApplicationSummaryPage then I doesn't get this error.
ds(wait: true)
{ module DatasourceInformationRow, $("table.ic-table-creditReportProduct table tr", it) }
class ApplicationSummaryPage extends Page
{
static url = "application-summary/application-summary.jsf"
static at =
{ assert title == "Application Summary" }
static content =
{
menu
{ module MenuModule }
userPanel
{module UserPanelModule }
ds(wait: true)
{ module DatasourceInformationRow, $("table.ic-table-creditReportProduct table tr", it) }
applicationSummaryForm
{ $("#applicationSummary_form") }
workItemDiv
{$("div", id: "consumerWorkItems:workItemPanel")}
workItemsSection
{workItemDiv.find (".ui-panel-title").text()}
resubmitLink
{$("a",id: "loginForm")}
overrideDecisionLink
{$("a",id: "loginForm")}
addNoteLink
{$("a",id: "loginForm")}
}
}
Spec
class SearchSpec extends BaseUiSpec
{
def setup()
{
login("manager")
}
def "cccc"()
{
when: "I search"
to SearchPage
at SearchPage
applicationid.value "10002000000010000"
searchButton.click()
at SearchPage
waitFor
{ searchResultsData }
println "------------"+ searchResults(0).ApplicationId.text()
searchResults(0).ApplicationId.click(ApplicationSummaryPage)
Thread.sleep 5000
at ApplicationSummaryPage
println "-----???"+ ds
}
}
Error
geb.waiting.WaitTimeoutException: condition did not pass in 15.0 seconds (failed with exception)
at geb.waiting.Wait.waitFor(Wait.groovy:126)
at geb.content.PageContentTemplate.create(PageContentTemplate.groovy:117)
at geb.content.PageContentTemplate.get(PageContentTemplate.groovy:98)
at geb.content.NavigableSupport.getContent(NavigableSupport.groovy:43)
at geb.content.NavigableSupport.propertyMissing(NavigableSupport.groovy:127)
at geb.Browser.propertyMissing(Browser.groovy:175)
at geb.spock.GebSpec.propertyMissing(GebSpec.groovy:55)
at test.SearchSpec.cccc(SearchSpec.groovy:33)
Caused by: geb.error.InvalidPageContent: Definition of page component template '$' of 'ApplicationSummaryPage' is invalid, params must be either a Closure, or Map and Closure (args were: [class java.lang.String, null])
at geb.content.PageContentTemplateBuilder.throwBadInvocationError(PageContentTemplateBuilder.groovy:69)
at geb.content.PageContentTemplateBuilder.methodMissing(PageContentTemplateBuilder.groovy:51)
at groovy.lang.GroovyObjectSupport.invokeMethod(GroovyObjectSupport.java:44)
at com.equifax.ic.testing.framework.ui.pages.applicationmanagement.ApplicationSummaryPage._clinit__closure2_closure5(ApplicationSummaryPage.groovy:24)
at com.equifax.ic.testing.framework.ui.pages.applicationmanagement.ApplicationSummaryPage._clinit__closure2_closure5(ApplicationSummaryPage.groovy)
at geb.content.PageContentTemplate.invokeFactory(PageContentTemplate.groovy:134)
at geb.content.PageContentTemplate.create_closure1(PageContentTemplate.groovy:103)
at geb.content.PageContentTemplate.create_closure1(PageContentTemplate.groovy)
at geb.waiting.Wait.waitFor(Wait.groovy:115)
... 7 more
The problem was that i wan't passing the index for ds. The corrected version is below
println "-----???"+ ds(0)
Got the response on Geb mailing list. Posting here for others.
How can I detect the language of the browser and automatically display the correctly localized version of my grails website depending on that value.
I put this in to Index action
Locale locale = new Locale(params.lang)
cookieLocaleResolver.setLocale(request, response, (Locale)
session.getAttribute('locale'))
{
render controller: "home", action: "index"
return
}
And I got exception--
Error 500: Executing action [index] of controller [socialworking.HomeController] caused exception: null
Servlet: grails
URI: /socialworking/grails/home.dispatch
Exception Message:
Caused by:
Class: Unknown
First off, you should put that in a filter in grails-app/conf directory. Create a filter if you don't already have one.
MyFilters.groovy
class MyFilters {
def filters = {
setLocale(controller:'*', action:'*') {
before = {
// Your logic here
}
}
}
}
Your logic here could look in many ways, but here is a try:
String langToSet = 'en';
if ( params.lang && params.lang in validLanguages )
langToSet = params.lang;
else if ( session.lang ) {
langToSet = session.lang;
}
else if ( ... ) // Cookie lang is set ( User might have accessed the site before and you have stored their preferred lang )
// Get cookie lang
Locale locale = new Locale( langToUse)
org.springframework.web.servlet.support.RequestContextUtils.getLocaleResolver(request).setLocale(request, response, locale);
// Set the cookie lang
...
// We set the session lang
session.lang = langToSet
Note that the above is not a complete implementation but it is almost. The cookie stuff and validLanguages you should be able to figure out what they do.
I hope that helps!