Grails: save is not working - grails

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.

Related

grailsApplication null in Service

I have a Service in my Grails application. However I need to reach the config for some configuration in my application. But when I am trying to use def grailsApplication in my Service it still gets null.
My service is under "Services".
class RelationService {
def grailsApplication
private String XML_DATE_FORMAT = "yyyy-MM-dd"
private String token = 'hej123'
private String tokenName
String WebserviceHost = 'xxx'
def getRequest(end_url) {
// Set token and tokenName and call communicationsUtil
setToken();
ComObject cu = new ComObject(tokenName)
// Set string and get the xml data
String url_string = "http://" + WebserviceHost + end_url
URL url = new URL(url_string)
def xml = cu.performGet(url, token)
return xml
}
private def setToken() {
tokenName = grailsApplication.config.authentication.header.name.toString()
try {
token = RequestUtil.getCookie(grailsApplication.config.authentication.cookie.token).toString()
}
catch (NoClassDefFoundError e) {
println "Could not set token, runs on default instead.. " + e.getMessage()
}
if(grailsApplication.config.webservice_host[GrailsUtil.environment].toString() != '[:]')
WebserviceHost = grailsApplication.config.webservice_host[GrailsUtil.environment].toString()
}
}
I have looked on Inject grails application configuration into service but it doesn't give me an answer as everything seems correct.
However I call my Service like this: def xml = new RelationService().getRequest(url)
EDIT:
Forgot to type my error, which is: Cannot get property 'config' on null object
Your service is correct but the way you are calling it is not:
def xml = new RelationService().getRequest(url)
Because you are instantiating a new object "manually "you are actually bypassing the injection made by Spring and so the "grailsApplication" object is null.
What you need to do is injecting your service using Spring like this:
class MyController{
def relationService
def home(){
def xml = relationService.getRequest(...)
}
}

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

Writing an Integration Test in Grails that will test DB persistence

My Integration-Test for my grails application is returning a null object when I try to get a domain object using grails dynamic get method.
This is a simplified example of my problem. Lets say I have a controller TrackerLogController that uses a service TrackerLogService to save an updated Log domain for another Tracker domain.
Domain Tracker:
class Tracker {
int id
String name
static hasMany = [logs: Log]
}
Domain Log:
class Log {
int id
String comment
static belongsTo = [tracker: Tracker]
}
Controller TrackerLogController save:
def TrackerLogService
def saveTrackerLog() {
def trackerId = params.trackerId
def trackerInstance = Tracker.get(trackerId)
Log log = TrackerLogService.saveTrackerLogs(trackerInstance, params.comment)
if( log.hasErrors() ){
//render error page
}
//render good page
}
Service TrackerLogService save:
Log saveTrackerLogs( Tracker tracker, String comment) {
Log log = new Log(tracker: tracker, comment: comment)
log.save()
return log
}
So now I want to write an Integration-Test for this service but I'm not sure if I should be writing one just for the simple logic in the controller (if error, error page else good page) I would think I would write a Unit test for that, and an Integration-Test to check the persistence in the Database.
This is what I have for my Integration-Test:
class TrackerLogServiceTests {
def trackerLogService
#Before
void setUp(){
def tracker = new Tracker(id: 123, name: "First")
tracker.save()
//Now even if I call Tracker.get(123) it will return a null value...
}
#Test
void testTrackerLogService() {
Tacker trackerInstance = Tracker.get(123) //I have tried findById as well
String commit = "This is a commit"
//call the service
Log log = trackerLogService.saveTrackerLogs(trackerInstance , commit)
//want to make sure I added the log to the tracker Instance
assertEquals log , trackerInstance.logs.findByCommit(commit)
}
}
So for this example my trackerInstance would be a null object. I know the Grails magic doesn't seem to work for Unit tests without Mocking, I thought for Intigration-Tests for persistence in the DB you would be able to use that grails magic.
You can't specify the id value unless you declare that it's "assigned". As it is now it's using an auto-increment, so your 123 value isn't used. It's actually ignored by the map constructor for security reasons, so you'd need to do this:
def tracker = new Tracker(name: "First")
tracker.id = 123
but then it would get overwritten by the auto-increment lookup. Use this approach instead:
class TrackerLogServiceTests {
def trackerLogService
private trackerId
#Before
void setUp(){
def tracker = new Tracker(name: "First")
tracker.save()
trackerId = tracker.id
}
#Test
void testTrackerLogService() {
Tacker trackerInstance = Tracker.get(trackerId)
String commit = "This is a commit"
//call the service
Log log = trackerLogService.saveTrackerLogs(trackerInstance , commit)
//want to make sure I added the log to the tracker Instance
assertEquals log , trackerInstance.logs.findByCommit(commit)
}
}
Also, unrelated - don't declare the id field unless it's a nonstandard type, e.g. a String. Grails adds that for you, along with the version field. All you need is
class Tracker {
String name
static hasMany = [logs: Log]
}
and
class Log {
String comment
static belongsTo = [tracker: Tracker]
}

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);
}

Domain class hasMany fails to add entry

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.

Resources