Parameter in jsf bean is null. why? - jsf

I have a jsf page where i show a datatable. In the p:column tag i want to set the background-Color. The Background-Color will be determined by the Method public String getTrafficColor(Trgs trgs) in the TrgsLazyDataActions Bean.
But The Parameter trgs of the Method getTrgsTrafficColor(Trgs trgs) is always null and so i get a NullPointerException.
In the p:column-tag i Transfer the tempTrgs Object
#{trgsLazyDataActions.getTrafficColor(tempTrgs)}"
The tempTrgs is the var of p:datatable and it is not null.
I don't why the transferd paramter is null in the Bean.
<p:column headerText="#{texts['trgs.atp']}"
filterBy="#{tempTrgs.atp}" width="40"
style="background-color: #{trgsLazyDataActions.getTrafficColor(tempTrgs)}">
....
</p:column>
.
#javax.faces.view.ViewScoped
#Named
public class TrgsLazyDataActions extends TrgsActionsBase implements Serializable {
//The Parameter trgs is null. I don't know why ?
public String getTrafficColor(Trgs trgs) {
Factory auditedFactory = getAuditedTrgs(trgs.getTrgsID()).getFactory();
if (trgs.getAtp() < auditedFactory.getAtpMin()) {
return Consts.RED;
} else if (trgs.getAtp() > auditedFactory.getAtpMax()) {
return Consts.YELLOW;
} else {
return Consts.GREEN;
}
}
}

Related

Expand EL-Context for some value

Example in xhtml works, because #{row} is defined in p:dataTable. If I call getData not in context of p:dataTable it returns null. See Values.iterateOverDatatableValues for this situation where method returns null. How can I define row to use in my context. Possibly has datatable some functions to iterate over values so that #{row} will be defined?
Java:
#Named
#SessionScoped
class Test {
public Object getData () {
return Faces.evaluateExpressionGet("#{row.someProperty}"); //The String "#{row.someProperty}" comes from a collection.
}
}
XHTML #{row} is defined in Test.getData():
<p:dataTable value="#{bean.values}" var="row">
<p:column>
<h:outputText value="#{test.data}" />
</p:column>
</p:dataTable>
Java, #{row} is undefined:
class Values {
#Inject
Test test;
public void iterateOverDatatableValues (){
DataTable dt = Components.findComponent("datatableId");
for (Object o : dt.getValues()){
test.getData(); // <---- NULL because #{row} is not defined.
}
}
}
The solution was to use expressionFactory().createValueExperssion method.
private void setRowEL(Object o) {
ELContext elContext = Faces.getELContext();
ExpressionFactory expressionFactory = Faces.getApplication().getExpressionFactory();
ValueExpression aliasValueExpression = expressionFactory.createValueExpression(elContext, "#{row}", MyValue.class);
aliasValueExpression.setValue(elContext, o);
}

How to Compare the values JSF selectonemenu

I am developing a JSF application
I have 2 selectOnemenu controls and submit button.
I need to disable the button if the values of 2 fields are equal
<h:selectOneMenu id="from" value="#{currencyBean.history.fromCurrency}" >
<f:selectItems value="#{currencyBean.currency}" var="c" itemValue="#{c}" itemLabel="#{c.name}"/>
</h:selectOneMenu>
<p:outputLabel for="to" value="to:" />
<h:selectOneMenu id="to" value="#{currencyBean.history.toCurrency}" >
<f:selectItems value="#{currencyBean.currency}" var="c" itemValue="#{c}" itemLabel="#{c.name}"/>
</h:selectOneMenu>
<p:commandButton id="calculateButton" value="Convert" update=":convert :historyPanel" onstart="PF('statusDialog').show()" onsuccess="PF('statusDialog').hide()" validateClient="true" ajax="true" action="#{currencyBean.Calculate()}" />
I tried to use onchange with ajax but everytime I change one dropdown the value of the second drowpdown became null in the backbean so I cannot read it.
Here is my backbean
#Named(value = "currencyBean")
#RequestScoped
public class CurrencyBean implements Serializable {
/**
* Creates a new instance of CurrencyBean
*/
private History history;
private Currency currency;
private Date currentDate;
#Inject
private Loginbean loginBean;
private List<History> historyList;
public List<History> getHistoryList() {
int userId = loginBean.getUserId();
if (userId != -1) {
return new HistoryHelper().GetHistoryListByUser(userId);
}
return null;
}
public CurrencyBean() {
history = new History();
}
public History getHistory() {
return history;
}
public void setHistory(History history) {
this.history = history;
}
public Currency[] getCurrency() {
return Currency.values();
}
public Date getCurrentDate() {
return new Date();
}
public void Calculate() {
int userId = loginBean.getUserId();
if (userId != -1) {
new CurrencyClient().Convert(userId, this.history);
}
}
}
any clue ?
My assumption is that all of your problems come from your managed bean scope. You have #Request scope so every request your managed bean will be removed from container, thus when you define onchange="submit()" (this is only my assumption because you haven't define how you implement onchange attribute) and you select value from one selectBox component values for this component is updated but the first one is still null. When you select second selectBox value updated from first selectBox doesn't exists anymore as managed bean has been removed after first request. You should try with wider scope for instance #ViewScope. If it doesn't help then further informations like implementation onchange attribute will be needed

inputHidden how to fetch value from backbean

I have an inputHidden element in a form to which i would like to fetch a property value from the backbean. Here is my JSF code:
<h:form id="imageEditor">
<p:toolbar id="theMenuBar">
<p:toolbarGroup align="left">
...
<p:commandButton value="Quit" ajax="true"
action="#{imageEditorBean.goToMainMenu()}"
icon="ui-icon-close" >
<p:ajax update="#this" immediate="true"/>
</p:commandButton>
</p:toolbarGroup>
</p:toolbar>
...
<p:fieldset id="viewer" legend="Viewer">
<h:inputHidden id="getJSONData" value="#{imageAnnotations.fetchJSONString()}">
</h:inputHidden>
...
My corresponding backbean class is:
#ManagedBean(name="imageAnnotations")
public class ImageAnnotations {
private String jsonString;
public String fetchJSONString () {
jsonString = new String();
...//populate property
return jsonString;
}
public String getJsonString() {
return jsonString;
}
public void setJsonString(String jsonString) {
this.jsonString = jsonString;
}
When the page loads value property of inputHidden field is populated BUT when i press the quit button to switch view the button is not working, and i get the following error:
Caused by: javax.el.PropertyNotWritableException: /views/image-editor.xhtml #110,82 value="#{imageAnnotations.fetchJSONString()}": Illegal Syntax for Set Operation
I have also tried to call my backbean class and populate the jsonString property like:
<h:inputHidden id="getJSONData" value="#{imageAnnotations.jsonString" action="#{imageAnnotations.fetchJSONString()}">
with no luck. Any ideas?
The inputHidden works in the same way as a inputText, except that it's not displayed in the screen. Therefore, the value property has to point to an attribute in the managed bean, with getter and setter. It can't point to a method. You will have to initialize the value of the property either in the constructor or in the #PostConstruct. If in order to populate this property you use a #ManagedProperty or a #EJB, you'll have to do it in the #PostConstruct since in the constructor they haven't been set yet.
<h:inputHidden id="getJSONData" value="#{imageAnnotations.jsonString" >
In the ManagedBean
#ManagedBean(name="imageAnnotations")
public class ImageAnnotations {
private String jsonString;
#PostConstruct
public void init() {
jsonString = ... // populate jsonString
}
// getter & setter for jsonString
}

p:selectOneMenu validation fails

I'm using PrimeFaces SelectOneMenu as follows:
<p:selectOneMenu id="inviteAbleRoleSelect"
styleClass="dropDownSelector"
value="#{invitationManagedBean.selectedRole}">
<f:selectItems value="#{invitationManagedBean.inviteAbleRoles}"
var="role"
itemValue="#{role}"
itemLabel="#{localized[role.concat('RoleName')]}">
</f:selectItems>
</p:selectOneMenu>
And the following JavaScript called on complete:
function handleUserInvitationRequest(xhr,status,args){
if (args.validationFailed) {
jQuery('#userInviterDialog').effect("shake", {
times : 3
}, 70);
} else {
userInviterDialogVar.hide();
refreshInvitedUserList();
}
}
When I submit the form, I get an ajax POST with the correctly filled form, but when it calls the handler, the validationFailed is true, even if the element is not required. Also the changes coming in the ajax response sets the select to an empty select.
Any idea?
It was a totally lame fault...
The bean was #RequestScoped ...
At least #ViewScoped is required.
If your role is not a String or any primitive type, then you are probably getting Validation Error: Value is not valid, therefor you need to implement a Converter for your Role Entity/Object, it would be something like this.
#FacesConverter("roleConverter")
public class RoleConverter implements Converter {
#Override
public Object getAsObject(FacesContext context,
UIComponent component,
String value) {
//prepare your datasource ex. EJB .. etc
if (value.trim().equals("")) {
return null;
} else {
Role role = datasource.findById(value); //get role from database
retun role;
}
}
#Override
public String getAsString(FacesContext context,
UIComponent component,
Object value) {
if (value == null || value.equals("")) {
return "";
} else {
return String.valueOf(((Role) value).getId());
}
}
}
selectOneMenu
<p:selectOneMenu id="inviteAbleRoleSelect"
styleClass="dropDownSelector"
value="#{invitationManagedBean.selectedRole}" converter="roleConverter">
<f:selectItems value="#{invitationManagedBean.inviteAbleRoles}"
var="role"
itemValue="#{role}"
itemLabel="#{localized[role.concat('RoleName')]}">
</f:selectItems>
</p:selectOneMenu>
And you need to make sure that your Role implements equals and hashcode.

JSF Dynamic Rendered Component's Value becomes null when the form is submitted

I have a JSF page which renders a text field depending on the value of a drop down using primefaces ajax listner. The dynamic rendering is done fine. but the problem is once I submit the form the the bound value of that textfield doesn't get bound instead it is shown as null.
this is the part of my JSF only the necessary fields are included here
<h:panelGroup id="textPanel" >
<h:form id="main" prependId="false">
<h:outputText value="WorkFlow ID:" />
<h:selectOneMenu id="workFlows" value="#{workFlowSelectionController.selectedWorkFlowId}" >
<p:ajax event="change" listener="#{workFlowSelectionController.dropDownChange}" update="textPanel"/>
<f:selectItems value="#{workFlowSelectionController.allActiveworkFlows}"/>
</h:selectOneMenu>
<p:inputText value="#{workFlowSelectionController.texField}" rendered="#{workFlowSelectionController.textfieldVisibility}"/>
<p:commandButton ajax="false" value="Next" action="#{workFlowSelectionController.addWorkFlowselectionDetails}"/>
</h:form>
</h:panelGroup>
this is my managed bean
#ManagedBean
#RequestScoped
public class WorkFlowSelectionController {
private boolean textfieldVisibility = false;
private String texField;
public void dropDownChange() {
logger.info("WorkFlowSelectionController.dropDownChange() entered");
if (selectedWorkFlowId != null) {
if (selectedWorkFlowId.equals("-1")) {
textfieldVisibility = true;
operationListStatus = false;
} else {
textfieldVisibility = false;
operationListStatus = true;
}
} else {
textfieldVisibility = false;
operationListStatus = true;
}
public void addWorkFlowselectionDetails() throws CloneNotSupportedException {
System.out.println("Selected Value of Text Field is" + texField);
}
public String getTexField() {
return texField;
}
public void setTexField(String texField) {
this.texField = texField;
}
}
i haven't included the dropdown code of the backing bean. i just need an idea of what i am doing wrong here if i remove the rendered attribute of the textfield it works fine.
thank you
Put the bean in the view scope instead of request scope. A request scoped is recreated on every single HTTP request. The boolean property will default to false again whenever you submit the form, so the submitted value won't be processed then.
#ManagedBean
#ViewScoped
public class WorkFlowSelectionController {
//
}
A view scoped bean will live as long as you're (ajax-) interacting with the same view by returning null or void from action(listener) methods.

Resources