Strange error i received from compiler:
Expected a child component type of UISelectItem/UISelectItems for component type javax.faces.SelectOne(siachoice). Found javax.faces.component.UISelectItems.
So, if he was expecting UISelectItems, and found UISelectItems, then where is the error?
My JSP implementation:
<h:selectOneMenu id="siachoice" value="#{dbSelectBean.currentOption}">
<f:selectItems value="#{dbSelectBean.dbs}" />
</h:selectOneMenu>
Method, where i am setting UISelectItem to UISelectItems:
private UISelectItems populateDatabases(String databaseString) {
UISelectItems selects = new UISelectItems();
List<UISelectItem> result = new ArrayList<UISelectItem>();
StringTokenizer tokeniz = new StringTokenizer(databaseString, GlobalConstants.DELIMITER);
while(tokeniz.hasMoreTokens()){
String tempDB = tokeniz.nextToken();
UISelectItem item = new UISelectItem();
item.setItemValue(tempDB);
item.setItemLabel(tempDB);
result.add(item);
}
selects.setValue(result);
return selects;
}
Then, of course, i am setting it to the bean variable dbs.
Help?
You must return a Collection of javax.faces.model.SelectItem
List list = new ArrayList();
list.add(new SelectItem(value, label));
return list;
The <f:selectItems value="#{bean.items}" /> expects one of the following values:
public SelectItem[] getItems() {}
public List<SelectItem> getItems() {}
public Map<String, Object> getItems() {}
The commonly used one is indeed the List<SelectItem>.
Edit: as response to the comment: UISelectItem represents the <f:selectItem> component. The same applies to UISelectItems and <f:selectItems>. E.g.
<f:selectItem binding="#{bean.selectItem}" />
<f:selectItems binding="#{bean.selectItems}" />
which are bound as
private UISelectItem selectItem;
private UISelectItems selectItems;
// +getter +setter
this way you can control the components programmatically -as for every other UIComponent.
<h:form>
<h:selectOneListbox size="5" >
<f:selectItems value="#{userManager.Test()}" />
</h:selectOneListbox>
</h:form>
import javax.faces.model.SelectItem;
import tn.com.ttnproject.entity.*;
#Name("userManager")
#Scope(ScopeType.CONVERSATION)
public class UserManager {
public List <SelectItem> listAllUsersNames;
SelectItem element;
public List<SelectItem> Test(){
listAllUsersNames = new ArrayList<SelectItem>();
for (int i=1;i<=10;i++)
{
element=new SelectItem(
new Integer(i),
i+".00 euros",
"Produit à "+i+".00 euros");
listAllUsersNames.add(element);
}
return listAllUsersNames;
}
}
The problem is UISelectItem is a component clas so it has to be paired with jsf tag by binding attribute. If you want to have pure values you have to use SelectItem(s) classes.
Related
I have a form where I create a user. In my form, I have multiple properties for that user (I actually use a User object for the retainment of data on submit to the backing bean)
create.xhtml
<h:form>
<h:outputLabel for="user_name" value="Name:" />
<h:inputText id="user_name" value="#{createUserView.newUser.username}" />
<br/><br/>
<h:outputLabel for="user_password" value="Default Password*:" />
<h:inputSecret id="user_password" value="#{createUserView.newUser.password}"></h:inputSecret><br/><br/>
<h:outputLabel for="user_organization" value="Organization:" />
<h:selectOneMenu id="user_organization" disabled="true" value="#{createUserView.newUser.organizationId}">
<f:selectItems
value="#{organizationBean.allOrganizations}"
var="org"
itemLabel="#{org.organizationName}"
itemValue="#{org.id}" />
</h:selectOneMenu><br/><br/>
<h:commandButton value="Create" action="#{createUserView.createNewUser}" />
</h:form>
CreateUserView
#ManagedBean(name = "createUserView")
#RequestScoped
public class CreateUserView {
private UserServices userSerivces;
private User newUser;
#ManagedProperty(value="#{organizationBean}")
private OrganizationBean organizationBean;
public CreateUserView() {
newUser = new User();
userSerivces = new UserServices();
}
public void createNewUser() {
userSerivces.createNewUser(newUser);
}
// Getters and Setters
}
OrganizationBean
#ManagedBean(name = "organizationBean")
#RequestScoped
public class OrganizationBean {
private List<Organization> allOrganizations;
private OrganizationServices orgServices;
public OrganizationBean() {
orgServices = new OrganizationServices();
allOrganizations = orgServices.retrieveAllOrganizations();
}
// Getters and Setters
}
The issue here is that when I reference the newUser object in the backing bean, the organizationId value is null.
I assume this is because OrganizationBean (excuse the confusing in naming, refactoring) is either not rendered for my current view or I need to somehow inject.
I've tried a managed property in the CreateUserView backing bean that references the OrganizationBean, but no luck. The organizationID value in the newUser object is null.
Do I need to populate a list in the CreateUserView bean using the OrganizationBean injection, so that it has it's own list it can render?
What am I missing? Feeling foolish.
JSF 2.0
The problem, as stated in the comments is that you don't have a Converter for your Organization class.
You must have it in order to know what Organization matches every SelectItem. The converter must be something like:
#FacesConverter(forClass = Organization.class, value = "organizationConverter")
public class OrganizationConverter implements Converter
{
#Override
public Object getAsObject(FacesContext fc, UIComponent uic, String id)
{
if (StringUtils.isEmpty(id))
{
return null;
}
// Convert id to an Organizacion
return organization;
}
#Override
public String getAsString(FacesContext fc, UIComponent uic, Object o)
{
if (o instanceof Organization)
{
return ...;//Convert organization to id
}
return null;
}
}
And then in your selectonemenu:
<h:selectOneMenu id="user_organization" disabled="true" value="#{createUserView.newUser.organizationId}"
converter="organizationConverter">
How can I use #ManagedProperty in backing component?
This is partner selector composite component. The component checks the typed partner code in the database and fills the partner name if code is valid.
The component:
<cc:interface componentType="partnerSelComp">
<cc:attribute name="value" type="java.lang.Long"/>
</cc:interface>
<cc:implementation>
<span id="#{cc.clientId}" style="white-space:nowrap">
<p:inputText id="id" type="hidden" binding="#{cc.partnerId}"/>
<p:inputText id="code" binding="#{cc.code}">
<p:ajax event="blur" update="id code name" listener="#{cc.validate}" />
</p:inputText>
<p:inputText id ="name" disabled="true" binding="#{cc.name}" />
<p:message for="code"/>
</span>
</cc:implementation>
In encodeBegin() I got NPE because service is null:
#FacesComponent("partnerSelComp")
public class PartnerSelComp extends UIInput implements NamingContainer {
private InputText partnerId;
private InputText code;
private InputText name;
#ManagedProperty("#{partnerService}")
private PartnerService service;
#Override
public void encodeBegin(FacesContext context) throws IOException {
Partner p=null;
Long i = (Long) getValue();
if (i != null) {
p = findPartnerById(service.getList(), i);
}
fill( (i==null) , p); // fills the code and name fields
}
...
}
This is the bean I'd like to access. (later it will replaced with a JPA query.)
#ManagedBean(name = "partnerService")
#ApplicationScoped
public class PartnerService {
private List<Partner> list;
public PartnerService() {
list = new ArrayList<>();
list.add( new Partner(1, "A", "Partner A"));
list.add( new Partner(2, "B", "Partner B"));
list.add( new Partner(3, "C", "Partner C"));
list.add( new Partner(4, "D", "Partner D"));
list.add( new Partner(5, "E", "Partner E"));
list.add( new Partner(6, "E", "Partner F"));
}
public List<Partner> getList() {
return list;
}
public void setList(List<Partner> list) {
this.list = list;
}
}
The solution:
The use of the component:
<my:PartnerSelComp value="#{myBean.partnerId}" service="#{partnerService}"/>
The component xhtml:
<cc:interface componentType="partnerSelComp">
<cc:attribute name="value" type="java.lang.Long"/>
<cc:attribute name="service"/>
</cc:interface>
<cc:implementation>
<span id="#{cc.clientId}" style="white-space:nowrap">
<p:inputText id="id" type="hidden" binding="#{cc.partnerId}"/>
<p:inputText id="code" binding="#{cc.code}">
<p:ajax event="blur" update="id code name" listener="#{cc.validate}" />
</p:inputText>
<p:inputText id ="name" disabled="true" binding="#{cc.name}" />
<p:message for="code"/>
</span>
</cc:implementation>
I note, I tried it to pass the reference as attribute default value: <cc:attribute name="service" default="#{partnerService}"/> and <my:PartnerSelComp value="#{myBean.partnerId}"/> I don't know why but it didn't worked me, I had to set service attribute in my:PartnerSelComp as you see above.
And the backing component:
#FacesComponent("partnerSelComp")
public class PartnerSelComp extends UIInput implements NamingContainer {
private InputText partnerId;
private InputText code;
private InputText name;
#ManagedProperty("#{partnerService}")
private PartnerService service;
#Override
public void encodeBegin(FacesContext context) throws IOException {
Partner p=null;
Long i = (Long) getValue();
PartnerService service = getAttributeValue("service", null );
if (i != null) {
p = findPartnerById(service.getList(), i);
}
fill( (i==null) , p); // fills the code and name fields
}
#SuppressWarnings("unchecked")
private <T> T getAttributeValue(String key, T defaultValue) {
T value = (T) getAttributes().get(key);
return (value != null) ? value : defaultValue;
}
...
}
I have to use getAttributes().get(key) to get the reference and cast it to PartnerService.
Thanks for the answers.
Try to load it using the html configuration interface:
<cc:interface componentType="partnerSelComp">
<cc:attribute name="value" type="java.lang.Long"/>
<cc:attribute name="service" default="#{partnerService}"/>
</cc:interface>
This is mostly for the usage inside of html implementation as inside of the bean class you would have to get it manually anyway:
FacesContext.getCurrentInstance().getAttributes().get("service");
Regarding the direct injection into #FacesComponent it is not possible until next version of JSF (2.3).
A possible workaround would be to use "#Named instead of #FacesComponent or if you cannot do that, then try out some of the features of the http://omnifaces.org/ library. It enables injection into #FacesConverter so maybe you could also apply it for this annotation.
I already tried to search through this site, but maybe I'm not getting understand well.
Please kindly advice for my cases..
I'm using Netbeans 7.3 + Primefaces + Hibernate.
I want to show a list from my query.
My query already in.. and there's no error showup, but the display is not what I want (I think it returning an object or something, not sure).
Please kindly correct me if I'm missed something.
Here's my PtlLovBean
#ManagedBean(name = "ptlLovBean")
#SessionScoped
public class PtlLovBean implements Serializable {
private static final String FLIGHT = "LOV_FLIGHT";
private List lovFlight;
public List getLovFlight() {
PtlLovDao ptlLovDao = new PtlLovDaoImpl();
return ptlLovDao.getByKey(FLIGHT);
}
}
Here's ptlLovDao
public interface PtlLovDao {
public List getByKey(String key);
}
Here's PtlLovDaoImpl
public class PtlLovDaoImpl implements PtlLovDao {
#Override
public List getByKey(String key) {
Session session = HibernateUtil.getSessionFactory().openSession();
Query query = session.createQuery("from PtlLov where LOV_KEY = :param");
query.setParameter("param", key);
return query.list();
}
}
Here's my JSF :
<p:selectOneMenu id="flightName" value="#{wizard.user.selectedFlightName}">
<f:selectItem itemLabel="Select Flight" itemValue="" />
<f:selectItems value="#{ptlLovBean.lovFlight}" />
</p:selectOneMenu>
Display after Code:
Sorry I'm not capable to insert picture, so here's the image link :
http://i117.photobucket.com/albums/o56/po_se_for/PIC_zps88ec4983.png
You can either override the toString method in your PtlLov class or define itemValue and itemLabel properties in your f:selectItems tag.
Something like this:
<f:selectItems value="#{ptlLovBean.lovFlight}" var="flight"
itemValue="#{flight}" itemLabel="#{flight.description}" />
I have a bean and there is cache and a method to get value from it.
public List<SelectItem> getSelectItemList(String key){
return cache.get(key).getValue();
}
May I know how can I get this list in JSF?
I have tried..
<f:selectItems value="#{Bean.getSelectItemList(abc)}" />
but it does not work, because it is expecting a property.
Note: I using JSF 1.2 , EHCache
JSF Code:
<t:selectOneMenu id="testId" value="#{testBean.selectedItem}" >
<f:selectItems value="#{testBean.selectItemList}" />
</t:selectOneMenu>
Manage Bean code:
private String selectedItem;
private List selectItemList;
public List<SelectItem> getselectItemList() {
if(null == selectItemList || selectItemList.isEmpty()){
selectUserList = new ArrayList<SelectItem>();
selectItemList.add(new SelectItem(this.selectedItem, cache.get(this.selectedItem).getValue()));
}
return selectItemList;
}
I have irritating problem when I populate a drill-down selection of two selectOneMenu. The first menu is Sector which controls the other one Categorty. I load the selection for the Category depending on Sector and all of this is working fine.
But when I edit a business object that has a Category (has one) Sector attached to it. The Category doesn't get display when first loading the edit.xhtml page. I know the value is correct in the SessionScoped backing bean. If I select another Sector-Category and then go back to the initial Sector, the Category get properly set at it was persisted in the first place.
The POJO classes (Sector-Category) has the hashCode() and equals(Object object) functions.
I have CRUD generated JSF converters for the POJO object, but I don't think this is causing the problem. I think the second selectOneMenu don't display its value as it should for some reason. If I flip the parent (Sector) to something else and the back to the initial state, the correct value from the manged bean get displayed.
Ho can I make the Category selectOneMenu component display the value in the managed bean?
Greetings Chris
Faces Error Message
FacesMessage(s) have been enqueued, but may not have been displayed.
sourceId=null[severity=(ERROR 2), summary=(No activity selected), detail=(No activity selected)]
Edit.xhtml
...
<h:outputLabel value="Sector:" />
<h:selectOneMenu id="sectorSelector" value="#{activityController.selectedSector}" title="#{bundle.CreateSectorLabel_sectorName}" required="false" requiredMessage="#{bundle.CreateSectorRequiredMessage_sectorName}"
valueChangeListener="#{activityController.changeSectorMenu}"
disabled="#{activityController.activityStatusOngoing or activityController.activityStatusComplete}">
<f:ajax event="change" execute="#this" render="categoryMenu"/>
<f:selectItems value="#{sectorController.itemsAvailableSelectOne}"/>
</h:selectOneMenu>
<h:outputLabel value="Category:" />
<h:selectOneMenu id="categoryMenu" value="#{activityController.selectedCategory}" title="#{bundle.CreateSectorLabel_sectorName}"
required="true" requiredMessage="#{bundle.CreateCategoryRequiredMessage_sector}"
disabled="#{activityController.activityStatusOngoing}" rendered="true">
<f:selectItems value="#{activityController.categorySelection}"/>
</h:selectOneMenu>
...
Controller bean for Category
#ManagedBean(name = "categoryController")
#SessionScoped
public class CategoryController implements Serializable{
....
#FacesConverter(forClass = Category.class)
public static class CategoryControllerConverter implements Converter {
#Override
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
if (value == null || value.length() == 0) {
return null;
}
CategoryController controller = (CategoryController) facesContext.getApplication().getELResolver().
getValue(facesContext.getELContext(), null, "categoryController");
return controller.ejbFacade.find(getKey(value));
}
java.lang.Integer getKey(String value) {
java.lang.Integer key;
key = Integer.valueOf(value);
return key;
}
String getStringKey(java.lang.Integer value) {
StringBuffer sb = new StringBuffer();
sb.append(value);
return sb.toString();
}
#Override
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof Category) {
Category o = (Category) object;
return getStringKey(o.getIdCategory());
}
else {
throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + CategoryController.class.getName());
}
}
}
Part of POJO object
...
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idCategory")
private Integer idCategory;
...
Option (not so difficult as I recently made a switch) is to include Seam Faces and Persistence modules. Seam Faces module enables ViewScope without #ManagedBean annotation.
But SeamFaces forces us (which is justified) to use CDI annotations (#Named instead of #ManagedBean etc).
Please refer this post. (You can use #EJB and also Inject any bean annotated with #Named)
It was not the Converters as I first thought. It was the rendering of the two selectOneMenu. This is the changes I did to the xhml file. Thank you for your time and effort, greetings Chris.
Edit.xhml
<h:outputLabel value="Sector:" />
<h:selectOneMenu id="sectorSelector" value="#{activityController.selectedSector}" title="#{bundle.CreateSectorLabel_sectorName}" required="false" requiredMessage="#{bundle.CreateSectorRequiredMessage_sectorName}"
valueChangeListener="#{activityController.changeSectorMenu}" immediate="true"
disabled="#{activityController.activityStatusOngoing or activityController.activityStatusComplete}">
<a4j:ajax event="change" execute="#this categoryMenu" render="categoryMenu"/>
<f:selectItems value="#{sectorController.itemsAvailableSelectOne}"/>
</h:selectOneMenu>
<h:outputLabel value="Category:" />
<h:selectOneMenu id="categoryMenu" value="#{activityController.selectedCategory}" title="#{bundle.CreateSectorLabel_sectorName}"
binding="#{activityController.categoryMenu}"
required="true" requiredMessage="#{bundle.CreateCategoryRequiredMessage_sector}"
disabled="#{activityController.activityStatusOngoing}">
<f:selectItems value="#{activityController.categorySelection}"/>
</h:selectOneMenu>