You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2007/03/30 17:25:07 UTC

svn commit: r524122 - in /tapestry/tapestry5/tapestry-core/trunk/src: main/java/org/apache/tapestry/annotations/ main/java/org/apache/tapestry/internal/services/ main/java/org/apache/tapestry/services/ main/java/org/apache/tapestry/test/ site/apt/guide...

Author: hlship
Date: Fri Mar 30 08:25:06 2007
New Revision: 524122

URL: http://svn.apache.org/viewvc?view=rev&rev=524122
Log:
TAPESTRY-1368: The @ApplicationState annotation should be capable of enhancing a boolean field to indicate whether the state object already exists

Modified:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/ApplicationState.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ApplicationStateManagerImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ApplicationStateWorker.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionApplicationStatePersistenceStrategy.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ApplicationStateManager.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ApplicationStatePersistenceStrategy.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ApplicationStateManagerImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ApplicationStateWorkerTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SessionApplicationStatePersistenceStrategyTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/StateHolder.java

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/ApplicationState.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/ApplicationState.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/ApplicationState.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/ApplicationState.java Fri Mar 30 08:25:06 2007
@@ -26,10 +26,18 @@
 /**
  * Marker annotation for a field that is an <em>application state object</em> as controlled by the
  * {@link ApplicationStateManager}.
+ * <p>
+ * An ASO file may have a companion field, of type boolean, used to see if the ASO has been created yet.
+ * If another field exists with the same name, suffixed with "Exists" (i.e., "_aso" for the ASO
+ * field, and "_asoExists" for the companion field) and the type of that field is boolean, then access
+ * to the field will determine whether the ASO has already been created. This is necessary because
+ * even a null check ("_aso != null") will force the ASO to be created. Instead, check te companion
+ * boolean field ("_asoExists").
  */
 @Target(FIELD)
 @Documented
 @Retention(RUNTIME)
-public @interface ApplicationState {
+public @interface ApplicationState
+{
 
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ApplicationStateManagerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ApplicationStateManagerImpl.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ApplicationStateManagerImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ApplicationStateManagerImpl.java Fri Mar 30 08:25:06 2007
@@ -53,13 +53,18 @@
         {
             _strategy.set(_asoClass, aso);
         }
+
+        boolean exists()
+        {
+            return _strategy.exists(_asoClass);
+        }
     };
 
     /**
      * The map will be extended periodically as new ASOs, not in the configuration, are encountered.
-     * Thus is is thread safe.
+     * Thut is is thread safe.
      */
-    private final Map<Class, ApplicationStateAdapter> _classToAdapter;
+    private final Map<Class, ApplicationStateAdapter> _classToAdapter = newConcurrentMap();
 
     private final ApplicationStatePersistenceStrategySource _source;
 
@@ -67,7 +72,6 @@
     public ApplicationStateManagerImpl(Map<Class, ApplicationStateContribution> configuration,
             ApplicationStatePersistenceStrategySource source)
     {
-        _classToAdapter = newConcurrentMap();
         _source = source;
 
         for (Class asoClass : configuration.keySet())
@@ -88,22 +92,21 @@
     private <T> ApplicationStateAdapter<T> newAdapter(final Class<T> asoClass, String strategyName,
             ApplicationStateCreator<T> creator)
     {
-        if (creator == null)
-            creator = new ApplicationStateCreator<T>()
+        if (creator == null) creator = new ApplicationStateCreator<T>()
+        {
+            public T create()
             {
-                public T create()
+                try
                 {
-                    try
-                    {
-                        return asoClass.newInstance();
-                    }
-                    catch (Exception ex)
-                    {
-                        throw new RuntimeException(ex);
-                    }
+                    return asoClass.newInstance();
                 }
+                catch (Exception ex)
+                {
+                    throw new RuntimeException(ex);
+                }
+            }
 
-            };
+        };
 
         ApplicationStatePersistenceStrategy strategy = _source.get(strategyName);
 
@@ -134,6 +137,11 @@
     public <T> void set(Class<T> asoClass, T aso)
     {
         getAdapter(asoClass).set(aso);
+    }
+
+    public <T> boolean exists(Class<T> asoClass)
+    {
+        return getAdapter(asoClass).exists();
     }
 
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ApplicationStateWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ApplicationStateWorker.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ApplicationStateWorker.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ApplicationStateWorker.java Fri Mar 30 08:25:06 2007
@@ -14,6 +14,8 @@
 
 package org.apache.tapestry.internal.services;
 
+import static java.lang.String.format;
+
 import java.lang.reflect.Modifier;
 import java.util.List;
 
@@ -43,8 +45,7 @@
     {
         List<String> names = transformation.findFieldsWithAnnotation(ApplicationState.class);
 
-        if (names.isEmpty())
-            return;
+        if (names.isEmpty()) return;
 
         String managerFieldName = transformation.addInjectedField(
                 ApplicationStateManager.class,
@@ -67,21 +68,46 @@
 
             }
 
-            String typeField = transformation.addInjectedField(
+            String typeFieldName = transformation.addInjectedField(
                     Class.class,
                     fieldName + "_type",
                     fieldClass);
 
-            replaceRead(transformation, fieldName, fieldType, managerFieldName, typeField);
+            replaceRead(transformation, fieldName, fieldType, managerFieldName, typeFieldName);
 
-            replaceWrite(transformation, fieldName, fieldType, managerFieldName, typeField);
+            replaceWrite(transformation, fieldName, fieldType, managerFieldName, typeFieldName);
 
             transformation.removeField(fieldName);
+
+            String booleanFieldName = fieldName + "Exists";
+
+            if (transformation.isField(booleanFieldName)
+                    && transformation.getFieldType(booleanFieldName).equals("boolean"))
+            {
+                replaceFlagRead(transformation, booleanFieldName, typeFieldName, managerFieldName);
+            }
         }
     }
 
+    private void replaceFlagRead(ClassTransformation transformation, String booleanFieldName,
+            String typeFieldName, String managerFieldName)
+    {
+        String readMethodName = transformation.newMemberName("read", booleanFieldName);
+
+        MethodSignature sig = new MethodSignature(Modifier.PRIVATE, "boolean", readMethodName,
+                null, null);
+
+        String body = format("return %s.exists(%s);", managerFieldName, typeFieldName);
+
+        transformation.addMethod(sig, body);
+
+        transformation.replaceReadAccess(booleanFieldName, readMethodName);
+        transformation.makeReadOnly(booleanFieldName);
+        transformation.removeField(booleanFieldName);
+    }
+
     private void replaceWrite(ClassTransformation transformation, String fieldName,
-            String fieldType, String managerFieldName, String typeField)
+            String fieldType, String managerFieldName, String typeFieldName)
     {
         String writeMethodName = transformation.newMemberName("write", fieldName);
 
@@ -89,7 +115,7 @@
                 writeMethodName, new String[]
                 { fieldType }, null);
 
-        String body = String.format("%s.set(%s, $1);", managerFieldName, typeField);
+        String body = format("%s.set(%s, $1);", managerFieldName, typeFieldName);
 
         transformation.addMethod(writeSignature, body);
 
@@ -97,7 +123,7 @@
     }
 
     private void replaceRead(ClassTransformation transformation, String fieldName,
-            String fieldType, String managerFieldName, String typeField)
+            String fieldType, String managerFieldName, String typeFieldName)
     {
 
         String readMethodName = transformation.newMemberName("read", fieldName);
@@ -105,11 +131,7 @@
         MethodSignature readMethodSignature = new MethodSignature(Modifier.PRIVATE, fieldType,
                 readMethodName, null, null);
 
-        String body = String.format(
-                "return (%s) %s.get(%s);",
-                fieldType,
-                managerFieldName,
-                typeField);
+        String body = format("return (%s) %s.get(%s);", fieldType, managerFieldName, typeFieldName);
 
         transformation.addMethod(readMethodSignature, body);
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java Fri Mar 30 08:25:06 2007
@@ -952,6 +952,22 @@
         return type.getName();
     }
 
+    public boolean isField(String fieldName)
+    {
+        failIfFrozen();
+
+        try
+        {
+            CtField field = _ctClass.getDeclaredField(fieldName);
+
+            return isInstanceField(field);
+        }
+        catch (NotFoundException ex)
+        {
+            return false;
+        }
+    }
+
     public int getFieldModifiers(String fieldName)
     {
         failIfFrozen();

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionApplicationStatePersistenceStrategy.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionApplicationStatePersistenceStrategy.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionApplicationStatePersistenceStrategy.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionApplicationStatePersistenceStrategy.java Fri Mar 30 08:25:06 2007
@@ -71,4 +71,13 @@
         getSession().setAttribute(key, aso);
     }
 
+    public <T> boolean exists(Class<T> asoClass)
+    {
+        String key = buildKey(asoClass);
+
+        Session session = _sessionHolder.getSession(false);
+
+        return session != null && session.getAttribute(key) != null;
+    }
+
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ApplicationStateManager.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ApplicationStateManager.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ApplicationStateManager.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ApplicationStateManager.java Fri Mar 30 08:25:06 2007
@@ -35,6 +35,15 @@
     <T> T get(Class<T> asoClass);
 
     /**
+     * Returns true if the ASO already exists, false if it has not yet been created.
+     * 
+     * @param asoClass
+     *            used to select the ASO
+     * @return true if ASO exists, false if null
+     */
+    <T> boolean exists(Class<T> asoClass);
+
+    /**
      * Stores a new ASO, replacing the existing ASO (if any). Storing the value null will delete the
      * ASO so that it may be re-created later.
      * 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ApplicationStatePersistenceStrategy.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ApplicationStatePersistenceStrategy.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ApplicationStatePersistenceStrategy.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ApplicationStatePersistenceStrategy.java Fri Mar 30 08:25:06 2007
@@ -35,4 +35,7 @@
      *            instance to store, or null to delete existing
      */
     <T> void set(Class<T> asoClass, T aso);
+
+    /** Returns true if the ASO already exists, false if null. */
+    <T> boolean exists(Class<T> asoClass);
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java Fri Mar 30 08:25:06 2007
@@ -184,6 +184,14 @@
     String getFieldType(String fieldName);
 
     /**
+     * Returns true if the indicated name is a private instance field.
+     * 
+     * @param fieldName
+     * @return true if field exists
+     */
+    boolean isField(String fieldName);
+
+    /**
      * Defines a new declared field for the class. The suggestedName may be modified to ensure
      * uniqueness.
      * 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java Fri Mar 30 08:25:06 2007
@@ -944,4 +944,9 @@
     {
         expect(annotation.value()).andReturn(value).atLeastOnce();
     }
+
+    protected final <T> void train_exists(ApplicationStatePersistenceStrategy strategy, Class<T> asoClass, boolean exists)
+    {
+        expect(strategy.exists(asoClass)).andReturn(exists);
+    }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/appstate.apt Fri Mar 30 08:25:06 2007
@@ -40,6 +40,22 @@
   Assigning a value to an ASO field will store that value.  Assigning null to an ASO field will remove the ASO (reading the field subsequently
   will force a new ASO instance to be created).
   
+Check for Creation
+
+  Scalable web applications do not create the server-side session needlessly. If you can avoid creating the session, especially on first
+  access to your web application, you will be able to handle an order of magnatude more users. So, if you can avoid creating the ASO, you should do so.
+  
+  But how to avoid creating it?  Simply checkng ("_myState != null") will force the creation of the ASO and the session to store it in.
+  
+  Instead, create a second field:
+  
++---+
+  private boolean _myStateExists;
++---+
+
+  This companion field is used to see if the ASO already exists. It is not annotated; it is located by name ("Exists" is appended to the name of the field
+  storing the ASO). It must be type boolean and must be a private instance variable.  
+  
 Persistence Strategies
 
   Each ASO is managed according to a persistence strategy. The default persistence strategy, "session", stores the ASOs inside the session.

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ApplicationStateManagerImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ApplicationStateManagerImplTest.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ApplicationStateManagerImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ApplicationStateManagerImplTest.java Fri Mar 30 08:25:06 2007
@@ -63,6 +63,58 @@
 
     @SuppressWarnings("unchecked")
     @Test
+    public void check_exists_when_null()
+    {
+        String strategyName = "ethereal";
+        ApplicationStatePersistenceStrategy strategy = newApplicationStatePersistenceStrategy();
+        ApplicationStatePersistenceStrategySource source = newApplicationStatePersistenceStrategySource();
+        Class asoClass = ReadOnlyBean.class;
+        ApplicationStateCreator<ReadOnlyBean> creator = newApplicationStateCreator();
+
+        Map<Class, ApplicationStateContribution> configuration = Collections.singletonMap(
+                asoClass,
+                new ApplicationStateContribution(strategyName, creator));
+
+        train_get(source, strategyName, strategy);
+        train_exists(strategy, asoClass, false);
+
+        replay();
+
+        ApplicationStateManager manager = new ApplicationStateManagerImpl(configuration, source);
+
+        assertFalse(manager.exists(asoClass));
+
+        verify();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void check_exists_when_true()
+    {
+        String strategyName = "ethereal";
+        ApplicationStatePersistenceStrategy strategy = newApplicationStatePersistenceStrategy();
+        ApplicationStatePersistenceStrategySource source = newApplicationStatePersistenceStrategySource();
+        Class asoClass = ReadOnlyBean.class;
+        ApplicationStateCreator<ReadOnlyBean> creator = newApplicationStateCreator();
+
+        Map<Class, ApplicationStateContribution> configuration = Collections.singletonMap(
+                asoClass,
+                new ApplicationStateContribution(strategyName, creator));
+
+        train_get(source, strategyName, strategy);
+        train_exists(strategy, asoClass, true);
+
+        replay();
+
+        ApplicationStateManager manager = new ApplicationStateManagerImpl(configuration, source);
+
+        assertTrue(manager.exists(asoClass));
+
+        verify();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
     public void set_configured_aso()
     {
         String strategyName = "ethereal";

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ApplicationStateWorkerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ApplicationStateWorkerTest.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ApplicationStateWorkerTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ApplicationStateWorkerTest.java Fri Mar 30 08:25:06 2007
@@ -100,6 +100,16 @@
 
         Object component = instantiator.newInstance(resources);
 
+        // Test the companion flag field
+
+        expect(manager.exists(asoClass)).andReturn(true);
+
+        replay();
+
+        assertEquals(_access.get(component, "beanExists"), true);
+
+        verify();
+
         // Test read property (get from ASM)
 
         Object aso = new ReadOnlyBean();

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java Fri Mar 30 08:25:06 2007
@@ -283,6 +283,21 @@
     }
 
     @Test
+    public void get_field_exists() throws Exception
+    {
+        Log log = newLog();
+
+        replay();
+
+        ClassTransformation ct = createClassTransformation(CheckFieldType.class, log);
+
+        assertTrue(ct.isField("_privateField"));
+        assertFalse(ct.isField("_doesNotExist"));
+
+        verify();
+    }
+
+    @Test
     public void find_fields_of_type_excludes_claimed_fields() throws Exception
     {
         Log log = newLog();

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SessionApplicationStatePersistenceStrategyTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SessionApplicationStatePersistenceStrategyTest.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SessionApplicationStatePersistenceStrategyTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SessionApplicationStatePersistenceStrategyTest.java Fri Mar 30 08:25:06 2007
@@ -26,7 +26,7 @@
     @Test
     public void get_aso_already_exists()
     {
-        SessionHolder holder = newMock(SessionHolder.class);
+        SessionHolder holder = newSessionHolder();
         Session session = newSession();
         Class asoClass = ReadOnlyBean.class;
         Object aso = new ReadOnlyBean();
@@ -48,15 +48,44 @@
 
     @SuppressWarnings("unchecked")
     @Test
+    public void check_exists_does_not_create_session()
+    {
+        SessionHolder holder = newSessionHolder();
+        Class asoClass = ReadOnlyBean.class;
+
+        train_getSession(holder, false, null);
+
+        replay();
+
+        ApplicationStatePersistenceStrategy strategy = new SessionApplicationStatePersistenceStrategy(
+                holder);
+
+        assertFalse(strategy.exists(asoClass));
+
+        verify();
+    }
+
+    private SessionHolder newSessionHolder()
+    {
+        return newMock(SessionHolder.class);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
     public void get_aso_needs_to_be_created()
     {
-        SessionHolder holder = newMock(SessionHolder.class);
+        SessionHolder holder = newSessionHolder();
         Session session = newSession();
         Class asoClass = ReadOnlyBean.class;
         Object aso = new ReadOnlyBean();
         String key = "aso:" + asoClass.getName();
         ApplicationStateCreator creator = newApplicationStateCreator();
 
+        // First for exists()
+        train_getSession(holder, false, session);
+        train_getAttribute(session, key, null);
+
+        // Second for get()
         train_getSession(holder, true, session);
         train_getAttribute(session, key, null);
 
@@ -64,13 +93,21 @@
 
         session.setAttribute(key, aso);
 
+        // Then for exists() after
+        train_getSession(holder, false, session);
+        train_getAttribute(session, key, aso);
+
         replay();
 
         ApplicationStatePersistenceStrategy strategy = new SessionApplicationStatePersistenceStrategy(
                 holder);
 
+        assertFalse(strategy.exists(asoClass));
+
         assertSame(strategy.get(asoClass, creator), aso);
 
+        assertTrue(strategy.exists(asoClass));
+
         verify();
     }
 
@@ -78,7 +115,7 @@
     @Test
     public void set_aso()
     {
-        SessionHolder holder = newMock(SessionHolder.class);
+        SessionHolder holder = newSessionHolder();
         Session session = newSession();
         Class asoClass = ReadOnlyBean.class;
         Object aso = new ReadOnlyBean();

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/StateHolder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/StateHolder.java?view=diff&rev=524122&r1=524121&r2=524122
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/StateHolder.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/StateHolder.java Fri Mar 30 08:25:06 2007
@@ -21,6 +21,8 @@
     @ApplicationState
     private ReadOnlyBean _bean;
 
+    private boolean _beanExists;
+
     public ReadOnlyBean getBean()
     {
         return _bean;
@@ -29,6 +31,11 @@
     public void setBean(ReadOnlyBean bean)
     {
         _bean = bean;
+    }
+
+    public boolean getBeanExists()
+    {
+        return _beanExists;
     }
 
 }