Grails update database row exception - grails

I am using grails,and i have web application.in which when call for update user profile,then i have service for it,in which i set current user properties by request parameters
user.properties = params (params-request parameters),
and in my user domain class i have onChange method(of audit plugins).
So when this method called after setting properties to user profile when control goes to user domain onChange method it gives error
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.web.User#3].
I am still finding solution how to update row.
Thanks in advance.
//userController update method -
def user = User.get(params.id)
user.properties = params
user.save(flush:true)
//and in user domain onChange method-
def onChange = { oldMap,newMap ->
try{
Msg.append("Your profile has been updated successfully with the following changes: ");
oldMap.each({ key, oldVal ->
if(oldVal != newMap[key]) {
if(key =="firstName" || key =="gender" || key =="lastName" || key =="phoneNo" || key =="city"){
Msg.append(" * $key changed from $oldVal to " + newMap[key])
}
}
sendMail(Msg,newMap.email)
})
}
}
After sending email it gives an error.

I think if you try to set all the fields on the user object, then it will work:
def user = User.get(params.id)
user.refresh()
user.firstName= params.firstName
user.lastName= params.lastName
user.gender= params.gender
user.phno= params.phno
user.city= params.city
if(user.save(flush:true, failOnError:true)){
// Now send success email
}
Now it should work.
I think your params map is having id as a property and on setting
user.properties = params
It tries to set id for the user object, that's why you are getting the issue.

Related

Grails .save() is not saving an associated Domain

I have a domain Guest which has a belongsTo association with Person and User domains as follows :
class Guest {
static belongsTo = [
person:Person,
user : User // owner for guest
]
}
In my service GuestService.groovy , i am trying to update associated Person info associated with a given guest :
#Transactional
def updateGuests(def guestArray) {
guestArray.each { data ->
User user = User.findById(data["userId"])
Guest guest = Guest.findByIdAndUser(data["guestId"] , user)
if( ! guest )
throw new NotFoundException("Invalid input parameters")
println(" email : " + guest.person.email + " new email " + data["email"])
Person person = guest.person
//person = Person.findById(person.id)
person.email = data["email"]
person.phoneNumber = data["phoneNumber"]
person.save(flush:true)
//guest.save(flush: true)
}
}
I am unable to update Person info and i don't receive any errors too.
I Debugged the code and all the values are present till exit of the debug point .I searched on internet and other related questions on this stack but no question is related to this kind of problem .
Have you tried person.save(flush: true, failOnError: true)?
It should overwrite a default behavior of returning null on save error and return exception instead.

How to do proper data binding in Grails

I'm trying to do standard flow with adding entity to DB. Flow should look like this:
User opens link example.co/connection/putForm
edit all fields
submit (POST) to example.co/connection/put
if no errors then he is redirected to ../conncetion/index otherwise he should see previous form with all fields filled (step 2) and error message
For now my code looks like this:
def putForm() {
[
providers: Provider.findAll(),
cities : City.findAll()
]
}
#Transactional
def put() {
// not important part of parsing fields from params
def provider = Provider.get(params.provider)
def startTime = parseStartTime(params)
def path = parsePath(params)
def departurePlace = params.departurePlace
def connection = new Connection(provider: provider, startTime: startTime, departurePlace: departurePlace, path: path)
if (connection.save()) {
redirect controller: 'connection', action: 'index', params: [addedConnection: connection.id] // this part is OK
} else {
render view: 'putForm', params: params, model: [connection: connection] // this sucks... look below
}
}
The problem is that I need to render view putForm but from link .../connection/put. This cause problem that after this render all text fields are empty (step 4 above). Also I have ugly link.
Does Grails has any pattern for this common situation?
PS I cannot use scaffolding.
You're not that far off.. try this:
def putForm() {
[
providers: Provider.findAll(),
cities : City.findAll(),
connection: new Connection() // everything defaulted to empty or whatever you want the default to be
]
}
#Transactional
def put( Connection connection ) {
// NOTE: by putting the connection as the parameter to this action,
// all params.X that match a property X in the connection will auto-
// populate, even the Provider, assuming the value of params.provider.id
// is the id of a provider or blank (in which case
// connection.provider will be null.
// Skip this now
//def provider = Provider.get(params.provider)
//def startTime = parseStartTime(params)
//def path = parsePath(params)
//def departurePlace = params.departurePlace
//def connection = new Connection(provider: provider,
// startTime: startTime, departurePlace: departurePlace, path: path)
if (connection.save()) {
redirect controller: 'connection', action: 'index',
params: [addedConnection: connection.id] // this part is OK
} else {
render view: 'putForm', model: [
providers: Provider.findAll(),
cities : City.findAll(),
connection: connection]
}
}
The thing you need now is to make sure your putForm.gsp actually uses the values you sent down. You should put in things like:
<g:input name="path" type="text"
value="${fieldValue( bean:connection, field:'path' )}" />
and
<g:select name="provider.id" from="${providers}" // note the .id in places here
value="${connection.provider?.id ?: ''}"
noSelection="['':'None']"/>
Note that these will populate with whatever is in the connection sent down each time the page is rendered. So the first time it'll just have the default values, and if it has to rerender due to errors, it'll have the connection values that failed validation.
Hope this helps.

Grails: Clear errors when passing object to view

I am checking if my user has entered the same password twice in controller:
if(params.password1 != "" || params.password2 != "") {
// change password
if(params.password1 != params.password2) {
user.errors.rejectValue('password', 'noMatch')
}
user.password = params.password1
}
if (user.errors.errorCount > 0 || !user.save()) {
println user.errors.errorCount
render(view: "edituser", model: [userInstance: user])
return
}
I get the correct user error count displayed in console so my if-clause works and Grails does not re-validate the object by using double pipe.
When I have a look into my GSP I get the following message:
grails.validation.ValidationErrors: 0 errors
It seams like Grails clears all errors or uses an other object. It's curious, because my custom validator in my domain class works fine...

Dart lang, manipulating server returned JSON data in the client

I want to check the user log in parameters, and if the parameters accepted, I want the server to send back to the client both the name and roles of the user, to be saved in the SeassonStorage for further usages.
my server side code is:
....
....
var users = <Map>[];
var logged = <Map>[];
....
....
.then((_) {
for (var user in users)
if(_theData['userName']==user['Alias'] && _theData['password']==user['Password'])
{
userFound=true;;
logged.add({
"Alias":user['Alias'],
"Roles": user['Roles']
});
}
})
.then((_) {
if(userFound == true)
res.write(JSON.encode(logged));
else
res.write('sorry, unknown loggin');
res.close();
});
in the client side, I've:
....
....
if(request.responseText != 'sorry, unknown loggen'){
server_msg.innerHtml='Welcome';
print(request.responseText);
print(JSON.decode(request.responseText));
var FonixLogin = JSON.decode(request.responseText);
print(FonixLogin['Alias']);
print(FonixLogin['Roles']);
Storage sessionStorage = window.sessionStorage;
sessionStorage['FonixAlias'] = FonixLogin['Alias'];
sessionStorage['FonixRoles'] = FonixLogin['Roles'];
....
the output I get is:
[{"Alias":"Admin","Roles":"admin"}]
[{Alias: Admin, Roles: admin}]
Exception: Illegal argument(s): Alias login.dart:66login_Element.onData
Why mistake I made here, so that the returned data is not saved properly in the
FonixLogin is a List and you access it like a Map.
Try print(FonixLogin[0]['Alias']);

return back the value of g:textfield

how can i show back the g:textfield value if the value already havebeen taken.
example :
<input type="text" name="simbol" id="simbol" value="${simbol}"/>
when input the textfield with "1A" then SAVE to database, then i input again with type "1A" again. it will be error because i protect with unique : true, when eror it will be return the input page..
and filled by "1A"
how can i do to get the "1A" when save error and return to the page?
catch(Exception E)
{
[simbol: params.simbol?: "",nama : params.nama?:""]
flash.message = "Simbol Sudah Dipakai !!! "
redirect (action:"tambah")
}
i use try cacth to throw unique save error.
and
[simbol: params.simbol?: "",nama : params.nama?:""], this line i tried to throw/get back the value when save eror or unique
You need put back data into model and `render page.
In your code you redirect without params at all.
This is the common way to do that you need. (Controller code)
def unInstance = new Un(params)
if (!unInstance.save(flush: true)) {
render(view: "create", model: [unInstance: unInstance])
return
}
....
}

Resources