I have created a composite component, based on PrimeFaces components that works as a multi-line text component. Text is added to an input, an "Add" button is clicked, and that text is added to a menu. The items in the menu are the submitted value. This works fine, until I set it up as a Composite Component. Then, the initial "Add" click does not add a value. Subsequent clicks work fine. From what I can tell the ViewState is not created until the second click. I assume this is the issue. Am I doing something wrong? Is it a bug? Here is the code:
Composite Component:
<cc:interface>
<cc:attribute name="value" type="java.util.Collection" />
</cc:interface>
<cc:implementation>
<p:inputText value="#{multiTextBean.text}" id="txtInput" />
<p:commandButton value="Add" action="#{multiTextBean.add}"
update="menu txtInput" />
<p:commandButton value="Clear"
action="#{multiTextBean.clear}" update="menu txtInput" />
<p:selectManyMenu id="menu"
value="#{multiTextBean.removes}">
<f:selectItems id="items"
value="#{multiTextBean.items}" />
</p:selectManyMenu>
<p:commandButton value="Remove"
action="#{multiTextBean.remove}" update="menu" />
</cc:implementation>
Backing Class for component:
package util;
import java.io.IOException;
import java.util.Set;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIInput;
import javax.faces.component.UISelectItems;
import javax.faces.context.FacesContext;
import javax.faces.convert.ConverterException;
import org.primefaces.component.selectmanymenu.SelectManyMenu;
public class multitext extends UIInput implements NamingContainer {
public String getFamily(){
return "javax.faces.NamingContainer";
}
#SuppressWarnings("unchecked")
#Override
protected Object getConvertedValue(FacesContext context, Object newSubmittedValue)
throws ConverterException {
SelectManyMenu menu = (SelectManyMenu) findComponent("menu");
UISelectItems items = (UISelectItems) menu.findComponent("items");
Set<String> localItems = (Set<String>) items.getValue();
return localItems;
}
#Override
public Object getSubmittedValue() {
return this;
}
#Override
public void encodeBegin(FacesContext context) throws IOException {
super.encodeBegin(context);
}
}
Bean referenced by Composite Component
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class MultiTextBean {
private String text;
private Set<String> items;
private List<String> removes;
#PostConstruct
public void init(){
items = new HashSet<String>();
removes = new ArrayList<String>();
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Set<String> getItems() {
return items;
}
public List<String> getRemoves() {
return removes;
}
public void setRemoves(List<String> removes) {
this.removes = removes;
}
public void add(){
if(!text.isEmpty())
{items.add(text);}
text = null;
}
public void clear(){
items.removeAll(items);
text = null;
}
public void remove(){
items.removeAll(removes);
}
}
The component looks like:
Using the component on this test page:
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:mt="http://java.sun.com/jsf/composite/util"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Insert title here</title>
</h:head>
<h:body>
<ui:debug hotkey="x"/>
<form>
<mt:multitext value="#{backingBean.submittedValues}"/>
<p:commandButton value="Submit" action="Submit" update="#all" process="#all"/>
#{backingBean.submittedValues}
</form>
</h:body>
</html>
In order to invoke (ajax) actions in JSF, you need a <h:form> instead of <form>.
Fix it accordingly:
<h:form>
...
</h:form>
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated
Related
I have a this simplified form to show the challenge:
It is a form with multiple tabs (2 in this MVCE).
My goal is to highlight both fields in case of validation failure (but only for tab it is failing for).
TabView (backing bean)
package betlista.so.pf.findComponent;
import com.sun.faces.component.visit.FullVisitContext;
import org.primefaces.PrimeFaces;
import org.springframework.stereotype.Component;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UIViewRoot;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;
import java.util.LinkedList;
import java.util.List;
#Component
public class TabView {
List<TabData> tabData = new LinkedList<>();
{
tabData.add(new TabData("name 1", "val1-a", null));
tabData.add(new TabData("name b", "val1-b", "val2-b"));
}
public List<TabData> getTabsData() {
return tabData;
}
public void save() {
boolean isValid = isValid();
if (isValid) {
// continue ...
}
}
private boolean isValid() {
boolean isOk = isOk();
if (isOk) {
return true;
}
FacesMessage message = new FacesMessage("Not saved!");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, message);
final UIViewRoot viewRoot = context.getViewRoot();
List<UIInput> componentList = new LinkedList<>();
viewRoot.visitTree(new FullVisitContext(context), new VisitCallback() {
#Override
public VisitResult visit(VisitContext context, UIComponent target) {
if (target != null) {
final String id = target.getId();
if ("val1".equals(id) || "val2".equals(id)) {
if (target instanceof UIInput) {
componentList.add((UIInput) target);
}
}
}
return VisitResult.ACCEPT;
}
});
for (UIInput uiInput: componentList) {
uiInput.setValid(false);
}
context.validationFailed();
PrimeFaces.current().ajax().update("form");
final UIComponent val1 = context.getViewRoot().findComponent("val1");
return false;
}
private boolean isOk() {
return false;
}
}
in this simplified version isOk() returns false.
In a validation I know whether data for 1st or second tab is not ok and I'm trying to find a way how to highlight those two fields in tab.
I tried initially context.getViewRoot().findComponent(...), but I'm not able to "find it" (returns null). So to have access to the components I used this:
List<UIInput> componentList = new LinkedList<>();
viewRoot.visitTree(new FullVisitContext(context), new VisitCallback() {
#Override
public VisitResult visit(VisitContext context, UIComponent target) {
if (target != null) {
final String id = target.getId();
if ("val1".equals(id) || "val2".equals(id)) {
if (target instanceof UIInput) {
componentList.add((UIInput) target);
}
}
}
return VisitResult.ACCEPT;
}
});
so I have (in this case) all 4 components (but let say only those for first tab are invalid).
I'm trying to find a way how to identified which component belong to which tab (not sure whether to rely on a an order in list).
I was trying dynamic ID's, but it's not working, e.g. I added tab name (tabName)as attribute and used
<p:inputText id="#{cc.attr.tabName}-val2" ... />
I found no way how to add some custom flag/attribute whatever to be able to link component to a tab.
I was reading that ID can be dynamic once I'd use EL custom function (I mean I can use concatenation), but I was not able to find a resource describing it (I have no web.xml).
Code is available in GitHub.
myTab.xhtml (custom component)
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="data" required="true" type="betlista.so.pf.findComponent.TabData" />
</composite:interface>
<composite:implementation>
<div class="ui-g">
<div class="ui-g-12">
<div class="ui-g-6">
<p:outputLabel value="Val 1:"/>
</div>
<div class="ui-g-6">
<p:inputText id="val1" value="#{cc.attrs.data.val1}" widgetVar="#{cc.attrs.data.tabName}-val1"/>
</div>
</div>
<div class="ui-g-12">
<div class="ui-g-6">
<p:outputLabel value="Val 2:"/>
</div>
<div class="ui-g-6">
<p:inputText id="val2" readonly="true" value="#{cc.attrs.data.val2}" widgetVar="#{cc.attrs.data.tabName}-val2"/>
</div>
</div>
</div>
</composite:implementation>
</html>
page.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:comp="http://xmlns.jcp.org/jsf/composite/comp">
<h:head>
<h:outputScript library="webjars" name="font-awesome/5.5.0/js/all.js"/>
</h:head>
<h:body styleClass="mainBody">
<h:form id="form">
<p:tabView id="tabView" value="#{tabView.tabsData}" var="tabVar">
<p:tab id="tab" title="#{tabVar.tabName}">
<comp:myTab data="#{tabVar}" />
</p:tab>
</p:tabView>
<p:commandButton value="Save" action="#{tabView.save()}" process="#form" update="#form" />
<p:growl id="growl" life="3000"/>
</h:form>
</h:body>
</html>
I got very confused by debugger...
The simplest solution is to add label like this:
<p:inputText id="val1" value="#{cc.attrs.data.val1}" label="someLabel1" />
...what I missed earlier is, that label is not a field therefor it was difficult to find it, it is available under stateHelper:
Probably better solution (despite label I cannot see in generated HTML) is to use custom attribute like this (I'd bet I tried that as well, apparently not):
<p:inputText id="val2" readonly="true" value="#{cc.attrs.data.val2}">
<f:attribute name="someAttribute" value="value2" />
</p:inputText>
and it's easily accessible:
i am trying to develop and understand communication in between classes and jsf tags. I figured out that jsf tags use classes directly without making any instance while when communication in between beans is required, an instance of the class is must to be built. In a dare need of dynamic listing and then copying selected values to different beans, i tried to build a custom tag for dynamic list but stuck at the point when selected value is required to be copied to the bean needing to hold the value other the bean used for building the list.
Following is the minimal reproducible example
pinnacleTags.taglib.xml
<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib>
<namespace>pinnacleTags/facelets</namespace>
<tag>
<tag-name>PinnacleCombo</tag-name>
<source>pinnacleCombo.xhtml</source>
<attribute>
<name>actionListenerBeanMethod</name>
</attribute>
</tag>
</facelet-taglib>
the List Tag
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:o="http://omnifaces.org/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
</h:head>
<h:body>
<ui:composition>
<o:methodParam name="method" value="#{actionListenerBeanMethod}" />
<p:dialog id="dlgTBL" modal="true" showEffect="bounce" widgetVar="dlg" resizable="false">
<p:dataTable var="result" id="tbl" widgetVar="dtlTBL"
value="#{liveRangeService.tableData}"
filteredValue="#{liveRangeService.filteredData}"
paginator="false"
scrollable="true" rowIndexVar="rowindex" scrollHeight="500"
scrollRows="50" liveScroll="true"
filterDelay="1100"
>
<p:ajax event="rowSelect" listener="#{method}" />
<f:facet name="header">
<p:outputPanel layout="inline" styleClass="tabSpacer">
<h:outputText value="Global Filter:" />
<p:inputText id="globalFilter" onkeyup="PF('dtlTBL').filter()" style="width:150px;margin-left:10px;"/>
</p:outputPanel>
</f:facet>
<p:column width="50">
<f:facet name="header">
<h:outputText value="Sr." />
</f:facet>
<p:commandButton value="#{rowindex}" style="width: 49px" action="#{method}"/>
</p:column>
<p:columns value="#{liveRangeService.tableHeaderNames}"
var="mycolHeader"
width="#{colIndex==0?'10%':colIndex==1?'70%':colIndex==2?'10%':colIndex==3?'10%':'0'}"
columnIndexVar="colIndex"
sortBy="#{result[mycolHeader]}"
filterBy="#{result[mycolHeader]}"
filterMatchMode="contains"
>
<f:facet name="header">
<h:outputText value="#{mycolHeader}" />
</f:facet>
<h:outputText value="#{result[mycolHeader]}" />
<br />
</p:columns>
</p:dataTable>
</p:dialog>
</ui:composition>
</h:body>
</html>
Dynamic List Bean
package classes;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.ViewScoped;
import org.primefaces.PrimeFaces;
#ManagedBean(name="liveRangeService", eager = true)
#RequestScoped
public class LiveRangeService implements Serializable {
private static List< Map<String, String> > tableData;
public static List< Map<String, String> > filteredData;
private static List<String> tableHeaderNames;
private String tableColWidths;
public List<Map<String, String>> getTableData() {
return tableData;
}
public List<String> getTableHeaderNames() {
return tableHeaderNames;
}
public LiveRangeService() {
}
public static void LiveRangeServicesss(int noOfRows) {
tableData = new ArrayList< Map<String, String> >();
filteredData = new ArrayList< Map<String, String> >();
tableHeaderNames = new ArrayList<String>();
try {
tableData.clear();
tableHeaderNames.clear();
filteredData.clear();
} catch (Exception e) {
System.out.println("error:!" + e.getMessage());
}
tableHeaderNames.add("ID");
tableHeaderNames.add("Title");
tableHeaderNames.add("Opn_Amt");
tableHeaderNames.add("Smr_Amt");
for (int i = 0; i < noOfRows; i++) {
Map<String, String> playlist = new HashMap<String, String>();
playlist.put("ID", "101000" + i);
playlist.put("Title", "Share Capital - Mr. " + i);
playlist.put("Opn_Amt", "0");
playlist.put("Smr_Amt", "0");
tableData.add(playlist);
}
filteredData=tableData;
System.out.println("Filled " + filteredData.size() + ", " + noOfRows);
String dlgTBL="form:dlgTBL";
String dlg="PF('dlg').show();";
PrimeFaces.current().ajax().update(dlgTBL);
PrimeFaces.current().executeScript(dlg);
}
public String getTableColWidths() {
return tableColWidths;
}
public void setTableColWidths(String tableColWidths) {
this.tableColWidths = tableColWidths;
}
public List<Map<String, String>> getFilteredData() {
return filteredData;
}
public void setFilteredData(List<Map<String, String>> filteredData) {
this.filteredData = filteredData;
}
}
test Bean
package classes;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.primefaces.PrimeFaces;
import org.apache.commons.beanutils.PropertyUtils;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author Administrator
*/
#ManagedBean(name="test")
#SessionScoped
public class Test implements Serializable {
public String id;
public String title;
public Test() {
id="1";
title="Testing";
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void onRowSelect(int row) {
try {
System.out.println("Start:");
String i="ID";
String t="Title";
String ci="id";
String ct="title";
this.getClass().getDeclaredField(ci).set(this, LiveRangeService.filteredData.get(row).get(i));
this.getClass().getDeclaredField(ct).set(this, LiveRangeService.filteredData.get(row).get(t));
PrimeFaces.current().ajax().update("form:inp");
PrimeFaces.current().ajax().update("form:inp1");
PrimeFaces.current().executeScript("PF('dlg').hide();");
System.out.println("End:");
} catch (Exception e) {
System.out.println("Error! " + e.getMessage() );
}
}
}
Assuming your problem is how to access the sessionScoped test bean from within the applicationScoped LiveRangeService: you cannot simply instantiate a ManagedBean this way:
test t = new test();
Instances are Managed by JSF and instantiated on demand with a lifespan defined by their scope.
Please read How to access property of one managed bean in another managed bean and the blog article Communication in JSF 2.0 - Injecting managed beans in each other linked by BalusC.
There are several additional issues with your example:
The scopes of your beans do not seeme to be chosen correctly, please read How to choose the right bean scope?
You do not follow java naming conventions. Class names should start with upper case character while fields and variables should start with lower case character. E.g. rename class test to class Test and private String CopyValuesToClass; to private String copyValuesToClass;
The example is by far not minimal. You should remove all the code not relevant to understand the problem.
You should think about migrating to a recent version of JSF and CDI as #ManagedBean is deprecated: Migrate JSF managed beans to CDI managed beans
I have the following page xhtml where i have to get some values for populate a DB table. The problem are the selection menu that don't work. Actually, the values of the selections are chosen from the database and are displayed but the values aren't taken when i use the button:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Add a Default Package</title>
</h:head>
<h:body>
<h:form>
<p:panel header="DefaultPackage Form">
<h:panelGrid columns="3" id="regGrid">
<h:outputLabel for="Name">Name:</h:outputLabel>
<p:inputText id="Name" value="#{addDefaultPackageBean.defpackDTO.name}" />
<p:message for="Name" />
<h:outputLabel for="location">Location:</h:outputLabel>
<p:inputText id="location" value="#{addDefaultPackageBean.defpackDTO.location}" />
<p:message for="location" />
<h:selectOneMenu value="#{addDefaultPackageBean.nameFlies}">
<f:selectItems value="#{addDefaultPackageBean.elelisfly}" var="ElementDTO" itemValue="#{ElementDTO.location}" itemLabel="#{ElementDTO.location}"/>
</h:selectOneMenu>
<h:selectOneMenu value="#{addDefaultPackageBean.nameHotels}">
<f:selectItems value="#{addDefaultPackageBean.elelishotel}" var="ElementDTO" itemValue="#{ElementDTO.location}" itemLabel="#{ElementDTO.location}"/>
</h:selectOneMenu>
</h:panelGrid>
<p:commandButton value="Add" update="regGrid" action="#{addDefaultPackageBean.add()}" />
</p:panel>
</h:form>
</h:body>
</html>
The image displayed is:
The bean page:
package beans;
import java.util.ArrayList;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import elementManagement.ElementMgr;
import elementManagementDTO.ElementDTO;
import DefaultPackageManagement.DefaultPackageMgr;
import DefaultPackageManagementDTO.DefaultPackageDTO;
#ManagedBean(name="addDefaultPackageBean") //come viene richiamato
#RequestScoped
public class AddDefaultPackageBean {
#EJB
private DefaultPackageMgr defpackMgr;
private DefaultPackageDTO defpackDTO;
private ArrayList<ElementDTO> elelisfly;
private ArrayList<ElementDTO> elelishotel;
private String nameFlies;
private String nameHotels;
#EJB
private ElementMgr elemMgr;
public AddDefaultPackageBean() {
defpackDTO = new DefaultPackageDTO();
defpackDTO.setElem(new ArrayList<ElementDTO>());
}
#PostConstruct
public void init()
{
setElelisfly(elemMgr.getAllFlights());
setElelishotel(elemMgr.getAllHotels());
}
public String add() {
this.AssignElemFlyFromSelection();
this.AssignElemHotelFromSelection();
defpackMgr.save(defpackDTO);
return "/employee/index?faces-redirect=true";
}
public DefaultPackageDTO getDefpackDTO() {
return defpackDTO;
}
public void setDefpackDTO(DefaultPackageDTO defpackDTO) {
this.defpackDTO = defpackDTO;
}
public ArrayList<ElementDTO> getElelisfly() {
return elelisfly;
}
public void setElelisfly(ArrayList<ElementDTO> elelisfly) {
this.elelisfly = elelisfly;
}
public ArrayList<ElementDTO> getElelishotel() {
return elelishotel;
}
public void setElelishotel(ArrayList<ElementDTO> elelishotel) {
this.elelishotel = elelishotel;
}
public String getNameFlies() {
return nameFlies;
}
public void setNameFlies(String nameFlies) {
this.nameFlies = nameFlies;
}
public String getNameHotels() {
return nameHotels;
}
public void setNameHotels(String nameHotels) {
this.nameHotels = nameHotels;
}
private void AssignElemFlyFromSelection()
{
for (ElementDTO elem:this.elelisfly)
{
if(elem.getLocation()==this.nameFlies)
{
this.defpackDTO.getElem().add(elem);
}
}
}
private void AssignElemHotelFromSelection()
{
for (ElementDTO elem:this.elelishotel)
{
if(elem.getLocation()==this.nameHotels)
{
this.defpackDTO.getElem().add(elem);
}
}
}
}
Thank you for the help!
You're comparing Java String objects using == operator instead of .equals() method. That causes a comparison between Object references to be performed, instead of implemented String comparison.
elem.getLocation()==this.nameFlies
and
elem.getLocation()==this.nameHotels
Change them for String#equals().
See also:
Java String.equals versus ==
Add process to your commandobutton.
Like this:
<p:commandButton process="#form" value="Add" update="regGrid" action="#{addDefaultPackageBean.add()}" />
I am setting values to object in xhtml, but it becoming to null in managed bean.
"Users" entity has many-to-many relation with "Groups" entity so in the form I reload "Groups" from db dynamically but after clicking command button "user" object becoming to null.
Here is my xhtml :
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Kullanıcı İşlemleri</title>
</h:head>
<h:body>
<h:form id="addUser">
<p:panel header="Kullanıcı Tanımlama">
<p:messages autoUpdate="true"/>
<h:panelGrid columns="2">
Adı:<p:inputText value="#{userBean.user.name}"/>
Soyadı : <p:inputText value="#{userBean.user.surname}"/>
Kullanıcı Adı : <p:inputText value="#{userBean.user.username}"/>
E-mail: <p:inputText value="#{userBean.user.email}"/>
Parola : <p:password value="#{userBean.user.password}"/>
Kullanıcı Tipi:
<p:selectManyCheckbox value="#{userBean.user.groupsCollection}">
<f:selectItems value="#{userBean.groupList}" var="grp" itemLabel="#{grp.groupName}" itemValue="#{grp.groupId}"/>
</p:selectManyCheckbox>
<p:commandButton value="Kullanıcıyı Ekle" action="#{userBean.persist()}" process="#this" update="#form" />
</h:panelGrid>
</p:panel>
</h:form>
</h:body>
Managed Bean :
package com.mkmturizm.bean;
import com.mkmturizm.entity.Groups;
import com.mkmturizm.entity.Users;
import com.mkmturizm.service.GroupService;
import com.mkmturizm.service.UserService;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
#ManagedBean
#ViewScoped
public class UserBean implements Serializable {
private Users user = new Users();
private List<Groups> groupList = new ArrayList<Groups>();
#EJB
UserService userService;
#EJB
GroupService groupService;
public void persist() throws Exception
{
userService.persist(user);
user = new Users();
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Kayıt başarıyla gerçeklerşti", ""));
}
#PostConstruct
public void getAllGroups()
{
groupList = groupService.groupsList();
}
public List<Groups> getGroupList()
{
return groupList;
}
public void setGroupList(List<Groups> groupList)
{
this.groupList = groupList;
}
public Users getUser()
{
return user;
}
public void setUser(Users user)
{
this.user = user;
}
}
UPDATE : (RESLOVED)
I changed value of selected items as grp because I am sending id of group so it can't cast Groups object but can't throw any exception. After that I wrote a custom converter and I guess custom converters could work well before I have changed xhtml.
<f:selectItems value="#{userBean.groupList}" var="grp" itemLabel="#{grp.groupName}" itemValue="#{grp}"/>
I have the following JSF view index.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<ui:composition template="template.xhtml">
<ui:define name="top">
Menu
</ui:define>
<ui:define name="content">
<h:form>
<p:menubar>
<p:submenu label="Admin">
<p:submenu label="User">
<p:menuitem value="Add User" ajax="true">
<f:setPropertyActionListener target="#{menuTab.action}" value="StudentAdd"/>
</p:menuitem>
<p:menuitem value="Edit User" ajax="true">
<f:setPropertyActionListener target="#{menuTab.action}" value="StudentEdit"/>
</p:menuitem>
</p:submenu>
</p:submenu>
</p:menubar>
</h:form>
<p:tabView>
<c:forEach items="#{menuTab.listOfObjs}" var="item" varStatus="loop">
<p:tab title="#{menuTab.value}" closable="true"/>
</c:forEach>
</p:tabView>
</ui:define>
</ui:composition>
And the following managed bean MenuTab.java
package com.menu;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name="menuTab")
#SessionScoped
public class MenuTab implements Serializable {
/** Creates a new instance of MenuTest */
public MenuTab() {
}
private String action;
private String value;
private List<String> listOfObjs = new ArrayList();
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
addValue(action);
}
//--------------------------------------
public void addValue(String act) {
if (listOfObjs.isEmpty()) {
setValue(act);
getListOfObjs().add(getValue());
System.out.println("First Data add First Data add First Data add::::::::::::::::" + value);
}
Iterator idvalu = listOfObjs.iterator();
while (idvalu.hasNext()) {
System.out.println("aaaaaaaaaaa=====" + idvalu.next());
value=act;
if (idvalu.next().equals(value)) {
System.out.println("Data Alrady Exite Data =====" + value);
}
else {
setValue(act);
getListOfObjs().add(getValue());
System.out.println("bbbbbbbbbbbbbbb=====" + value);
}
}
}
/**
* #return the listOfObjs
*/
public List<String> getListOfObjs() {
return listOfObjs;
}
/**
* #param listOfObjs the listOfObjs to set
*/
public void setListOfObjs(List<String> listOfObjs) {
this.listOfObjs = listOfObjs;
}
/**
* #return the value
*/
public String getValue() {
return value;
}
/**
* #param value the value to set
*/
public void setValue(String value) {
this.value = value;
}
}
When i click Add User menu;tomcat show this massage:
aaaaaaaaaaa=====StudentAdd
Jun 24, 2012 3:30:04 PM com.sun.faces.lifecycle.InvokeApplicationPhase execute
WARNING: /index.xhtml #22,110 target="#{menuTab.action}": Error writing 'action' on type com.menu.MenuTab
javax.el.ELException: /index.xhtml #22,110 target="#{menuTab.action}": Error writing 'action' on type com.menu.MenuTab
at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:139)
at com.sun.faces.facelets.tag.jsf.core.SetPropertyActionListenerHandler$SetPropertyListener.processAction(SetPropertyActionListenerHandler.java:206)
javax.el.ELException: /index.xhtml #22,110 target="#{menuTab.action}": Error writing 'action' on type com.menu.MenuTab
This means that the setter method behind the expression #{menuTab.action} has thrown an exception. Look further down in the stacktrace for that exception and then fix the code accordingly based on the information provided in the exception.
A quick glance on the setAction() code suggests that the most probable cause is a NoSuchElementException because you're calling Iterator#next() twice inside the loop. Every time the next() is called, it moves to the next element. It does not return the "current" element as you seemed to expect.
Remove the following line:
System.out.println("aaaaaaaaaaa=====" + idvalu.next());
or at least assign it to a variable
String next = idvalu.next();
System.out.println("aaaaaaaaaaa=====" + next);
if (next.equals(value)) {
// ...