
Question:
I have a bean "Player" When I select a value in the selectOneMenu I would like to "switch" to the bean that's matching in the database.
I have the beans sent back to the select one menu in
public List<Player> getAllPlayers() { }
Updated the dropdown to this.
<pre class="lang-xhtml prettyprint-override"><h:selectOneMenu value="#{servicePlayer.myPlayer.combinedName}"
converter="playerConverter" id="playerList">
<f:selectItems value="#{servicePlayer.allPlayers}" var="player"
itemLabel="#{player.combinedName}" itemValue="#{player.id}" />
</h:selectOneMenu>
But I still can't get it to send the ID to the converter. It will send in the firstName from the player.
@FacesConverter(value = "playerConverter")
public class PlayerConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value == null) {
return null;
}
long idValue;
try {
idValue = Long.parseLong(value);
}
catch (NumberFormatException ex)
{
return null;
}
ServicePlayer servicePlayer = context.getApplication()
.evaluateExpressionGet(context, "#{servicePlayer}",
ServicePlayer.class);
Player player = servicePlayer.getPlayerByID(idValue);
return player;
}
@Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object value) {
String string = null;
if (value instanceof Player) {
string = ((Player) value).getFirstName();
}
return string;
}
}
public class ServicePlayer {
private static final String PERSISTENCE_UNIT_NAME = "BowlingFacelets";
public static EntityManagerFactory factory;
Player myPlayer;
public Player getMyPlayer() {
return myPlayer;
}
public void setMyPlayer(Player myPlayer) {
this.myPlayer = myPlayer;
}
public List<Player> getAllPlayers() {
if (factory == null) {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
}
EntityManager em = factory.createEntityManager();
//Order by the matchdate.
//Query q = em.createQuery("select t from DBTest t");
Query q = em.createQuery("select t from Player t");
List<Player> players = q.getResultList();
for (Player aPlayer : players) {
System.out.println(aPlayer);
}
System.out.println("Size: " + players.size());
em.close();
return players;
}
public Player getPlayerByID(long id) {
if (factory == null) {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
}
EntityManager em = factory.createEntityManager();
//Query q = em.createQuery("select t from Player t where t.name = '" + playerName + "'");
//List<Player> players = q.getResultList();
Player currentPlayer = em.find(Player.class, id);
return currentPlayer;
}
}
Answer1:A JSF Converter
does the job of converting an Object to the string value for the itemValue
attribute and then recover that Object from the string value. For your case, the <strong>Object</strong> is the Player
entity while the <strong>value</strong> is the String
representation of its id (could be anything else, as long as you know it's <em>unique</em>).
Basically, using this converter:
@FacesConverter(value = "playerConverter")
public class PlayerConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value == null) {
return null;
}
long idValue;
try {
idValue = Long.parseLong(value);
}
catch (NumberFormatException ex)
{
return null;
}
ServicePlayer servicePlayer = context.getApplication()
.evaluateExpressionGet(context, "#{servicePlayer}",
ServicePlayer.class);
Player player = servicePlayer.getPlayerByID(idValue);
return player;
}
@Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object value) {
String string = null;
if (value instanceof Player) {
string = ((Player) value).getId();
}
return string;
}
}
Note <strong>I changed the name you're returning by the id</strong>. That way, being the player id 1
, JSF knows the String value for that is "1"
. That's the value for the selection, which is obtained by the getAsString
method.
When you <em>POST</em> the form, JSF has to recover the Player
entity from the "1"
value, so you use Converter's getAsObject
to load it from the DB.
That way it would be enough to reference the object itself from the view to let jsf do the conversion:
<pre class="lang-xhtml prettyprint-override"><h:selectOneMenu value="#{servicePlayer.myPlayer.combinedName}"
converter="playerConverter" id="playerList">
<f:selectItems value="#{servicePlayer.allPlayers}" var="player"
itemLabel="#{player.combinedName}" itemValue="#{player}" />
</h:selectOneMenu>
Answer2:I think you've misunderstood what the value attribute of the selectOneMenu refers to. It's use is like in all other input components the place to store the user input (or where to take an existing value from).
Check <a href="http://www.jsftoolbox.com/documentation/help/12-TagReference/core/f_selectItems.html" rel="nofollow">http://www.jsftoolbox.com/documentation/help/12-TagReference/core/f_selectItems.html</a>. You will need to set key and value pairs based on a 'var' attribute on the f:select items, else JSF has no real way of knowing what you want to do with the Player object.
So given that key/value pairs (key goes into whatever you sets as the value attribute and value is shown to the user) is in place, and if you for example use the player.id as the value, you can fetch a user based on that id.