Pick Custom Object from Select one menu JSF Converter Exception [duplicate] - jsf

This question already has answers here:
Pick Custom Object from Select one menu JSF [duplicate]
(2 answers)
Closed 9 years ago.
i want to pick custom object from select one menu. it neither shows an error nor values. what to do? please help me. thanks in advance.
Now i'm seeing Null pointer exception at getAsObject at this line:
return getCurrencyService().getCurrencyBtId(currencyId);
this is my xhtml document
<h:panelGrid columns="2">
<p:outputLabel value="" />
<p:selectOneMenu id="CurrencyMenu" value="#{CurrencyMB.currency}" converter="currencyConverter" >
<f:selectItems value="#{CurrencyMB.currencyList}" var="currency" itemValue="#{currency}" itemLabel="#{currency.currencyName}" >
</f:selectItems>
<p:ajax update="currencyOut" />
</p:selectOneMenu>
<p:outputLabel value="Currency Id : #{CurrencyMB.currency.currencyId}" id="currencyOut" />
</h:panelGrid>
this is my managedBean class.
#ManagedBean(name = "CurrencyMB")
#RequestScoped
public class CurrencyManagedBean implements Serializable{
private Currency currency;
private List<Currency> currencyList;
public Currency getCurrency() {
return currency;
}
public void setCurrency(Currency currency) {
this.currency = currency;
}
public List<Currency> getCurrencyList() {
currencyList = new ArrayList<Currency>();
currencyList.addAll(getiCurrencyService().getCurrencies());
return currencyList;
}
public void setCurrencyList(List<Currency> currencyList) {
this.currencyList = currencyList;
}
}
this is my currencyConverter class code:
**#FacesConverter("currencyConverter")
public class CurrencyConverter implements Converter {
#ManagedProperty(value = "#{currencyService}")
private ICurrencyService currencyService;
public ICurrencyService getCurrencyService() {
return currencyService;
}
public void setCurrencyService(ICurrencyService currencyService) {
this.currencyService = currencyService;
}
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String value) {
int currencyId = Integer.valueOf(value);
return getCurrencyService().getCurrencyBtId(currencyId);
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object value) {
Currency currency = (Currency) value;
int currencyId = currency.getCurrencyId();
return String.valueOf(currencyId);
}
}**

As it can be seen in many questions, and their answers, here, #FacesConverter is not eligible for injection. In your case, you try to inject your service via #ManagedProperty, which yields NPE, as Luiggi told you in a comment to your initial question.
With the current JSF release, all you can do to inject services in your converters is to give up using #FacesConverter and switch to using standard #ManagedBean annotation, thus referring to your converter not by id, but by bean name, like in converter="#{currencyConverter}".

Related

custom converter - dependent selectonemenu not populated

I have tried to set up two selectOneMenus where the first selects an object, and in the second, one of five object parameters can be selected. For this, I have built a custom converter, and "id" should be passed from the first selectOneMenu to uniqely identify the object for the second menu. On page load, the getAsString method is called and iterated through all items of the first menu. On selecting an item, getAsObject is called, and the correct id is used and the correct Question is returned. But: the second menu is not populated at all. What did I miss? Help appreciated, I'm still learning this.
Here is the first selectOneMenu:
<h:selectOneMenu converter="answerDeliverer">
<f:selectItems value="#{questionBean.list}" var="question" itemValue="#{question}" itemLabel="#{question.text}"/>
<f:ajax event="change" render="answers"></f:ajax>
</h:selectOneMenu>
And the second:
<h:selectOneMenu id="answers">
<f:selectItem itemValue="1" itemLabel="#{question.a1}"/>
<f:selectItem itemValue="2" itemLabel="#{question.a2}"/>
<f:selectItem itemValue="3" itemLabel="#{question.a3}"/>
<f:selectItem itemValue="4" itemLabel="#{question.a4}"/>
<f:selectItem itemValue="5" itemLabel="#{question.a5}"/>
</h:selectOneMenu>
And the converter:
#ManagedBean (name = "answerDeliverer")
#RequestScoped
public class answerDeliverer implements Converter {
#EJB
private QuestionDAO questionDAO;
#Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
return questionDAO.get(Integer.parseInt(s));
}
#Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object o) {
if (o instanceof Question) {
return ((Question) o).getId();
} else if (o instanceof String) {
return ((String) o);
} else throw new ConverterException(new FacesMessage(o + " is not a valid Question or id"));
//just so I can try either question or question.id as itemValues
}
}
The error log is empty, only on startup I get several warnings of this type:
Unknow type constant pool 18 at position 7
Nov 03, 2015 1:17:10 PM com.sun.faces.config.JavaClassScanningAnnotationScanner$ConstantPoolInfo containsAnnotation
After hours and hours of debugging, I'm stuck now. I can conclude the following:
The answerDeliverer seems to work. On selection, getAsObject fetches the correct question from the DB
XHR is registered in browser debug mode on every selection with a "200 OK" server answer
There is no other error in the log
I seem to have something wrong with bringing the question into the scope of the second selectOneMenu. Question is not a ManagedBean, and in my QuestionBean, private Question question = new Question(), so, could it be that no matter what I do in the first selectOneMenu, the second always generates a new instance and doesn't care about what I did before? And thus erases any question I had before? How could I avoid that?
I'm using Mojarra-2.2.1 on Tomcat 8. Also tried to go with OmniFaces, but got stuck in an infinite loop of debugging the setup there before giving up on that.
I'll add my Question POJO and the Bean if that helps any.
public class Question implements Serializable {
private String text;
private String a1 = Constants.defaulta1;
private String a2 = Constants.defaulta2;
private String a3 = Constants.defaulta3;
private String a4 = Constants.defaulta4;
private String a5 = Constants.defaulta5;
private String id;
private String nodeid;
//getters and setters
#Override
public boolean equals(Object other) {
return (other != null && getClass() == other.getClass() && id != null)
? id.equals(((Question) other).id)
: (other == this);
}
#Override
public int hashCode() {
return (id != null)
? (getClass().hashCode() + id.hashCode())
: super.hashCode();
}
#Override
public String toString() {
return id;
}
}
and the QuestionBean:
#ManagedBean (name="questionBean")
#ViewScoped
public class QuestionBean implements Serializable {
private List<Question> list;
//this was for a CRUD page; I deleted the other irrelevant code
private Question question = new Question();
private boolean edited;
#EJB
private QuestionDAO questionDAO;
#PostConstruct
public void init() {
list = questionDAO.getAll();
}
public List<Question> getList() {
return list;
}
public Question getQuestion() {
return question;
}
}

Primefaces pickList with inputText not working

I'm trying to add an inputText field to my primefaces pickList, but I've got some problems with it.
At first: I can't write in the textField with a normal left-click. I have to right click to be able to type in the textField.
Second: It doesn't seem to save the value from the textField to the corresponding entity.
My case:
<h:form id="pickListForm">
<p:pickList converter="primeFacesPickListConverter" id="pickList" value="#{locodeBackingBean.locodes}"
var="locode" showCheckbox="true"
itemValue="#{locode.id}">
<f:facet name="sourceCaption">#{msgs['locode.not.infected']}</f:facet>
<f:facet name="targetCaption">#{msgs['locode.infected']}</f:facet>
<p:column style="width:70%;">
<h:outputText value="#{locode.description}"/>
</p:column>
<p:column style="width:30%">
<p:inputText value="#{locode.incubationPeriod}"/>
</p:column>
</p:pickList>
<p:commandButton value="#{msgs.save}" action="#{locodeBackingBean.save()}" update="growl"/>
</h:form>
My backing bean:
#ManagedBean
#ViewScoped
public class LocodeBackingBean implements Serializable {
private static final long serialVersionUID = 1L;
#Inject
private transient LocodeRepositoryBean locodeRepository;
private DualListModel<Locode> locodes = new DualListModel<>();
public void save() {
for (Locode locode : locodes.getTarget()) {
locode.setInfectedArea(true);
locodeRepository.save(locode);
}
for (Locode locode : locodes.getSource()) {
locode.setInfectedArea(false);
locodeRepository.save(locode);
}
addFacesMessage("locode.action.saved");
}
#PostConstruct
public void search() {
List<Locode> source = locodeRepository.findAllNotInfected(locodeSearchCriteria);;
List<Locode> target locodeRepository.findAllInfected(locodeSearchCriteria);
locodes.setSource(source);
locodes.setTarget(target);
}
public DualListModel<Locode> getLocodes() {
return locodes;
}
public void setLocodes(DualListModel<Locode> locodes) {
this.locodes = locodes;
}
And to be complete, my converter:
#FacesConverter(value = "primeFacesPickListConverter")
public class PrimeFacesPickListConverter<T extends Domain> implements Converter {
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
if (arg1 instanceof PickList) {
Object dualList = ((PickList) arg1).getValue();
DualListModel dl = (DualListModel) dualList;
for (Object o : dl.getSource()) {
if (equalsById(arg2, o)) return o;
}
for (Object o : dl.getTarget()) {
if (equalsById(arg2, o)) return o;
}
}
throw new PrimeFacesPickListConverterException("Could not match object's id (" + arg2 + ") to any id's in the list.");
}
private boolean equalsById(String arg2, Object o) {
String id = String.valueOf((((T) o)).getId());
return arg2.equals(id);
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
return String.valueOf(arg2);
}
using PrimeFaces 5.2
Picklists in general are not intended to contain 'controls'. So it was never designed to work this way and if it does not work, that is just unfortunate. Redesigning your ui is the only thing to do.

Retrieve class values from selectCheckboxMenu

I have a <p:selectCheckboxMenu> and I want to get the selected values back in bean. But the value I receive
when I select an item from the menu it's a string, representing the type field from the CategorizationBean.
I just want when I select an item from the table, to get the whole CategorizationBean structure in the bean.
This is the snippet from the xhtml page:
<p:selectCheckboxMenu label="Categorization"
value="#alertMB.selectedCategories}"
converter="com.converter.CategoryConverter">
<f:selectItems value="#{alertMB.categoryDomainEntry}"
var="category"
itemLabel="#{category.type}"
itemValue="#{category}"/>
</p:selectCheckboxMenu>
Snippet from bean:
public List<CategorizationBean> getSelectedCategories() {
return selectedCategories;
}
public void setSelectedCategories(List<CategorizationBean> selectedCategories) {
this.selectedCategories = selectedCategories;
}
public class CategorizationBean implements Serializable{
private String type;
private long id;
I think that you have missed by using a list of beans, I use this example and it works:
<p:selectCheckboxMenu id="slctRdBtn"
value="#{yourBean.compLovDtgrid}"
converter="compLovDtgridConverter">
<f:selectItems
value="#{yourBean.listCompLovDtgrid}"
var="rdbtn" itemLabel="#{rdbtn.vjlrLibelleRep}"
itemValue="#{rdbtn}" />
</p:selectCheckboxMenu>
and for the converter:
#FacesConverter(forClass=CompLovDtgrid.class , value="compLovDtgridConverter")
public class CompLovDtgridConverter implements Converter{
#Override
public String getAsString(FacesContext context, UIComponent component, Object value)
{
return (value instanceof CompLovDtgrid) ? ((CompLovDtgrid) value).getVjlrCodeRep() : null;
}
#Override
public Object getAsObject(FacesContext context, UIComponent component,String value)
{
if(value == null)
return null;
YourBean data = context.getApplication().evaluateExpressionGet(context, "#{yourBean}", YourBean.class);
for(CompLovDtgrid compLovDtgrid : data.getListCompLovDtgrid())
{
if(compLovDtgrid.getVjlrCodeRep().equals(value))
return compLovDtgrid;
}
throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to CompLovDtgrid", value)));
}
}
and for the list, I use:
public List<CompLovDtgrid> getListCompLovDtgrid()
{
return listCompLovDtgrid;
}
public void setListCompLovDtgrid(List<CompLovDtgrid> listCompLovDtgrid) {
this.listCompLovDtgrid = listCompLovDtgrid;
}

Using a Enum with a ActionParam

I am using the following piece of code in my JSF 2.0 with RichFaces 4.0. I have a managed bean that has an enum. Now i want to assign the value of the enum via an ActionParam. How can I do this? Here is the code:
<a4j:commandLink id="pendingTransactions"
action="#{tellerBean.getPendingTransactions}" value="Show Pending"
styleClass="button category-btn">
<a4j:actionparam name="first" value=""
assignTo="" />
</a4j:commandLink>
and my managed bean:
#ManagedBean
#SessionScoped
public class TellerBean implements Serializable{
public enum TransactionType {
PENDING,PROCESSED,ALL
}
private static final long serialVersionUID = -321111;
private String recipientID;
private String recipientName;
private String transactionAmount;
private TransactionType transactionType;
public String getRecipientID() {
return recipientID;
}
public void setRecipientID(String recipientID) {
this.recipientID = recipientID;
}
public String getRecipientName() {
return recipientName;
}
public void setRecipientName(String recipientName) {
this.recipientName = recipientName;
}
public String getTransactionAmount() {
return transactionAmount;
}
public void setTransactionAmount(String transactionAmount) {
this.transactionAmount = transactionAmount;
}
public void searchTransactions() {}
public TransactionType getTransactionType() {
return transactionType;
}
public void setTransactionType(TransactionType transactionType) {
this.transactionType = transactionType;
}
public void getTransactions() {}
}
Now I want to assign the value of the transactionType variable to an Enum value. How can I do this?
I don't know what you want to do with the variable or how you want to display it, so here's a generic example.
First of all, the JSF page must be able to 'iterate' over the enum to discover the possible values. I'm using h:selectOneMenu as an example which is filled using f:selectItems. f:selectItems expects a List<> as input so we need to create a method in the TellerBean:
public List<TransactionType> getTransactionTypes()
{
List<TransactionTypes> tt = new ArrayList<TransactionType>();
for (TransactionType t : TransactionType.values())
{
tt.add(new TransactionType(t, t.toString()))
}
return tt;
}
Then for an example JSF page:
<h:form>
<h:selectOneMenu value="#{tellerBean.transactionType}">
<f:selectItems value="#{tellerBean.transactionTypes}"/>
</h:selectOneMenu>
<h:commandButton value="Submit" action="#{tellerBean.someMethod}"/>
</h:form>
The JSF page should display a drop-down list with the values of the enum. When clicking the button labeled "Submit" it executes someMethod() in TellerBean. Of course this doesn't work because the method doesn't exist, but it's just an example. ;-)

JSF 2 <f:selectItems> not recognizing itemLabel and itemValue attributes

I have the following dropdown in a Facelets page:
<h:selectOneMenu value="#{contactBean.selectedContact}" converter="#{contactConverter}">
<f:selectItems value="#{contactsHolder.contacts}" var="contact"
itemLabel="#{contact.firstName}" itemValue="#{contact}" />
</h:selectOneMenu>
The problem is, no matter what I put in for itemLabel (JSF EL expression or just plain text), it doesn't display. Any idea what I'm doing wrong?
Here's ContactConverter:
#ManagedBean(name = "contactConverter")
#RequestScoped
public class ContactConverter implements Converter, Serializable {
#ManagedProperty(value = "#{contactsHolder}")
private ContactsHolder contactsHolder;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return contactsHolder.getContacts().get(value);
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return ((Contact) value).getContactID();
}
//getter & setters...
}
And ContactsHolder:
#ManagedBean
#SessionScoped
public class ContactsHolder implements Serializable {
private Map<String, Contact> contacts;
#PostConstruct
public void init() {
contacts = new LinkedHashMap<String, Contact>();
//get Contacts data and populate map...
}
//getters & setters...
}
You're feeding a Map<String, Contact> to <f:selectItems value>. Each item in var attribute will be a Map.Entry<String, Contact> which has only getKey() and getValue() methods returning the String map key and Contact map value respectively. The Map.Entry class indeed doesn't have a getFirstName() method.
Fix it accordingly:
<f:selectItems value="#{contactsHolder.contacts}" var="contact"
itemLabel="#{contact.value.firstName}" itemValue="#{contact.value}" />
Or, if you target a Servlet 3.0 / EL 2.2 capable container which allows invoking non-getter methods, so that you can use Map#values() to get a Collection<Contact>:
<f:selectItems value="#{contactsHolder.contacts.values()}" var="contact"
itemLabel="#{contact.firstName}" itemValue="#{contact}" />
Or, make the #{contactsHolder.contacts} a List<Contact> instead so that your initial view code will work:
<f:selectItems value="#{contactsHolder.contacts}" var="contact"
itemLabel="#{contact.firstName}" itemValue="#{contact}" />

Resources