Question about PickList and Pojo Support

UI Components for JSF
User avatar
Daedalus
Posts: 164
Joined: 28 Jan 2010, 12:03

03 Nov 2010, 12:29

Hello,

I have a small question.
If I look at the picklist in the Showcase it says there is support for Pojos. Does that mean, that I don't need converters anymore?
The Picklist in the example has the attribute converter set but it has the value of the attribute var.

Code: Select all

 <p:pickList value="#{pickListBean.players}"  
                    var="player" iconOnly="true" effect="bounce"  
                     itemLabel="#{player.name}"  
                     itemValue="#{player}" converter="player"  
                     showSourceControls="true" showTargetControls="true">  
PrimeFaces 3.0, Glassfish 3.1.2, Mojarra 2.1.6,

cagatay.civici
Prime
Posts: 18616
Joined: 05 Jan 2009, 00:21
Location: Cybertron
Contact:

03 Nov 2010, 12:46

Picklist needs converters if any other type than string is used as model type.

User avatar
Daedalus
Posts: 164
Joined: 28 Jan 2010, 12:03

03 Nov 2010, 12:57

Ok thx for the answer-
PrimeFaces 3.0, Glassfish 3.1.2, Mojarra 2.1.6,

User avatar
bumble.bee
Posts: 723
Joined: 29 Sep 2010, 21:39
Location: United States

03 Nov 2010, 14:51

I recently attempted to implement an entity converter. I've put it aside for now because I couldn't get it working easily. If you're working with entities and you get this working please post your experience.

Here is what I know:

There is an issue in JSF preventing you from injecting an EntityManager into a converter.

There appear to be two paths to solving this. First, Seam 3 is supposed to address this limitation. Second, you can use the BeanManager to access a bean to indirectly use the EntityManager.

dark_prime
Posts: 46
Joined: 02 Dec 2010, 14:30

20 Jun 2011, 10:23

Sorry to bring this up again, but I think it is still an unsolved issue of quite an importance.

I tried to get this working in 2.2., now I've been trying to get it to work in PF 3 for 2 days - and hell it is damn complicated.

My Old workaround was to handover the id instead of the object, but thats rather unpretty..

Code: Select all

itemlabel="#{player.name}" 
itemvalue="#{player.id}"
Honestly I dont know why u use two different approaches for this issue, the way it is in datatable is totally perfect...

Why this DualList and Converter sh** ?

Thanks in advance

User avatar
bumble.bee
Posts: 723
Joined: 29 Sep 2010, 21:39
Location: United States

20 Jun 2011, 14:31

Since bean injection doesn't work in converters you can manually inject a bean with a utility function like this:

Code: Select all

public class BeanHelper {
    public static Object manualInject(String beanELName) {
        FacesContext fc = FacesContext.getCurrentInstance();
        return fc.getApplication().getELResolver().
                getValue(fc.getELContext(), null, beanELName);
    }
}
I've got a few entity converters and they all share the same basic pattern so I created an abstract class:

Code: Select all

public abstract class EntityConverter implements Converter {

    private static final Logger log = LoggerFactory.getLogger(EntityConverter.class);

    @Override
    public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
        if (value == null || value.length() == 0) {
            return null; // Validator will decide if null is allowed
        }

        Object obj = null;

        try {
            obj = getStringAsEntity(fc, uic, value);
        } catch (Exception e) {
            log.debug("EntityConverter getAsObject Error", e);
        }

        if (obj == null) {
            String msg = "Unable to obtain object of type '"
                    + getEntityClass().getSimpleName() + "' with ID '"
                    + value + "'";

            throw new ConverterException(new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, msg, null));
        }

        return obj;
    }

    @Override
    public String getAsString(FacesContext fc, UIComponent uic, Object object) {
        if (object == null) {
            return null;
        }

        Class entityClass = getEntityClass();
        String msg;

        if (entityClass.isInstance(object)) {
            try {
                return getEntityAsString(fc, uic, object);
            } catch (Exception e) {
                log.error("EntityConverter getAsString Error", e);
                msg = "Unable to obtain String from Object";
            }
        }
        else {
            msg = "Object " + object + " is of type "
                + object.getClass().getSimpleName() + "; expected type: "
                + entityClass.getSimpleName();
        }

        throw new ConverterException(new FacesMessage(
                FacesMessage.SEVERITY_ERROR, msg, null));
    }

    protected int getKey(String value) {
        return Integer.parseInt(value);
    }

    protected String getStringKey(int value) {
        return Integer.toString(value);
    }

    protected abstract Object getStringAsEntity(FacesContext fc,
            UIComponent uic, String value);

    protected abstract String getEntityAsString(FacesContext fc,
            UIComponent uic, Object object);

    protected abstract Class getEntityClass();
}
An example entity converter that uses an entity named Fruit and a managed bean named FruitControllerBean would then look something like:

Code: Select all

@FacesConverter(value =
"fruitConverter")
public class FruitConverter extends
        EntityConverter {

    @Override
    protected Object getStringAsEntity(FacesContext fc, UIComponent uic,
            String value) {

        FruitControllerBean bean = (FruitControllerBean) 
                BeanHelper.manualInject("fruitControllerBean");

        return bean.findFruit(getKey(value));
    }

    @Override
    protected String getEntityAsString(FacesContext fc, UIComponent uic,
            Object object) {

        Fruit entity = (Fruit) object;

        return getStringKey(entity.getId());
    }

    @Override
    protected Class getEntityClass() {
        return Fruit.class;
    }
}
You would then hook this converter up to a p:pickList via the converter attribute like so:

Code: Select all

<p:pickList converter="fruitConverter" value="#{fruitControllerBean.fruit}" var="f" itemLabel="#{f.name}" itemValue="#{f}"/>

dark_prime
Posts: 46
Joined: 02 Dec 2010, 14:30

20 Jun 2011, 16:30

Thanks for your reply.

what confuses me is, that your picklist maps f.name->f but your converter converts object to id.

Furthermore the p:picklist returns a vector in my case, so casting like u do in

Code: Select all

Fruit entity = (Fruit) object;
is not possible.

Here is my code, I managed to get my EJB via a JNDI lookup and the getAsObject() part works quite well, but the getAsString() part throws me an

Code: Select all

java.lang.NumberFormatException: For input string: "name"
converter:

Code: Select all

@FacesConverter(value = "NamePlayerConverter")
public class NamePlayerConverter implements Converter {

    /**
     * converts the String representation of the key back to the Object
     */
    @Override
    public Object getAsObject(FacesContext context, UIComponent component,
            String value) {
        // will throw new IllegalArgumentException if it can't parse.
        Object obj = new Object();
        CRUDService crudService;
        try {
            crudService = ServiceLocator.getInstance().getService(CRUDService.class);
           obj = crudService.findWithNamedQueryAndParam(Player.findByName, "name", value);
        } catch (Exception ex) {
            Logger.getLogger(NamePlayerConverter.class.getName()).log(Level.SEVERE, null, ex);
        }
        
         
        return obj;
    }

    /**
     * converts the Key object into its String representation.
     */
    @Override
    public String getAsString(FacesContext context, UIComponent component,
            Object value) {
            System.out.print(value.getClass().toString());
        if (value instanceof Player) {
            Player player = (Player) value;
            return player.getName();
        }
        else if(value instanceof Vector){
            Vector vector = (Vector) value;
            Player player = (Player) vector.get(0);
            return player.getName();
        } 

         else {
            throw new IllegalArgumentException("Cannot convert non-player object in NamePlayerConverter");
        }
    }

      
        
}
xhtml page

Code: Select all

 <p:panel header="Neues Match melden">
                    <h:panelGrid columns="6">
                        <h:outputText value="Team 1"/>  
                      <p:pickList value="#{gameController.d1}"  
                    var="player" iconOnly="true" effect="bounce"  
                    itemLabel="#{player.name}"  
                    itemValue="#{player}" converter="NamePlayerConverter"
                    showSourceControls="false" showTargetControls="false" >  
                        <f:facet name="sourceCaption">Spieler auswählen</f:facet>  
                        <f:facet name="targetCaption">Teamaufstellung</f:facet>  
                     </p:pickList>  
ServiceLocator

Code: Select all

public class ServiceLocator {

    private static ServiceLocator instance;
    InitialContext context;
    private ServiceLocator() throws Exception {
        try {
            Properties p = new Properties();
            p.put(Context.INITIAL_CONTEXT_FACTORY,
                    "com.sun.enterprise.naming.SerialInitContextFactory");
            p.put(Context.URL_PKG_PREFIXES,
                    "com.sun.enterprise.naming");
            p.put(Context.PROVIDER_URL, "iiop://127.0.0.1:3700");
            context = new InitialContext(p);
        } catch (NamingException e) {
            throw new Exception(e);
        }
    }

    public static ServiceLocator getInstance() throws Exception {
        if (instance == null)
            instance = new ServiceLocator();
        return instance;
    }

    @SuppressWarnings("unchecked")
    public <T> T getService(Class<T> clazz) throws Exception {
        try {
  
            String lookupName = "java:global/nC-Kicker-Ticker/" + clazz.getSimpleName() + "!" + "de.nobiscum.nckickerticker.EJB" + "." + clazz.getSimpleName();
            showJndiContext(context, null, null);   
            
            T lookup = (T) context.lookup(lookupName);
            return lookup;
        } catch (ClassCastException e) {
            throw new Exception(e);
        } catch (NamingException e) {
            throw new Exception(e);
        }
    }

Would be awesome if you could take a look, cause it is getting really frustrating

User avatar
bumble.bee
Posts: 723
Joined: 29 Sep 2010, 21:39
Location: United States

20 Jun 2011, 22:09

your picklist maps f.name->f but your converter converts object to id
Why do you say that?
itemValue="#{f}"
The itemValue attribute assignment means that I'm handing the pickList an entity. It must use the converter I provided to get a String representation for rendering. It also must use the converter to get an Object from that String representation when processing a request.

AmmarAsim
Posts: 8
Joined: 14 May 2012, 20:42

21 May 2012, 15:04

After reading all the posts, I'm still unable to write a working code for picklist control. Can any one please explain with a simple example code. The problem is with writing a converter. Please give a working code for the 'Player' example at PrimeFaces showcase.

User avatar
T.dot
Expert Member
Posts: 620
Joined: 01 Feb 2012, 15:39
Location: Vienna/Austria

21 May 2012, 15:25

Why don't you look at the showcase source? It looks like it's working there...
http://www.primefaces.org/showcase-labs/ui/picklist.jsf

You can always get the full source code from SVN:
http://code.google.com/p/primefaces/sou ... src%2Fmain

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 57 guests