You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2006/07/29 04:32:58 UTC

svn commit: r426747 - in /tapestry/tapestry5/tapestry-core/trunk/src: main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java site/apt/ioc/service.apt

Author: hlship
Date: Fri Jul 28 19:32:57 2006
New Revision: 426747

URL: http://svn.apache.org/viewvc?rev=426747&view=rev
Log:
Add some documentation about service lifecycles, including perthread.

Modified:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/service.apt

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java?rev=426747&r1=426746&r2=426747&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java Fri Jul 28 19:32:57 2006
@@ -26,7 +26,6 @@
 import org.apache.tapestry.ioc.annotations.Id;
 import org.apache.tapestry.ioc.annotations.InjectService;
 import org.apache.tapestry.ioc.annotations.Lifecycle;
-import org.apache.tapestry.ioc.annotations.Private;
 
 /**
  * Defines the base set of services for the Tapestry IOC container.
@@ -65,8 +64,8 @@
     }
 
     /**
-     * Provides access to additional service lifecycles. Two lifecycles are builtin ("singleton" and
-     * "primitive") but additional ones are accessed via this service (and its mapped
+     * Provides access to additional service lifecycles. Two lifecycles are built in ("singleton"
+     * and "primitive") but additional ones are accessed via this service (and its mapped
      * configuration).
      */
     public ServiceLifecycleSource buildServiceLifecycleSource(
@@ -81,6 +80,7 @@
         };
     }
 
+    /** Contributes the "perthread" service lifecycle. */
     public void contributeServiceLifecycleSource(
             MappedConfiguration<String, ServiceLifecycle> configuration,
             @InjectService("ThreadCleanupHub")

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/service.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/service.apt?rev=426747&r1=426746&r2=426747&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/service.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/service.apt Fri Jul 28 19:32:57 2006
@@ -81,8 +81,84 @@
   
 Defining Service Lifecycle
 
-  <TBD>
+  Each service has a <lifecycle> that controls when the service implementation is instantiated.
+  There are three build in lifecycles: "singleton", "primitive" and "perthread", but
+  more can be added.
+  
+  Service lifecycle is specified using the 
+  {{{../apidocs/org/apache/tapestry/ioc/annotations/Lifeycle.html}@Lifecycle annotation}},
+  which is attached to a builder method.  When this annotation is not present, the
+  default lifecycle, "singleton" is used.
     
+* singleton
+  
+  Most services use the default lifecycle, "singleton".  With this lifecycle a <proxy>
+  is created when the service is first referenced.  By reference, we mean any situation in which
+  the service is requested by name, such as using the @InjectService annotation on a
+  service builder method, or by using the
+  {{{../apidocs/org/apache/tapestry/ioc/Registry.html}Registry}} API from outside the
+  container.
+  
+  In any case, the service proxy will only create the service implementation when a method
+  on the service interface is invoked. Until then, the service can be thought of as "virtual".
+  As the first method is invoked, the service builder method is invoked, then any service
+  decorations occur.  This construction process occurs only once.
+  
+* primitive
+
+  A few built-in services use the primitive lifecycle. With primitive, the service
+  is instantiated on first reference, rather than later, on first method invocation,
+  and there is no proxy.  Other services, and the outside world, 
+ 
+  An example of this is in the TapestryIOCModule; the ClassFactory service is itself needed
+  to create service proxies, so it must be primitive.
+  
++----+
+    @Lifecycle("primitive")
+    public ClassFactory buildClassFactory(Log log)
+    {
+        return new ClassFactoryImpl(log);
+    }
++----+ 
+
+  Using primitive, it becomes more likely that you'll create a recursive dependency:
+  A service whose builder method invokes methods on the service it is trying to
+  create. Tapestry IoC detects this situation (otherwise there would be an endless loop
+  until the JVM ran out of heap), but it is up to you to avoid this situation, often
+  by splitting a service into two parts. In any case, this situation is slightly easier
+  to slip into when using the primitive service.
+
+  There is rarely a need to use the primitive lifecycle, outside of the internal Tapestry
+  IoC services.  The lack of a proxy makes invoking methods on primitive services
+  infinitesmly faster, but this is not something to worry about.
+  
+* perthread
+
+  The perthread service lifecycle exists primarily to help multi-threaded servlet applications,
+  though it has other applications.
+  
+  With perthread, the service proxy will delegate to a local service instance that is associated
+  with the current thread. Two different threads, invoking methods on the same proxy, will
+  ultimately be invoking methods on two different service instances, each reserved to their own thread.
+  
+  This is useful when a service needs to keep request specific state, such as information extracted
+  from the HttpServletRequest (in a web application). The default singleton model would not work
+  in such a multi threaded environment.  Using perthread on select services allows state to be isolated
+  to those services.  Because the dispatch occurs <inside> the proxy, you can treat the service
+  as a global, like any other.
+  
+  You will see that your service builder method is invoked more than once.
+  
+  At the end of the request, the  Registry's cleanupThread() method is invoked; it will discard
+  any perthread service implementations for the current thread.  Generally, this is integrated
+  into the main service loop of the web application's servlet.
+  
+  Similar techniques can be used whenever multiple threads are in use, such as processing of
+  messages from a JMS (Java Messaging System) queue, or when using any sort of thread pool.
+  The important thing is to invoke the cleanupThread() method, to discard any request/thread
+  specific information, before processing the next request, message, transaction, or
+  what have you.  
+     
 Injecting Resources
 
   In addition to injecting services, Tapestry will key off of the parameter type to allow