I have a ViewScoped jsf page which lists a bunch of transactions based on an accountId. When a user navigates to the page, the accountId is passed in the URL like transactions_byaccount?accountId=3. This loads up the transactions in the @PostConstruct cycle for accountId(bound to #{param.accountId}) supplied and lists them using .
On each transaction listed the user is also able to change the category of the transaction by selecting a drop down and clicking a button, which calls an action passing the transaction in an EL method expression. This works as expected except in the scenario below.
Once in the page, a drop down is also available with a list of other accounts with the drop down value bound to accountId. When the user clicks the reload button the action is invoked to get the transactions associated with the newly selected account. The transactions are listed as expected. However when the user now selects a new category for the transaction and clicks the button to update the transaction, the EL method expression invokes the action with the transaction from the first transaction list the user used to navigate to the page.
It was mentioned that this may happen if the list value changes incompatibly, but my getter method is currently a very simple method.
Any help would be most appreciated.
jsf passing parameters in a method expression failes in ViewScoped bean
The full code is as below
My bean package applogic.transactions;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import applogic.Conns;
import finance.bean.TransactionsListBean;
import finance.dao.AccountsDAO;
import finance.dao.TransactionsDAO;
import finance.daobase.BusinessDAO;
import finance.model.Accounts;
import finance.model.Transactions;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@ManagedBean(name = "transactions_byaccount")
@ViewScoped
public class Transactions_Byaccount extends TransactionsListBean implements Serializable {
List<Transactions> resultList;
boolean initialized;
@ManagedProperty("#{param.accountId}")
private int accountId;
public SelectItem[] accountsSelections;
@ManagedProperty("#{param.sortOrder}")
private int sortOrder;
public SelectItem[] sortOrderSelections;
@ManagedProperty("#{param.orderColumn}")
private int orderColumn;
public SelectItem[] orderColumnSelections;
public Transactions_Byaccount() {
}
public String updateCategories(String redirectURL) {
String result = redirectURL;
Connection cons = Conns.getConFinanceDB();
for( Transactions temp : (List<Transactions>)this.getPageList() )
TransactionsDAO.Update(cons, temp);
resultList = null;
if( redirectURL != null && redirectURL.length() == 0 )
redirectURL = null;
return redirectURL;
}
public String updateCategory(String redirectURL, Transactions arg) {
String result = redirectURL;
Connection cons = Conns.getConFinanceDB();
TransactionsDAO.Update(cons, arg);
resultList = null;
if( redirectURL != null && redirectURL.length() == 0 )
redirectURL = null;
return result;
}
@PostConstruct
public void init() {
//if (FacesContext.getCurrentInstance().) {
if(resultList == null || initialized == false) {
Connection cons = Conns.getConFinanceDB();
List<Accounts> accountsList = AccountsDAO.List(cons);
List<SelectItem> listOfAccountsSelectItems = new
ArrayList<SelectItem>();
for( Accounts temp : accountsList ) {
listOfAccountsSelectItems.add(new SelectItem(temp.getId(), temp.getTitle()));
}
accountsSelections = listOfAccountsSelectItems.toArray(new SelectItem[listOfAccountsSelectItems.size()]);
List<SelectItem> sortOrderList = new ArrayList<SelectItem>();
sortOrderList.add(new SelectItem(1, "Asc"));
sortOrderList.add(new SelectItem(2, "Desc"));
sortOrderSelections = sortOrderList.toArray(new SelectItem[sortOrderList.size()]);
List<SelectItem> orderColumnList = new ArrayList<SelectItem>();
orderColumnList.add(new SelectItem(1, "Transaction Date"));
orderColumnList.add(new SelectItem(2, "Action Date"));
orderColumnList.add(new SelectItem(3, "Reconciled Date"));
orderColumnSelections = orderColumnList.toArray(new SelectItem[orderColumnList.size()]);
resultList = TransactionsDAO.ListByaccount(cons, accountId, getCurrentPageNo(), getPageSize(), orderColumn, sortOrder);
initialized = true;
}
// }
}
public void reload() {
Connection con = Conns.getConFinanceDB();
resultList = TransactionsDAO.ListByaccount(con, accountId, getCurrentPageNo(), getPageSize(), orderColumn, sortOrder);
initialized = true;
}
public String reload(String returnUrl) {
Connection con = Conns.getConFinanceDB();
resultList = TransactionsDAO.ListByaccount(con, accountId, getCurrentPageNo(), getPageSize(), orderColumn, sortOrder);
initialized = true;
return returnUrl;
}
public Object getPageList() {
return resultList;
}
public int getMaxCount() {
Connection con = Conns.getConFinanceDB();
int result = TransactionsDAO.CountByaccount(con, accountId);
return result;
}
public int getAccountId() {
return accountId;
}
public void setAccountId(int accountId) {
this.accountId = accountId;
}
public SelectItem[] getAccountsSelections() {
return accountsSelections;
}
public void setAccountsSelections(SelectItem[] accountsSelections) {
this.accountsSelections = accountsSelections;
}
public int getSortOrder() {
return sortOrder;
}
public void setSortOrder(int sortOrder) {
this.sortOrder = sortOrder;
}
public SelectItem[] getSortOrderSelections() {
return sortOrderSelections;
}
public void setSortOrderSelections(SelectItem[] sortOrderSelections) {
this.sortOrderSelections = sortOrderSelections;
}
public int getOrderColumn() {
return orderColumn;
}
public void setOrderColumn(int orderColumn) {
this.orderColumn = orderColumn;
}
public SelectItem[] getOrderColumnSelections() {
return orderColumnSelections;
}
public void setOrderColumnSelections(SelectItem[] orderColumnSelections) {
this.orderColumnSelections = orderColumnSelections;
}
public boolean isInitialized() {
return initialized;
}
public void setInitialized(boolean initialized) {
this.initialized = initialized;
}
public List<Transactions> getResultList() {
return resultList;
}
public void setResultList(List<Transactions> resultList) {
this.resultList = resultList;
}
}
And now my page
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:t="http://myfaces.apache.org/tomahawk"
xmlns:f="http://java.sun.com/jsf/core" xml:lang="en" lang="en">
<ui:composition template="/WEB-INF/templates/template_main.xhtml">
<ui:param name="title" value="transactions"></ui:param>
<f:metadata>
<f:viewParam name="pageNo" value="#{transactions_byaccount.pageNo}"/>
<f:viewParam name="accountId" value="#{transactions_byaccount.accountId}"/>
<f:viewParam name="sortOrder" value="#{transactions_byaccount.sortOrder}"/>
<f:viewParam name="orderColumn" value="#{transactions_byaccount.orderColumn}"/>
<f:event type="preRenderView" listener="#{transactions_byaccount.init}" />
</f:metadata>
<ui:define name="operationalbar">
<div>
<span >
<h:selectOneMenu value="#{transactions_byaccount.accountId}" >
<f:selectItems value="#{transactions_byaccount.accountsSelections}"/>
</h:selectOneMenu>
</span>
<span >
<h:commandLink action="#{transactions_byaccount.reload('')}">
<h:outputText value="Reload"></h:outputText>
<f:param name="pageNo" value="1" />
<f:param name="accountId" value="#{transactions_byaccount.accountId}" />
<f:param name="sortOrder" value="#{transactions_byaccount.sortOrder}" />
<f:param name="orderColumn" value="#{transactions_byaccount.orderColumn}" />
</h:commandLink>
</span>
<span>
<h:link outcome="transactions_byaccount_header">
<h:outputText value="Back to accounts list"></h:outputText>
</h:link>
</span>
<span>
<h:commandLink action="#{transactions_byaccount.updateCategories('')}">
<h:outputText value="Update Categories"></h:outputText>
<f:param name="pageNo" value="#{param.pageNo}" />
<f:param name="accountId" value="#{param.accountId}" />
<f:param name="sortOrder" value="#{param.sortOrder}" />
<f:param name="orderColumn" value="#{param.orderColumn}" />
</h:commandLink>
</span>
<div></div>
</div>
</ui:define>
<ui:define name="pagingbar">
<div>
<span>
<h:commandLink title="Go to page first page" >
<h:outputText value="first"></h:outputText>
<f:param name="pageNo" value="#{transactions_byaccount.firstPage}" />
<f:param name="accountId" value="#{param.accountId}" />
<f:param name="sortOrder" value="#{param.sortOrder}" />
<f:param name="orderColumn" value="#{param.orderColumn}" />
</h:commandLink>
</span>
<span>
<h:commandLink title="Go to page prev page">
<h:outputText value="prev"></h:outputText>
<f:param name="pageNo" value="#{transactions_byaccount.prevPage}" />
<f:param name="accountId" value="#{param.accountId}" />
<f:param name="sortOrder" value="#{param.sortOrder}" />
<f:param name="orderColumn" value="#{param.orderColumn}" />
</h:commandLink>
</span>
<ui:repeat value="#{transactions_byaccount.pages}" var="itemx">
<span style="font-weight: #{itemx == transactions_byaccount.currentPageNo ? 'bold' : 'lighter' }">
<h:commandLink>
<h:outputText value="#{itemx}"></h:outputText>
<f:param name="pageNo" value="#{itemx}" />
<f:param name="accountId" value="#{param.accountId}" />
<f:param name="sortOrder" value="#{param.sortOrder}" />
<f:param name="orderColumn" value="#{param.orderColumn}" />
</h:commandLink>
</span>
</ui:repeat>
<span>
<h:commandLink title="Go to page next page">
<h:outputText value="next"></h:outputText>
<f:param name="pageNo" value="#{transactions_byaccount.nextPage}" />
<f:param name="accountId" value="#{param.accountId}" />
<f:param name="sortOrder" value="#{param.sortOrder}" />
<f:param name="orderColumn" value="#{param.orderColumn}" />
</h:commandLink>
</span>
<span>
<h:commandLink title="Go to page last page">
<h:outputText value="last"></h:outputText>
<f:param name="pageNo" value="#{transactions_byaccount.lastPage}" />
<f:param name="accountId" value="#{param.accountId}" />
<f:param name="sortOrder" value="#{param.sortOrder}" />
<f:param name="orderColumn" value="#{param.orderColumn}" />
</h:commandLink>
</span>
</div>
<div class="currentPagerIndex">
</div>
</ui:define>
<ui:define name="maincontent">
<table class="datatable">
<thead>
<tr class="headRow">
<td>datetransaction</td>
<td>description</td>
<td>amount</td>
<td>Edit</td>
<td>Delete</td>
</tr>
</thead>
<ui:repeat value="#{transactions_byaccount.pageList}" var="itmy">
<tr class="dataRow">
<td class="dataCell cltdtransactionsdatetransaction">
<h:outputText value="#{itmy.datetransaction}" >
<f:convertDateTime pattern="EEE dd-MMM-yyyy HH:mm" />
</h:outputText>
</td>
<td class="dataCell cltdtransactionsdescription">#{itmy.description}</td>
<td class="dataCell cltdtransactionsamount">#{itmy.amount}</td>
<td style="width: 45px">
<span class="pagerDBspan" style="font-weight: bold;">
<h:link outcome="transactions_edit" style="font-weight: bold;">
<h:outputText value="Edit"></h:outputText>
<f:param name="pageNo" value="#{param.pageNo}" />
<f:param name="itemId" value="#{itmy.id}" />
</h:link>
</span>
</td>
<td style="width: 45px">
<span class="pagerDBspan" style="font-weight: bold;">
<h:link outcome="transactions_edit" >
<h:outputText value="Delete"></h:outputText>
<f:param name="pageNo" value="#{param.pageNo}" />
<f:param name="itemId" value="#{itmy.id}" />
<f:param name="deleteFlag" value="true" />
</h:link>
</span>
</td>
</tr>
<tr class="dataRow">
<td class="dataCell"></td>
<td class="dataCell" colspan="2">
<h:selectOneMenu value="#{itmy.fkCategoriesId}" >
<f:selectItems value="#{categories_edit.categories}"/>
</h:selectOneMenu>
</td>
<td colspan="2">
<span class="pagerDBspan" style="font-weight: bold;">
<h:commandLink action="#{transactions_byaccount.updateCategory('', itmy)}" >
<h:outputText value="Update"></h:outputText>
<f:param name="pageNo" value="#{param.pageNo}" />
<f:param name="accountId" value="#{param.accountId}" />
<f:param name="sortOrder" value="#{param.sortOrder}" />
<f:param name="orderColumn" value="#{param.orderColumn}" />
</h:commandLink>
</span>
</td>
</tr>
<tr>
<td class="cssBottomLine" colspan="0"></td>
</tr>
</ui:repeat>
</table>
</ui:define>
<ui:define name="bottomoperationalbarhost">
</ui:define>
</ui:composition>
</html>