Error in creating objects - grails

Hello I have these two classes
class Company {
String company_name
static constraints = {
company_name size: 3..20, unique: true, nullable: false
}
String toString() { return company_name}
}
class Job {
String job_name
Company company
static constraints = {
job_name size: 3..20, unique: false, nullable: false
company nullable: false
}
String toString() { return job_name}
}
and this method :
def register(String company_name,String job_name)
{
def job = new Job(company : new Company(company_name : company_name), job_name: job_name)
if (job.validate() && job.save())
{
redirect(url:"https//localhost:8080")
}
}
I can create object for example Company:nvidia, Job:worker but if I try to create another position for the company nvidia- Company:nvidia, Job:owner I get an error why?It is in the if clause

You have a unique constraint at the company_name attribute and your code is trying to create a new Company instance with every new Job instance.
You should do it like this:
def nvidiaCompany = new Company(company_name: 'nVidia').save()
def jobDesigner = new Job(company: nvidiaCompany, job_name: 'designer')
def jobDeveloper = new Job(company: nvidiaCompany, job_name: 'developer')
So you're reusing the Company instance. If you create just one Job instance in the code, you have to obtain the Company instance first:
def nvidiaCompany = Company.findByCompanyName('nvidia')
def jobDesigner = new Job(company: nvidiaCompany, job_name: 'designer')

Related

ElasticSearch in Grails, search return no results when domain field has value with # character

I encountered a problem when I was changing Searchable plugin to ElasticSearch plugin (:elasticsearch:0.0.3.8) for Grails (2.4.4).
Let's say that I have domain object and a service:
class Person {
String firstName
String lastName
String email
static constraints = {
id bindable: true
firstName blank: false
lastName blank: false
email blank: false, unique: true, email: true
}
static searchable = {
root true
only = ['id', 'firstName', 'lastName', 'email']
}
}
class SearchService {
List<Person> findPersons(String searchPhrase) {
Innovator.search(searchPhrase + '*').searchResults
}
}
My Config.groovy file contains following config:
elasticSearch {
client.mode = 'local'
index.store.type = 'memory'
date.formats = []
defaultExcludedProperties = ["password"]
disableAutoIndex = false
datastoreImpl = 'hibernateDatastore'
bulkIndexOnStartup = true
maxBulkRequest = 500
}
Suppose that we have following person in DB:
Person(firstName: 'Julius', lastName: 'Caesar', email: 'julius.caesar#domain.com')
Now, when I invoke findPersons('Julius') or findPersons('Caesar') or findPersons('Jul') etc. then as a result I get list with one Person object.
But when I try to search using phrase with '#' character for example: findPersons('julius.caesar#doma') or findPersons('julius.caesar#domain.com') I do not receive any results, hovever findPersons('julius.caesar') is ok.
Analogical code in Searchable plugin works correct.
I've tried to remove '*' character and it didn't help.
As workaround I changed searchable closure to:
static searchable = {
root true
email index : 'not_analyzed'
only = ['id', 'firstName', 'lastName', 'email']
}
and findPersons method to:
List<Person> findPersons(String searchPhrase) {
if(!searchPhrase.contains('#'){
searchPhrase += '*'
}
Innovator.search(searchPhrase).searchResults
}
Now I can use findPersons('julius.caesar#domain.com') to find Person object. But this is exact value and I would like to use also prefix search for email field.
For example: findPersons('julius.caesar#doma') should also return Person as a result.
Thank you for any tips and any help in solving this issue.
Regards,
Kamil

Saving related entity in grails

I have a problem with saving form values from two domain classes
One class is
class Ip {
String inetAddress
String dns
String os
String toString(){
"${inetAddress}"
}
Hoster hoster
static constraints = {
....
and the second one is just
class Hoster {
static HOSTER_OPTIONS = ["Name1", "Name2", "Name3"]
String name;
String toString(){
"${name}"
}
List ips = new ArrayList()
static hasMany = [ips : Ip]
static constraints = {
name(unique: true, blank: false, inList: HOSTER_OPTIONS)
}
I have a Controller where I handle the data from a form
def systems = new Ip()
systems.inetAddress = params.ip
systems.dns = params.dns
systems.os = params.os
systems.hoster.name = params.hoster
def result = systems.save(flush: true, failOnError: true)
But I didn't get it managed that the data is saved.
You're not associating correctly your domain classes in the controller:
systems.hoster.name = params.hoster
Instead of setting the name, you need to set the instance that exists in the database:
systems.hoster = Hoster.findByName(params.hoster)

how to prevent casade on updates

I'm working in grails and I've noticed some strange behavior to which I'd like to fix but I cannot figure out what I'm missing.
I have a location which can have may buildings. Each building can have multiple suites.
In addition I have a tenant who has a tenant location. The tenant location is used more for historical reporting so that we can see if tenants have moved locations.
The classes look like this
class Location {
String name
String shortName
Country country
LocationTypeEnum locationType = LocationTypeEnum.STUD // as default
static hasMany = [building: Building]
Date dateCreated
Date lastUpdated
static constraints = {
name unique: true, maxSize: 30
shortName unique: true, maxSize: 3
country nullable: false
locationType nullable: false
}
static mapping = {
cache usage: 'nonstrict-read-write', include: 'non-lazy'
}
}
class Building {
String type
String name
Date dateCreated
Date lastUpdated
static belongsTo = [location: Location]
static hasMany = [suites: Suite]
static constraints = {
name unique: true, maxSize: 25
type inList: ["A", "B", "C"], nullable: true
}
String toString() {
name
}
}
class Suite {
int suiteNumber
Date dateCreated
static belongsTo = [building: Building]
static constraints = {
pen(validator: { return it > 0 && (it.toString().length()) <= 3 })
}
String toString() {
suite.toString()
}
}
class Tenant {
static hasMany = [tenantLocation: TenantLocation]
----
Suite suite
String comments
Date dateCreated
Date lastUpdated
boolean active = true
static constraints = {
--------
type
nullable: false
comments maxSize: 5000
}
}
class TenantLocation {
static belongsTo = [tenant: Tenant]
Tenant tenant
Suite suite
Date dateCreated
}
So the idea is that a tenant location is created when tenant is created and a new tenantLocation is created only if and when the current tenant suite changes.
However, what I'm seeing is not only is the tenantLocation being saved (which is what I want) the suite is also being updated (which is not what I want).
For example I have Building 1 and suites 1 - 20 and Building 2 with suites 1 - 25. I have a tenant that is in Building 1 suite 5, they move to Building 2 suite 23. Now all of a sudden Building 2 has two suites with a suite number of 5.
How do I keep my suites from moving from one building to another when I only want the suite the tenant has to change?
The Code that is doing the updating is in the Tenant Controller and looks like this:
def update() {
def tenantInstance = Tenant.get(params.id)
if (!tenantInstance) {
flash.message = message(code: 'default.not.found.message', args: [
message(code: 'tenant.label', default: 'Tenant'),
params.id
])
redirect action: "list"
return
}
if (params.version) {
def version = params.version.toLong()
if (tenantInstance.version > version) {
tenantInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
[
message(code: 'tenantInstance.label', default: 'Tenant')] as Object[],
"Another user has updated this Tenant while you were editing")
render view: "edit", model: [tenantInstance: tenantInstance, BuidingListInstance: Building.list()]
return
}
}
tenantInstance.properties = params
if (!tenantInstance.save(flush: true)) {
render view: "edit", model: [tenantInstance: tenantInstance, BuildingListInstance: Building.list()]
return
}
def tenantLocation= TenantLocation.findAllByTenant(tenantInstance)
def locationCheck = tenantLocation.last()
//if tenant location is not null and the suite/building change create new Tenant Location entry
if (tenantLocation!=null)
{
if(locationCheck.pen.id !=tenantInstance.suite.id)
{
def location = new TenantLocation(
tenant: tenantInstance,
suite: tenantInstance.suite,
dateCreated: new Date()
).save(flush:true)
}
}
flash.message = message(code: 'default.updated.message', args: [
message(code: 'tenant.label', default: 'Tenant'),
tenantInstance.id
])
redirect action: "show", id: tenantInstance.id
}

Deserialize a JSON object with support for embedded associations

Is there an easy way to deserialize a JSON string to a domain class with support of embedded association; belongsTo and hasMany
{
name: "Customer",
contact: {
name: "Contact"
}
}
class Customer {
name
Contact contact
}
class Contact {
String name
static belongsTo = [customer:Customer]
}
in my controller I would like to do the following
def save() {
def customer = new Customer(request.JSON)
customer.save();
}
Now i'm forced to do
def save() {
def contact = new Contact(request.JSON.contact);
def customer = new Customer(request.JSON);
customer.contact = contact;
customer.save();
}
Have you tried using JsonSlurper?
Example usage:
def slurper = new JsonSlurper()
def result = slurper.parseText('{"person":{"name":"Guillaume","age":33,"pets":["dog","cat"]}}')
assert result.person.name == "Guillaume"
assert result.person.age == 33
assert result.person.pets.size() == 2
assert result.person.pets[0] == "dog"
assert result.person.pets[1] == "cat"
Ref: http://groovy.codehaus.org/gapi/groovy/json/JsonSlurper.html
you can try this
Test test
def result = new JsonSlurper().parseTest('yourString')
test = result
Try this will work.

Grails Integration test: Failure...Cannot invoke method addToPosts() on null object

:D
I was following a tutorial in a book, and I did follow it thoroughly.
However, come the part where I am supposed to write an integration test, it suddenly failed saying: Cannot invoke method addToPosts() on null object right after I ran the test. I wonder, what could be wrong... :| Please help! :) Below is the code for the test:
void testFirstPost() {
def user = new User(userID: 'joemillan', password:'youaretheonly',
homepage: 'www.geeee.com').save()
def post = new Post (content: 'hellloo oasdo sjdosa daodkao ')
user.addToPosts(post)
assertEquals 1, User.get(user.id).posts.size()
}
Here is the user class:
class User {
String userID
String password
String homepage
Profile profile
static hasMany=[posts:Post, tags:Tag]
static constraints = {
userID (unique: true, size: 6..20)
password (size: 6..20, validator:{password,userID-> return password !=userID.userID}) //validator = The password must not match the username.
homepage (url:true, nullable: true)
profile (nullable: true)
}
}
Here is the Post class:
class Post {
String content
Date dateCreated
static constraints = {
content (blank:false)
}
static belongsTo = [user:User]
static hasMany = [tags:Tag]
static mapping = {
sort dateCreated: "desc"
}
}
save() returns null if validation fails, and "www.geeee.com" isn't a valid URL. It would work with "http://www.geeee.com".
But you should split the creation and saving into 2 steps so you can check it:
def user = new User(userID: 'joemillan', password:'youaretheonly',
homepage: 'www.geeee.com')
user.save()
assertFalse user.hasErrors()
or use failOnError if you are confident that that part should succeed and only want to test the other parts, e.g.
def user = new User(userID: 'joemillan', password:'youaretheonly',
homepage: 'www.geeee.com').save(failOnError: true)

Resources