You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Jesse Kuhnert <jk...@gmail.com> on 2006/07/08 19:51:14 UTC

Re: svn commit: r420171 - in /tapestry/tapestry5/tapestry-core/trunk/src: main/java/org/apache/tapestry/internal/ioc/ main/java/org/apache/tapestry/ioc/ main/resources/org/apache/tapestry/internal/ioc/ test/java/org/apache/tapestry/internal/ioc/ test

"Big surprise", I like the direction you are going in with this..

(I promise I'm not a constant positive "cheerleader", when/if I ever see
something I don't agree with I'll pipe up, just haven't had it happen yet.
(happily) )

On 7/8/06, hlship@apache.org <hl...@apache.org> wrote:
>
> Author: hlship
> Date: Sat Jul  8 10:44:05 2006
> New Revision: 420171
>
> URL: http://svn.apache.org/viewvc?rev=420171&view=rev
> Log:
> Move proxy creation code into ModuleImpl.
>
> Added:
>
>     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java
> Removed:
>
>     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/PrimitiveServiceLifecycle.java
> Modified:
>
>     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
>
>     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
>
>     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
>
>     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
>
>     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
>
>     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java
>
>     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java
>
>     tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
>
>     tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java
>
>     tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTestModule.java
>
>     tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycleTest.java
>
>     tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/RegistryBuilderTest.java
>
> Modified:
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java?rev=420171&r1=420170&r2=420171&view=diff
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
> (original)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
> Sat Jul  8 10:44:05 2006
> @@ -80,9 +80,9 @@
>                  .format("instantiate-builder-error", builderClass.getName(),
> moduleId, cause);
>      }
>
> -    static String singletonProxyToString(String serviceId, Class
> serviceInterface)
> +    static String proxyToString(String serviceId, Class serviceInterface)
>      {
> -        return MESSAGES.format("singleton-proxy-to-string", serviceId,
> serviceInterface.getName());
> +        return MESSAGES.format("proxy-to-string", serviceId,
> serviceInterface.getName());
>      }
>
>      static String builderMethodError(Method m, String serviceId,
> Throwable cause)
>
> Added:
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java?rev=420171&view=auto
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java
> (added)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java
> Sat Jul  8 10:44:05 2006
> @@ -0,0 +1,53 @@
> +// Copyright 2006 The Apache Software Foundation
> +//
> +// Licensed under the Apache License, Version 2.0 (the "License");
> +// you may not use this file except in compliance with the License.
> +// You may obtain a copy of the License at
> +//
> +//     http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing, software
> +// distributed under the License is distributed on an "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> +// See the License for the specific language governing permissions and
> +// limitations under the License.
> +
> +package org.apache.tapestry.internal.ioc;
> +
> +import org.apache.tapestry.ioc.ServiceCreator;
> +import org.apache.tapestry.ioc.ServiceLifecycle;
> +import org.apache.tapestry.ioc.ServiceResources;
> +
> +/**
> + * Wrapper around a lifecycle, a set of resources for a service, and an
> underlying service creator
> + * for a service that allows the service lifecycle to alter the way that
> the service is created
> + * (this is needed for the more advanced, non-singleton types of service
> lifecycles).
> + *
> + * @author Howard M. Lewis Ship
> + */
> +public class LifecycleWrappedServiceCreator implements ServiceCreator
> +{
> +    private final ServiceLifecycle _lifecycle;
> +
> +    private final ServiceResources _resources;
> +
> +    private final ServiceCreator _creator;
> +
> +    public LifecycleWrappedServiceCreator(ServiceLifecycle lifecycle,
> ServiceResources resources,
> +            ServiceCreator creator)
> +    {
> +        _lifecycle = lifecycle;
> +        _resources = resources;
> +        _creator = creator;
> +    }
> +
> +    /**
> +     * Passes the resources and the service creator through the
> +     * {@link org.apache.tapestry.ioc.ServiceLifecycle}.
> +     */
> +    public Object createService()
> +    {
> +        return _lifecycle.createService(_resources, _creator);
> +    }
> +
> +}
>
> Modified:
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java?rev=420171&r1=420170&r2=420171&view=diff
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
> (original)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
> Sat Jul  8 10:44:05 2006
> @@ -14,10 +14,18 @@
>
> package org.apache.tapestry.internal.ioc;
>
> +import java.lang.reflect.Modifier;
> import java.util.Collection;
> import java.util.Map;
>
> +import org.apache.hivemind.service.BodyBuilder;
> +import org.apache.hivemind.service.ClassFab;
> +import org.apache.hivemind.service.ClassFabUtils;
> +import org.apache.hivemind.service.ClassFactory;
> +import org.apache.hivemind.service.MethodIterator;
> +import org.apache.hivemind.service.MethodSignature;
> import org.apache.tapestry.internal.annotations.SuppressNullCheck;
> +import org.apache.tapestry.ioc.IOCConstants;
> import org.apache.tapestry.ioc.ServiceCreator;
> import org.apache.tapestry.ioc.ServiceLifecycle;
> import org.apache.tapestry.ioc.ServiceResources;
> @@ -157,16 +165,123 @@
>
>          ServiceResources resources = new ServiceResourcesImpl(_registry,
> this, def);
>
> -        ServiceCreator creator = new BasicServiceCreator(def,
> _moduleBuilder, resources);
> +        ServiceCreator creator = new
> LifecycleWrappedServiceCreator(lifecycle, resources,
> +                new BasicServiceCreator(def, _moduleBuilder, resources));
>
>          // TODO: Somewhere, in here, we have to add a chance for
> decorators to
>          // create interceptors for the service.
>
> -        Object service = lifecycle.createService(resources, creator);
> +        // For primitive services, we just create the service right here.
> For non-primitive services
> +        Object service = lifecycle.getCreateProxy() ?
> createProxy(resources, creator) : creator
> +                .createService();
>
>          _services.put(def.getServiceId(), service);
>
>          return service;
>      }
>
> +    private Object createProxy(ServiceResources resources, ServiceCreator
> creator)
> +    {
> +        String serviceId = resources.getServiceId();
> +        Class serviceInterface = resources.getServiceInterface();
> +
> +        String description = IOCMessages.proxyToString(serviceId,
> serviceInterface);
> +
> +        return createProxyInstance(creator, serviceId, serviceInterface,
> description);
> +    }
> +
> +    private Object createProxyInstance(ServiceCreator creator, String
> serviceId,
> +            Class serviceInterface, String description)
> +    {
> +        Class proxyClass = createProxyClass(serviceId, serviceInterface,
> description);
> +
> +        try
> +        {
> +            return proxyClass.getConstructors()[0].newInstance(creator);
> +        }
> +        catch (Exception ex)
> +        {
> +            // This should never happen, so we won't go to a lot of
> trouble
> +            // reporting it.
> +            throw new RuntimeException(ex.getMessage(), ex);
> +        }
> +    }
> +
> +    private Class createProxyClass(String serviceId, Class
> serviceInterface, String proxyDescription)
> +    {
> +
> +        String name = ClassFabUtils.generateClassName(serviceInterface);
> +
> +        ClassFactory factory = _registry.getService(
> +                IOCConstants.CLASS_FACTORY_SERVICE_ID,
> +                ClassFactory.class,
> +                this);
> +
> +        ClassFab cf = factory.newClass(name, Object.class);
> +
> +        addInfrastructure(cf, serviceInterface);
> +
> +        addDelegateGetter(cf, serviceInterface);
> +
> +        addServiceMethods(cf, serviceId, serviceInterface,
> proxyDescription);
> +
> +        return cf.createClass();
> +    }
> +
> +    private void addServiceMethods(ClassFab cf, String serviceId, Class
> serviceInterface,
> +            String proxyDescription)
> +    {
> +        MethodIterator mi = new MethodIterator(serviceInterface);
> +
> +        while (mi.hasNext())
> +        {
> +            MethodSignature sig = mi.next();
> +
> +            // Make each method in the proxy delegates to the service
> implementation (or outermost
> +            // interceptor). The "($r)" cast is magic for converting to
> the return type and
> +            // understands void methods. The "$$" is just the list of
> method arguments.
> +
> +            String body = "return ($r) _delegate()." + sig.getName() +
> "($$);";
> +
> +            cf.addMethod(Modifier.PUBLIC, sig, body);
> +        }
> +
> +        // If toString() is not part of the service interface, then add a
> toString()
> +        // to the class. Objects visible to client code need a toString()
> to help
> +        // with debugging.
> +
> +        if (!mi.getToString())
> +            ClassFabUtils.addToStringMethod(cf, proxyDescription);
> +    }
> +
> +    private void addDelegateGetter(ClassFab cf, Class serviceInterface)
> +    {
> +        BodyBuilder builder = new BodyBuilder();
> +        builder.begin();
> +
> +        // We can release the creator after invoking it, we only create
> the service once.
> +
> +        builder.addln("if (_delegate == null)");
> +        builder.begin();
> +        builder.addln("_delegate = ({0}) _creator.createService();",
> serviceInterface.getName());
> +        builder.addln("_creator = null;");
> +        builder.end();
> +
> +        builder.addln("return _delegate;");
> +        builder.end();
> +
> +        MethodSignature sig = new MethodSignature(serviceInterface,
> "_delegate", null, null);
> +
> +        cf.addMethod(Modifier.PRIVATE | Modifier.SYNCHRONIZED, sig,
> builder.toString());
> +    }
> +
> +    private void addInfrastructure(ClassFab cf, Class serviceInterface)
> +    {
> +        cf.addInterface(serviceInterface);
> +        cf.addField("_delegate", serviceInterface);
> +        cf.addField("_creator", ServiceCreator.class);
> +
> +        cf.addConstructor(new Class[]
> +        { ServiceCreator.class }, null, "_creator = $1;");
> +    }
> }
>
> Modified:
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java?rev=420171&r1=420170&r2=420171&view=diff
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
> (original)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
> Sat Jul  8 10:44:05 2006
> @@ -125,7 +125,7 @@
>      {
>          ServiceLifecycle result = _lifecycles.get(lifecycle);
>
> -        // TODO: Check elsewhere for contributed lifecycles
> +        // TODO: Check elsewhere for contributed lifecycles if not one of
> the builtin lifecycle
>
>          if (result == null)
>              throw new RuntimeException(IOCMessages.unknownLifecycle
> (lifecycle));
>
> Modified:
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java?rev=420171&r1=420170&r2=420171&view=diff
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
> (original)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
> Sat Jul  8 10:44:05 2006
> @@ -14,121 +14,27 @@
>
> package org.apache.tapestry.internal.ioc;
>
> -import java.lang.reflect.Modifier;
> -
> -import org.apache.hivemind.service.BodyBuilder;
> -import org.apache.hivemind.service.ClassFab;
> -import org.apache.hivemind.service.ClassFabUtils;
> -import org.apache.hivemind.service.ClassFactory;
> -import org.apache.hivemind.service.MethodIterator;
> -import org.apache.hivemind.service.MethodSignature;
> -import org.apache.tapestry.ioc.IOCConstants;
> import org.apache.tapestry.ioc.ServiceCreator;
> import org.apache.tapestry.ioc.ServiceLifecycle;
> import org.apache.tapestry.ioc.ServiceResources;
>
> /**
> - * The basic implementation of a service lifecycle, which provides for a
> proxy that forces the
> - * creation of the real service when a method is invoked on the proxy.
> + * The basic implementation of a service lifecycle, which simply uses the
> + * {@link org.apache.tapestry.ioc.ServiceCreator} to create an instance
> of the service when asked.
>   *
>   * @author Howard M. Lewis Ship
>   */
> public class SingletonServiceLifecycle implements ServiceLifecycle
> {
> -    public Object createService(ServiceResources resources,
> ServiceCreator creator)
> -    {
> -        Class proxyClass = createProxyClass(resources);
> -
> -        try
> -        {
> -            return proxyClass.getConstructors()[0].newInstance(creator);
> -        }
> -        catch (Exception ex)
> -        {
> -            // This should never happen, so we won't go to a lot of
> trouble
> -            // reporting it.
> -            throw new RuntimeException(ex.getMessage(), ex);
> -        }
> -    }
> -
> -    private Class createProxyClass(ServiceResources resources)
> -    {
> -        String serviceId = resources.getServiceId();
> -        Class serviceInterface = resources.getServiceInterface();
> -
> -        String name = ClassFabUtils.generateClassName(serviceInterface);
> -
> -        ClassFactory factory = resources.getService(
> -                IOCConstants.CLASS_FACTORY_SERVICE_ID,
> -                ClassFactory.class);
> -
> -        ClassFab cf = factory.newClass(name, Object.class);
> -
> -        addInfrastructure(cf, serviceInterface);
> -
> -        addDelegateGetter(cf, serviceInterface);
> -
> -        addServiceMethods(cf, serviceId, serviceInterface);
> -
> -        return cf.createClass();
> -    }
> -
> -    private void addServiceMethods(ClassFab cf, String serviceId, Class
> serviceInterface)
> -    {
> -        MethodIterator mi = new MethodIterator(serviceInterface);
> -
> -        while (mi.hasNext())
> -        {
> -            MethodSignature sig = mi.next();
> -
> -            // Make each method in the proxy delegates to the service
> implementation (or outermost
> -            // interceptor). The "($r)" cast is magic for converting to
> the return type and
> -            // understands void methods. The "$$" is just the list of
> method arguments.
> -
> -            String body = "return ($r) _delegate()." + sig.getName() +
> "($$);";
> -
> -            cf.addMethod(Modifier.PUBLIC, sig, body);
> -        }
> -
> -        // If toString() is not part of the service interface, then add a
> toString()
> -        // to the class. Objects visible to client code need a toString()
> to help
> -        // with debugging.
> -
> -        if (!mi.getToString())
> -            ClassFabUtils.addToStringMethod(cf,
> IOCMessages.singletonProxyToString(
> -                    serviceId,
> -                    serviceInterface));
> -    }
>
> -    private void addDelegateGetter(ClassFab cf, Class serviceInterface)
> +    /** Returns true. */
> +    public boolean getCreateProxy()
>      {
> -        BodyBuilder builder = new BodyBuilder();
> -        builder.begin();
> -
> -        // We can release the creator after invoking it, we only create
> the service once.
> -
> -        builder.addln("if (_delegate == null)");
> -        builder.begin();
> -        builder.addln("_delegate = ({0}) _creator.createService();",
> serviceInterface.getName());
> -        builder.addln("_creator = null;");
> -        builder.end();
> -
> -        builder.addln("return _delegate;");
> -        builder.end();
> -
> -        MethodSignature sig = new MethodSignature(serviceInterface,
> "_delegate", null, null);
> -
> -        cf.addMethod(Modifier.PRIVATE | Modifier.SYNCHRONIZED, sig,
> builder.toString());
> +        return true;
>      }
>
> -    private void addInfrastructure(ClassFab cf, Class serviceInterface)
> +    public Object createService(ServiceResources resources,
> ServiceCreator creator)
>      {
> -        cf.addInterface(serviceInterface);
> -        cf.addField("_delegate", serviceInterface);
> -        cf.addField("_creator", ServiceCreator.class);
> -
> -        cf.addConstructor(new Class[]
> -        { ServiceCreator.class }, null, "_creator = $1;");
> +        return creator.createService();
>      }
> -
> }
>
> Modified:
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java?rev=420171&r1=420170&r2=420171&view=diff
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
> (original)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
> Sat Jul  8 10:44:05 2006
> @@ -81,9 +81,13 @@
>          _modules.put(id, moduleDef);
>      }
>
> -    public void add(Class moduleBuilderClass)
> +    public void add(Class... moduleBuilderClasses)
>      {
> -        add(new DefaultModuleDefImpl(moduleBuilderClass, _errorLog));
> +        for (Class c : moduleBuilderClasses)
> +        {
> +            ModuleDef def = new DefaultModuleDefImpl(c, _errorLog);
> +            add(def);
> +        }
>      }
>
>      public void add(String classname)
>
> Modified:
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java?rev=420171&r1=420170&r2=420171&view=diff
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java
> (original)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java
> Sat Jul  8 10:44:05 2006
> @@ -14,8 +14,6 @@
>
> package org.apache.tapestry.ioc;
>
> -import org.apache.tapestry.internal.ioc.SingletonServiceLifecycle;
> -
> /**
>   * Interface used to encapsulate any strategy used to obtain a service
> implementation (the real
>   * service implementation, not a proxy) on demand.
>
> Modified:
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java?rev=420171&r1=420170&r2=420171&view=diff
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java
> (original)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java
> Sat Jul  8 10:44:05 2006
> @@ -15,26 +15,33 @@
> package org.apache.tapestry.ioc;
>
> /**
> - * A strategy for creating a service when first referenced. Most
> implementations create a proxy to
> - * the service, and defer the creation of the actual service
> implementation until needed. Service
> - * lifecycles represent a <em>stateless</em> strategy, a single instance
> will be shared across
> - * many threads and used to create proxies for many services.
> + * Allows certain types of lifecycles to control exactly how services are
> instantiated.
>   *
>   * @author Howard M. Lewis Ship
>   */
> public interface ServiceLifecycle
> {
>      /**
> -     * Creates the service implementation or, more commonly, creates a
> proxy that will cause the
> -     * service itself to be created as needed.
> +     * Returns the same creator, or a new one, that encapsulates the
>       *
>       * @param resources
>       *            source of information about the service to be created,
> and source of additional
>       *            services or other resources that may be needed when
> constructing the core service
>       *            implementation
>       * @param creator
> -     *            object capable of creating the service implementation
> on demand
> +     *            object capable of creating the service implementation
> on demand. This is a wrapper
> +     *            around the service's builder method.
>       * @return the service or equivalent service proxy
>       */
>      Object createService(ServiceResources resources, ServiceCreator
> creator);
> +
> +    /**
> +     * Returns true if this lifecycle requires a proxy to be generated.
> This is true in nearly all
> +     * cases. When this is true, first reference to a service does not
> create the service, but
> +     * creates a proxy that defers creation of the service until a method
> of the service is invoked.
> +     * When this is false, the {@link #createService(ServiceResources,
> ServiceCreator)} will be
> +     * invoked when the service is first referenced, and is responsible
> for returning an appropriate
> +     * service or proxy.
> +     */
> +    boolean getCreateProxy();
> }
>
> Modified:
> tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties?rev=420171&r1=420170&r2=420171&view=diff
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
> (original)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
> Sat Jul  8 10:44:05 2006
> @@ -21,7 +21,7 @@
> no-such-module=Module ''{0}'' does not exist. Please ensure that the JAR
> file for the module is on the classpath.
> service-wrong-interface=Service ''{0}'' implements interface {1}, which is
> not compatible with the requested type {2}.
> instantiate-builder-error=Unable to instantiate class {0} as builder for
> module ''{1}'': {2}
> -singleton-proxy-to-string=<Singleton proxy for {0}({1})>
> +proxy-to-string=<Proxy for {0}({1})>
> builder-method-error=Error invoking service builder method {0} (for
> service ''{1}''): {2}
> builder-method-returned-null=Builder method {0} (for service ''{1}'')
> returned null.
> service-is-private=Service ''{0}'' is private, and may not be referenced
> outside of its containing module.
>
> Modified:
> tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java?rev=420171&r1=420170&r2=420171&view=diff
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java
> (original)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java
> Sat Jul  8 10:44:05 2006
> @@ -20,6 +20,8 @@
> import org.apache.hivemind.service.impl.ClassFactoryImpl;
> import org.apache.tapestry.internal.test.InternalBaseTestCase;
> import org.apache.tapestry.ioc.ErrorLog;
> +import org.apache.tapestry.ioc.Registry;
> +import org.apache.tapestry.ioc.RegistryBuilder;
> import org.apache.tapestry.ioc.def.ModuleDef;
> import org.testng.annotations.Test;
>
> @@ -141,5 +143,32 @@
>          assertTrue(ids.contains("ioc.test.Upcase"));
>
>          verify();
> +    }
> +
> +    private Registry buildRegistry()
> +    {
> +        RegistryBuilder builder = new RegistryBuilder();
> +        builder.add(TapestryIOCModule.class, ModuleImplTestModule.class);
> +
> +        return builder.build();
> +    }
> +
> +    /** The following tests work better as integration tests. */
> +
> +    @Test
> +    public void integrationTests()
> +    {
> +        Registry registry = buildRegistry();
> +
> +        UpcaseService us = registry.getService(UpcaseService.class);
> +
> +        assertEquals(us.upcase("hello"), "HELLO");
> +        assertEquals(
> +                us.toString(),
> +                "<Proxy for ioc.test.Upcase(
> org.apache.tapestry.internal.ioc.UpcaseService)>");
> +
> +        ToStringService ts = registry.getService(ToStringService.class);
> +
> +        assertEquals(ts.toString(), "<ToStringService: ioc.test.ToString
> >");
>      }
> }
>
> Modified:
> tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTestModule.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTestModule.java?rev=420171&r1=420170&r2=420171&view=diff
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTestModule.java
> (original)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTestModule.java
> Sat Jul  8 10:44:05 2006
> @@ -36,6 +36,18 @@
>          return new UpcaseServiceImpl();
>      }
>
> +    public ToStringService buildToString(final String serviceId)
> +    {
> +        return new ToStringService()
> +        {
> +            @Override
> +            public String toString()
> +            {
> +                return "<ToStringService: " + serviceId + ">";
> +            }
> +        };
> +    }
> +
>      public FieService buildFie()
>      {
>          return null;
>
> Modified:
> tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycleTest.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycleTest.java?rev=420171&r1=420170&r2=420171&view=diff
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycleTest.java
> (original)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycleTest.java
> Sat Jul  8 10:44:05 2006
> @@ -14,117 +14,35 @@
>
> package org.apache.tapestry.internal.ioc;
>
> -import org.apache.hivemind.service.ClassFactory;
> -import org.apache.hivemind.service.impl.ClassFactoryImpl;
> import org.apache.tapestry.internal.test.InternalBaseTestCase;
> -import org.apache.tapestry.ioc.IOCConstants;
> import org.apache.tapestry.ioc.ServiceCreator;
> import org.apache.tapestry.ioc.ServiceLifecycle;
> import org.apache.tapestry.ioc.ServiceResources;
> import org.testng.annotations.Test;
>
> -import static org.testng.Assert.assertEquals;
> +import static org.testng.Assert.assertSame;
>
> /**
>   * @author Howard M. Lewis Ship
>   */
> public class SingletonServiceLifecycleTest extends InternalBaseTestCase
> {
> -    private static final String UPCASE_SERVICE_ID = "ioc.Upcase";
> -
> -    private static final String TO_STRING_SERVICE_ID = "ioc.ToString";
> -
>      @Test
> -    public void basic()
> +    public void test()
>      {
>          ServiceResources resources = newServiceResources();
>          ServiceCreator creator = newServiceCreator();
> -        UpcaseService service = newMock(UpcaseService.class);
> -
> -        ClassFactory cf = new ClassFactoryImpl();
> -
> -        trainGetServiceId(resources, UPCASE_SERVICE_ID);
> -
> -        trainGetServiceInterface(resources, UpcaseService.class);
> -
> -        trainGetService(resources, IOCConstants.CLASS_FACTORY_SERVICE_ID,
> ClassFactory.class, cf);
> -
> -        replay();
> -
> -        ServiceLifecycle lf = new SingletonServiceLifecycle();
> -
> -        UpcaseService proxy = (UpcaseService) lf.createService(resources,
> creator);
> -
> -        verify();
> -
> -        assertEquals(
> -                proxy.toString(),
> -                "<Singleton proxy for ioc.Upcase(
> org.apache.tapestry.internal.ioc.UpcaseService)>");
> -
> -        // Now to test when the creator gets invoked
> -
> -        trainCreateService(creator, service);
> -
> -        service.upcase("hello");
> -        setReturnValue("HELLO");
> -
> -        replay();
> -
> -        assertEquals(proxy.upcase("hello"), "HELLO");
> -
> -        verify();
> -
> -        // Now test that the creator is not used again
> -
> -        service.upcase("bye");
> -        setReturnValue("BYE");
> -
> -        replay();
> -
> -        assertEquals(proxy.upcase("bye"), "BYE");
> -
> -        verify();
> -    }
> -
> -    @Test
> -    public void toStringService()
> -    {
> -        ServiceResources resources = newServiceResources();
> -        ServiceCreator creator = newServiceCreator();
> -        ToStringService service = new ToStringService()
> -        {
> -            @Override
> -            public String toString()
> -            {
> -                return "ToStringService";
> -            }
> -        };
> -
> -        ClassFactory cf = new ClassFactoryImpl();
> -
> -        trainGetServiceId(resources, TO_STRING_SERVICE_ID);
> -
> -        trainGetServiceInterface(resources, ToStringService.class);
> -
> -        trainGetService(resources, IOCConstants.CLASS_FACTORY_SERVICE_ID,
> ClassFactory.class, cf);
> -
> -        replay();
> -
> -        ServiceLifecycle lf = new SingletonServiceLifecycle();
> -
> -        ToStringService proxy = (ToStringService) lf.createService(resources,
> creator);
> -
> -        verify();
> +        Object expected = new Object();
>
> -        trainCreateService(creator, service);
> +        trainCreateService(creator, expected);
>
>          replay();
>
> -        assertEquals(proxy.toString(), "ToStringService");
> +        ServiceLifecycle lifecycle = new SingletonServiceLifecycle();
>
> -        // Now test that the creator is not used again
> +        Object actual = lifecycle.createService(resources, creator);
>
> -        assertEquals(proxy.toString(), "ToStringService");
> +        assertSame(actual, expected);
>
>          verify();
>      }
>
> Modified:
> tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/RegistryBuilderTest.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/RegistryBuilderTest.java?rev=420171&r1=420170&r2=420171&view=diff
>
> ==============================================================================
> ---
> tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/RegistryBuilderTest.java
> (original)
> +++
> tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/RegistryBuilderTest.java
> Sat Jul  8 10:44:05 2006
> @@ -19,7 +19,6 @@
> import org.apache.hivemind.service.ClassFactory;
> import org.apache.tapestry.internal.ioc.TapestryIOCModule;
> import org.apache.tapestry.internal.test.InternalBaseTestCase;
> -import org.testng.Assert;
> import org.testng.annotations.Test;
>
> import static org.testng.Assert.assertEquals;
>
>
>


-- 
Jesse Kuhnert
Tacos/Tapestry, team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind.

Re: svn commit: r420171 - in /tapestry/tapestry5/tapestry-core/trunk/src: main/java/org/apache/tapestry/internal/ioc/ main/java/org/apache/tapestry/ioc/ main/resources/org/apache/tapestry/internal/ioc/ test/java/org/apache/tapestry/internal/ioc/ test

Posted by Howard Lewis Ship <hl...@gmail.com>.
I had an epiphany almost two years ago that all the XML in HiveMind or
Spring was an attempt to create callbacks, of the kind most natural in
Ruby.  That's why Ruby's Needle IoC container is so small and simple.

The module builder, with the service builder callback methods, is
pretty close to Ruby blocks.

Better yet, we can use the type system of Java to streamline things
further, by having the container automatically figure out dependencies
and just pass them in as method parameters.

This style, of an "invisible" container flexibly invoking methods,
driven by annotations, will extend to all aspects of Tapestry 5.

It's also very fast; no time spent loading XML parser classes or
parsing XML documents.

On 7/8/06, Jesse Kuhnert <jk...@gmail.com> wrote:
> "Big surprise", I like the direction you are going in with this..
>
> (I promise I'm not a constant positive "cheerleader", when/if I ever see
> something I don't agree with I'll pipe up, just haven't had it happen yet.
> (happily) )
>
> On 7/8/06, hlship@apache.org <hl...@apache.org> wrote:
> >
> > Author: hlship
> > Date: Sat Jul  8 10:44:05 2006
> > New Revision: 420171
> >
> > URL: http://svn.apache.org/viewvc?rev=420171&view=rev
> > Log:
> > Move proxy creation code into ModuleImpl.
> >
> > Added:
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java
> > Removed:
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/PrimitiveServiceLifecycle.java
> > Modified:
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTestModule.java
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycleTest.java
> >
> >     tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/RegistryBuilderTest.java
> >
> > Modified:
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java?rev=420171&r1=420170&r2=420171&view=diff
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
> > (original)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
> > Sat Jul  8 10:44:05 2006
> > @@ -80,9 +80,9 @@
> >                  .format("instantiate-builder-error", builderClass.getName(),
> > moduleId, cause);
> >      }
> >
> > -    static String singletonProxyToString(String serviceId, Class
> > serviceInterface)
> > +    static String proxyToString(String serviceId, Class serviceInterface)
> >      {
> > -        return MESSAGES.format("singleton-proxy-to-string", serviceId,
> > serviceInterface.getName());
> > +        return MESSAGES.format("proxy-to-string", serviceId,
> > serviceInterface.getName());
> >      }
> >
> >      static String builderMethodError(Method m, String serviceId,
> > Throwable cause)
> >
> > Added:
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java?rev=420171&view=auto
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java
> > (added)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java
> > Sat Jul  8 10:44:05 2006
> > @@ -0,0 +1,53 @@
> > +// Copyright 2006 The Apache Software Foundation
> > +//
> > +// Licensed under the Apache License, Version 2.0 (the "License");
> > +// you may not use this file except in compliance with the License.
> > +// You may obtain a copy of the License at
> > +//
> > +//     http://www.apache.org/licenses/LICENSE-2.0
> > +//
> > +// Unless required by applicable law or agreed to in writing, software
> > +// distributed under the License is distributed on an "AS IS" BASIS,
> > +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> > implied.
> > +// See the License for the specific language governing permissions and
> > +// limitations under the License.
> > +
> > +package org.apache.tapestry.internal.ioc;
> > +
> > +import org.apache.tapestry.ioc.ServiceCreator;
> > +import org.apache.tapestry.ioc.ServiceLifecycle;
> > +import org.apache.tapestry.ioc.ServiceResources;
> > +
> > +/**
> > + * Wrapper around a lifecycle, a set of resources for a service, and an
> > underlying service creator
> > + * for a service that allows the service lifecycle to alter the way that
> > the service is created
> > + * (this is needed for the more advanced, non-singleton types of service
> > lifecycles).
> > + *
> > + * @author Howard M. Lewis Ship
> > + */
> > +public class LifecycleWrappedServiceCreator implements ServiceCreator
> > +{
> > +    private final ServiceLifecycle _lifecycle;
> > +
> > +    private final ServiceResources _resources;
> > +
> > +    private final ServiceCreator _creator;
> > +
> > +    public LifecycleWrappedServiceCreator(ServiceLifecycle lifecycle,
> > ServiceResources resources,
> > +            ServiceCreator creator)
> > +    {
> > +        _lifecycle = lifecycle;
> > +        _resources = resources;
> > +        _creator = creator;
> > +    }
> > +
> > +    /**
> > +     * Passes the resources and the service creator through the
> > +     * {@link org.apache.tapestry.ioc.ServiceLifecycle}.
> > +     */
> > +    public Object createService()
> > +    {
> > +        return _lifecycle.createService(_resources, _creator);
> > +    }
> > +
> > +}
> >
> > Modified:
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java?rev=420171&r1=420170&r2=420171&view=diff
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
> > (original)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
> > Sat Jul  8 10:44:05 2006
> > @@ -14,10 +14,18 @@
> >
> > package org.apache.tapestry.internal.ioc;
> >
> > +import java.lang.reflect.Modifier;
> > import java.util.Collection;
> > import java.util.Map;
> >
> > +import org.apache.hivemind.service.BodyBuilder;
> > +import org.apache.hivemind.service.ClassFab;
> > +import org.apache.hivemind.service.ClassFabUtils;
> > +import org.apache.hivemind.service.ClassFactory;
> > +import org.apache.hivemind.service.MethodIterator;
> > +import org.apache.hivemind.service.MethodSignature;
> > import org.apache.tapestry.internal.annotations.SuppressNullCheck;
> > +import org.apache.tapestry.ioc.IOCConstants;
> > import org.apache.tapestry.ioc.ServiceCreator;
> > import org.apache.tapestry.ioc.ServiceLifecycle;
> > import org.apache.tapestry.ioc.ServiceResources;
> > @@ -157,16 +165,123 @@
> >
> >          ServiceResources resources = new ServiceResourcesImpl(_registry,
> > this, def);
> >
> > -        ServiceCreator creator = new BasicServiceCreator(def,
> > _moduleBuilder, resources);
> > +        ServiceCreator creator = new
> > LifecycleWrappedServiceCreator(lifecycle, resources,
> > +                new BasicServiceCreator(def, _moduleBuilder, resources));
> >
> >          // TODO: Somewhere, in here, we have to add a chance for
> > decorators to
> >          // create interceptors for the service.
> >
> > -        Object service = lifecycle.createService(resources, creator);
> > +        // For primitive services, we just create the service right here.
> > For non-primitive services
> > +        Object service = lifecycle.getCreateProxy() ?
> > createProxy(resources, creator) : creator
> > +                .createService();
> >
> >          _services.put(def.getServiceId(), service);
> >
> >          return service;
> >      }
> >
> > +    private Object createProxy(ServiceResources resources, ServiceCreator
> > creator)
> > +    {
> > +        String serviceId = resources.getServiceId();
> > +        Class serviceInterface = resources.getServiceInterface();
> > +
> > +        String description = IOCMessages.proxyToString(serviceId,
> > serviceInterface);
> > +
> > +        return createProxyInstance(creator, serviceId, serviceInterface,
> > description);
> > +    }
> > +
> > +    private Object createProxyInstance(ServiceCreator creator, String
> > serviceId,
> > +            Class serviceInterface, String description)
> > +    {
> > +        Class proxyClass = createProxyClass(serviceId, serviceInterface,
> > description);
> > +
> > +        try
> > +        {
> > +            return proxyClass.getConstructors()[0].newInstance(creator);
> > +        }
> > +        catch (Exception ex)
> > +        {
> > +            // This should never happen, so we won't go to a lot of
> > trouble
> > +            // reporting it.
> > +            throw new RuntimeException(ex.getMessage(), ex);
> > +        }
> > +    }
> > +
> > +    private Class createProxyClass(String serviceId, Class
> > serviceInterface, String proxyDescription)
> > +    {
> > +
> > +        String name = ClassFabUtils.generateClassName(serviceInterface);
> > +
> > +        ClassFactory factory = _registry.getService(
> > +                IOCConstants.CLASS_FACTORY_SERVICE_ID,
> > +                ClassFactory.class,
> > +                this);
> > +
> > +        ClassFab cf = factory.newClass(name, Object.class);
> > +
> > +        addInfrastructure(cf, serviceInterface);
> > +
> > +        addDelegateGetter(cf, serviceInterface);
> > +
> > +        addServiceMethods(cf, serviceId, serviceInterface,
> > proxyDescription);
> > +
> > +        return cf.createClass();
> > +    }
> > +
> > +    private void addServiceMethods(ClassFab cf, String serviceId, Class
> > serviceInterface,
> > +            String proxyDescription)
> > +    {
> > +        MethodIterator mi = new MethodIterator(serviceInterface);
> > +
> > +        while (mi.hasNext())
> > +        {
> > +            MethodSignature sig = mi.next();
> > +
> > +            // Make each method in the proxy delegates to the service
> > implementation (or outermost
> > +            // interceptor). The "($r)" cast is magic for converting to
> > the return type and
> > +            // understands void methods. The "$$" is just the list of
> > method arguments.
> > +
> > +            String body = "return ($r) _delegate()." + sig.getName() +
> > "($$);";
> > +
> > +            cf.addMethod(Modifier.PUBLIC, sig, body);
> > +        }
> > +
> > +        // If toString() is not part of the service interface, then add a
> > toString()
> > +        // to the class. Objects visible to client code need a toString()
> > to help
> > +        // with debugging.
> > +
> > +        if (!mi.getToString())
> > +            ClassFabUtils.addToStringMethod(cf, proxyDescription);
> > +    }
> > +
> > +    private void addDelegateGetter(ClassFab cf, Class serviceInterface)
> > +    {
> > +        BodyBuilder builder = new BodyBuilder();
> > +        builder.begin();
> > +
> > +        // We can release the creator after invoking it, we only create
> > the service once.
> > +
> > +        builder.addln("if (_delegate == null)");
> > +        builder.begin();
> > +        builder.addln("_delegate = ({0}) _creator.createService();",
> > serviceInterface.getName());
> > +        builder.addln("_creator = null;");
> > +        builder.end();
> > +
> > +        builder.addln("return _delegate;");
> > +        builder.end();
> > +
> > +        MethodSignature sig = new MethodSignature(serviceInterface,
> > "_delegate", null, null);
> > +
> > +        cf.addMethod(Modifier.PRIVATE | Modifier.SYNCHRONIZED, sig,
> > builder.toString());
> > +    }
> > +
> > +    private void addInfrastructure(ClassFab cf, Class serviceInterface)
> > +    {
> > +        cf.addInterface(serviceInterface);
> > +        cf.addField("_delegate", serviceInterface);
> > +        cf.addField("_creator", ServiceCreator.class);
> > +
> > +        cf.addConstructor(new Class[]
> > +        { ServiceCreator.class }, null, "_creator = $1;");
> > +    }
> > }
> >
> > Modified:
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java?rev=420171&r1=420170&r2=420171&view=diff
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
> > (original)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
> > Sat Jul  8 10:44:05 2006
> > @@ -125,7 +125,7 @@
> >      {
> >          ServiceLifecycle result = _lifecycles.get(lifecycle);
> >
> > -        // TODO: Check elsewhere for contributed lifecycles
> > +        // TODO: Check elsewhere for contributed lifecycles if not one of
> > the builtin lifecycle
> >
> >          if (result == null)
> >              throw new RuntimeException(IOCMessages.unknownLifecycle
> > (lifecycle));
> >
> > Modified:
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java?rev=420171&r1=420170&r2=420171&view=diff
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
> > (original)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
> > Sat Jul  8 10:44:05 2006
> > @@ -14,121 +14,27 @@
> >
> > package org.apache.tapestry.internal.ioc;
> >
> > -import java.lang.reflect.Modifier;
> > -
> > -import org.apache.hivemind.service.BodyBuilder;
> > -import org.apache.hivemind.service.ClassFab;
> > -import org.apache.hivemind.service.ClassFabUtils;
> > -import org.apache.hivemind.service.ClassFactory;
> > -import org.apache.hivemind.service.MethodIterator;
> > -import org.apache.hivemind.service.MethodSignature;
> > -import org.apache.tapestry.ioc.IOCConstants;
> > import org.apache.tapestry.ioc.ServiceCreator;
> > import org.apache.tapestry.ioc.ServiceLifecycle;
> > import org.apache.tapestry.ioc.ServiceResources;
> >
> > /**
> > - * The basic implementation of a service lifecycle, which provides for a
> > proxy that forces the
> > - * creation of the real service when a method is invoked on the proxy.
> > + * The basic implementation of a service lifecycle, which simply uses the
> > + * {@link org.apache.tapestry.ioc.ServiceCreator} to create an instance
> > of the service when asked.
> >   *
> >   * @author Howard M. Lewis Ship
> >   */
> > public class SingletonServiceLifecycle implements ServiceLifecycle
> > {
> > -    public Object createService(ServiceResources resources,
> > ServiceCreator creator)
> > -    {
> > -        Class proxyClass = createProxyClass(resources);
> > -
> > -        try
> > -        {
> > -            return proxyClass.getConstructors()[0].newInstance(creator);
> > -        }
> > -        catch (Exception ex)
> > -        {
> > -            // This should never happen, so we won't go to a lot of
> > trouble
> > -            // reporting it.
> > -            throw new RuntimeException(ex.getMessage(), ex);
> > -        }
> > -    }
> > -
> > -    private Class createProxyClass(ServiceResources resources)
> > -    {
> > -        String serviceId = resources.getServiceId();
> > -        Class serviceInterface = resources.getServiceInterface();
> > -
> > -        String name = ClassFabUtils.generateClassName(serviceInterface);
> > -
> > -        ClassFactory factory = resources.getService(
> > -                IOCConstants.CLASS_FACTORY_SERVICE_ID,
> > -                ClassFactory.class);
> > -
> > -        ClassFab cf = factory.newClass(name, Object.class);
> > -
> > -        addInfrastructure(cf, serviceInterface);
> > -
> > -        addDelegateGetter(cf, serviceInterface);
> > -
> > -        addServiceMethods(cf, serviceId, serviceInterface);
> > -
> > -        return cf.createClass();
> > -    }
> > -
> > -    private void addServiceMethods(ClassFab cf, String serviceId, Class
> > serviceInterface)
> > -    {
> > -        MethodIterator mi = new MethodIterator(serviceInterface);
> > -
> > -        while (mi.hasNext())
> > -        {
> > -            MethodSignature sig = mi.next();
> > -
> > -            // Make each method in the proxy delegates to the service
> > implementation (or outermost
> > -            // interceptor). The "($r)" cast is magic for converting to
> > the return type and
> > -            // understands void methods. The "$$" is just the list of
> > method arguments.
> > -
> > -            String body = "return ($r) _delegate()." + sig.getName() +
> > "($$);";
> > -
> > -            cf.addMethod(Modifier.PUBLIC, sig, body);
> > -        }
> > -
> > -        // If toString() is not part of the service interface, then add a
> > toString()
> > -        // to the class. Objects visible to client code need a toString()
> > to help
> > -        // with debugging.
> > -
> > -        if (!mi.getToString())
> > -            ClassFabUtils.addToStringMethod(cf,
> > IOCMessages.singletonProxyToString(
> > -                    serviceId,
> > -                    serviceInterface));
> > -    }
> >
> > -    private void addDelegateGetter(ClassFab cf, Class serviceInterface)
> > +    /** Returns true. */
> > +    public boolean getCreateProxy()
> >      {
> > -        BodyBuilder builder = new BodyBuilder();
> > -        builder.begin();
> > -
> > -        // We can release the creator after invoking it, we only create
> > the service once.
> > -
> > -        builder.addln("if (_delegate == null)");
> > -        builder.begin();
> > -        builder.addln("_delegate = ({0}) _creator.createService();",
> > serviceInterface.getName());
> > -        builder.addln("_creator = null;");
> > -        builder.end();
> > -
> > -        builder.addln("return _delegate;");
> > -        builder.end();
> > -
> > -        MethodSignature sig = new MethodSignature(serviceInterface,
> > "_delegate", null, null);
> > -
> > -        cf.addMethod(Modifier.PRIVATE | Modifier.SYNCHRONIZED, sig,
> > builder.toString());
> > +        return true;
> >      }
> >
> > -    private void addInfrastructure(ClassFab cf, Class serviceInterface)
> > +    public Object createService(ServiceResources resources,
> > ServiceCreator creator)
> >      {
> > -        cf.addInterface(serviceInterface);
> > -        cf.addField("_delegate", serviceInterface);
> > -        cf.addField("_creator", ServiceCreator.class);
> > -
> > -        cf.addConstructor(new Class[]
> > -        { ServiceCreator.class }, null, "_creator = $1;");
> > +        return creator.createService();
> >      }
> > -
> > }
> >
> > Modified:
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java?rev=420171&r1=420170&r2=420171&view=diff
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
> > (original)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
> > Sat Jul  8 10:44:05 2006
> > @@ -81,9 +81,13 @@
> >          _modules.put(id, moduleDef);
> >      }
> >
> > -    public void add(Class moduleBuilderClass)
> > +    public void add(Class... moduleBuilderClasses)
> >      {
> > -        add(new DefaultModuleDefImpl(moduleBuilderClass, _errorLog));
> > +        for (Class c : moduleBuilderClasses)
> > +        {
> > +            ModuleDef def = new DefaultModuleDefImpl(c, _errorLog);
> > +            add(def);
> > +        }
> >      }
> >
> >      public void add(String classname)
> >
> > Modified:
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java?rev=420171&r1=420170&r2=420171&view=diff
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java
> > (original)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java
> > Sat Jul  8 10:44:05 2006
> > @@ -14,8 +14,6 @@
> >
> > package org.apache.tapestry.ioc;
> >
> > -import org.apache.tapestry.internal.ioc.SingletonServiceLifecycle;
> > -
> > /**
> >   * Interface used to encapsulate any strategy used to obtain a service
> > implementation (the real
> >   * service implementation, not a proxy) on demand.
> >
> > Modified:
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java?rev=420171&r1=420170&r2=420171&view=diff
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java
> > (original)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java
> > Sat Jul  8 10:44:05 2006
> > @@ -15,26 +15,33 @@
> > package org.apache.tapestry.ioc;
> >
> > /**
> > - * A strategy for creating a service when first referenced. Most
> > implementations create a proxy to
> > - * the service, and defer the creation of the actual service
> > implementation until needed. Service
> > - * lifecycles represent a <em>stateless</em> strategy, a single instance
> > will be shared across
> > - * many threads and used to create proxies for many services.
> > + * Allows certain types of lifecycles to control exactly how services are
> > instantiated.
> >   *
> >   * @author Howard M. Lewis Ship
> >   */
> > public interface ServiceLifecycle
> > {
> >      /**
> > -     * Creates the service implementation or, more commonly, creates a
> > proxy that will cause the
> > -     * service itself to be created as needed.
> > +     * Returns the same creator, or a new one, that encapsulates the
> >       *
> >       * @param resources
> >       *            source of information about the service to be created,
> > and source of additional
> >       *            services or other resources that may be needed when
> > constructing the core service
> >       *            implementation
> >       * @param creator
> > -     *            object capable of creating the service implementation
> > on demand
> > +     *            object capable of creating the service implementation
> > on demand. This is a wrapper
> > +     *            around the service's builder method.
> >       * @return the service or equivalent service proxy
> >       */
> >      Object createService(ServiceResources resources, ServiceCreator
> > creator);
> > +
> > +    /**
> > +     * Returns true if this lifecycle requires a proxy to be generated.
> > This is true in nearly all
> > +     * cases. When this is true, first reference to a service does not
> > create the service, but
> > +     * creates a proxy that defers creation of the service until a method
> > of the service is invoked.
> > +     * When this is false, the {@link #createService(ServiceResources,
> > ServiceCreator)} will be
> > +     * invoked when the service is first referenced, and is responsible
> > for returning an appropriate
> > +     * service or proxy.
> > +     */
> > +    boolean getCreateProxy();
> > }
> >
> > Modified:
> > tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties?rev=420171&r1=420170&r2=420171&view=diff
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
> > (original)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
> > Sat Jul  8 10:44:05 2006
> > @@ -21,7 +21,7 @@
> > no-such-module=Module ''{0}'' does not exist. Please ensure that the JAR
> > file for the module is on the classpath.
> > service-wrong-interface=Service ''{0}'' implements interface {1}, which is
> > not compatible with the requested type {2}.
> > instantiate-builder-error=Unable to instantiate class {0} as builder for
> > module ''{1}'': {2}
> > -singleton-proxy-to-string=<Singleton proxy for {0}({1})>
> > +proxy-to-string=<Proxy for {0}({1})>
> > builder-method-error=Error invoking service builder method {0} (for
> > service ''{1}''): {2}
> > builder-method-returned-null=Builder method {0} (for service ''{1}'')
> > returned null.
> > service-is-private=Service ''{0}'' is private, and may not be referenced
> > outside of its containing module.
> >
> > Modified:
> > tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java?rev=420171&r1=420170&r2=420171&view=diff
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java
> > (original)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java
> > Sat Jul  8 10:44:05 2006
> > @@ -20,6 +20,8 @@
> > import org.apache.hivemind.service.impl.ClassFactoryImpl;
> > import org.apache.tapestry.internal.test.InternalBaseTestCase;
> > import org.apache.tapestry.ioc.ErrorLog;
> > +import org.apache.tapestry.ioc.Registry;
> > +import org.apache.tapestry.ioc.RegistryBuilder;
> > import org.apache.tapestry.ioc.def.ModuleDef;
> > import org.testng.annotations.Test;
> >
> > @@ -141,5 +143,32 @@
> >          assertTrue(ids.contains("ioc.test.Upcase"));
> >
> >          verify();
> > +    }
> > +
> > +    private Registry buildRegistry()
> > +    {
> > +        RegistryBuilder builder = new RegistryBuilder();
> > +        builder.add(TapestryIOCModule.class, ModuleImplTestModule.class);
> > +
> > +        return builder.build();
> > +    }
> > +
> > +    /** The following tests work better as integration tests. */
> > +
> > +    @Test
> > +    public void integrationTests()
> > +    {
> > +        Registry registry = buildRegistry();
> > +
> > +        UpcaseService us = registry.getService(UpcaseService.class);
> > +
> > +        assertEquals(us.upcase("hello"), "HELLO");
> > +        assertEquals(
> > +                us.toString(),
> > +                "<Proxy for ioc.test.Upcase(
> > org.apache.tapestry.internal.ioc.UpcaseService)>");
> > +
> > +        ToStringService ts = registry.getService(ToStringService.class);
> > +
> > +        assertEquals(ts.toString(), "<ToStringService: ioc.test.ToString
> > >");
> >      }
> > }
> >
> > Modified:
> > tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTestModule.java
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTestModule.java?rev=420171&r1=420170&r2=420171&view=diff
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTestModule.java
> > (original)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTestModule.java
> > Sat Jul  8 10:44:05 2006
> > @@ -36,6 +36,18 @@
> >          return new UpcaseServiceImpl();
> >      }
> >
> > +    public ToStringService buildToString(final String serviceId)
> > +    {
> > +        return new ToStringService()
> > +        {
> > +            @Override
> > +            public String toString()
> > +            {
> > +                return "<ToStringService: " + serviceId + ">";
> > +            }
> > +        };
> > +    }
> > +
> >      public FieService buildFie()
> >      {
> >          return null;
> >
> > Modified:
> > tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycleTest.java
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycleTest.java?rev=420171&r1=420170&r2=420171&view=diff
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycleTest.java
> > (original)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycleTest.java
> > Sat Jul  8 10:44:05 2006
> > @@ -14,117 +14,35 @@
> >
> > package org.apache.tapestry.internal.ioc;
> >
> > -import org.apache.hivemind.service.ClassFactory;
> > -import org.apache.hivemind.service.impl.ClassFactoryImpl;
> > import org.apache.tapestry.internal.test.InternalBaseTestCase;
> > -import org.apache.tapestry.ioc.IOCConstants;
> > import org.apache.tapestry.ioc.ServiceCreator;
> > import org.apache.tapestry.ioc.ServiceLifecycle;
> > import org.apache.tapestry.ioc.ServiceResources;
> > import org.testng.annotations.Test;
> >
> > -import static org.testng.Assert.assertEquals;
> > +import static org.testng.Assert.assertSame;
> >
> > /**
> >   * @author Howard M. Lewis Ship
> >   */
> > public class SingletonServiceLifecycleTest extends InternalBaseTestCase
> > {
> > -    private static final String UPCASE_SERVICE_ID = "ioc.Upcase";
> > -
> > -    private static final String TO_STRING_SERVICE_ID = "ioc.ToString";
> > -
> >      @Test
> > -    public void basic()
> > +    public void test()
> >      {
> >          ServiceResources resources = newServiceResources();
> >          ServiceCreator creator = newServiceCreator();
> > -        UpcaseService service = newMock(UpcaseService.class);
> > -
> > -        ClassFactory cf = new ClassFactoryImpl();
> > -
> > -        trainGetServiceId(resources, UPCASE_SERVICE_ID);
> > -
> > -        trainGetServiceInterface(resources, UpcaseService.class);
> > -
> > -        trainGetService(resources, IOCConstants.CLASS_FACTORY_SERVICE_ID,
> > ClassFactory.class, cf);
> > -
> > -        replay();
> > -
> > -        ServiceLifecycle lf = new SingletonServiceLifecycle();
> > -
> > -        UpcaseService proxy = (UpcaseService) lf.createService(resources,
> > creator);
> > -
> > -        verify();
> > -
> > -        assertEquals(
> > -                proxy.toString(),
> > -                "<Singleton proxy for ioc.Upcase(
> > org.apache.tapestry.internal.ioc.UpcaseService)>");
> > -
> > -        // Now to test when the creator gets invoked
> > -
> > -        trainCreateService(creator, service);
> > -
> > -        service.upcase("hello");
> > -        setReturnValue("HELLO");
> > -
> > -        replay();
> > -
> > -        assertEquals(proxy.upcase("hello"), "HELLO");
> > -
> > -        verify();
> > -
> > -        // Now test that the creator is not used again
> > -
> > -        service.upcase("bye");
> > -        setReturnValue("BYE");
> > -
> > -        replay();
> > -
> > -        assertEquals(proxy.upcase("bye"), "BYE");
> > -
> > -        verify();
> > -    }
> > -
> > -    @Test
> > -    public void toStringService()
> > -    {
> > -        ServiceResources resources = newServiceResources();
> > -        ServiceCreator creator = newServiceCreator();
> > -        ToStringService service = new ToStringService()
> > -        {
> > -            @Override
> > -            public String toString()
> > -            {
> > -                return "ToStringService";
> > -            }
> > -        };
> > -
> > -        ClassFactory cf = new ClassFactoryImpl();
> > -
> > -        trainGetServiceId(resources, TO_STRING_SERVICE_ID);
> > -
> > -        trainGetServiceInterface(resources, ToStringService.class);
> > -
> > -        trainGetService(resources, IOCConstants.CLASS_FACTORY_SERVICE_ID,
> > ClassFactory.class, cf);
> > -
> > -        replay();
> > -
> > -        ServiceLifecycle lf = new SingletonServiceLifecycle();
> > -
> > -        ToStringService proxy = (ToStringService) lf.createService(resources,
> > creator);
> > -
> > -        verify();
> > +        Object expected = new Object();
> >
> > -        trainCreateService(creator, service);
> > +        trainCreateService(creator, expected);
> >
> >          replay();
> >
> > -        assertEquals(proxy.toString(), "ToStringService");
> > +        ServiceLifecycle lifecycle = new SingletonServiceLifecycle();
> >
> > -        // Now test that the creator is not used again
> > +        Object actual = lifecycle.createService(resources, creator);
> >
> > -        assertEquals(proxy.toString(), "ToStringService");
> > +        assertSame(actual, expected);
> >
> >          verify();
> >      }
> >
> > Modified:
> > tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/RegistryBuilderTest.java
> > URL:
> > http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/RegistryBuilderTest.java?rev=420171&r1=420170&r2=420171&view=diff
> >
> > ==============================================================================
> > ---
> > tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/RegistryBuilderTest.java
> > (original)
> > +++
> > tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/RegistryBuilderTest.java
> > Sat Jul  8 10:44:05 2006
> > @@ -19,7 +19,6 @@
> > import org.apache.hivemind.service.ClassFactory;
> > import org.apache.tapestry.internal.ioc.TapestryIOCModule;
> > import org.apache.tapestry.internal.test.InternalBaseTestCase;
> > -import org.testng.Assert;
> > import org.testng.annotations.Test;
> >
> > import static org.testng.Assert.assertEquals;
> >
> >
> >
>
>
> --
> Jesse Kuhnert
> Tacos/Tapestry, team member/developer
>
> Open source based consulting work centered around
> dojo/tapestry/tacos/hivemind.
>
>


-- 
Howard M. Lewis Ship
Independent J2EE / Open-Source Java Consultant
Creator and PMC Chair, Apache Tapestry
Creator, Jakarta HiveMind

Professional Tapestry training, mentoring, support
and project work.  http://howardlewisship.com

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org