Hi,

Yes of course I can share if you find it useful. Here you are (sorry for my "spanished code"):

public class ObjectConverter implements Converter
{

    // CGLIB class separator string "$$"
    private final String CGLIB_CLASS_SEPARATOR_CHAR = "$$";

    public Object getAsObject(FacesContext context, UIComponent component,
            String value) throws ConverterException
    {
        int start = value.indexOf("::");
        String parteIzq = value.substring(0, start);
        String parteDer = value.substring(start + 2);
        int nameEndIndex = parteDer.indexOf(CGLIB_CLASS_SEPARATOR_CHAR);
        if (nameEndIndex == -1)
        {
            nameEndIndex = parteDer.length();
        }

        // If value represents "all the possible values"...
        if (parteIzq.equals(Constantes.TODOS_ELEMENTOS_MENU_DESPLEGABLE
                .toString()))
        {
            // ...then we simply instantiate the class...
            Object object = ClassUtils.newInstance(parteDer.substring(0,
                    nameEndIndex));

            try
            {
                // ...an we call setCodigo method with a special value
                // TODOS_ELEMENTOS_MENU_DESPLEGABLE
                BeanUtils
                        .findDeclaredMethodWithMinimalParameters(
                                object.getClass(), "setCodigo")
                        .invoke(
                                object,
                                new Object[] { Constantes.TODOS_ELEMENTOS_MENU_DESPLEGABLE });
            }
            catch (IllegalArgumentException e)
            {
                throw new ConverterException(e);
            }
            catch (IllegalAccessException e)
            {
                throw new ConverterException(e);
            }
            catch (InvocationTargetException e)
            {
                throw new ConverterException(e);
            }

            return object;
        }

        return ((DummyDAOHibernateImpl) FacesUtils.getBean("dummyDAO"))
                .getHibernateTemplate().get(
                        parteDer.substring(0, nameEndIndex),
                        Integer.valueOf(parteIzq));
    }

    public String getAsString(FacesContext context, UIComponent component,
            Object value) throws ConverterException
    {
        if (value instanceof String)
        {
            return (String) value;
        }

        try
        {
            String left = String.valueOf(BeanUtils
                    .findDeclaredMethodWithMinimalParameters(value.getClass(),
                            "getCodigo").invoke(value, null));
            String right = value.getClass().getName();

            return (left + "::" + right);
        }
        catch (IllegalAccessException e)
        {
            throw new ConverterException(e);
        }
        catch (InvocationTargetException e)
        {
            throw new ConverterException(e);
        }
    }

}

Please notice that all my objects have a get/set method to retrieve the object ID (in this case, get/setCodigo). This can be easily achieved by forcing all your object to implement an interface ;-) The dummy DAO is a simply DAO which can be a simply extension of the HibernateSupportDao from Spring.

Also notice that I do a little trick with a special value represented in the constant TODOS_ELEMENTOS_MENU_DESPLEGABLE to be able to get all the objects of the class. You can simply bypass this issue or use it ;-)

Then, you have to define the converter in the faces-config.xml file this way:

    <converter>
        <converter-for-class>
            com.xxxx.yyyy.objectmodel.vo.AnyVO
        </converter-for-class>
        <converter-class>
            com.xxxx.yyyy.web.common.converters.ObjectConverter
        </converter-class>
    </converter>

Regarding the FacesUtils helper class, here is the relevant code:

    public static Object getBean(String name)
    {
        WebApplicationContext wac = WebApplicationContextUtils
                .getRequiredWebApplicationContext(getServletContext());

        return wac.getBean(name);
    }

    public static ServletContext getServletContext()
    {
        return (ServletContext) FacesContext.getCurrentInstance()
                .getExternalContext().getContext();
    }


Hope it helps you.

2005/7/22, Clément Maignien <[EMAIL PROTECTED]>:

Hi,

I am currently developping a JSF application with Spring services which uses Hibernate DAO.

I'm quite interrested by the generic converter you've created. It seems to be great.

Do you plan to share it or not ?

 

Thanks,

Clément

 

-----Message d'origine-----
De : En
rique Medina [mailto:[EMAIL PROTECTED]]
Envoyé : vendredi 22 juillet 2005 15:45
À :
MyFaces Discussion
Objet : Re: Dynamic Converter

 

Hi,

I implemented a generic object converter for Hibernate using a dummy dao that only needs the ID for the object (in terms of Hibernate) and its class.

So when the object has to be converted to a String, I simply generate a string with the class name and the ID of the object. And when a string needs to be converted to an object, I simply ask Hibernate to load the object whose class and ID is obtained from the previously created string.

I can do this generic thing due to the fact that I'm working with Hibernate, but I think it can be easily extended to whatever scope you need.

Hope it helps ;-)

2005/7/21, [EMAIL PROTECTED] <[EMAIL PROTECTED]>:


There are 29 lookup tables in my db. The selectOneMenu tags of the site are populated via objects that have been mapped to each table using Hibernate.  I want "one converter to rule them all".

getAsString() is done (determine the identifier/pk property of the bean at runtime by querying the OR meta data, call it w/ reflection, return the value as a string).  getAsObject() however is difficult - it needs some way to know which class it must create.

Is there a way to determine this by walking the UIcomponent passed to getAsObject() ?  I can cast it to a HtmlSelectOneMenu but that's as far as I get.

One idea was to extend the tag handler, add a className attribute and pass the value of this attribute to the dynamic converter in an over ridden createConverter().  Despite the fact that this means the class's full java name appears directly in the JSP, I still did this only to find that it only works for the first conversion.  The dynamic converter is recreated for each request, and the createConverter() of the tag class only fires for the first request.

I'm open to the possibility this smart converter is not a smart idea.  Someone throw me a bright idea before I go with the following:

Write 29 classes, each implements getAsObject() - each class inherits getAsString() from 30th class.

Dennis Byrne

 


Reply via email to