remoteFunction won't work without render - grails

Here is a fragment of my javascript code:
${remoteFunction(controller: 'job', action: 'updateTimeStamp', update: 'randomString', params: '{timeStamp:timeStamp, sessionId:sessionId}')};
var jobIsDone = ${remoteFunction(controller: 'job', action: 'jobIsDone', params: '{sessionId:sessionId}')};
The first line works as expected, and the second one gives me 404 exception. jobIsDone() method doesn't render anything. I couldn't find proper explanation of remoteFunction tag, but as far as I understood it can be used without rendering, am I mistaken?
Here are the controller methods:
def updateTimeStamp(){
timeStampMap.putAt(params.sessionId, params.timeStamp)
def randomString = bcvjobService.saySomething()
render "<p>${randomString}</p>"
}
def jobIsDone(){
if (jobDone.get(params.sessionId)){
return true
}
else return false
}

Try with this:
def jobIsDone(){
if (jobDone.get(params.sessionId)){
response.sendError(200,"ok")
}
else {
response.sendError(500,"error")
}
}
This will prevent the 404 not found. If you want that come back a true or false with a JSON for example is:
def jobIsDone(){
def result = [error:true]
if (jobDone.get(params.sessionId)){
result.error = false
}
render result as JSON
}

Related

ERR_TOO_MANY_REDIRECTS in grails

I have a filter that is applicable for all controllers and actions
all(controller:'*', action:'*')
If a certain condition is met, I am trying to redirect the user to another page. But I am getting the above stated error. I inserted some logs to see if the filter is being applied or not and I noticed that the
if(condition){} block was being executed multiple times and hence I believe the error is occurring.
Please let me know how I can overcome this. Thank you.
I have code, I hope this help you
def filters = {
sessionCheck(controller: '*', action: '*') {
before = {
if(!(controllerName=="valueSet" && (actionName=="MATReleases" || actionName=="downloadReleases"))) {
if ("your condition") {
def url =new ApplicationTagLib().createLink(controller:'router',action:'sessionExpired')
render(status: 500, contentType: 'text/html', text: "<script>var sessionExpired ; window.location.href='${url}';</script>")
return false
}else{
}
} else {
println "else part"
}
}
}
}

Grails loading widgets in Parallel

I have some widgets in my application. I want to load them in a single page. It works always when loaded sequentially,but fails(throws exception-java.lang.IllegalStateException-Cannot ask for request attribute - request is not active anymore!) when loaded in parallel. Am I missing something ? Is there any other way to load these in parallel? Please suggest. Here is my code snippet
class TestController {
def widget1() {
render "Widget 1"
}
def widget2() {
render "Widget 2"
}
}
class ManagerController {
def loadSequential(){
def data = [:]
data['view1'] = g.include(action: 'widget1', controller: 'test')
data['view2'] = g.include(action: 'widget2', controller: 'test')
render data['view1']
render data['view2']
}
def loadParallel(){
def data = [:]
PromiseMap pm = new PromiseMap()
pm['view1'] = { g.include(action: 'widget1', controller: 'test') }
pm['view2'] = { g.include(action: 'widget2', controller: 'test') }
def result = pm.get()
render result['view1']
render result['view2']
}
}
Here's my 2p on this matter.
We've tried really hard to make Grails render pages in parallel but we couldn't make it work. After digging really deep we simply found that Grails is not ready for this kind of stuff. It's build in a way where rendering is always thread-exclusive.
I'd say it's all due to the org.codehaus.groovy.grails.web.pages.GroovyPageOutputStack that is not ready for a concurrent access.
I'll watch this space just in case someone managed to make it work.
Try this:
import static grails.async.Promises.*
...
def loadParallel() {
task {
def data = [:]
PromiseMap pm = new PromiseMap()
pm['view1'] = { g.include(action: 'widget1', controller: 'test') }
pm['view2'] = { g.include(action: 'widget2', controller: 'test') }
def result = pm.get()
render result['view1'] + result['view2']
}
}
In the loadSequential() example you are not loading response sequentially, but concatenating two views into a single response. Parallel rendering should be a client side job. See for example how Lift does it with jQuery.

Grails 2.3.8 function being called by itself?

I have this grails function in my controller:
def remediationSearch() {
def resultList
if (params.rerender) {
println "<><><> remediationsearch called with rerender."
resultList = recordSearchService.individualSearch(session.oldIndRemedParams)
}
else {
params.selectedBatch = selectedBatch
session.oldIndRemedParams = params
resultList = recordSearchService.individualSearch(params)
println "<><><> remediationsearch called fresh."
}
render(template: 'indivSearchResults', model: [resultList: resultList, resultCount: resultList?.size()])
println "<><><> remediationsearch done at " + new Date()
}
which seems to get called when I call this method(in the same controller) which has nothing to do with it:
def chooseupload = {
println "<><><> Begin choose/upload at: " + System.nanoTime()
if (session.user == null) {
render(contentType: 'text/json') {
[success: true, url: createLink(controller: 'customer', action: 'logout')]
}
}
else {
selectedBatch = null
def batchList = (Batch.findAllWhere(userId: session.user.id.toLong(), [sort: "lastUpdate", order: "desc"]))
render(template: 'chooseupload', model: [batchList: batchList, batchCount: batchList.size()])
}
println "<><><> End choose/upload at: " + System.nanoTime()
}
The second method finishes executing and then the first one gets called for a reason I don't understand.
Is it(the first function) being called by some browser mechanism that is being invoked because it stores things in the session? I'd appreciate any pointers in the right direction. I get this printed as a result of calling the 'chooseupload' method:
<><><> Begin choose/upload at: 446158993759810
<><><> End choose/upload at: 446159022252873
<><><> Begin remediationSearch at: 446159080286132
<><><> Rerender call to entityRemediationSearch.
<><><> End remediationSearch at: 446159135646835
So what is happening is that the chooseupload function's template renders but it is immediately rendered over by the template rendered by the remediationSearch() function. And that is the undesired result that led me to investigate this whole thing.
Not sure if this makes more sense as a comment or answer, but I don't have the 50 reputation needed to make a comment, so here it is as an answer :-)
I noticed that in your text output you have the line:
<><><> Rerender call to entityRemediationSearch.
But that is not included in the code you provided. Would it be possible that you're using an IDE that has not properly cleaned out old versions of the class files? Did chooseupload() call remediationSearch() at one point in time? If so, it seems like it would be good to try running this from the command line, after running grails clean.

Grails redirect after uploadForm

I am trying to redirect a page after a g:uploadForm has submitted.
my g:uploadForm action is save.
the save is as follows:
#Transactional
def save(DesignCategory designCategoryInstance) {
if (designCategoryInstance == null) {
notFound()
return
}
if (designCategoryInstance.hasErrors()) {
respond designCategoryInstance.errors, view: 'create'
return
}
def disotypeFile = request.getFile('disotype1')
if(!disotypeFile.empty){
print('here')
def fname = disotypeFile.getOriginalFilename()
def fileAtt = new FileAttachment()
fileAtt.originalFilename = fname
fileAtt.newFilename = "disotype-"
fileAtt.fileURI = '/Users/work/Desktop/files/' + fileAtt.newFilename
disotypeFile.transferTo(new File(fileAtt.fileURI))
response.sendError(200, 'Done')
fileAtt.save(flush: true)
designInstance.disotype = fileAtt;
}
designCategoryInstance.save flush: true, failOnError:true
flash.message = message(code: 'default.created.message', args: [message(code: 'designCategoryInstance.label', default: 'DesignCategory'), designCategoryInstance.id])
redirect designCategoryInstance
}
This gives the following error:
Cannot issue a redirect(..) here. The response has already been committed either by another redirect or by directly writing to the response.. Stacktrace follows:
Message: Cannot issue a redirect(..) here. The response has already been committed either by another redirect or by directly writing to the response.
This does work if i take out the
def disotypeFile = request.getFile('disotype1')
but obviously I cannot get the file.
any ideas?
Try to remove line:
response.sendError(200, 'Done')

webflow in grails application

how can i redirect to the same state more than one time using web flow
ex:
on('submit'){
def destinationInstance = Destination.get(params.destination)
def destinationGroupsInstance = DestinationGroup.get(params.destinationGroups)
def h = destinationInstance.addToDestinationGroups(destinationGroupsInstance)
}.to('flowList')
what i need is how to enter to this state more than one time until destinations ends
thx
on('submit'){
def destinationInstance = Destination.get(params.destination)
def destinationGroupsInstance = DestinationGroup.get(params.destinationGroups)
def h = destinationInstance.addToDestinationGroups(destinationGroupsInstance)
}.to{
(condition or while loop or for loop)
if success then
return "<state name>"
else
return "flowList"
}
Reference:
http://livesnippets.cloudfoundry.com/docs/guide/2.%20Grails%20webflow%20plugin.html
Well, you'd probably have something like the following code, which is untested but may give you a general idea.
def destinationFlow = {
initialize {
action {
flow.destination = Destination.get(params.id)
}
on('success').to 'destinationList'
}
destinationList {
render(view: 'destinationList')
on('addDestination') {
def destinationGroup = DestinationGroup.get(params.destinationGroupId)
flow.destination.addToDestinationGroups(destinationGroup)
}.to 'destinationList'
on('finish').to 'done'
}
done {
flow.destination.save()
redirect(...) // out of the flow
}
}
You'll need buttons on your destinationList view that invoke the 'addDestination' or 'finish' actions. See the WebFlow documentation and Reference Guide.

Resources