Overwriting Setter&Getter Domain class grails - grails

I am trying to overwrite getter and setter for domain class. The rational for doing is so that i don't have to redo initialization of this domain class that is in so many places in code.
I have a domain class 'Bank' that used to have one 'address' and it was initialized as follows:
new Bank(address: Address)
Now, i need multiple addresses, so I have a mapping class BankAddress and Bank now have 'addresses' list of BankAddress
To keep initialization the same 'new Bank(address:Address)', i am rewriting 'getAddress' and 'setAddress' like the following:
Address getAddress(){
if(addresses?.size()>0){
addresses.asList().get(0).getAddress()
}else{
return null
}
}
void setAddress(Address instance){
if(addresses?.size()>0){
addresses*.delete()
addresses.clear()
}
def bankAddress = new BankAddress(address: instance, bank: this, isPrimary: true).save(flush: true)
addToAddresses(bankAddress)
}
Problem is that while my setter is called, the 'instance' parameter of the function is empty making to fail on save - new Bank(address:someAddress):
'AddressId', table 'someDB.Config.BankAddress'; column does not allow nulls. INSERT fails.
How come the setter has empty argument? ... I am newbee to groovy & its dynamic nature
Thank You for your help

In your setter you're creating a new BankAddress object and then doing a save(flush:true). One of the properties of your BankAddress object is the submitted Address object. If the submitted Address object hasn't been saved to the database already, the new BankAddress object will try to save a null id in its foreign key column in the database, which will fail because the foreign key column is not nullable.
Make sure your submitted Address object has already been persisted to the database so it has a primary key id, or delay persisting the new BankAddress object until later.

Related

Grails 3: Disable database binding for incoming data

In Grails If I have a Command object such as
class MyCommand {
MyObject object;
}
If the incoming request data has an ID value for object then when the Grails data binding occurs my command object is actually populated with a instance of the object from the database.
I don't want this. I just want a new instance of MyObject populated with the incoming request data. I don't care of if there is already an instance in the DB with the same ID, I will handle that on my own.
How can disable this DB type data-binding at either a global level or preferably some way (annotation?) at the property level.
The only other alternative I can think of is when I send the request data I will have the ID values and object properties separate and join them later. I don't want to do that if it can be avoided.
You can have endpoints called differently using ROLES. For example:
def show(){
Person user = new Person()
if(isSuperuser() && params?.id){
user = Person.get(params.id.toLong())
}else{
user = Person.get(springSecurityService.principal.id)
}
...
}
This sets it up so only admin's can supply the ID otherwise it uses the principal to get the logged in user.

Is it possible to save a specific id for a grails domain object?

I am in the process of trying to copy the properties of one domain object to another similar domain object (Basically moving retired data from an archive collection to an active one). However, when I try to save with a manually inputed id the save will not actually put anything into the collection.
def item = new Item(style: "631459")
item.id = new ObjectId("537da62d770359c2fb4668e2")
item.save(flush: true, validate: false, failOnError:true)
The failOnError does not throw an exception and it seems like the save works correctly. Also if I println on the item.save it will return the correct id. Am I wrong in thinking that you can put a specific id on a domain object?
You can set the id generator as 'assigned' so then you can put the value that you want and is going to be saved with that value.
class Item {
...
static mapping = {
id generator:'assigned'
}
}
The identifier id is a somewhat sensitive name to use. If you check your dbconsole, you will find that GORM has provided one for you even without asking. When you use that name for yourself, confusion happens. Grails will respect you with the println stuff, but GORM has the last word on how id gets initialized and stored, and it is not listening to you then.
You can rename the id to something else like you see in this post and maybe then you can use the name id for yourself. Otherwise, I suggest leaving id to GORM, and have your own identifier for your old keys. You won't have problems retrieving data anyway and there won't be performance issues.

How to load any attributes without using the Mapping ' lazy: false' in Grails

Constantly faced with a problem when I need to compare and manipulate objects that reference other objects. For example:
Class Student {
...
String Name
Integer Age
...
}
Class Stuff {
...
Student student
...
}
When I invoke an instance of Stuff (Stuff.get (id)/load(id)) and will access the Name, Age and other attribute I see in debug mode (stuff .name = null, they're like 'null' although they are not null. It
command when analyzing values ​​of these attributes (stuff
.name == "pen") error occurs.
I need to invoke the instances and compare their values ​​to execute business rules, but do not know how to resolve this issue.
I read something about the inclusion in the configuration Stuff Mapping 'student lazy: false' for all the time you need to load the instance ofstuff , also charge the Student, but that in addition to overload the memory (since stuff is a Domain Great) would solve this case being the only solution to put all references as 'lazy: false' which would slow the application just to make a simple comparison.
Does anyone know how to invoke instances (Stuff), automatically invoking the attribute to be working (student) just to make the comparison of data, without using the 'student lazy: false' that invokes the data at all times?...
Using Grails 2.2.0 e o Groovy 2
Stuff don't have a property called name so you should get MissingPropertyException calling stuff.name. This has nothing to do with the lazy or eager relationship.
You can check the definition of a lazy relationship in the documentation and also the difference between the types of fetch.
To access the name property you need to access the student property before:
Stuff instance = Stuff.get(id)
println instance.student.name //this, if lazy, will trigger a new database query.
If you know that your code will access the Student instance by the relation with Stuff you could fetch both in one database access (eager and not lazy):
Stuff instance = Stuff.withCriteria {
eq('id', id)
fetchMode("student", FetchMode.JOIN)
}

How to dynamically add a property / field to a domain class in Grails?

For a project I'm currently working on I need to dynamically add properties to a domain class and persist them later in the database. In general, I need a key/value store attached to a "normal" domain class. Sadly I cannot use a NoSQL database (e.g. Redis).
My approach would be to handle the additional properties on a save() by identifying them within afterInsert or afterUpdate and writing them to another table - I would prefer not to use a map property within the domain class but an additional "Field" table (to better support searches).
I tried to add properties using the metaClass approach:
person.metaClass.middlename = "Biterius"
assert person.middlename == "Biterius" // OK
This works and I can identify the additional properties in the afterInsert/afterUpdate methods but it seems that I cannot change the value thereafter - i.e., the following does not work:
person.middlename = "Tiberius"
assert person.middlename == "Tiberius" // FAIL
Then I tried an Expando approach by extending the Person class by the Expando class (directly ("Person extends Expando") and via an abstract intermediate class ("Person extends AbstractPerson" and "AbstractPerson extends Expando")).
def person = new Person()
assert person in Person // OK
assert person in AbstractPerson // OK
assert person in Expando // OK
Both variants did not work - I could assign values to arbitrary "properties" but the values were not stored!
person.mynewproperty = "Tiberius" // no MissingPropertyException is thrown
println person.mynewproperty // returns null
So how can I add properties to a domain class programmatically during runtime, change them and retrieve them during afterInsert or afterUpdate in order to "manually" store them in a "Fields" table?
Or am I doing something completely wrong? Are there other / simpler ways to do this?
What about turning your DB into a "NoSQL" one?
In one of my projects, I just used a String-property to store a map as JSON-Object.
For Groovy it's not a big problem to convert between a map and a JSON-Object. And since you can access a map just like an object with properties, I found this solution very convenient.
Only drawback: you have to plan the size of your String-property in advance...
Update: sorry, just read that you want to support searches...
what about
class Person {
...
static hasMany = [extProperties:KeyValue]
...
def invokeMethod(String name, args) {
if (name.startsWith('get')) {
//an unknown properties's getter is called
}
//add same for setter
}
}
class KeyValue {
String key
String value
}
I guess such a schema would give you all freedom you need. Even without the hasMany, you can make use of invokeMethod to handle your external tables...
The getter and setter can save your values in a transient string propertie (static transients = ['myTransientProperty']). This property should be available in the afterInsert / `afterUpdate´ events.
Why don't you just create a map of strings on the domain object and store your extra data there manually? Unless you're storing complex data you should be able to cast anything you need to/from a string.

org.springframework.dao.InvalidDataAccessApiUsageException when using grails dynamic finder

Using Grails i'm trying a dynamic finder like this one
Policy.findAllByResourceAndUser(resource,user)
But When i call this, grails raise this exception
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: object references
an unsaved transient instance - save the transient instance before flushing: gmedia.User;
nested exception is org.hibernate.TransientObjectException: object references an unsaved
transient instance - save the transient instance before flushing: gmedia.User
Do we need to save the parameter of the finder?
Where i'm wrong?
http://www.grails.org/DomainClass+Dynamic+Methods#findAllBy*
Policy.findAllByResourceAndUser(resource,user)
capital "B" in "By" is the first thing I see wrong? Is that a type on the question?
def res = new Resource(name:"resource name").save()
def user = new User(name:"My Name").save()
def policy = new Policy( user:user, resource:res, right: "right string").save()
println Policy.findAllByResourceAndUser(res,user)
not elegant, but you get the idea, there must be a problem in the way you are saving your objects
your user object will "never" get saved with that code... you have to specify values for all of you properties or define your constraints appropriately. I think you should review the documentation for Domain Objects in Grails because it appears there are fundamental problems in your approach see http://www.grails.org/GORM+-+Creating+a+domain+class
#Aaron Saunders
these are two domain class
class Resource{
static contraints={}
}
class User extends Resource{
String name
String password
String email
Date creationDate
Date lastModicationDate
}
class Policy{
Resource resource
User user
String right
static mapping={
user cascade:'all-delete-orpahn'
resource cascade:'all-delete-orpahn'
}
Maybe it a consequence of the inheritance between User and Resource
i faced the same issue today..i found the solution...there is a foreign key relation which is getting set as NULL.....so when it tries to save null it throws this exception..so make sure all the values are not null...else u may need to change the cascade definition in ur mapping xml..

Resources