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

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.

Related

Preventing a write to the database from Grails controller

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()])
}
}

How to modify the value of the ID column (or columns) in the edit view in Grails 3?

How do you allow the values of the ID columns to be modified at runtime in Grails 3? In my case, I have a table with a composite primary key consisting of three columns. I manually specified them to appear in the edit view and my update() method code looks like this:
#Transactional
def update(AliasFrequencyDict aliasFrequencyDict) {
aliasFrequencyDict = AliasFrequencyDict.get( new AliasFrequencyDict(params) )
if (aliasFrequencyDict == null) {
notFound()
return
}
aliasFrequencyDict.properties = params
try {
aliasFrequencyDict.save(insert: false, flush: true)
} catch (ValidationException e) {
respond aliasFrequencyDict.errors, view:'edit'
return
}
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'aliasFrequencyDict.label', default: 'AliasFrequencyDict'), aliasFrequencyDict.getPK()])
redirect(action: 'show', params: params)
}
'*'{ respond aliasFrequencyDict, [status: OK] }
}
}
...and when I go into edit view and edit the property not being part of the key, it saves correctly but as soon as I change one of the other ones, I get a message reading that Grails could not found an AliasFreuqencyDict instance of ID null. I guess the problem is that, once you change one of such columns, the ID changes too and Grails somehow doesn't know how to switch from the primary key that the object used to have to the new ones.
How should I modify the controller to allow for editing the part-of-key columns too, then?
The (most obvious) problem here is the way you're looking up the one you want to update. If you share your domain model for AliasFrequencyDict I can be more specific, but say you have a composite key of First and Last and an instance where [first:"John", last:"Doe"].
Now you update that to set first=Jane and press update... you are creating a new AliasFrequencyDict for "Jane Doe" and using that in the lookup of .get(), of course that's not going to return an instance of AliasFrequencyDict. If you're changing the value of a PK field, you'll need to pass in the old values to look up the object, and then set the new values accordingly.

GORM instance auto persist to database on update issue

I have a custom validation in controller because I need to validate with database.
def update(Object instance) {
if (instance == null) {
notFound()
return
}
if (instance.hasErrors()) {
//redirect code here
return
}
def obj = objService.someMethod()
//some validation code here
if(someCheck){
// if i discard it wont work
instance.discard()
flash.error = message(code: 'message.code')
//render code here
return
}
In the above code even the instance.discard() does not work after the database access is performed. The changed data is automatically saved even there is no save method call. The same instance.discard() will work if there is no database access is performed. How do I discard the changed value to be persisted to the database when there is a validation failure.
Add the annotation #Transactional(readonly = true) above your update action. That should do the trick.
This is the in built feature of Grails that automatically persist the instance to the database.
Please read my answer here for more detail
https://stackoverflow.com/a/32659803/2405040

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.

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