Tuesday, December 29, 2009

EJB and ADF Faces RC: How to Create a SelectOneChoice with Value Bound to an Object Property

There has been a lot of blog post with regards to creating SelectOneChoice in ADF Faces RC but all are bound to a data control based on ADF Business Components . In this post, I will try show you how to create a selectOneChoice component if you want to bound the value to an object property (not just mapping simple data types like String, Long, etc.).
Please see below a demonstrative code snippet being ConversionRate as the object to be edited or created and the CurrencyFrom and CurrencyTo are the object attributes of ConversionRate that will be implemented as SelectOneChoice:
<af:selectOneChoice value="#{bindings.findConversionRateByIdIterator.currentRow.dataProvider.currencyFrom}"
                       label="CurrencyFrom"
                       required="true" id="soc1"
                       autoSubmit="true">
   <f:selectItems value="#{myBackingBean.currencyItems}"
                     id="si1"/>
</af:selectOneChoice>
<af:selectOneChoice value="#{bindings.findConversionRateByIdIterator.currentRow.dataProvider.currencyTo}"
                          label="CurrencyTo"
                          required="true" id="soc2"
                          autoSubmit="true">
     <f:selectItems value="#{myBackingBean.currencyItems}"
                       id="si2"/>
</af:selectOneChoice>
The trick on this is the "currentRow.dataProvider" thing. Replace the "findConversionRateByIdIterator" above with your own applicable iterator.

Please see below a dummy backing bean class to enforce illustration of the idea:
package blogspot.soadev.view.backing;

import java.util.ArrayList;
import java.util.List;
import oracle.binding.BindingContainer;
import oracle.binding.OperationBinding;
import javax.faces.model.SelectItem;

public class MyBackingBean {
  private List<SelectItem> currencyItems;
  public List<SelectItem> getCurrencyItems() {
      if (currencyItems == null) {
          List<Currency> currencyList = getCurrencyList();
          currencyItems = new ArrayList<SelectItem>();
          for (Currency currency : currencyList) {
              currencyItems.add(new SelectItem(currency, currency.getCode()));
          }
      }
      return currencyItems;
  }
    public List<Currency> getCurrencyList() {
        //findAllCurrencies is methodAction binding
        return (List<Currency>)getOperationBinding("findAllCurrencies").execute();
    }

  public OperationBinding getOperationBinding(String operation) {
    BindingContainer bindings =
      (BindingContainer)JSFUtils.resolveExpression("#{bindings}");
    return bindings.getOperationBinding(operation);
  }
}
class Currency {
  private String code;
  private String description;

  public void setCode(String code) {
    this.code = code;
  }

  public String getCode() {
    return code;
  }

  public void setDescription(String description) {
    this.description = description;
  }

  public String getDescription() {
    return description;
  }
}
class ConversionRate{
  private Currency currencyFrom;
  private Currency currencyTo;
  private Double rate;

  public void setCurrencyFrom(Currency currencyFrom) {
    this.currencyFrom = currencyFrom;
  }

  public Currency getCurrencyFrom() {
    return currencyFrom;
  }

  public void setCurrencyTo(Currency currencyTo) {
    this.currencyTo = currencyTo;
  }

  public Currency getCurrencyTo() {
    return currencyTo;
  }

  public void setRate(Double rate) {
    this.rate = rate;
  }

  public Double getRate() {
    return rate;
  }
}

3 comments:

  1. Hi Pino,

    in your post you write "...as the object to be edited"

    In a similar case I run into

    <_getSelectedIndex> Could not find selected item matching value "MyClassForChoice@102b1c7" in RichSelectOneChoice[UIXEditableFacesBeanImpl, id=soc1]


    when opening My object for edit. So the selectOneChoice is not set to the right index..


    Any idea? Thx.

    ReplyDelete
  2. Hi Andreas,

    The problem could be that you were not able to properly implement the hashCode() and equals() method of the MyClassForChoice class.
    For creating similar selectOneChoice LOVs without necessarily creating a backing bean to generate the select items, please see the following post:
    https://blogs.oracle.com/adf/entry/simulating_lovlist_of_values_in_ejb

    ReplyDelete
  3. Thx for the hint. That's exactly the point.

    May the comments help others too;)

    ReplyDelete