Handling currency using <h:selectOneMenu> in JSF - jsf

I'm using an <h:selectOneMenu>on the header of a template <p:layoutUnit position="north".../> as follows.
<h:selectOneMenu value="#{currencyRateBean.currency}" onchange="submit();">
<f:selectItems var="row" value="#{currencyBean.currency}" itemLabel="#{row}" itemValue="#{row}"/>
</h:selectOneMenu>
This list is populated using a List<String> representing a list of currencies. The list is stored in an application scoped bean, CurrencyBean.
The JSF managed bean involved is as follows.
#ManagedBean
#SessionScoped
public final class CurrencyRateBean implements Serializable
{
private static final long serialVersionUID = 1L;
private String currency;
private BigDecimal currencyRate;
public CurrencyRateBean() {}
#PostConstruct
private void init()
{
currencyRate=new BigDecimal(1);
}
public BigDecimal getCurrencyRate() {
return currencyRate;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) throws MalformedURLException, IOException
{
BufferedReader in = null;
URLConnection connection;
try
{
URL url = new URL("http://www.exchangerate-api.com/INR/"+currency+"/1?k=FQRxs-xT2tk-NExQj");
connection = url.openConnection();
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String jsonObject = "";
String line;
while ((line = in.readLine()) != null)
{
jsonObject += line;
}
this.currencyRate = new Gson().fromJson(jsonObject, BigDecimal.class);
this.currency = currency;
}
finally
{
if(in!=null){in.close();}
}
}
}
The setCurrency() method is invoked on changing a currency in <h:selectOneMenu> (onchange="submit();") which is a POST request as it should be.
After this request is completed, there is a duplicate page submit on refreshing the page. To avoid this duplicate submit, a GET Http request should arise after this POST request is made.
How can this be made?
Please suggest, if there is a better, new, precise alternative for handling a multi-currency application.

Try this, and avoid onchange as much as possible.
<h:selectOneMenu value="#{currencyRateBean.currency}">
<p:ajax event="valueChange" update="here write the id(s) of component(s) or "#all" to rerender the whole page (which is really bad)" process="#this" partialSubmit="true"/>
<f:selectItems var="row" value="#{currencyBean.currency}" itemLabel="#{row}" itemValue="#{row}"/>
</h:selectOneMenu>

Related

For exact same JSF EL expression, getter is being called for ouputText but not for inputText. Why?

This is my JSF pages
<h:form>
First Name: <h:inputText value="#{userBean.first}" valueChangeListener="#{userBean.updateLastName}" onblur="submit()"/><br/>
Last Name: <h:inputText value="#{userBean.last}"/><br/>
Last Name: <h:outputText value="#{userBean.last}"/><br/> </h:form>
Following is the managed bean code.
#Named
#RequestScoped
public class UserBean {
private Map<String, String> names;
private String first, last;
public UserBean() {
names = new HashMap<>();
names.put("first1", "last1");
names.put("first2", "last2");
}
public String getFirst() {return first;}
public void setFirst(String first) {this.first = first;}
public String getLast() {return last;}
public void setLast(String last) {this.last = last;}
public void updateLastName(ValueChangeEvent e){
last = names.get(e.getNewValue().toString());
FacesContext.getCurrentInstance().renderResponse();
}
}
Now, when I type "first1" on the FirstName field and tab out, I see "last1" on the outputText field but inputText field remains empty.
I did the debugging and found getter is being called only once, so I wonder why getter is not being called for the inputText? Considering EL Expression is exactly same and based on my knowledge getter should be called during Render Response phase???

ManagedBean functions not being called

I am trying to create a basic datatable which fetches the value from database and displays in the table format. However while I try to debug I see that managed bean functions are not being called. Below is the code
list.xhtml:
<h:body>
<h3>Expense list</h3>
<h:dataTable value="#{userMB.entries}" var="e" styleClass="table"
headerClass="table-header" rowClasses="table-odd-row,table-even-row">
<h:column>
<f:facet name="header">Date</f:facet>
#{e.date}
</h:column>
</h:dataTable>
</h:body>
UserMB.java
#ManagedBean
#SessionScoped
public class UserMB {
private List<Entry> entries;
#EJB(mappedName = "entryServices")
private EntryServices entryServices;
public UserMB() {
}
#PostConstruct
public void init() {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context
.getExternalContext().getRequest();
HttpSession httpSession = request.getSession(false);
User user = (User) httpSession.getAttribute("user");
entries = new ArrayList<Entry>();
entries = entryServices.getEntryByUser(user);
}
public List<Entry> getEntries() {
return entries;
}
public void setEntries(List<Entry> entries) {
this.entries = entries;
}
public EntryServices getEntryServices() {
return entryServices;
}
public void setEntryServices(
EntryServices entryServices) {
this.entryServices = entryServices;
}
}
I don't see any error in the code or the facelet, sometimes I not choose the right package for the annotation that must be javax.faces.ManagedBean and javax.faces.SessionScoped otherwise the bean is never created.
In glassfish when I use a EJB in the ManagedBean it need to be serialized could you try this.
I hope this could help you.
This is my problem.
Change the imports and works:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

Managed property between SessionScoped ManagedBeans

I have the following problem!
On one of my sites i have a button:
<h:commandButton value="IDA Analyzer Results" action="#{SelectionBean.monitoringLog()}"/>
The method it calls with some part of the bean:
#ManagedBean(name = "SelectionBean")
#SessionScoped
public class TableSelectionBean {
private List<String> analyzerLog = new ArrayList<String>();
public String monitoringLog() throws FileNotFoundException, IOException{
String fileName = "/opt/IDA2/Linux/bin/"+"filtered_"+selectionMonitoringData.get(0).getMonitoringName()+"_result.txt";
if(selectionMonitoringData.get(0).getIsExecuted())
{
BufferedReader br = new BufferedReader(new FileReader(fileName));
try {
String line;
while ((line=br.readLine()) != null) {
getAnalyzerLog().add(line);
}
} finally {
br.close();
System.out.println(getAnalyzerLog());
}
}
return "analyzerresult.xhtml";
}
After i click this button as you can see it navigates me to an other page:
<h:body>
<h:form>
<h:commandButton value="hi" action="#{AnalyzerBean.myMethod()}"></h:commandButton>
</h:form>
</h:body>
Here is the Bean:
#ManagedBean(name = "AnalyzerBean")
#SessionScoped
public class AnalyzerResultBean {
#ManagedProperty(value="#{SelectionBean.analyzerLog}")
private List<String> analyzerLog;
public void myMethod(){
System.out.print(analyzerLog);
}
/**
* #return the analyzerLog
*/
public List<String> getAnalyzerLog() {
return analyzerLog;
}
/**
* #param analyzerLog the analyzerLog to set
*/
public void setAnalyzerLog(List<String> analyzerLog) {
this.analyzerLog = analyzerLog;
}
So when I'm trying to use this Managed property it says:
The scope of the object referenced by expression #{SelectionBean.analyzerLog}, view, is shorter than the referring managed beans (AnalyzerBean) scope of session but as you can see both of the is Session Scoped. What could be the problem?
If you use JSF 2.x and you want to navigate analyzerresult.xhtml page return analyzerresult
public String monitoringLog() throws FileNotFoundException, IOException{
return "analyzerresult";
}
.xhtml extension is not needed.

h:selectManyListBox setter not setting all the values selected

<h:selectManyListbox id="sectorsListBox" size="2" multiple="multiple" value="#{Mybean.classificationSelectedItems}">
<f:selectItems id="sectors" value="#{Mybean.classificationSelectItems}"/>
</h:selectManyListbox>
Backing Bean has:
public class Mybean
{
private Map<String,String> classificationSelectItems = new LinkedHashMap<String,String>();
private List<String> classificationSelectedItems = new ArrayList<String>();
//getter and setter for both.
}
init()
{
classificationSelectItems.put("INS","Insurance")
classificationSelectItems.put("HLC","HealthCare")
}
The select many box gets initialized with these 2 values but the problem is only the last selected entry is getting stored in classificationSelectedItems. Why is that so ? And how do I get all the selected entries stored in the list of classificationSelectedItems ?
Adding FYI, the init method is class by Spring.
I have tested with an examle(reference:http://www.mkyong.com/jsf2/jsf-2-multiple-select-listbox-example/), good luck :)
Facelets:
<h:form id="form">
<h:selectManyListbox value="#{user.favFood1}" >
<f:selectItems value="#{user.favFood2Value}" />
</h:selectManyListbox>
<h:commandButton value="test"/>
</h:form>
Bean:
#ManagedBean(name = "user")
#ViewScoped
public class UserBean implements Serializable {
private static final long serialVersionUID = 1L;
public List<String> favFood1;
private Map<String, Object> food2Value;
public UserBean() {
favFood1 = new ArrayList<String>();
food2Value = new LinkedHashMap<String, Object>();
food2Value.put("Food2 - Fry Checken", "Fry Checken1"); //label, value
food2Value.put("Food2 - Tomyam Soup", "Tomyam Soup2");
food2Value.put("Food2 - Mixed Rice", "Mixed Rice3");
}
public List<String> getFavFood1() {
return favFood1;
}
public void setFavFood1(List<String> favFood1) {
this.favFood1 = favFood1;
}
public Map<String, Object> getFavFood2Value() {
return food2Value;
}
}
I noticed exactly this behaviour when I used a Collection in the setter method, like
public void setClassificationSelectedItems(Collection<String> in){
// store it somewhere
}
This setter is called during the restore phase but not during the update phase, so the previously set value will be set, but never the new one. If you use a List, it works as expected:
public void setClassificationSelectedItems(List<String> in){
// store it somewhere
}
Note that you will need to redeploy the application after such a change because the JSP needs to be recompiled but this isn’t done automatically.

JSF UIRepeat and PostBack

I have a simple page where a I use <ui:repeat> and it gets the value from a backing bean.
The initial request will give it an empty list. The postback then will invoke an action that will change the model behind the <ui:repeat> but it is not rendered?!
I debugged through it and I saw that the <ui:repeat> evaluates the value at restore view phase but thats it. When it reaches render response it does not use the latest value from my bean. Is that the expected behavior?
How can I make that work? Do I have to write my own repeat tag?
I can't really tell what could be the problem without some of your code, but these are the basics:
Backing bean:
public class ObjectService{
private DataModel objectDataModel;
private List<Object> objectList;
private Pagination paginationHelper;
private ObjectDao objectDao = new ObjectDao();
private String queryOption;
public void setQueryOption(String queryOption){
this.queryOption = queryOption;
}
public String getQueryOption(){
return this.queryOption;
}
public <E> PaginationHelper getPagination(final List<E> list) {
pagination = new PaginationHelper(10) {
#Override
public int getItemsCount() {
return list.size();
}
#Override
public DataModel createPageDataModel() {
return new ListDataModel(list);
}
};
return pagination;
}
public void setPagination(PaginationHelper pagination) {
this.pagination = pagination;
}
public List<Object> getObjectList(){
this.objectList = objectDao.readObjectsWhere(queryOption);
return this.objectList;
}
public void setObjectList(List<Object> objectList){
this.objectList = objectList;
}
public DataModel getObjectDataModel(){
if (objectDataModel == null) {
objectDataModel = getPagination(getObjectList()).createPageDataModel();
}
return objectDataModel;
}
public void setObjectDataModel(DataModel objectDataModel){
this.objectDataModel = objectDataModel
}
public String changeModel(){
objectDataModel = null;
return null;
}
}
XHTML page:
...
<h:form>
<fieldset>
<label>
<span>Option:</span>
<h:inputText value="#{objectService.queryOption}" />
</label>
<h:commandButton action="#{objectService.changeModel}" value="request data" />
</fieldset>
<ui:repeat value="#{objectService.objectDataModel}" var="objectVar">
<h:outputLabel value="#{objectVar.property1}" />
<h:outputLabel value="#{objectVar.property2}" />
<h:outputLabel value="#{objectVar.property3}" />
</ui:repeat>
</h:form>
...

Resources