JSF + Primefaces, SelectOneListBox not working [duplicate] - jsf-2

This question already has answers here:
Validation Error: Value is not valid
(3 answers)
Closed 7 years ago.
I am currently working on a small Voting-Tool with JSF, Primefaces, CDI etc... The main purpose of that is to improve my programming skills and learning a bit about Java EE.
In the tool, one can collect PC-games and create Game-Votings, where people (Lan-Party) can (or should be able to) vote for a game.
For the Voting-Form I want to use Primefaces "SelectOneListBox". It gets the List of Games from a #ApplicationScoped Bean that handels the Voting ("votingListProducer") and looks as follows:
<h:form id="votingFormID">
<p:selectOneListbox value="#{votingListController.selectedGame}" converter="#{gameConverter}"
var="g" showCheckbox="true" style="width:500px;" >
<f:selectItems value="#{votingListProducer.voting.gameList}" var="game" itemLabel="#{game.name}" itemValue="#{game}" />
<p:column>
<p:graphicImage value="resources/images/#{g.imgSrc}" width="40"/>
</p:column>
<p:column>
#{g.name}
</p:column>
<p:column>
#{g.version}
</p:column>
</p:selectOneListbox>
<p:commandButton value="Submit" action="#{votingListController.doAddVoteAktion}" />
<p:commandButton value="Zeige selektierte List" action="#{votingListController.doPrintSelectedGame}"/>
</h:form>
When I call this view, the correct List of Games is displayed. But when I select one and click on "Submit" the converter converts it right, because it returns the correct Game, but in the Controller the attribute "selectedGame" will not be set to this Game. And also the Methods are not called.
Here is the Controller:
#SessionScoped
#Named
public class VotingListController implements Serializable{
private static final long serialVersionUID = -7222543653854660316L;
private Game selectedGame;
#Inject #AddedChoice
private Event<Game> addChoiceEventSrc;
public void doAddVoteAktion (){
if (selectedGame!=null){
addChoiceEventSrc.fire(selectedGame);
}
}
public void doPrintSelectedGame(){
if (selectedGame!=null){
System.out.println(selectedGame.getName());
}
}
public Game getSelectedGame() {
return selectedGame;
}
public void setSelectedGame(Game selectedGame) {
this.selectedGame = selectedGame;
}
}
Do you have any Idea why this does not work?
Thank You!
Edit: Converter-Code
#RequestScoped
#Named
public class GameConverter implements Converter{
#Inject
private GameListManager gameListManager;
#Override
public Object getAsObject(FacesContext fc, UIComponent ui, String value) {
for (Game g : gameListManager.getGameList()){
if (g.getGameId().toString().equalsIgnoreCase(value)){
System.out.println ("I receive: "+g.getName());
return g;
}
}
return null;
}
#Override
public String getAsString(FacesContext fc, UIComponent ui, Object value) {
if (value!=null){
Game game = (Game) value;
String res = game.getGameId().toString();
System.out.println(res);
return res;
}
return null;
}
}

Try:
<p:commandButton value="Submit" actionListener="#{votingListController.doAddVoteAktion}"
process=":votingFormID"/>
Maybe it can be a error when your converter calls getAsObject, can you post the converter code?

Change your action Listener definition to
public void doAddVoteAktion (ActionEvent event){
if (selectedGame!=null){
addChoiceEventSrc.fire(selectedGame);
}
}
And
<p:commandButton value="Submit" actionListener="#votingListController.doAddVoteAktion}" ajax="true" process="#this"/>

Related

OneMenu not persisting changed value

After my post (Hibernate Primefaces AutoComplete text) I switched the implementation a little. But now I am facing a problem.
Even if I use an AJAX event I do not keep the selected value saved to populate a second drop down.
my CREATE.XHTML
<h:head></h:head>
<ui:debug rendered="true"/>
<body>
<h:form id="createAddressForm" prependId="true">
<!-- <p:messages autoUpdate="true" /> -->
<p:growl id="msgs" showDetail="true" />
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
<p:outputLabel for="countryDropDown" value="Country" />
<p:selectOneMenu id="countryDropDown" value="#{addressController.selectedIsoCountry}" >
<p:ajax listener="#{addressController.onCountryChange}" update="stateDropDown" />
<f:selectItem itemValue="" itemLabel="Select a country"/>
<f:selectItems value="#{addressController.countryMap}" />
</p:selectOneMenu>
<p:outputLabel for="stateDropDown" value="State" />
<p:selectOneMenu id="stateDropDown" value="#{addressController.state}" >
<f:selectItem itemValue="" itemLabel="Selecione a State" />
<f:selectItems value="#{addressController.stateMap}" />
</p:selectOneMenu>
</h:panelGrid>
</h:form>
</body>
</html>
And this is AddressController.java
import java.util.Map;
import java.util.TreeMap;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.SessionScoped;
import javax.inject.Named;
import br.com.azulseguros.ejb.CountryEJB;
import br.com.azulseguros.entity.Country;
import br.com.azulseguros.entity.State;
#SessionScoped
#Named
public class AddressController {
#EJB
private CountryEJB countryEJB;
private String selectedIsoCountry = null;
private State state = null;
private Map<String, String> countryMap = null;
private Map<String, String> stateMap = null;
#PostConstruct
private void init() {
Map<String, String> retorno = new TreeMap<String, String>();
for (Country _tmp : countryEJB.findAll()) {
retorno.put(_tmp.getName(), _tmp.getIso());
}
countryMap = retorno;
}
public Map<String, String> getCountryMap() {
return countryMap;
}
public Map<String, String> getStateMap() {
return stateMap;
}
public String getSelectedIsoCountry() {
return selectedIsoCountry;
}
public State getState() {
return state;
}
public void setSelectedIsoCountry(String selectedIsoCountry) {
this.selectedIsoCountry = selectedIsoCountry;
}
public void setState(State state) {
this.state = state;
}
public void setCountryMap(Map<String, String> countryMap) {
this.countryMap = countryMap;
}
public void setStateMap(Map<String, String> stateMap) {
this.stateMap = stateMap;
}
public void onCountryChange() {
setStateMap(getStatesFromSelectedCountry());
}
private Map<String, String> getStatesFromSelectedCountry() {
Map<String, String> retorno = new TreeMap<String, String>();
if (selectedIsoCountry != null && !selectedIsoCountry.equals("")) {
for (State _tmp : countryEJB.findByIso(selectedIsoCountry).getStates()) {
retorno.put(_tmp.getName(), _tmp.getFu());
}
}
return retorno;
}
}
The EJB responsibile for finding all countries and states is working fine. There is a lot of issues with that and I do not know what to do to fix it.
1 - After I invoke the page for the first time it calls the init method 10 times;
2 - After that it evoked the method getStatesFromSelectedCountry even not choosing any country from the 1st drop down and after that evokes the init method again;
3 - When i choose a country it evokes 7 times the init method and then the getStatesFromSelectedCountry() but the selectedIsoCountry is null.
The bean's init method is invoked many times because you have defined the bean both as a CDI bean using javax.inject.Named, without scope, and as a JSF Managed Bean using javax.faces.bean.SessionScoped; if you intended to use CDI beans, simply replace the latter annotation with javax.enterprise.context.SessionScoped. See Why are there different bean management annotations
From a CDI point of view, the bean is by default RequestScoped, this should explain also the second issue you are experiencing.
Concerning the third issue, see this Q/A:
Why is the getter called so many times by the rendered attribute?
Why JSF calls getters multiple times

Not getting selected value from Dropdown in primefaces backing bean

Hi I have built two consecutive dropdowns one being initialized in init() method and the other being populated on the basis on first one's selection.
Command Button is used to use both the selected values for processing, Strange that Setter for the selected values is being called twice(setting blank the second time..as I found out in debugging)..I need understand whyu I am getting blank values?
myPage.xhtml
<p:selectOneMenu id="dbList"
value="#{backingBean.selectedConnection}"
style="width:200px">
<p:ajax listener="#{backingBean.onConnectionChange()}"
update="aliasList" />
<f:selectItem itemLabel="Select" itemValue="#{backingBean.selectedConnection}"
noSelectionOption="false" />
<f:selectItems value="#{backingBean.connectionsTypeList}" />
</p:selectOneMenu>
<p:outputLabel for="aliasList" value="Connection Alias" />
<p:selectOneMenu id="aliasList"
value="#{backingBean.aliasSelected}" style="width:200px">
<f:selectItem itemLabel="Select" itemValue="#{backingBean.aliasSelected}"
noSelectionOption="false"/>
<f:selectItems value="#{backingBean.connectionsList}" />
</p:selectOneMenu>
<p:commandButton value="myButton"
actionListener="#{backingBean.myMethod()}"
id="myButton" />
backingBean.java
#ManagedBean
#ViewScoped
public class BackingBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private ArrayList<String> connectionsList;
private String aliasSelected;
private String selectedConnection;
private ArrayList<String> connectionsTypeList;
#PostConstruct
public void init() {
// Initialize the connection alias drop down here
this.connectionsTypeList = getConnectionTypeList();
this.connectionsList=new ArrayList<String>();
}
public void onConnectionChange() {
System.out.println("In Connection Change, populating aliases");
getConnectionDBList();
}
public String getAliasSelected() {
return aliasSelected;
}
//Dont know why this is called twice on button click and second time value set is blank
public void setAliasSelected(String aliasSelected) {
this.aliasSelected = aliasSelected;
}
public ArrayList<String> getConnectionsList() {
return connectionsList;
}
public void setConnectionsList(ArrayList<String> connectionsList) {
this.connectionsList = connectionsList;
}
public String getSelectedConnection() {
return selectedConnection;
}
public void setSelectedConnection(String selectedConnection) {
this.selectedConnection = selectedConnection;
}
public ArrayList<String> getConnectionsTypeList() {
return connectionsTypeList;
}
public void setConnectionsTypeList(ArrayList<String> connectionsTypeList) {
this.connectionsTypeList = connectionsTypeList;
}
public void myMethod() {
System.out.println("selected Alias is "+aliasSelected);
System.out.println("selected connection is "+selectedConnection);
}
}
New to primefaces,please help
Answer to this :"setting blank the second time..as I found out in debugging"
This is happening because I realized I was pointing the same property to two ui components..as in..two dropdowns in the same page were linked to the same property of the backing bean..Sillyh Mistake..hence the second call to the setter..with Blank values..as it was not initialized for the second UI Component

How to fire a ValueChangeEvent on blur for an inputtext component with primefaces

I still have the problem that i need the old and the new value of an inputtext component on a blur event. But i don't see a way to get the blur event without the use of "p:ajax".
Are there any other ways to get the old and new value?
xhtml:
<h:form>
<p:inputtext value="#{myController.value}"
valueChangeListener="#{myController.handleEvent}">
<p:ajax event="blur" listener="#{myController.handleEvent}" />
</p:inputtext>
</h:form>
Controller:
#ViewAccessScoped
#Named("myController")
public class MyController implements Serializable {
private static final long serialVersionUID = 8736461860325705841L;
public void intervalChanged(AjaxBehaviorEvent event) {
// I need the old value here!
}
public void intervalChanged(ValueChangeEvent event) {
// Here i got the old value but this listener method is not invoked on blur
}
}

CDI Conversation instance is not being created

I am try to develop a web application where I need the Conversation scope to carry on with the same String value in multiple xhtml pages with Primefaces 3.5.
When I begin the conversation with conversation.begin(), it throws null pointer exception with conversation being as null.
I know I can't create a instance of Conversation using 'new'. But I can't figure out where am I going wrong and why is it coming to be null.
Please guide.
Snippet of the xhtml where the bean method is called:
<p:column style="text-align: left" headerText="Deal ID"
width="30">
<p:commandLink value="#{selectedDealBean.getDealID()}"
action="#{SearchBean.action(selectedDealBean.getDealID())}"
process="#this" >
</p:commandLink>
</p:column>
Snippet of bean:
#Named()
#ManagedBean
#ConversationScoped
public class SearchBean implements Serializable {
#Inject
private Conversation conversation;
private DealBean selectedDealBean;
private String selectedID;
private SearchObject searchObj = new SearchObject();
public void start() {
this.conversation.begin();
}
public void end() {
conversation.end();
}
public void submit() {
System.out.println(selectedDealBean);
}
public String action(String selectedID) {
String actionstatus = null;
setSelectedID(selectedID);
actionstatus = "/common/dealDisplay.xhtml?faces-redirect=true" ;
start();
return actionstatus;
}
public String onFinish() {
end();
return "/common/create.xhtml";
}
}
You're mixing annotations. Since you're using CDI you should remove #ManagedBean annotation which is possibly the reason why your injection isn't working.

Is primefaces live scrolling compatible with Lazy loading

I have a datatable where huge data sets need to be displayed.So i decided to go with primefaces live scrolling.I also got to know that to improve datatable performance with huge data sets we need to implement lazy loading.With reference to the primefaces showcase example
here,what i observed that there in the statement
, a LazyDataModel needs to be implemented to query the datasource when pagination, sorting, filtering or live scrolling happens
live scrolling is mentioned but i cannot see the code to handle scrolling.It only has the code to handle sorting,filtering,row count and pagination.Can someone please clarify my confusion if both live scolling and lazy datamodel implementation are compatible with each other or should i add some code to handle live scrolling also.
It works exactly the same as if you were having a pagination.
Here's a small example:
xhtml
<p:dataTable var="user"
value="#{bean.lazyDataModel}"
scrollRows="20"
liveScroll="true"
scrollHeight="500"
lazy="true"
scrollable="true">
<p:column headerText="name">
<h:outputText value="#{user.name}" />
</p:column>
</p:dataTable>
Bean
#ManagedBean
#ViewScoped
public class Bean {
private LazyDataModel<User> lazyDataModel;
#EJB
UserEJB userEJB;
#PostConstruct
public void init() {
lazyDataModel = new LazyUserModel(userEJB);
}
public LazyDataModel<User> getLazyDataModel() {
return lazyDataModel;
}
public void setLazyDataModel(LazyDataModel<User> lazyDataModel) {
this.lazyDataModel = lazyDataModel;
}
//setters and getters for userEJB
}
LazyUserModel
public class LazyUserModel extends LazyDataModel<User> {
private Integer findAllCount;
#EJB
private UserEJB userEJB;
public LazyUserModel(UserEJB userEJB) {
this.userEJB = userEJB;
}
#Override
public List<User> load(int first, int pageSize, String sortField, SortOrder sortOrder,
Map<String, String> filters) {
List<User> data = new ArrayList<User>();
// pageSize is scrollRows="20" in the datatable
data = userEJB.findAll(first, pageSize);
// findAll is using query.setFirstResult(first).setMaxResults(pageSize).getResultList()
// rowCount
if (findAllCount == null) {
findAllCount = userEJB.findAllCount();
this.setRowCount(findAllCount);
}
return data;
}
}
Hope this helps.
Looks like there's a new attribute for it in 6.1, liveScroll="true"
https://github.com/primefaces/primefaces/issues/2105

Resources