Preventing a write to the database from Grails controller - grails

I have a small Grails project I'm writing as a learning exercise. It gathers some user input from a form (eg. enter two numbers to add), then it calls a service to process that data (eg. add the two numbers), and finally it shows the results on a another page.
When I turned on SQL logging I noticed that the data the user is entering is being saved to the database before the call to the service method inside the controller.
How do I prevent this? I would like ONE write to the database after the call to the service method is complete and there are no errors.
Save method from controller code:
def save() {
def myInstance = new myDomainClass(params)
myInstance.sessionId = session.id
myService argh = new myService()
// wtf does this do?
if (!myInstance.save(flush: true)) {
render(view: "create", model: [myInstance: myInstance])
return
}
// Execute the api and process the results. what is writing the user input to the database before this call?!?!?!?!
def results1 = argh.executeApi(myInstance)
// if the results are null throw an error
if (results1 == null) {
flash.message = message(code: 'api.null.error')
render(view: "create", model: [apiInstance: apiInstance])
return
} else {
forward(action: "list", id: 2, model: [apiInstanceList: Api.list(params), apiInstanceTotal: Api.count()])
}
}
Pointers or help appreciated.

Calling .save(flush:true) will automatically save the myInstance instance to the database at that point. You will want to move the .save(flush:true) to after the service method, and since you said you wanted to make sure there were no errors, you would want to add it to your conditional:
def save() {
def myInstance = new myDomainClass(params)
myInstance.sessionId = session.id
myService argh = new myService()
// Execute the api and process the results. what is writing the user input to the database before this call?!?!?!?!
def results1 = argh.executeApi(myInstance)
// if the results are null throw an error
if (results1 == null) {
flash.message = message(code: 'api.null.error')
render(view: "create", model: [apiInstance: apiInstance])
return
} else {
// save here when you know there are no errors
if (!myInstance.save(flush: true)) {
render(view: "create", model: [myInstance: myInstance])
return
}
forward(action: "list", id: 2, model: [apiInstanceList: Api.list(params), apiInstanceTotal: Api.count()])
}
}

Related

Grails behavior method AddTo*

I'm an instability in my addTo* method which I have a record that constantly have to make the relationship information in one instance . The problem is that when I place multiple inserts in a short time , they cease to be persisted in the database and not after a they return , they are simply discarded time.
My simple class is ' Occurrence ' and ' Monitoring ' , whenever I make a call I have to register it and it occurred on and after 2 consecutive records the 3rd no longer persists in the database and I lose the record .
Class Occurrence implements Serializable{
...
hasMany = [accompaniments: Monitoring]
...
}
Class Monitoring implements Serializable{
...
belongsTo = [occurrence : Occurrence]
...
}
Have the controller looks like this:
def regMonitoring(Long id){
def chamadoInstance = Occurrence.get(id)
if (!chamadoInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'Occurrence .label', default: 'Occurrence '), id])
return
}
chamadoInstance.status = StatusChamado.findByCodigo("MOV")
if (!chamadoInstance.save(flush: true)) {
render(view: "editMonitoring", model: [chamadoInstance: chamadoInstance])
return
}
def mov = chamadoService.regMonitoring("") //returns an instance of Customer with preset output values ​​.
chamadoInstance.addToAccompaniments (mov)
redirect(action: "showChamado", id: chamadoInstance.id)
}
Add in a save of your domain instance after you add to the collection.
chamadoInstance.addToAccompaniments (mov)
chamadoInstance.save(flush: true)
This should solve the issue.

Grails update() cannot locate record, show() and edit() can

I've got a fairly simple Grails app against a DB2 database. Everything works fine except when I try to update a record. show() and edit() are able to find the record , but the update fails saying that it cannot be located. Here's the edit:
def edit()
{
def flatAdjustmentInstance = FlatAdjustment.get( new FlatAdjustment(compPayeeID: params["compPayeeID"], effectiveQuarterBeginDate: params["effectiveQuarterBeginDate"]) ) //here are your inbound params
if(!flatAdjustmentInstance)
{
flash.message = "MRI Modifier Record not found with ${params}"
redirect(action:"list")
}
else
{
return [ flatAdjustmentInstance: flatAdjustmentInstance]
}
}
Now the update()
def flatAdjustmentInstance = FlatAdjustment.get( new FlatAdjustment(compPayeeID: params["compPayeeID"], effectiveQuarterBeginDate: params["effectiveQuarterBeginDate"]) ) //here are your inbound params
//def flatAdjustmentInstance = new FlatAdjustment(compPayeeID: params["compPayeeID"], effectiveQuarterBeginDate: params["effectiveQuarterBeginDate"])
if (!flatAdjustmentInstance)
{
flash.message = message(code: 'default.not.found.message', args: [message(code: 'flatAdjustment.label', default: 'FlatAdjustment'), params])
redirect(action: "list")
return
}
As I said, all controller methods/closures create the instance of the domain object in the same way and all work correctly except for update(). Any ideas?
.get() retrieves an existing object based on its ID. You cannot pass a new object to that method.
FlatAdjustment flatAdjustmentInstance = FlatAdjustment.findByCompPayeeIDAndEffectiveQuarterBeginDate(params.compPayeeID, params.date("effectiveQuarterBeginDate", "INSERTYOURDATEFORMATHERE"))
I figured this one out, and it was a really bone-headed mistake. The form I had created was passing in the compPayeeID, but since the field is not editable by the user, I changed it from an input to a textField. That meant is was no longer being passed in with the grails params object. I changed it back, set the field to read only, and now all is well.

how come some statements require the return statement at the end of some groovy closures?

def handleLogin = {
def hashPassd = DU.md5Hex(params.password)
// Find the username
def user = User.findByUserNameAndPassword(params.userName, hashPassd)
if (!user) {
flash.message = "User not found for userName: ${params.userName}"
redirect(action:'index')
return
} else {
session.user = user
redirect(controller:'todo')
}
}
how come the if condition requires the return statement? and the else block don't require it?
In this case the return is not necessary. If the return isn't there it will continue to after the if, which is the end of the method, and thus returns.
The return is not strictly necessary but it's a good habit to get into. Calls like render and redirect in a controller action are usually intended to be the conceptual "end" of the action, and its easy to forget sometimes and treat the redirect as if it were a return
def someAction() {
if(!params.id) {
flash.message = "no ID provided"
redirect action:'error'
}
def myObj = MyObj.get(params.id)
//...
}
This will fail at runtime, probably with a rather obscure error message, and to avoid this possibility it's a good idea to remember to put an explicit return after any calls to redirect or render. It's the kind of thing that has bitten me when coming back to make changes to a controller action I originally wrote 6 months previously...

Problem with Grails GORM

I am developing an application which queries data from an XML file and creates multiple objects with that data.
class Search {String artist}
class Performance {static belongsTo = [events:Event, artists:Artist]}
class Location {static belongsTo = [events:Event]}
class Event {static hasMany = [performances:Performance]}
class Artist {static hasMany = [performances:Performance]}
This are the domain classes (for the sake of simplicity only relationships are shown).
Then I want to create instances of this objects when the user inserts a new artist in the SearchController. I tried to do that with the following code for the save closure in the SearchController but it seems that it's not working. The resultList is a Map with the values queried from the XML file.
def save = {
def searchInstance = new Search(params)
def resultsList = searchService.lastFmVenues(params.artist)
resultsList.each{
def performanceInstance = new Performance()
def locationInstance = new Location(venue:it.venue, street:it.street, city:it.city, postcode:it.postalcode, country:it.country, lat:it.lat, lng:it.lng)
def artistInstance = new Artist(name:params.artist).addToPerformances(performanceInstance)
def eventInstance = new Event(eventId:it.eventID, title:it.eventTitle, date:it.date, location:locationInstance)
if (searchInstance.save(flush:true) && eventInstance.save(flush: true) && artistInstance.save(flush: true) && locationInstance.save(flush: true) && performanceInstance.save(flush:true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'search.label', default: 'Search'), searchInstance.id])}"
}
else {
render(view: "create", model: [searchInstance: searchInstance])
}
}
redirect(action: "show", id: searchInstance.id)
}
Any ideas?
Thank you.
Try saving your objects with save(failOnError: true). This will cause grails to throw an exception if the objects don't validate. The default behavior is to simply return false from the save method.
You can make failOnError the default behavior by setting grails.gorm.failOnError=true in your Config.groovy, but I wouldn't recommend it for anything besides troubleshooting.

Why are setters in Grails called twice on save?

Look at the following Grails domain class, which modifies a value within a setter, if the object is saved the first time (if it has no id):
class Idtest {
String name
void setName(String name) {
if(!this.id)
this.name = name + "TEST"
else
this.name = name
}
}
If I generate views and controller with generate-all, start the app, and enter "hello" in the generated form, "helloTESTTEST" is saved.
The save function looks like this:
def save = {
def idtestInstance = new Idtest(params)
if (idtestInstance.save(flush: true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'idtest.label', default: 'Idtest'), idtestInstance.id])}"
redirect(action: "show", id: idtestInstance.id)
}
else {
render(view: "create", model: [idtestInstance: idtestInstance])
}
}
Why is the setter called twice?
Instead of doing
if(!this.id){ }
You should use beforeInsert()
GORM Advanced Features
I believe it is called once when you create the object and it is saved
Then it would be called again when you retrieved the object from the database.
So..
On saving to to the database the property is set, lets assume a counter = counter + 1. so now one is saved to the database.
When you retrieve the object from the database, the domain object setter will be called again thereby incrementing the counter again counter++
This is all an assumption since the there is no controller code here for us to see how you are creating and or saving the objects so dont bash me if I am completely off

Resources