You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Craig McClanahan <cr...@apache.org> on 2004/04/09 20:05:56 UTC

Re: DynaBeans with struts faces

Joe Hertz wrote:

>Matthias-
>
>I've tried it both ways. I suspect the problem is my JSTL Knowledge. Code 
>follows.
>
>The problem, I believe boils down to, "How do I get at the item var declared 
>in the datatable/foreach? I can't use a ".", right?
>
>  
>
Actually, you can, in JSF expressions ("#{foo.bar}").  The struts-faces 
integration library includes a customized PropertyResolver class that 
makes JSF understand what a DynaBean is.  However, you're going to find 
that <c:forEach> and JSF components don't interoperate well, so 
Matthias's advice about using <h:dataTable> is well advised.

>Then again, it could be something very different FAIK. I'm getting the 
>wonderfully helpful exception,"One or more parameters are null", so I'm sure 
>it's something obvious I am doing wrong in my JSP. None of the values in my 
>beans are null.
>
>  
>
Could you refresh us on what your JSP code looks like now?

Going back to your earlier comment "both the list and the component 
Objects are declared as Dynabeans in struts-config", this doesn't sound 
like quite the right strategy in general -- dynabeans in Struts are 
focused on being *form* beans, not general purpose data objects.  For 
that, you might want to investigate how managed beans work in JSF, which 
is somewhat a generalization on how Struts creates form beans on 
demand.  You declare such a bean in faces-config.xml, and it gets 
instantiated on demand the first time it is referenced in an EL expression.

For example, let's say that you need to dynamically populate the set of 
options for an <h:selectOneListbox>.  Let's include the following code 
snippet in the JSP page:

  <h:selectOneListbox id="currency" value="#{item.currency}">
    <f:selectItems value="#{currencies.currencyList}"/>
  </h:selectOneListbox>

Note that we're using a single tag inside, pointing at a property getter 
that will return the dynamically calculated list, instead of trying to 
manually list the items in the page.  This is analogous to using the 
Struts <html:options> tag instead of a bunch of <html:option> tags to 
construct the options list.

This exampe assumes that "item" is a bean (either a real JavaBean or a 
DynaBean if you're using struts-faces.jar) that has a "currency" 
property of type String.  Note also that I put the expression in the 
*value* attribute ... one of your snippets had it in the "id", which 
isn't going to work.  In the faces-config.xml file, create an entry like 
this:

  <managed-bean>
    <managed-bean-name>currencies</managed-bean-name>
    
<managed-bean-class>com.mycompany.CurrenciesListFactory</managed-bean-class>
    <managed-bean-scope>application</managed-bean-scope>
  </managed-bean>

which says "the first time any JSF EL expression mentions "currencies", 
instantiate a CurrenciesListFactory object and stick it in application 
scope".  (This assumes you want to share the list across all users -- if 
the list is unique to each user, stick it in session scope instead and 
each user will get their own instance.)

Now, the factory class might look something like this:

    package com.mycompany;
    import java.util.ArrayList;
    import java.util.List;
    import javax.faces.model.SelectItem;
    public class CurrenciesListFactory {

        private List currencyList = null;
        public List getCurrencyList() {
            if (currencyList == null) {
                currencyList = new ArrayList();
                Iterator items  = ... iterate over database rows or 
whatever ...
                while (items.hasNext()) {
                    Item item = items.next();
                    currencyList.add(new SelectItem(item.getValue(), 
item.getName());
                }
            }
            return currencyList;
        }

    }

Using this strategy, your list of available currencies will be 
auto-magically created the first time someone uses the expression 
"#{currencies.currencyList}".  It also nicely separates the business 
logic needed to construct the options list out of your page, and lets 
the page author focus on the look and feel issues.  The factory bean is 
also easily unit testable ... it's only dependence on JSF APIs is the 
SelectItem class, which is a real simple JavaBean that represents an 
individual selection option.

>-Joe, hoping the answer isn't *too* embarrassing.
>
>  
>
Craig

><h:dataTable value="#{MaintenanceListForm.items}" var="item">
>
>  <h:column>
>    <f:facet name="header">
>	 <h:outputText value="Cost Per Credit"/>
>    </f:facet>
>    <h:inputHidden id="id" value="#{item.id}"/>
>    <h:inputText id="creditCost" value="#{item.creditCost}"/>
>  </h:column>
>  <h:column>
>    <f:facet name="header">
>	 <h:outputText value="Minimum Purchase"/>
>    </f:facet>
>    <h:inputText id="minPurchase" value="#{item.minPurchase}"/>
>  </h:column>
>< <h:column>
>    <f:facet name="header">
>	 <h:outputText value="Currency"/>
>    </f:facet>
>  <h:selectOneListbox id="currency">
>  
>
You probably want a value attribute here, with an expression like 
"#{item.currency}".

>  <f:selectItem itemValue="USD" />
>  <f:selectItem itemValue="CAD" />
>  <f:selectItem itemValue="EUR" />
>  <f:selectItem itemValue="JPY" />
>  </h:selectOneListbox>
></h:column>
>  <h:column>
>    <f:facet name="header">
>	 <h:outputText value="Begin Date"/>
>    </f:facet>
>    <h:inputText id="beginDate" value="#{item.beginDate}"/>
>  </h:column>
>  <h:column>
>    <f:facet name="header">
>	 <h:outputText value="End Date"/>
>    </f:facet>
>    <h:inputText id="endDate" value="#{item.endDate}"/>
>  </h:column>
></h:dataTable
>
>
>
>  
>
>>-----Original Message-----
>>From: Matthias Wessendorf [mailto:mailings@matthias-wessendorf.de] 
>>Sent: Friday, April 09, 2004 8:19 AM
>>To: struts-user@jakarta.apache.org
>>Subject: RE: DynaBeans with struts faces 
>>
>>
>>Joe,
>>can you provide some code ?
>>
>>btw.
>>i would use <h:dataTable>-Tag for "forEach" in JSF
>>and <h:colimn> for rendering <td></td>
>>
>>like this:
>><h:dataTable value=#{MaintenanceListForm.items} var{item}>
>>
>>  <h:column>
>>    <f:facet name="header">
>>	 <h:outputText value="HEADER_TEXT"/>
>>    </f:facet>
>>
>>    <h:outputText value="#{item.foo}"/>
>>
>>    <f:facet name="footer">
>>       <h:outputText value="footer_text"/>
>>    </f:facet>
>>  </h:column>
>></h:dataTable>
>>
>>note with <f:facet> you can "group" components logicaly. 
>>dataTable has a "footer" and a "header" it renders <tfoot> 
>>and <thead> for a HTML-Table
>>
>>and look at http://myfaces.sf.net
>>they have a nice example for editing table
>>-->Master/Detail-Example
>>
>>
>>hope that was helpful
>>Cheers
>>
>>Matthias
>>
>>
>>---------------------------------------------------------------------
>>To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>>For additional commands, e-mail: user-help@struts.apache.org
>>
>>
>>
>>    
>>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>For additional commands, e-mail: user-help@struts.apache.org
>  
>


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org