-
1. Re: EntityHome for nested entity CRUD?
kingcu May 24, 2007 10:57 AM (in response to kingcu)Tried to pass parentBusiness through <f:param>, but got java.lang.IllegalArgumentException. It looks like <f:param> only allows primitive types plus the String type.
-
2. Re: EntityHome for nested entity CRUD?
gavin.king May 24, 2007 11:15 AM (in response to kingcu)If you use a seam page parameter, you can specify a JSF converter.
-
3. Re: EntityHome for nested entity CRUD?
kingcu May 24, 2007 12:17 PM (in response to kingcu)Could you elaborate a little more on this? I only know JSF converter is used to convert between string representation and object type. However, parentBusiness here is a managed entity instance.
-
4. Re: EntityHome for nested entity CRUD?
gavin.king May 24, 2007 1:13 PM (in response to kingcu)Convert the id, not the entity instance.
-
5. Re: EntityHome for nested entity CRUD?
kingcu May 24, 2007 4:24 PM (in response to kingcu)Converter is not needed for id, since it's a Long. Now I can pass the id from the page to Home and use getEntityManager().find() to load the parent business entity and wire it up with the child. But we are kind of falling back to the old style, I was hoping that there be a way to inject the parent or its home into the child's Home. It looks to me that Seam's bijection is not general or flexible enough to cover this specific situation.
And now, I am getting into a new problem: the parent's Home object does not get cleaned up when creating the child, so the edit page for creating the child still shows values from the parent and thus the wrong set of buttons. Here is how my page looks like:<ui:define name="body"> <h:messages globalOnly="true" styleClass="message" id="globalMessages"/> <h:form id="business" styleClass="edit"> <rich:panel> <f:facet name="header">Edit Business</f:facet> <s:decorate id="nameDecoration" template="layout/edit.xhtml"> <ui:define name="label">name</ui:define> <h:inputTextarea id="name" cols="80" rows="3" value="#{businessHome.instance.name}"/> </s:decorate> <s:decorate id="descriptionDecoration" template="layout/edit.xhtml"> <ui:define name="label">description</ui:define> <h:inputTextarea id="description" cols="80" rows="3" value="#{businessHome.instance.description}"/> </s:decorate> <div style="clear:both"> <span class="required">*</span> required fields </div> </rich:panel> <div class="actionButtons"> <h:commandButton id="save" value="Save" action="#{businessHome.persist}" disabled="#{!businessHome.wired}" rendered="#{!businessHome.managed}"/> <h:commandButton id="update" value="Update" action="#{businessHome.update}" rendered="#{businessHome.managed}"/> <h:commandButton id="delete" value="Delete" action="#{businessHome.remove}" rendered="#{businessHome.managed}"/> <s:button id="done" value="Done" propagation="end" view="/BusinessSearch.xhtml" rendered="#{businessHome.managed}"/> <s:button id="cancel" value="Cancel" propagation="end" view="/BusinessSearch.xhtml" rendered="#{!businessHome.managed}"/> </div> <s:div styleClass="actionButtons"> <s:button view="/BusinessEdit.xhtml" id="createChild" value="Create Child Business"> <f:param name="parentBusinessId" value="#{businessHome.instance.id}"/> </s:button> </s:div> </h:form> </ui:define>
<page no-conversation-view-id="/BusinessSearch.xhtml"> <begin-conversation nested="true"/> <action execute="#{businessHome.wire}"/> <param name="businessId" value="#{businessHome.businessId}"/> <param name="parentBusinessId" value="#{businessHome.parentBusinessId}"/> <navigation from-action="#{businessHome.persist}"> <end-conversation/> <redirect view-id="/BusinessSearch.xhtml"/> </navigation> <navigation from-action="#{businessHome.update}"> <end-conversation/> <redirect view-id="/BusinessSearch.xhtml"/> </navigation> <navigation from-action="#{businessHome.remove}"> <end-conversation/> <redirect view-id="/BusinessSearch.xhtml"/> </navigation> </page>
-
6. Re: EntityHome for nested entity CRUD?
gavin.king May 24, 2007 4:28 PM (in response to kingcu)Huh?
The only reason you would have stuff not getting "cleaned up" is that you have a conversation.
If you have a conversation, why would you need to use page parameters??
Sounds like you're in a bit of a muddle here. -
7. Re: EntityHome for nested entity CRUD?
kingcu May 24, 2007 4:56 PM (in response to kingcu)Because the one-to-many relation is on the Business entity itself, both parent and child have the same EntityHome class, which is BusinessHome. Accordingly, they will have the same Seam component name - "businessHome". And I don't think there can be two Seam components with teh same name within one conversation. Then I thought they should live in two separate conversations, that's why I have
<begin-conversation nested="true"/>
and was hoping whenever BusinessEdit.xhtml is loaded, a new conversation is created. The page parameter "id" is really meant to be passed from the parent conversation to the child conversation. -
8. Re: EntityHome for nested entity CRUD?
gavin.king May 24, 2007 11:13 PM (in response to kingcu)Why not just give BusinessHome two different roles?
A nested conversation shares the instances from the outer conversation, so your approach certainly won't work. -
9. Re: EntityHome for nested entity CRUD?
hvram May 25, 2007 9:39 AM (in response to kingcu)Hi
We faced the same situation and we did the following
Added entries in the components.xml for the other entityhome .. So something like
and we used the reference to the childHome .
We added page parameters (in the .page.xml ) for the childentities id .
Let me know if this helps
Regards
Hari -
10. Re: EntityHome for nested entity CRUD?
kingcu May 25, 2007 12:08 PM (in response to kingcu)Thank you both for the help. Now, I got it to work by adding another @Role to the BusinessHome. But, I had to create a second page for creating the child (the page is almost identical to the page creating the parent, except for the different name used for the Home component), which is a little less than ideal: originally, I though I could do this with just one page and now I have to maintain two almost identical pages.
One other thing is that I have my BusinessHome with two different names, but both in CONVERSATION scope and seem to work fine, which seems to be against what is stated in the reference doc (section 3.2.9):The @Role annotation lets us define an additional named role for a component, with a different scope
Can someone please clarify?
Anyway, I'll post my code below and hopefully it will be helpful for others who may face the same issue. Please do let me know if there is any possibility of improvement. Thanks.
BusinessHome.java@Name("businessHome") @Scope(CONVERSATION) @Role(name="childBusinessHome", scope=CONVERSATION) public class BusinessHome extends EntityHome<Business> { private Long parentBusinessId; @Logger Log log; public Long getParentBusinessId() { return parentBusinessId; } public void setParentBusinessId(Long parentBusinessId) { this.parentBusinessId = parentBusinessId; } public void setBusinessId(Long id) { setId(id); } public Long getBusinessId() { return (Long) getId(); } @Override protected Business createInstance() { Business business = new Business(); return business; } public void wire() { if (parentBusinessId != null) { EntityManager em = getEntityManager(); Business parentBusiness = em.find(Business.class, parentBusinessId); getInstance().setParentBusiness(parentBusiness); } } public boolean isWired() { return true; } public Business getDefinedInstance() { return isIdDefined() ? getInstance() : null; } }
BusinessEdit.xhtml<ui:define name="body"> <h:messages globalOnly="true" styleClass="message" id="globalMessages"/> <h:form id="business" styleClass="edit"> <rich:panel> <f:facet name="header">Edit Business</f:facet> <s:decorate id="nameDecoration" template="layout/edit.xhtml"> <ui:define name="label">name</ui:define> <h:inputTextarea id="name" cols="80" rows="3" value="#{businessHome.instance.name}"/> </s:decorate> <s:decorate id="descriptionDecoration" template="layout/edit.xhtml"> <ui:define name="label">description</ui:define> <h:inputTextarea id="description" cols="80" rows="3" value="#{businessHome.instance.description}"/> </s:decorate> <div style="clear:both"> <span class="required">*</span> required fields </div> </rich:panel> <div class="actionButtons"> <h:commandButton id="save" value="Save" action="#{businessHome.persist}" disabled="#{!businessHome.wired}" rendered="#{!businessHome.managed}"/> <h:commandButton id="update" value="Update" action="#{businessHome.update}" rendered="#{businessHome.managed}"/> <h:commandButton id="delete" value="Delete" action="#{businessHome.remove}" rendered="#{businessHome.managed}"/> <s:button id="done" value="Done" propagation="end" view="/BusinessSearch.xhtml" rendered="#{businessHome.managed}"/> <s:button id="cancel" value="Cancel" propagation="end" view="/BusinessSearch.xhtml" rendered="#{!businessHome.managed}"/> </div> <s:div styleClass="actionButtons"> <s:button view="/ChildBusinessEdit.xhtml" id="createChild" value="Create Child Business"> <f:param name="parentBusinessId" value="#{businessHome.instance.id}"/> </s:button> </s:div> </h:form> </ui:define>
BusinessEdit.page.xml<page no-conversation-view-id="/BusinessSearch.xhtml"> <begin-conversation join="true"/> <action execute="#{businessHome.wire}"/> <param name="businessId" value="#{businessHome.businessId}"/> <navigation from-action="#{businessHome.persist}"> <end-conversation/> <redirect view-id="/BusinessSearch.xhtml"/> </navigation> <navigation from-action="#{businessHome.update}"> <end-conversation/> <redirect view-id="/BusinessSearch.xhtml"/> </navigation> <navigation from-action="#{businessHome.remove}"> <end-conversation/> <redirect view-id="/BusinessSearch.xhtml"/> </navigation> </page>
ChildBusinessEdit.xhtml<ui:define name="body"> <h:messages globalOnly="true" styleClass="message" id="globalMessages"/> <h:form id="business" styleClass="edit"> <rich:panel> <f:facet name="header">Edit Business</f:facet> <s:decorate id="nameDecoration" template="layout/edit.xhtml"> <ui:define name="label">name</ui:define> <h:inputTextarea id="name" cols="80" rows="3" value="#{childBusinessHome.instance.name}"/> </s:decorate> <s:decorate id="descriptionDecoration" template="layout/edit.xhtml"> <ui:define name="label">description</ui:define> <h:inputTextarea id="description" cols="80" rows="3" value="#{childBusinessHome.instance.description}"/> </s:decorate> <div style="clear:both"> <span class="required">*</span> required fields </div> </rich:panel> <div class="actionButtons"> <h:commandButton id="save" value="Save" action="#{childBusinessHome.persist}"> <f:param name="businessId" value="#{childBusinessHome.instance.id}"/> </h:commandButton> <s:button id="cancel" value="Cancel" propagation="end" view="/BusinessEdit.xhtml"/> </div> </h:form> </ui:define>
ChildBusinessEdit.page.xml<page no-conversation-view-id="/BusinessEdit.xhtml"> <begin-conversation join="true"/> <action execute="#{childBusinessHome.wire}"/> <param name="parentBusinessId" value="#{childBusinessHome.parentBusinessId}"/> <navigation from-action="#{childBusinessHome.persist}"> <end-conversation/> <redirect view-id="/BusinessEdit.xhtml"/> </navigation> <navigation from-action="#{childBusinessHome.update}"> <end-conversation/> <redirect view-id="/BusinessEdit.xhtml"/> </navigation> <navigation from-action="#{childBusinessHome.remove}"> <end-conversation/> <redirect view-id="/BusinessEdit.xhtml"/> </navigation> </page>
-
11. Re: EntityHome for nested entity CRUD?
fernando_jmt May 25, 2007 2:18 PM (in response to kingcu)In order to avoid to have basically the same page twice, I think you can improve that in two ways:
1) Use a page composition for Edit form and pass the component instance as ui:param.
2) Declare in your pages.html alias view-id for each case but render only one page. Something like this:<page view-id="/admin/userListing.xhtml"> <action execute="#{userList.refresh}"/> <navigation evaluate="#{userList.wired}"> <render view-id="/userList.xhtml"/> </navigation> </page> <page view-id="/admin/userListingSpecific.xhtml"> <action execute="#{userList.refresh}"/> //do something with the action <navigation evaluate="#{userList.wired}"> <render view-id="/userList.xhtml"/> </navigation> </page>
With above code I can define some component variables that then I can use to render specific content inside userList.xhtml.
userListing.xhtml and userListingSpecific.xhtml do not exist physically they are only declared in pages.xml.
HTH. -
12. Re: EntityHome for nested entity CRUD?
fernando_jmt May 25, 2007 2:25 PM (in response to kingcu)In my last post in point 2) I meant pages.xml not pages.html