Grails - check if item has parent - grails

I'm new to Grails, Groovy and GSP.
I have a domain class "ProductCategory".
class ProductCategory {
static constraints = {
}
static mapping = {
table 'product_category';
version false;
cache usage: 'read-only';
columns {
parent column: 'parentid';
procedure column: 'procid';
}
}
static hasMany = [children:ProductCategory];
ProductProcedure procedure;
Integer lineorder;
String name;
ProductCategory parent;
String templatelink;
char offline;
String toString() {
return id + " (" + name + ")";
}
}
Each category CAN have a parent. I am using an existing database, and the table has a column 'parentid' to do that. When a category has no parent (root level), its parentid is 0.
I have a GSP trying to show data about the parent if any.
<g:if test="${category.parent}">
hello
</g:if>
I was under the impression that this would test for existence.
It works fine if the category DOES have a parent, but as soon as parentid=0, it blows up.
No row with the given identifier exists: [ProductCategory#0]
I tried to check for ==0, but it didn't work, I assume because 'parent' is supposed to be an object.
So how can I make it so that it assumes that parentid=0 is the same as parent=null, or NO parent?
Thanks

I think I may have found the answer:
parent column: 'parentid', ignoreNotFound: true;
ignoreNotFound is nowhere on the documentation, but it seems to work!

parentid should not be equal to 0. It should be null.
What I don't understand in your question, is how can you have parentid == 0 ?

You don't need to handle the parentid manually. As soon as you define a domain class like this:
Class Foo {
Bar bar
}
Gorm/Grails will automatically create a foreign key column for you. And if you define the property nullable:
Class Foo {
Bar bar
static constraints = {
bar(nullable:true)
}
}
...you can just set it to null and test for null:
def f = new Foo(bar:null)
if (f.bar == null) { ... }

Related

Grails - Validation of embedded object attributes only while updating

I have a grails domain class with an embedded object, I want to validate the embedded object's attributes only while updating.
I know I can do this on a normal grails domain class by using a custom validator and checking if the domain's class id is not null.
I can't do this because of the lack of an id on an embedded object.
There is a little example of what I want to do.
//This is on domain/somePackage/A.groovy
class A{
B embeddedObject
static embedded = ['embeddedObject']
static constraints = {
embeddedObject.attribute validator:{val, obj-> //The app fails to start when this code is added!!
if(obj.id && !val) //if the id is not null it means the object it's updating...
return 'some.error.code'
}
}
}
//this class is on src/groovy/somePackage/B.groovy
class B{
String attribute
static constraints={
attribute validator:{val,obj->
if(obj.id && !val) //This will fail too! because the lack of an id on this object....
return 'some.error.code'
}
}
}
Is there a way to get the id of the 'parent' on the embedded object??
Any help will be appreciated
way too complicated:
class A{
B embeddedObject
static embedded = ['embeddedObject']
static constraints = {
embeddedObject validator:{ val, obj ->
if( obj.id && !val.attribute )
return 'some.error.code'
}
}
}

Grails JAXB element list null

I am using this Domain Class :
#XmlRootElement(name="Target")
#XmlAccessorType(XmlAccessType.NONE )
class TargetElement {
static constraints = {
testPurpose()
}
#XmlAttribute(name="TestPurpose")
String testPurpose
// instead of bellow in comment use this
#XmlElementWrapper(name = "Bag")
#XmlElement(name="Child")
List<Child> bag= new ArrayList<Child>()
// 1..n Child
static hasMany = [child:Child]
}
If I want to add Child elem, I use
def target = new TargetElement(testPurpose:"TestPurpose")
target.getBag().add(child)
target.save(flush:true)
if (target.hasErrors()){
println '3 ***********' + target.errors
}
But I get list == null for bag.
Why my list is null? It is working for another project and only name is changing. May be my eyes are missing something...
For whom who get the same trouble : having #XmlElementWrapper value(bag) to null
in my Bootstrap.groovy.I have to declare :
ArrayList<Child> bag = new ArrayList<Child>()
bag.add(child1)
bag.add(child2)
targetElement.getBag().addAll(bag)
also I have met another issue whith GROM lazy loading and JAXB. Check that objects nested are retreived :
eg :
static mapping = {
nested lazy: false
}
Hope this will helps

Can't persist one-to-many relationship

In my current project I'm unable to persists a one-to-many relationship.
Both sides of the relationship will be saved - just the link between them is missing.
The one-to-many relationship between my two domains looks like this :
class Parent {
String name
...
static hasMany = [childs: Child]
Parent() {}
Parent(SomeOtherClass obj) {
this.properties = obj.properties
}
}
class Child {
int code
String description
}
I'm creating my Parent instances within a ParentService:
public Boolean createParents(List parentIds) {
boolean savedSuccessfully = true
Parent.withTransaction {status ->
parentIds.each { parentIdString ->
if (parentIdString && parentIdString.isInteger()) {
int parentId = parentIdString.toInteger()
def parentInstance = new Parent(someOtherService.getExternalParentObj(parentId))
someOtherService.getExternalChilds(parentId).each { entry ->
parentInstance.addToChilds(Child.findOrSaveWhere(code: entry.key, description: entry.value))
}
if(!parentInstance.save()) {
status.setRollbackOnly()
savedSuccessfully = false
}
}
}
}
return savedSuccessfully
}
Both, the Parent instances and the Child instances are created and saved successfully. Just the link between parent and child is missing. The childs property of each Parent instance is an empty list.
I dont't know what is wrong here.
Why does the relationship won't be persited? Any ideas?
Update
I've added an integration test for the ParentService to test the existence of the childs list after creating all Parent instances :
...
assert parentService.createParents(["123","234","356"]) == true
def parent = Parent.get(1)
assert parent.childs.size() > 0
...
Unexpectedly - the test passed.
I found the origin of the error.
I totally missed that some entry.value are null. Don't know why I didn't see it during debugging.
Now I only use Child.findOrSaveWhere() if entry.value is not null.
I would have expected that the whole parentInstance.save() would pass or fail completely. Still don't understand why the join table won't be filled without giving any error.

one to many- Showing list of children related to parent id

I have two domain class
1)
package opfwflowmonitor
import java.io.Serializable;
class OpfWF_Entry implements Serializable{
String name
Date create_date
static hasOne=[siteName:OpfWF_SiteName, currentStepStatus:OpfWF_CurrentStepStatus,currentStepName:OpfWF_CurrentStepName]
static hasMany = [historySteps:OpfWF_HistoryStepsInfo]
static mapping = {
table name: "OS_WFENTRY", schema: "GSI"
version false
cache true
historySteps cache:true
sort id:"desc"
columns{
name column:'NAME'
create_date column:'CREATE_DATE'
}
}
}
And
package opfwflowmonitor
import java.util.Date;
class OpfWF_HistoryStepsInfo {
Long entry_id
Long action_id
Long step_id
Date start_date
Date finish_date
String status
static belongsTo = [historyEntry: OpfWF_Entry]
static mapping = {
table name: "OS_HISTORYSTEP", schema: "GSI"
version false
cache true
historyEntry cache: true
sort id:"desc"
id generators: 'assigned'
columns{
id column:'ID'
action_id column:'ACTION_ID'
step_id column:'STEP_ID'
start_date column:'START_DATE'
finish_date column:'FINISH_DATE'
status column:'STATUS'
// ENTRY_ID column:'ENTRY_ID'
}
historyEntry column:'entry_id'
historyEntry insertable:false
historyEntry updateable:false
}
String toString() { "$id" }
}
How i can show list of all historystep with all properties when i select OpfWF_Entry ?
How to get a list table of childs(with all properties of history table) when user click on list of OpfWF_Entry table's record.
I'm not entirely sure if I understood you question correctly. The properties should be visible when you have the OpfWF_Entry object, but if in your case you can't access it, you can create a method to expose any properties you want.
Controller:
def showAllHistorySteps = {
def opfwfEntry = OpfWF_Entry.findById(params.id)
def historySteps = opfwfEntry.historySteps
historySteps.each {
println "Step: ${it.toString()}"
}
return [historySteps:historySteps]
}
Domain:
class OpfWF_HistoryStepsInfo {
def getAllProperties() {
// code to return a list of properties you want
}
}
View:
< g:each in="historySteps" > <br/>
< g:set var="listOfProps" value="${it.getAllProperties()"/> <br/>
// do what you want with listOfProps <br/>
< /g:each> <br/>
All Right- Answering my question. Here how i solved it.
1)
From list view of OpfWF_Entry, I have called historyStepInfo-Controller's searchme action(search me action added by myself).
2)
In historyStepInfoController- I have added searchme action- that finds inside hisotryStepInfo domain for all matching rows using params.id(passed from list view of opfEntry)
def opfWF_HistoryStepsInfoInstanceList =OpfWF_HistoryStepsInfo.findAllByEntry_id(params.id)
render (view:'list',model:[opfWF_HistoryStepsInfoInstanceList:opfWF_HistoryStepsInfoInstanceList,opfWF_HistoryStepsInfoInstanceTotal: opfWF_HistoryStepsInfoInstanceList.count()])
3)
Added HistoryStepsInfoInstanceList to list view of historyStepInfo "in"-varibale
And there i got all children related to a parent select.
This work for everything. Search,Children List and whatever.

Problem with GRAILS select - trying to insert a number for a field that appears as text in dropdown list

Here is the domain class I have defined:
package mypackage
public enum UFModeType {
I(0),
O(1),
R(3)
Integer mode
public UserFileModeType(Integer mode) {
this.mode = mode;
}
static list() {
[I, O, R]
}
}
This is a property of another domain Parent where it is as follows:
package mypackage
class Parent {
String name
... ... ...
UFModeType uFMode
static mapping = {
table 'parent_table_with_ufMode_col_as_number'
version false
tablePerHierarchy false
id generator:'sequence', params:[sequence:'myseq']
columns {
id column:'parentid'
uFMode column: 'UFMODE'
}
}
static constraints = {
userFileMode(nullable: true)
}
}
The gsp call for this looks like this:
g:select name="uFMode" from="${mypackage.UFModeType?.list()}" value="${parentInstance?.uFMode?.name()}" /
I have tried a lot of variants of the above in the gsp call but I am getting error that the db insert fails saying the entry of ufmode is invalid number, thus this is not being passed as a number. I printed the params in the controllers save and it shows this:
Params in save=[uFMode:I ...
I am sure I may be missing some minor thing in syntax, but I have tried a lot of things without much success, so any inputs will be greatly appreciated.
Thanks!
Try changing
value="${parentInstance?.uFMode?.name()}
to
value="${parentInstance?.uFMode?.mode()}
From the definition of UFModeType you give you do not have a name attribute.

Resources