Domain class hasMany fails to add entry - grails

I'm a Grails noob so please excuse my noob question.
I've created a domain classes User and Device. User hasMany devices:Device, and Device belongsTo user:User.
It is important that only 1 device will never belong to two users so my UserController code looks like this:
class UserController {
static allowedMethods = [create: 'POST']
def index() { }
def create() {
def user = User.findByUsername(request.JSON?.username)
def device = Device.findById(request.JSON?.deviceId)
if (device) {
device.user.devices.remove(device)
}
// device can only be owned by 1 person
def new_device = new Device(id: request.JSON?.deviceId, type: request.JSON?.deviceType)
if ( !user ) {
user = new User(
username: request.JSON?.username
)
user.devices = new HashSet() // without this I get null on the add in next line
user.devices.add(new_device)
user.save()
if(user.hasErrors()){
println user.errors
}
render "user.create " + request.JSON?.username + " devices.size " + user.devices.size()
} else {
user.devices.add( new_device )
user.save()
if(user.hasErrors()){
println user.errors
}
render "user.create exists, new token: " + user.token + " devices.size " + user.devices.size()
}
}
}
But now I get a strange server error:
null id in Device entry (don't flush the Session after an exception occurs)
What am I missing here??
Thanks a lot!

First of all, there are special methods to add to and remove from. Do not operate straight on hasMany collections. Maybe this is problematic.

Related

Can't make Grails and audit-logging plugin work

I'm trying to add data auditing to my Grails project, but it doesn't work. I've read this tutorial on grails site and did everything as described there.
What I have now is a domain class Event looking as simple as this:
class Event {
static auditable = true;
String name;
def onSave = {
println "event inserted";
}
def onChange = {
println "event changed";
}
}
and a method in the main controller:
def addEvent = {
def obj = new Event([name:"Test event 1"]);
if (obj.save(flush:true)){
render "addEvent complete for " + obj.toString();}
else{
render "addEvent failed for " + obj.toString();
obj.errors.allErrors.each {
log.error( it.toString() );
}
}
}
I also added auditLog.verbose = true to the Config.groovy file.
Still when I call this method from my browser, the new event is created in DB, but there is nothing in the audit_log table, nor in the console about this happening.
What am I missing here?

Grails querying the database

I am trying to query a database within grails using:
def per = User.get(springSecurityService.principal.id)
def query = Post.whereAny {
author { username == per.username }
}.order 'dateCreated', 'desc'
messages = query.list(max: 10)
My User is in a User domain and in the Post domain I have:
String message
User author
Date dateCreated
when I run this query its empty every time my method in the controller for populating the database is:
def updateStatus() {
def status = new Post(message: params.message)
System.out.println("test " + params.message)
status.author = User.get(springSecurityService.principal.id)
status.save()
}
I am very new at quering databases in grails so if anyone could recommend some reading this would be good too.
Thanks
New version of spring-security-core plugin add methods to you controller, thus you can replace:
def per = User.get(springSecurityService.principal.id)
def query = Post.whereAny {
author { username == per.username }
}.order 'dateCreated', 'desc'
messages = query.list(max: 10)
with
messages = Post.findAllByAuthor(principal, [sort: 'dateCreated', order 'desc', max: 10])
Without declaring springSecurityService
You can replace the updateStatus action with:
def updateStatus(){
def status = new Post(message: params.message, author: principal)
status.save()
}
Empty query may be resolved with:
def updateStatus() {
def status = new Post(message: params.message)
System.out.println("test " + params.message)
status.author = User.get(springSecurityService.principal.id)
status.save(flush: true)
}
This may help you find the data later as the save() just gives your hibernate context the instruction to persist the data, but does not force hibernate to do it at that moment. passing flush:true will force data to be persisted immediately. Also status.save(failOnError:true) will reveal if your domain object properties have validation issues preventing the domain instance from being saved at all to the database (by throwing an Exception). You can use both if desired:
def updateStatus() {
def status = new Post(message: params.message)
System.out.println("test " + params.message)
status.author = User.get(springSecurityService.principal.id)
status.save(flush: true, failOnError: true)
}
hope that helps.
You can set flush and failOnError: true globally as well in grails-app/conf/Config.groovy:
grails.gorm.failOnError=true
grails.gorm.autoFlush=true

Grails login doesn't work

I'm new to Grails, and having a problem that is no doubt trivial, but I cannot find anything online!
I have a class:
package lib
class Login {
String name
String email
String password
String phonenumber
static constraints = {
}
}
In my Bootstrap file I create two instances of this class:
new Login(email:"tom", password:"password1")
new Login(email:"ian", password:"password2")
Now I have set up a Login form and I am trying to loop over these values and do something if they match:
def submit() {
def result = Login.findAll { email == params.email && password == params.password }
if (result.size() > 0) {
println "good login"
}
else {
println "bad login"
}
// some other stuff
}
The problem is that it is printing "bad login" every time, every when the entered email and password match those declared in the Bootstrap file. It's probably just a misunderstanding on my end, but I can't figure it out!
Thanks.
phonenumber and name are null in your initialisation. Therefore the users cannot be persisted in your bootstrap.groovy. Double check, that save works:
def login1 = new Login(..)
if (!login1.save()) {
log.error("Login cannot be persisted: " + login1.errors);
}

Grails: save is not working

i have created new domain in grails and from a controller i've tried to save but nothing get saved in the database.. the code is as follow
controller
def register={
String name = params.name
String email = params.email
String pass = params.password
boolean signedIn = params.signedIn
System.out.println(name + " " + email +" "+ pass+" " + signedIn)
def rUser = new Registered(params)
rUser.signedIn = signedIn
System.out.println(rUser)
rUser.save(flush:true)
}
domain
class Registered {
String name;
String email;
String password;
boolean signedIn =false;
static constraints = {
}
}
and i'm trying to save by this url
http://localhost:8080/egypths/apps/register?name=hegab&email=eio#gmail.com&password=tom&signedIn=false
so what am i doing wrong ... putting in mind that there's no error in the stack trace
I would start by wrapping this in an integration test that would look like this:
import groovy.util.GroovyTestCase
import org.junit.Test
public class RegisterControllerTests extends GroovyTestCase {
#Test
void saveAction() {
def controller = new RegisterController() //or whatever the controller name is
controller.params.name = "SomethingUnique"
controller.params.email = "example#example.com"
controller.params.password = "password"
controller.params.signedIn = "false"
controller.register()
def registered = Registered.findByName("SomethingUnique")
assert "example#example.com" == registered.email
assert "password" == registered.password
assert false == registered.signedIn
}
}
Then I would start by making your controller action as simple as possible:
def register={
String name = params.name
String email = params.email
String pass = params.password
boolean signedIn = params.signedIn
def rUser = new Registered()
rUser.name = name
rUser.email = email
rUser.password = pass
rUser.signedIn = signedIn
rUser.save(flush:true, failOnError:true) //I would remove the failOnError after you identify the issue.
}
This way you can quickly repeat your test and figure out where your problem is. Adding the failOnError:true to the save call will cause an exception to be thrown if it doesn't pass validation. If this simple example works start working back towards a more elegant solution to identify where you're issue resides.

Save On My Domain Class Object Is Not Working.

I have a User class which has a List field namely pt. This field is not initialized when User register his account. But when user goes this controller action :
def updatePt() {
//performs some action
def user = User.get(springSecurityService.principal.id) //find the user
user.pt = []
//on certain conditions i put values into user.pt like this
user.pt << "E"
//at last I save it
user.save()
}
But using user/show action via scaffolding I found that pt field is not saved on users object. Where I'm making a mistake?
You have to provide a static mapping in the Users domain class so that Grails knows the field must be persisted:
class User {
static hasMany = [pt: String]
}
It's possible because of validation error. Try with
if (!user.save()) {
log.error('User not saved')
user.errors.each {
log.error('User error: $it')
}
}
PS or you can use println instead of log.error

Resources