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">
Related
Normaly i implements my jsf converter as my example. But if i have 10 components that need converter, i need 10 converters, too.
Question: Give it a better solution or a global solution for a jsf converter, so that not every component needs his own converter?
Converter:
#FacesConverter(value="PersonConverter")
public class PersonConverter implements Converter{
#Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
if(value != null){
MyBean bean = (MyBean)FacesContext.getCurrentInstance().getViewRoot().getViewMap().get("myBean");
for(Person p : bean.getSearchedPersons()){
if(p.getName().equals(value)){
return p;
}
}
}
return null;
}
#Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
if(value != null && value instanceof Person){
return ((Person)value).getName();
}
return null;
}
}
Bean:
#ViewScoped
#ManagedBean
public class MyBean {
#EJB
private PersonService service;
private List<Person> searchedPersons;
private Person selectedPerson;
public void printSelectedPerson(ActionEvent event) {
System.out.println("Selected Person: "
+ selectedPerson.getName());
}
public List<Person> searchValues(String str) {
searchedPersons = service.searchPerson(str);
return searchedPersons;
}
/** GETTER & SETTER */
XHTML:
<h:form id="mainform">
<p:autoComplete completeMethod="#{myBean.searchValues}" value="#{myBean.selectedPerson}"
converter="PersonConverter" var="p" itemLabel="#{p.name}" itemValue="#{p}" forceSelection="true"/>
<p:commandButton value="Test" actionListener="#{myBean.printSelectedPerson}"/>
<p:messages globalOnly="false" autoUpdate="true"/>
</h:form>
If you want to use that converter everywhere for a value of type Person you can use #FacesConverter(forClass=Person.class). Look here.
..., whenever that class is specified by a value attribute of an input component, the converter is invoked automatically
If you want a generic converter then Omnifaces SelectItemsConverter is the best in all.
Omniface SelectItemConverter
If you don't want to use Omnifaces then look at answer here
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}" />
In my code, I have a PrimeFaces' wizard component with several tabs as following:
<h:form id="myForm">
<p:wizard flowListener="#{mrBean.flowControl}" widgetVar="wiz">
<p:tab id="tab1"></p:tab>
<p:tab id="tab2"></p:tab>
<p:tab id="tab3">
<h:selectOneMenu id="couponList" value="#{mrBean.coupon}"
converter="#{codeToCouponConverter}" >
<f:ajax listener="#{mrBean.doSomething}" execute="#this"/>
<f:selectItem noSelectionOption="true" itemLabel="Choose one..." />
<f:selectItems value="#{mrBean.coupons}" var="c"
itemValue="#{c}" itemLabel="#{c.name} - $ #{c.discount}" />
</h:selectOneMenu>
</p:tab>
</p:wizard>
</h:form>
This is the code for the managed bean:
#ManagedBean(name = "mrBean")
#ViewScoped
public class MrBean {
private List<Coupon> coupons;
private Coupon coupon;
public void doSomething() {
System.out.println("DONE");
}
public String flowControl(FlowEvent event) {
...
}
// Getters and Setters
}
In 1 of the tab, I have a <h:selectOneMenu> component which contains a <f:ajax> tag. I have no idea why the listener is only triggered when I choose the Choose one... option. When I choose any other options from the mrBean.coupons list, the listener is never triggered. In other words, I never saw any DONE printed on the console.
*UPDATE***: The problem turns out to be coming from the following Converter:
#RequestScoped
#ManagedBean
public class CodeToCouponConverter implements Converter {
#EJB
private MrsBeanInterface mrsBean;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
String couponCode = value;
if (value != null) return mrsBean.getCoupon(couponCode);
else return null;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value != null) {
Coupon c = (Coupon) value;
return c.getId();
} else return null;
}
// Getters and Setters
public MrsBeanInterface getMrsBean() {
return mrsBean;
}
public void setMrsBean(MrsBeanInterface mrsBean) {
this.mrsBean = mrsBean;
}
}
If I change the <h:selectOneMenu> as following:
<h:selectOneMenu id="couponList" value="#{mrBean.couponCode}" >
<f:ajax listener="#{mrBean.doSomething}" execute="#this"/>
<f:selectItem noSelectionOption="true" itemLabel="Choose one..." />
<f:selectItems value="#{mrBean.coupons}" var="c"
itemValue="#{c.id}" itemLabel="#{c.name} - $ #{c.discount}" />
</h:selectOneMenu>
and update the mrBean.doSomething function as following:
#EJB
private MrsBeanInterface mrsBean;
private String couponCode;
private Coupon coupon;
public void doSomething() {
this.coupon = mrsBean.getCoupon(couponCode);
System.out.println("DONE");
}
everything works perfectly.
I would be very grateful if you could give me an explanation of what I have done wrong with the Converter.
Best regards,
James Tran
Use #{mrBean.doSomething()} with the braces or add the event parameter to the method.
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>
I use this class for doing validation from input fields:
#ManagedBean
#RequestScoped
public class UserInputValidation {
public void validateCity(FacesContext context, UIComponent validate,
Object value) {
String inputFromField = (String) value;
if (inputFromField.equals("") || inputFromField.equals(" ")) {
FacesMessage msg = new FacesMessage("Odaberite grad");
throw new ValidatorException(msg);
}
}
//...
}
And this is the managed bean that holds the inputed values:
#ManagedBean
#RequestScoped
public class InputController {
//Attributes
private String city;
//Get set methods
Why when i create a selectOneComponent and i select the first component(blank input), the validation message is not shown?
<h:selectOneMenu id="city" value="#{inputController .city}">
<f:selectItems value="#{searchController.formatedCities()}" validator="#{userInputValidation.validateCity}"/>
</h:selectOneMenu>
<span style="color: red;"><b><h:message for="city"
showDetail="true" /></b></span>
The first of the fields in the selectOneMenu is a blank(The formatedCitiesMethod() returns a "" as first element), so why the validation message is not being shown if the form is submit button is clicked with the blank selected?
The validator attribute has to go in the <h:selectOneMenu>, not in the <f:selectItems>
Said that, why don't you just use required="true"? Why is the validator a #ManagedBean instead of a #FacesValidator?