How well did you test this?
Because i think the biggest problem here is that the
IComponentInstantiationListener is invoked in the constructor of
Component and thus before any childclass constructor has run.

Maurice

On Mon, Apr 28, 2008 at 1:42 PM, James Carman
<[EMAIL PROTECTED]> wrote:
> On Mon, Apr 28, 2008 at 6:27 AM, James Carman
>  <[EMAIL PROTECTED]> wrote:
>  >  Yes, this would involve making up some rules about the order in which
>  >  the parent class' initializer methods are invoked.  A couple that come
>  >  to mind:
>  >
>  >  1.  There should only be one initializer method declared per class (to
>  >  avoid the which do we call first problem).
>  >  2.  Parent class' initializer methods should be invoked first.
>  >
>  >  I don't agree that marking "lifecycle" methods with annotations is an
>  >  abuse (of annotations?) at all.  Perhaps this wouldn't belong in the
>  >  "core", but I can see it as an extension or a wicketstuff project
>  >  maybe?
>  >
>
>  I actually played around with this a bit.  I've created an annotation:
>
>  @Retention( RetentionPolicy.RUNTIME)
>  @Target( ElementType.METHOD)
>  public @interface Initialization
>  {
>  }
>
>  Then, I created the listener:
>
>  public class InitializationInstantiationListener implements
>  IComponentInstantiationListener
>  {
>  
> //**********************************************************************************************************************
>  // Fields
>  
> //**********************************************************************************************************************
>
>     private final Map<Class, Initializer> initializersMap = new
>  HashMap<Class, Initializer>();
>
>  
> //**********************************************************************************************************************
>  // IComponentInstantiationListener Implementation
>  
> //**********************************************************************************************************************
>
>
>     public void onInstantiation( Component component )
>     {
>         Initializer initializer = getInitializer(component);
>         initializer.initialize(component);
>     }
>
>     private synchronized Initializer getInitializer( Component component )
>     {
>         final Class<? extends Component> componentClass = 
> component.getClass();
>         Initializer initializer = initializersMap.get(componentClass);
>         if( initializer == null )
>         {
>             final List<Method> initializationMethods =
>  getInitializationMethods(component);
>             initializer = createInitializer(componentClass,
>  initializationMethods);
>             initializersMap.put(componentClass, initializer);
>         }
>         return initializer;
>     }
>
>  
> //**********************************************************************************************************************
>  // Other Methods
>  
> //**********************************************************************************************************************
>
>     private synchronized List<Method> getInitializationMethods(
>  Component component )
>     {
>         List<Method> initializationMethods = new LinkedList<Method>();
>         Class c = component.getClass();
>         while( c != null )
>         {
>             Method initializer = getInitializationMethod(c);
>             if( initializer != null )
>             {
>                 initializationMethods.add(0, initializer);
>             }
>             c = c.getSuperclass();
>         }
>         return initializationMethods;
>     }
>
>     private Method getInitializationMethod( Class c )
>     {
>         Set<Method> initializers = new HashSet<Method>();
>         final Method[] declaredMethods = c.getDeclaredMethods();
>         for( Method declaredMethod : declaredMethods )
>         {
>             if( declaredMethod.getAnnotation(Initialization.class) != null )
>             {
>                 if( Modifier.isPublic(declaredMethod.getModifiers()) &&
>                         Void.TYPE.equals(declaredMethod.getReturnType()) &&
>                         declaredMethod.getParameterTypes().length == 0 )
>                 {
>                     initializers.add(declaredMethod);
>                 }
>                 else
>                 {
>                     throw new WicketRuntimeException("Invalid
>  initializer method declared on class " + c.getName() +
>                             ".  Initializers must be public, have a
>  void return type, and take no parameters.");
>                 }
>             }
>         }
>         switch( initializers.size() )
>         {
>             case 1:
>                 return initializers.iterator().next();
>             case 0:
>                 return null;
>             default:
>                 throw new WicketRuntimeException("Class " +
>  c.getName() + " declares multiple (" + initializers.size() +
>                         ") initializer methods.");
>         }
>     }
>
>     protected Initializer createInitializer( Class componentClass,
>  List<Method> initializationMethods )
>     {
>         return initializationMethods.isEmpty() ? new NullInitializer()
>  : new ReflectionInitializer(initializationMethods);
>     }
>
>  
> //**********************************************************************************************************************
>  // Inner Classes
>  
> //**********************************************************************************************************************
>
>     protected static interface Initializer
>     {
>         public void initialize( Component component );
>     }
>
>     protected static class NullInitializer implements Initializer
>     {
>         public void initialize( Component component )
>         {
>             // Do nothing!
>         }
>     }
>
>     protected static class ReflectionInitializer implements Initializer
>     {
>         private final List<Method> initializationMethods;
>
>         public ReflectionInitializer( List<Method> initializationMethods )
>         {
>             this.initializationMethods = initializationMethods;
>         }
>
>         public void initialize( Component component )
>         {
>             for( Method initializationMethod : initializationMethods )
>             {
>                 try
>                 {
>                     initializationMethod.invoke(component);
>                 }
>                 catch( IllegalAccessException e )
>                 {
>                     throw new WicketRuntimeException("Failed to invoke
>  initializer method " + initializationMethod.getName() +
>                             " on component of type " +
>  component.getClass().getName() + ".", e);
>                 }
>                 catch( InvocationTargetException e )
>                 {
>                     throw new WicketRuntimeException("Failed to invoke
>  initializer method " + initializationMethod.getName() +
>                             " on component of type " +
>  component.getClass().getName() + ".", e);
>                 }
>             }
>         }
>     }
>  }
>
>  If one really wanted to, they could override the createInitializer()
>  method to provide the capability of dynamically generating a class at
>  runtime which merely invokes the initialization methods on the
>  component (using Javassist perhaps).  This class basically enforces
>  the two simple rules I mentioned before.
>
>
>
>  ---------------------------------------------------------------------
>  To unsubscribe, e-mail: [EMAIL PROTECTED]
>  For additional commands, e-mail: [EMAIL PROTECTED]
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to