i'm trying to create some domain objects from xml.
class A {
String name
}
class B {
A a
int something
}
i first created an instance of A,and flushed. when creating B, first map the available attributes.
def b = new B(xml.attributes())
this would map 'something' correctly, but not the object type A. So, I retrieve the instance of A and add like
b.a = A.findByA("id of a")
I could see the object b is constructed (both fields filled in) in the debugger, but it doesn't persist on save(flush:true).
What is wrong in the above assignemt, or should use the id instead (b.a.id = ..)
How can I see what is going wrong in the log file? which trace needs to be enabled. I enabled there in config file
trace 'org.hibernate.SQL', 'org.hibernate.type' (which gives the sql trace for insert, select etc. But not for the above scenario, may be because it doesn't reach to hibernate).
Any pointer, highly appreciated.. thanks.
I would wager to guess that your save() is failing validation. You can add save(failOnError:true) to throw an exception when the validation fails, or add the following code to print each of the errors:
b.errors.allErrors.each {
println it
}
With the debugging tip from Rich, I could narrow down the problem... had to rename the attribute to prevent auto mapping. See a similar issue, and response at http://grails.1312388.n4.nabble.com/domain-controller-and-Failed-to-convert-property-value-of-type-problem-td1357947.html
To create association you must pass an object of A
new B(a:A.get(id))
or
B b = new B()
b.a = A.get(id)
Where id must be Integer or Long
Either I miss some context but class A doesn't have method findByA. There is no such A attribute for class A. Suggest you to use method get for strict findings.
Related
In Grails framework I saw the command object pattern but its use is not very clear for me. In addition most of examples given by Grails documentation are about domain classes not command objects (maybe to simplify code example).
1 - Command object is something used between view and controller layer and must stay there ?
2 - Or is it a good practice to pass command object to service layer ?
To illustrate point 2 :
class MyController {
def updateUserPassword (UserPasswordCommand cmd) {
...
myService.updatePassword(cmd)
...
}
}
If point 2 is a bad practice, then how do you pass submitted data to the service layer ? Via domain class ?
EDIT : Seems OK
[EDIT]
If I use command object and not domain class what to do in this case :
def signup(UserCreateCommand cmd)
{
if (!cmd.hasErrors()) {
def userInstance = userService.signup(cmd)
}
}
if (cmd.hasErrors()) {
/* Stay on form in order to display errors */
render(view:"/app/authentication/_signupForm", model:[userCreateCommand: cmd])
return
}
...
}
what happen if when user service transaction ends, there is an exception raided by database (because of flushing data not respecting schema constraints) ?
The problem in my point of view is that there are two queries :
Firstly - when call cmd.hasErrors() there is a persistent call for unique constraint on email for example
Secondly - when service transaction ends, there is a flush to DB (which result in one SQL insert in my case), and maybe raises an exception on column email which has unique constraint
Test cmd.hasErrors() doesn't prevent the case where DB raises a violated constraint unique exception or I'm wrong ?
That's the best way to pass request params to service layer. I have seen people passing params to service which is really a worst practice. Our controllers should be dump, Max 5-8 LOC in controller method is a guideline in my company.
Command object gives you so much power out of the box like validation, method etc.
Constraints like unique which needs to validated from database cannot be applied on command object. In this case you can use validator http://grails.github.io/grails-doc/2.5.1/ref/Constraints/validator.html.
You can also use importFrom constraint to have all the constraint form User domain to command object http://grails.github.io/grails-doc/2.5.1/guide/validation.html.
I'm looking at using Spring Batch within Grails using the Grails Spring Batch plugin.
If I have a number of fixed length records referring to an entity in my input file, where part of that record indicates whether the record is a new item, an existing item that should be updated or an existing item that should be deleted, what is the best pattern for integrating into the Spring Batch pattern?
So if my possible records look like this:
// create new record of type AA, data is 12345
AAN12345
// update record of type AA, data is 12345 (assume that the data is the key and I can find the existing AA item using this key)
AAU12345
// delete record of type AA using 12345 as the key
AAD12345
I'm happy with a LineMapper that takes a line from a FlatFileItemReader and creates a new item and passes it to a writer for saving.
The LineMapper could look like:
class AaLineMapper implements LineMapper<AaItem> {
#Override
AaItem mapLine(String line, int lineNumber) throws Exception {
switch (line[0..1]) {
case 'N':
AaItem item = new AaItem()
// set fields here based on line
return item
break
case 'U':
// possibly this?
AaItem item = AaItem.findByKey(someValueWithinLine)
// set fields here based on line
return item
break
case 'D':
// not sure on this one, deleting and returning null doesn't seem to work
// I thought the writer should delete the object?
break
}
}
}
However, for update, am I to assume that the best way is to use Item.findByKey(12345) within the LineMapper and then modify the Item and call save() within the writer?
How do I implement a delete? If I return a null from my LineMapper then the application seems to stop. I thought the writer should be deleting the object, not this? Or do I just use findByKey(12345), then pass to the writer with a delete flag set?
Apologies for the basic question, this is Day 1 of using the framework. I'm interested in understanding best-practices please.
You are close, but not quite there. What you really need your line mapper to produce is an instance of a class that contains not only the instance of the domain class to effect but also a property to indicate what action needs to be taken (presumably by an item processor, or a classifying item writer, depending on your requirements).
So something like this might work:
class MyActionContainerClass {
Object target
String actionType // U, D, N
}
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)
}
I'm having an issue where calling .contains() on one of my domain classes' hasMany relationships is not doing the same when running normally, or when debugging. The situation is as follows:
I have 2 domain objects, A and B. A has a hasMany relationship with B.
class A {
...
static hasMany = [bees: B]
...
}
Now, during the execution of one of my filters, I grab my current user from the spring security service. This user also contains a single instance of B. What my filter should do is to check if the instance of B in the user is contained in some instance of A.
Assume that the instances of B are actually referring to the same object (since they are).
Now, the issue arises. Calling:
if (instanceOfA.bees.contains(user.instanceOfB)) {
println 'success'
} else {
println 'failure'
}
prints failure during normal (or debugging without stepping through the code) execution. However, if I put a break-point there, and step through the code, it correctly executes the contains() and prints success.
I have also implemented equals, hashCode and compareTo in an attempt to resolve this, but with the same behaviour.
This is usually due to lazyloading or cache. Use instanceOfA.bees.id.contains(user.instanceOfB.id) and it always works.
Maybe your user.instanceOfB object is a hibernate proxy object and therefore not a real B. You can check this using a debugger or printing user.instanceOfB.getClass().
You can use GrailsHibernateUtil.unwrapIfProxy(proxyObject) to get the real object from the proxy.
I would do this with HQL:
A.executeQuery("select a from A a join a.bees as b where b = :b and a = :a", [a: instanceOfA, b: user.instanceOfB])
So it seems that using one of the Groovy transform annotations seems to do the trick. Simply adding:
// uid is a uniqe UUID we use to identify with other systems.
#EqualsAndHashCode(includes = ["id", "uid"])
does the trick. Seems a bit strange that the IDE generated methods (using the same fields) did not...
When I use criteria queries, the result contains array list of lazy initialized objects. that is, the list has values with handler org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwareJavassistLazyInitializer.
This prevent me from doing any array operation (minus, remove etc) in it. When I use, GORM methods, I get array list of actual object types. How can I get the actual objects in criteria query?
The code is listed below.
availableTypes = Type.withCriteria() {
'in'("roleFrom", from)
'in'("roleTo", to)
}
availableTypes (an array list) has one value , but not actual object but value with a handler of GroovyAwareJavassistLazyInitializer
availableTypes (an array list) has values with type Type
availableTypes = Type.findByRoleFrom(from)
---------- Update ----------
I did further troubleshooting, and this is what I found. Probably the above description might be misleading, but I kept it in case it helps.
When using findAllBy for the first time, I get proxy objects rather than the actual instance. Then, I invoke the method through an ajax call, the actual instance is loaded (anything to do with cache loading??). When I refresh the page, it again loads the proxy
def typeFrom = Type.findAllByParty(partyFrom)
there is another use of findAllBy in the same method, which always returns actual instances.
def relFrom = Relation.findAllByParty(partyFrom)
When compared the two classes, the attribute 'party' of class Roles is part of a 1-m relation. like
class Role {
RoleType roleType
LocalDate validFrom
LocalDate validTo
static belongsTo = [party : Party ]
...
}
I know if I do statement like Party.findAll(), the role instances would be proxy till they access. But, when using gorm directly on the class (Role), why I am getting the proxy objects ???
thanks for the help.
thanks.
Turns out are a couple of possible solutions which I came across but didn't try, such as
Overloading the equals method so that the proxy and the domain
object use a primary key instead of the hashCode for equality
Using a join query so that you get actual instances back and not proxies
GrailsHibernateUtil.unwrapProxy(o)
HibernateProxyHelper.getClassWithoutInitializingProxy(object)
One solution that worked for me was to specify lazy loading to be false in the domain object mapping.
History of this problem seems to be discussed here: GRAILS-4614
See also: eager load