This was exactly my initial attempt when externalizing all reflection code to the ReflectionUtils class. Unfortunately, at that time I couldn't make the change everywhere.
If you can submit the patch than me or Christophe will take a look at it and commit it. ./alex -- .w( the_mindstorm )p. InfoQ.com Architect On 4/19/06, Daniel Mora <[EMAIL PROTECTED]> wrote:
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 <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> 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 > > > > >
