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}" />
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">
I have started learning JSF, but sadly most tutorials out there present only a log in or a register section.
Can you point me to some more in depth examples? One thing I'm interested in is a page presenting a list of products. I'm on page home and I press on page products so that I can see the latest products added. And every time I visit the page, the product list will be created from the latest entries in the database. How can I handle this?
One way to solve this would be to create a session scoped managed bean in which I would place different entities updated through other managed beans. I found this kind of approach in some tutorials, but it seems quite difficult and clumsy.
Which would be the best approach to solve a thing like this? What is the correct usage of session scope in two-page master-detail user interface?
What is the correct usage of session scope
Use it for session scoped data only, nothing else. For example, the logged-in user, its settings, the chosen language, etcetera.
See also:
How to choose the right bean scope?
And every time I visit the page, the product list will be created from the latest entries in the database. How can I handle this?
Typically you use the request or view scope for it. Loading of the list should happen in a #PostConstruct method. If the page doesn't contain any <h:form>, then the request scope is fine. A view scoped bean would behave like a request scoped when there's no <h:form> anyway.
All "view product" and "edit product" links/buttons which just retrieve information (i.e. idempotent) whould be just plain GET <h:link> / <h:button> wherein you pass the entity identifier as a request parameter by <f:param>.
All "delete product" and "save product" links/buttons which will manipulate information (i.e. non-idempotent) should perform POST by <h:commandLink>/<h:commandButton> (you don't want them to be bookmarkable/searchbot-indexable!). This in turn requires a <h:form>. In order to preserve the data for validations and ajax requests (so that you don't need to reload/preinitialize the entity on every request), the bean should preferably be view scoped.
Note that you should basically have a separate bean for each view and also note that those beans doesn't necessarily need to reference each other.
So, given this "product" entity:
#Entity
public class Product {
#Id
private Long id;
private String name;
private String description;
// ...
}
And this "product service" EJB:
#Stateless
public class ProductService {
#PersistenceContext
private EntityManager em;
public Product find(Long id) {
return em.find(Product.class, id);
}
public List<Product> list() {
return em.createQuery("SELECT p FROM Product p", Product.class).getResultList();
}
public void create(Product product) {
em.persist(product);
}
public void update(Product product) {
em.merge(product);
}
public void delete(Product product) {
em.remove(em.contains(product) ? product : em.merge(product));
}
// ...
}
You can have this "view products" on /products.xhtml:
<h:dataTable value="#{viewProducts.products}" var="product">
<h:column>#{product.id}</h:column>
<h:column>#{product.name}</h:column>
<h:column>#{product.description}</h:column>
<h:column>
<h:link value="Edit" outcome="/products/edit">
<f:param name="id" value="#{product.id}" />
</h:link>
</h:column>
</h:dataTable>
#Named
#RequestScoped
public class ViewProducts {
private List<Product> products; // +getter
#EJB
private ProductService productService;
#PostConstruct
public void init() {
products = productService.list();
}
// ...
}
And you can have this "edit product" on /products/edit.xhtml:
<f:metadata>
<f:viewParam name="id" value="#{editProduct.product}"
converter="#{productConverter}" converterMessage="Unknown product, please use a link from within the system."
required="true" requiredMessage="Bad request, please use a link from within the system."
/>
</f:metadata>
<h:messages />
<h:form rendered="#{not empty editProduct.product}>
<h:inputText value="#{editProduct.product.name}" />
<h:inputTextarea value="#{editProduct.product.description}" />
...
<h:commandButton value="save" action="#{editProduct.save}" />
</h:form>
#Named
#ViewScoped
public class EditProduct {
private Product product; // +getter +setter
#EJB
private ProductService productService;
public String save() {
productService.update(product);
return "/products?faces-redirect=true";
}
// ...
}
And this converter for <f:viewParam> of "edit product":
#Named
#RequestScoped
public class ProductConverter implements Converter {
#EJB
private ProductService productService;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value == null || value.isEmpty()) {
return null;
}
try {
Long id = Long.valueOf(value);
return productService.find(id);
} catch (NumberFormatException e) {
throw new ConverterException("The value is not a valid Product ID: " + value, e);
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return "";
}
if (value instanceof Product) {
Long id = ((Product) value).getId();
return (id != null) ? String.valueOf(id) : null;
} else {
throw new ConverterException("The value is not a valid Product instance: " + value);
}
}
}
You can even use a generic converter, this is explained in Implement converters for entities with Java Generics.
See also:
How to navigate in JSF? How to make URL reflect current page (and not previous one)
JSF Controller, Service and DAO
JSF Service Layer
How to inject #EJB, #PersistenceContext, #Inject, #Autowired, etc in #FacesConverter?
Communication in JSF 2.0 - Contains several examples/hints
As a small improvement to what BalusC recommended, sometimes you can remove the required / requiredMessage part from the <f:viewParam> of your "details" screen and instead use the conditional rendering of the editing form (as BalusC did) with a reverse condition for recommending a specific link for the "list/master" screen or, even use a viewAction that would test the param and force a redirect to that list.
I have a problem with taking names of tUsers and print them on the screen. May be i dont call the method for getting names properly () because when i call the function listAgencies, it prints them correctly in the Eclipse console. Thanks for any advices!
In .xthml file, I have:
<h:panelGrid id="panel2" columns="2" cellpadding="5">
<c:forEach items="${agencyBean.listAgencies()}" var="inputBoxes">
<h:outputText value="${inputBoxes.gettUser().name}" />
<h:inputText />
</c:forEach>
</h:panelGrid>
My bean class:
#ManagedBean(name = "agencyBean")
#SessionScoped
public class AgencyBean {
private TAgency tEventType = new TAgency();
public void listAgencies() {
EntityManager em = HibernateUtil.getEntityManager();
// read the existing entries and write to console
Query q = em.createQuery("select u from TAgency u");
List<TAgency> agencyList = q.getResultList();
for (TAgency agency : agencyList) {
System.out.println("NAme: " + agency.gettUser().getName());
}
}
public TAgency gettEventType() {
return tEventType;
}
public void settEventType(TAgency tEventType) {
this.tEventType = tEventType;
}
}
TUser is another entity from where i want to get the name. I have getName() method which is public.
The problem is here:
<c:forEach items="${agencyBean.listAgencies()}" ... >
It should look for a getter method for listAgencies attribute, but instead it is a void method that will be executed and there's nothing to access to.
The best bet would be:
Creating an attribute in your class called List<TAgency> listAgencies.
Define proper getter and setter methods for listAgencies attribute. NEVER define business logic in managed bean getters. Related: Why JSF calls getters multiple times
Probably, change the scope of the bean to #RequestScope to load this list every time users access to this view. Related: How to choose the right bean scope?
Load the list using #PostConstruct method.
Based on these advices, the code would look like this:
#ManagedBean(name = "agencyBean")
#RequestScoped
public class AgencyBean {
private TAgency tEventType = new TAgency();
private List<TAgency> listAgencies;
#PostConstruct
public void init() {
EntityManager em = HibernateUtil.getEntityManager();
// read the existing entries and write to console
Query q = em.createQuery("select u from TAgency u");
List<TAgency> agencyList = q.getResultList();
for (TAgency agency : agencyList) {
System.out.println("NAme: " + agency.gettUser().getName());
}
}
public TAgency gettEventType() {
return tEventType;
}
public void settEventType(TAgency tEventType) {
this.tEventType = tEventType;
}
public List<TAgency> getListAgencies() {
return listAgencies;
}
public void setListAgencies(List<TAgency> listAgencies) {
this.listAgencies = listAgencies;
}
}
And your JSF code:
<!-- Note: no parenthesis usage -->
<c:forEach items="#{agencyBean.listAgencies}" var="inputBoxes">
<!-- no need to call the getter verbosely, Expression Language call it for you automatically -->
<h:outputText value="#{inputBoxes.user.name}" />
<!-- what you want to do here? -->
<h:inputText />
</c:forEach>
Also, probably you don't want to use <c:forEach> but <ui:repeat> instead. Related: JSTL in JSF2 Facelets... makes sense?
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>
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.