incubator-graffito-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Daniel Mora" <moradan...@gmail.com>
Subject Re: Classloader problem
Date Wed, 19 Apr 2006 17:48:33 GMT
I found a solution and maybe can be a contribution to Graffito mapper. I
modified a little some graffito mapping files (ReflectionUtils,
FieldDescriptor, ManegeableCollectionUtil, ObjectConverterImpl) that use
Class.forName. Now only ReflectionUtils calls Class.forName, the others use
ReflectionUtils.forName. I added to ReflectionUtils a private static
attribute called classLoader and its setter and getter. I also modified the
Mapper interface and added
public abstract void setClassLoader(ClassLoader classLoader);
public abstract ClassLoader getClassLoader();

Now I can do things like:
Mapper mapper = new DigesterMapperImpl(this.files);
mapper.setClassLoader(myClassLoader);
mapper.buildMapper();

And this is the ReflectionUtils file:

package org.apache.portals.graffito.jcr.reflection;

import java.lang.reflect.InvocationTargetException;
import net.sf.cglib.proxy.Enhancer;
import org.apache.commons.beanutils.ConstructorUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.portals.graffito.jcr.exception.JcrMappingException;
import
org.apache.portals.graffito.jcr.persistence.collectionconverter.CollectionConverter
;


/**
 * Utility class for handling reflection using BeanUtils.
 *
 * @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru
Popescu</a>
 */
abstract public class ReflectionUtils {

    private static ClassLoader classLoader = null;

    public static Object getNestedProperty(Object object, String fieldName)
{
        if (null == object) {
            return null;
        }

        try {
            return PropertyUtils.getNestedProperty(object, fieldName);
        }
        catch(IllegalAccessException e) {
            throw new JcrMappingException("Cannot access property "
                    + fieldName,
                    e);
        }
        catch(InvocationTargetException e) {
            throw new JcrMappingException("Cannot access property "
                    + fieldName,
                    e);
        }
        catch(NoSuchMethodException e) {
            throw new JcrMappingException("Cannot access property "
                    + fieldName,
                    e);
        }
    }

    public static Class getPropertyType(Object object, String fieldName) {
        try {
            return PropertyUtils.getPropertyType(object, fieldName);
        }
        catch(Exception ex) {
            throw new JcrMappingException("Cannot access property "
                    + fieldName,
                    ex);
        }
    }

    public static Object newInstance(Class clazz) {
        try {
            return clazz.newInstance();
        }
        catch(Exception ex) {
            throw new JcrMappingException("Cannot create instance for class
"
                    + clazz,
                    ex);
        }
    }

    /**
     * @param className
     * @param objects
     * @return
     */
    public static CollectionConverter invokeConstructor(String className,
                                                        Object[] params) {
        try {

            Class converterClass = ReflectionUtils.forName(className);
            return (CollectionConverter)
ConstructorUtils.invokeConstructor(converterClass,
params);
        }
        catch(Exception ex) {
            throw new JcrMappingException("Cannot create instance for class
"
                    + className,
                    ex);
        }
    }

    /**
     * @param object
     * @param fieldName
     * @param path
     */
    public static void setNestedProperty(Object object, String fieldName,
Object value) {
        try {
            PropertyUtils.setNestedProperty(object, fieldName, value);
        }
        catch(Exception ex) {
            throw new JcrMappingException("Cannot set the field " +
fieldName + " in the class : " + object.getClass().toString(),
                    ex);
        }
    }

    /**
     * @param string
     * @return
     */
    public static Object newInstance(String clazz) {
        try {
            return ReflectionUtils.forName(clazz).newInstance();
        }
        catch(Exception ex) {
            throw new JcrMappingException("Cannot create instance for class
"
                    + clazz,
                    ex);
        }
    }

    /**
     * @param elementClassName
     * @return
     */
    public static Class forName(String clazz) throws JcrMappingException{
        try {
            Class aClass = null;
            if(ReflectionUtils.classLoader!=null){
                aClass =  Class.forName(clazz,false,
ReflectionUtils.classLoader);
            }
            if(aClass!=null){
                return aClass;
            }

            return Class.forName(clazz);
        }
        catch(Exception ex) {
            throw new JcrMappingException("Cannot load class " + clazz, ex);
        }
    }

    public static boolean isProxy(Class beanClass)
    {
         return Enhancer.isEnhanced(beanClass);
    }

    public static Class getBeanClass(Object bean)
    {
             Class beanClass = bean.getClass();
         if (isProxy(beanClass))
         {
                 //CGLIB specific
                 return beanClass.getSuperclass();
         }
         return beanClass;
    }

    public static ClassLoader getClassLoader() {
        return ReflectionUtils.classLoader;
    }

    public static void setClassLoader(ClassLoader classLoader) {
        ReflectionUtils.classLoader = classLoader;
    }

}


On 4/19/06, Daniel Mora <moradaniel@gmail.com> wrote:
>
> Yes, I am using Tomcat. The problem is that I have a custom classloader
> called LocalClassLoader and is conflicting with WebAppClassloader, and both
> are loading DefaultTipology.class from WEB-INF\classes.
> I had the same problem using XStream, but XStream has the posibility to
> set the classloader.
>         ClassLoader classLoader = DefaultTipology.class.getClassLoader();
>         xstream.setClassLoader(classLoader);
> The solution I am thinking is to modify some graffito files, for example
> ReflectionUtils.java , and change Class.forName(className) into
> Class.forName(className, classloader).
> Maybe I can contribute with Graffito with this extra feature, what do you
> think?
>
>
>
> On 4/19/06, Christophe Lombart <christophe.lombart@gmail.com> wrote:
> >
> > Graffito is a classic java application. So, classloader is working as
> > usual.
> > Can you give me more information on your deployement. How your jars are
> > deployed ? Are you using Jetspeed ?
> > Where is deployed DefaultTipology ? Are you using Tomcat ? I'm not sure
> > it
> > is necessary to set the classloader.
> >
> >
> > On 4/19/06, Daniel Mora <moradaniel@gmail.com> wrote:
> > >
> > > Hi all,
> > > I am successfully integrating Graffito mapping tools into my J2EE CMS
> > > environment. But now Im facing a classloader problem. The following
> > code
> > > is
> > > throwing a ClassCastException in (DefaultTipology) resultIter.next()
> > > because
> > > DefaultTipology.class.getClassLoader () != resultIter.next
> > > ().getClass().getClassLoader()
> > > One is LocalClassLoader and the other is WebAppClassLoader.
> > >
> > >           Filter filter = this.queryManager.createFilter(
> > > DefaultTipology.class );
> > >           Query query = this.queryManager.createQuery(filter);
> > >           Collection result = this.persistenceManager.getObjects
> > (query);
> > >           Iterator resultIter = result.iterator();
> > >           while( resultIter.hasNext()){
> > >               DefaultTipology defTipo = (DefaultTipology)
> > resultIter.next
> > > ();
> > >               this.tipologyIds.put(defTipo.getIdName(),defTipo);
> > >           }
> > >
> > > Is there a way to set the classloader in graffito, in order to have
> > only
> > > one
> > > instance of a class?
> > >
> > >
> >
> >
> > --
> > Best regards,
> >
> > Christophe
> >
> >
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message