You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Josh Canfield <jo...@gmail.com> on 2011/06/29 16:47:57 UTC

Re: svn commit: r1139536 - in /tapestry/tapestry5/trunk/tapestry-core: ./ src/main/java/org/apache/tapestry5/ src/main/java/org/apache/tapestry5/internal/services/ src/main/java/org/apache/tapestry5/services/ src/test/cluster/ src/test/cluster/WEB-IN

Ah, silly typo. I was wondering why the checkin wasn't something up in the
issue...
On Jun 29, 2011 2:23 AM, "Ulrich Stärk" <ul...@spielviel.de> wrote:
> Nice one. In the future please make sure to correctly state the issue
number (you omitted the 5
> after TAP) so that we have them linked from JIRA. This makes finding the
corresponding code changes
> for an issue a lot easier!
>
> Uli
>
> On 25.06.2011 14:31, joshcanfield@apache.org wrote:
>> Author: joshcanfield
>> Date: Sat Jun 25 12:31:36 2011
>> New Revision: 1139536
>>
>> URL: http://svn.apache.org/viewvc?rev=1139536&view=rev
>> Log:
>> TAP-1489 - Created a SessionFactory which determines which implementation
to provide to the request.
>> - Updated Session object to be able to report if it's been invalidated
outside of tapestry
>>
>> TAP-1355 - Removed code that set session attributes to null to force a
HttpSessionBindingListener event.
>> - Created mini-cluster integration test to ensure proper session storage
with different approaches.
>> - Changed isDirty flags to atomic checkAndSet style to avoid missed
updates
>>
>> Added:
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClusteredSessionImpl.java
>> - copied, changed from r1139143,
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionImpl.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionFactory.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionFactoryImpl.java
>> tapestry/tapestry5/trunk/tapestry-core/src/test/cluster/
>> tapestry/tapestry5/trunk/tapestry-core/src/test/cluster/WEB-INF/
>> tapestry/tapestry5/trunk/tapestry-core/src/test/cluster/WEB-INF/web.xml
>> - copied, changed from r1139143,
tapestry/tapestry5/trunk/tapestry-core/src/test/app5/WEB-INF/web.xml
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/ClusterTests.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/base/
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/base/BaseSessionDemo.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/AnalyzedSessionObject.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/ImmutableByAnnotation.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/MutablePojo.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/SessionStateObject.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/ImmutableSessionPersistedObjectDemo.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/PersistedMutablePojoDemo.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/SessionPersistedObjectAnalyzerDemo.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/services/
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/services/AppModule.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/cluster/
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/cluster/base/
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/cluster/base/BaseSessionDemo.tml
>> Modified:
>> tapestry/tapestry5/trunk/tapestry-core/build.gradle
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/BaseOptimizedSessionPersistedObject.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/OptimizedSessionPersistedObject.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/ValidationTrackerImpl.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DefaultSessionPersistedObjectAnalyzer.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/OptimizedSessionPersistedObjectAnalyzer.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestImpl.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionImpl.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/Session.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/SessionPersistedObjectAnalyzer.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/RequestImplTest.java
>>
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/SessionImplTest.java
>>
>> Modified: tapestry/tapestry5/trunk/tapestry-core/build.gradle
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/build.gradle?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> --- tapestry/tapestry5/trunk/tapestry-core/build.gradle (original)
>> +++ tapestry/tapestry5/trunk/tapestry-core/build.gradle Sat Jun 25
12:31:36 2011
>> @@ -23,6 +23,8 @@ dependencies {
>>
>> // Antlr3 tool path used with the antlr3 task
>> antlr3 "org.antlr:antlr:3.3"
>> +
>> + testRuntime "org.hsqldb:hsqldb:1.8.0.10"
>> }
>>
>> // This may spin out as a plugin once we've got the details down pat
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/BaseOptimizedSessionPersistedObject.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/BaseOptimizedSessionPersistedObject.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/BaseOptimizedSessionPersistedObject.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/BaseOptimizedSessionPersistedObject.java
Sat Jun 25 12:31:36 2011
>> @@ -1,4 +1,4 @@
>> -// Copyright 2008, 2009 The Apache Software Foundation
>> +// Copyright 2008, 2009, 2011 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.
>> @@ -14,57 +14,33 @@
>>
>> package org.apache.tapestry5;
>>
>> -import javax.servlet.http.HttpSessionBindingEvent;
>> -import javax.servlet.http.HttpSessionBindingListener;
>> +import java.util.concurrent.atomic.AtomicBoolean;
>>
>> /**
>> * Base implementation of
>> * {@link org.apache.tapestry5.OptimizedSessionPersistedObject}.
Subclasses
>> - * should invoke {@link #markDirty()} when internal state of the object
changes.
>> + * should invoke {@link #markDirty()} after the internal state of the
object changes.
>> + * <p>
>> + * Due to the concurrent nature of session attributes it's important
that markDirty occurs <strong>after</strong>
>> + * the object has been changed. If the change occurs before the object
has been mutated it's possible that another
>> + * thread may re-store the object before the changes are actually made!
>> * <p>
>> - * Note that (due to TAP5-834), the object will receive a spurious
>> - * <code>valueUnbound()</code> notification when dirty. Tapestry sets
dirty
>> - * session attributes to null, then to the persisted object, to force a
>> - * <code>valueBound()</code> notification, and that unfortunately also
sends the
>> - * <code>valueUnbound()</code>.
>> - *
>> * @since 5.1.1.0
>> */
>> -public abstract class BaseOptimizedSessionPersistedObject implements
>> - OptimizedSessionPersistedObject, HttpSessionBindingListener
>> +public abstract class BaseOptimizedSessionPersistedObject implements
OptimizedSessionPersistedObject
>> {
>> - private transient boolean dirty;
>> -
>> - public final boolean isSessionPersistedObjectDirty()
>> - {
>> - return dirty;
>> - }
>> + private transient AtomicBoolean dirty = new AtomicBoolean(false);
>>
>> - /**
>> - * Invoked by the servlet container when the value is stored (or
re-stored)
>> - * as an attribute of the session. This
>> - * clears the dirty flag. Subclasses may override this method, but
should
>> - * invoke this implementation.
>> - */
>> - public void valueBound(HttpSessionBindingEvent event)
>> - {
>> - dirty = false;
>> - }
>> -
>> - /**
>> - * Does nothing.
>> - */
>> - public void valueUnbound(HttpSessionBindingEvent event)
>> + public final boolean checkAndResetDirtyMarker()
>> {
>> + return dirty.getAndSet(false);
>> }
>>
>> /**
>> - * Invoked by the subclass whenever the internal state of the object
>> - * changes. Typically, this is invoked from
>> - * mutator methods.
>> + * Invoked by the subclass after internal state of the object changes.
>> */
>> protected final void markDirty()
>> {
>> - dirty = true;
>> + dirty.set(true);
>> }
>> }
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/OptimizedSessionPersistedObject.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/OptimizedSessionPersistedObject.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/OptimizedSessionPersistedObject.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/OptimizedSessionPersistedObject.java
Sat Jun 25 12:31:36 2011
>> @@ -1,4 +1,4 @@
>> -// Copyright 2008 The Apache Software Foundation
>> +// Copyright 2008, 2011 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.
>> @@ -17,9 +17,11 @@ package org.apache.tapestry5;
>> /**
>> * An optional interface implemented by objects that are persisted in the
{@link org.apache.tapestry5.services.Session}.
>> * At the end of each request, any objects read from the session are
re-stored into the session, to ensure that
>> - * in-memory changes are flushed to other servers in a cluster. Objects
that implement this interface are expected to
>> - * track when they are dirty (have pending changes), so that the save
back into the session can be avoided when not
>> - * necessary.
>> + * in-memory changes are flushed to other persistent session stores
(e.g. RDBMS, servers in a cluster, etc). Objects
>> + * that implement this interface are expected to track when they are
dirty (have pending changes), so that the save
>> + * back into the session can be avoided when not necessary.
>> + * <p>
>> + * This method is accessed concurrently.
>> *
>> * @see org.apache.tapestry5.annotations.ImmutableSessionPersistedObject
>> * @see org.apache.tapestry5.services.SessionPersistedObjectAnalyzer
>> @@ -28,10 +30,7 @@ package org.apache.tapestry5;
>> public interface OptimizedSessionPersistedObject
>> {
>> /**
>> - * Returns true if the object has in-memory changes. It is the object's
responsibility to set its internal flag to
>> - * false, typically by implementing {@link
javax.servlet.http.HttpSessionBindingListener}.
>> - *
>> - * @return
>> + * @return true if the object has in-memory changes since the last time
this method was called.
>> */
>> - boolean isSessionPersistedObjectDirty();
>> + boolean checkAndResetDirtyMarker();
>> }
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java
Sat Jun 25 12:31:36 2011
>> @@ -294,4 +294,16 @@ public class SymbolConstants
>> * @since 5.3.0
>> */
>> public static final String MINIFICATION_ENABLED =
"tapestry.enable-minification";
>> +
>> + /**
>> + * If "true" then at the end of each request the
>> + * {@link org.apache.tapestry5.services.SessionPersistedObjectAnalyzer}
will be called on each session persisted
>> + * object that was accessed during the request.
>> + * <p>
>> + * This is provided as a performance enhancement for servers that do not
use clustered sessions.
>> + *
>> + * @since 5.3.1
>> + */
>> + public static final String CLUSTERED_SESSIONS =
"tapestry.clustered-sessions";
>> +
>> }
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/ValidationTrackerImpl.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/ValidationTrackerImpl.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/ValidationTrackerImpl.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/ValidationTrackerImpl.java
Sat Jun 25 12:31:36 2011
>> @@ -1,4 +1,4 @@
>> -// Copyright 2006, 2008, 2010 The Apache Software Foundation
>> +// Copyright 2006, 2008, 2010, 2011 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.
>> @@ -84,8 +84,6 @@ public final class ValidationTrackerImpl
>>
>> private void store(FieldTracker fieldTracker)
>> {
>> - markDirty();
>> -
>> if (fieldTrackers == null)
>> fieldTrackers = CollectionFactory.newList();
>>
>> @@ -98,15 +96,17 @@ public final class ValidationTrackerImpl
>> fieldTrackers.add(fieldTracker);
>> fieldToTracker.put(key, fieldTracker);
>> }
>> +
>> + markDirty();
>> }
>>
>> public void clear()
>> {
>> - markDirty();
>> -
>> extraErrors = null;
>> fieldTrackers = null;
>> fieldToTracker = null;
>> +
>> + markDirty();
>> }
>>
>> public String getError(Field field)
>> @@ -161,12 +161,12 @@ public final class ValidationTrackerImpl
>>
>> public void recordError(String errorMessage)
>> {
>> - markDirty();
>> -
>> if (extraErrors == null)
>> extraErrors = CollectionFactory.newList();
>>
>> extraErrors.add(errorMessage);
>> +
>> + markDirty();
>> }
>>
>> public void recordInput(Field field, String input)
>>
>> Copied:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClusteredSessionImpl.java
(from r1139143,
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionImpl.java)
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClusteredSessionImpl.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClusteredSessionImpl.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionImpl.java&r1=1139143&r2=1139536&rev=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionImpl.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClusteredSessionImpl.java
Sat Jun 25 12:31:36 2011
>> @@ -1,41 +1,33 @@
>> -// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
>> +// Copyright 2011 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
>> +// 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
>> +// 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.
>> +// 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.tapestry5.internal.services;
>>
>> import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
>> -import org.apache.tapestry5.ioc.internal.util.InternalUtils;
>> -import org.apache.tapestry5.services.Session;
>> import org.apache.tapestry5.services.SessionPersistedObjectAnalyzer;
>>
>> +import javax.servlet.http.HttpServletRequest;
>> import javax.servlet.http.HttpSession;
>> -import java.util.Collections;
>> -import java.util.Enumeration;
>> -import java.util.List;
>> import java.util.Map;
>>
>> /**
>> - * A thin wrapper around {@link HttpSession}.
>> + * A thin wrapper around {@link javax.servlet.http.HttpSession}.
>> */
>> -public class SessionImpl implements Session
>> +public class ClusteredSessionImpl extends SessionImpl
>> {
>> private final SessionPersistedObjectAnalyzer analyzer;
>>
>> - private final HttpSession session;
>> -
>> - private boolean invalidated = false;
>> -
>> /**
>> * Cache of attribute objects read from, or written to, the real session.
>> * This is needed for end-of-request
>> @@ -43,77 +35,42 @@ public class SessionImpl implements Sess
>> */
>> private final Map<String, Object> sessionAttributeCache =
CollectionFactory.newMap();
>>
>> - public SessionImpl(HttpSession session, SessionPersistedObjectAnalyzer
analyzer)
>> + public ClusteredSessionImpl(
>> + HttpServletRequest request,
>> + HttpSession session,
>> + SessionPersistedObjectAnalyzer analyzer)
>> {
>> - this.session = session;
>> + super(request, session);
>> this.analyzer = analyzer;
>> }
>>
>> + @Override
>> public Object getAttribute(String name)
>> {
>> - Object result = session.getAttribute(name);
>> + Object result = super.getAttribute(name);
>>
>> sessionAttributeCache.put(name, result);
>>
>> return result;
>> }
>>
>> - public List<String> getAttributeNames()
>> - {
>> - return InternalUtils.toList(session.getAttributeNames());
>> - }
>> -
>> public void setAttribute(String name, Object value)
>> {
>> - session.setAttribute(name, value);
>> + super.setAttribute(name, value);
>>
>> sessionAttributeCache.put(name, value);
>> }
>>
>> - public List<String> getAttributeNames(String prefix)
>> - {
>> - List<String> result = CollectionFactory.newList();
>> -
>> - Enumeration e = session.getAttributeNames();
>> - while (e.hasMoreElements())
>> - {
>> - String name = (String) e.nextElement();
>> -
>> - if (name.startsWith(prefix)) result.add(name);
>> - }
>> -
>> - Collections.sort(result);
>> -
>> - return result;
>> - }
>> -
>> - public int getMaxInactiveInterval()
>> - {
>> - return session.getMaxInactiveInterval();
>> - }
>> -
>> public void invalidate()
>> {
>> - invalidated = true;
>> -
>> - session.invalidate();
>> + super.invalidate();
>>
>> sessionAttributeCache.clear();
>> }
>>
>> - public boolean isInvalidated()
>> - {
>> - return invalidated;
>> - }
>> -
>> - public void setMaxInactiveInterval(int seconds)
>> - {
>> - session.setMaxInactiveInterval(seconds);
>> - }
>> -
>> public void restoreDirtyObjects()
>> {
>> - if (invalidated) return;
>> + if (isInvalidated()) return;
>>
>> if (sessionAttributeCache.isEmpty()) return;
>>
>> @@ -125,15 +82,9 @@ public class SessionImpl implements Sess
>>
>> if (attributeValue == null) continue;
>>
>> - if (analyzer.isDirty(attributeValue))
>> + if (analyzer.checkAndResetDirtyState(attributeValue))
>> {
>> - // TAP5-834: Jetty & Tomcat work by object identity, will not update
the attribute
>> - // and fire the session binding event unless there's a real change. So
we set the
>> - // attribute to null and then to the new value and that should force
the necessary
>> - // notification.
>> -
>> - session.setAttribute(attributeName, null);
>> - session.setAttribute(attributeName, attributeValue);
>> + super.setAttribute(attributeName, attributeValue);
>> }
>> }
>> }
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DefaultSessionPersistedObjectAnalyzer.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DefaultSessionPersistedObjectAnalyzer.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DefaultSessionPersistedObjectAnalyzer.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DefaultSessionPersistedObjectAnalyzer.java
Sat Jun 25 12:31:36 2011
>> @@ -1,4 +1,4 @@
>> -// Copyright 2008 The Apache Software Foundation
>> +// Copyright 2008, 2011 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.
>> @@ -28,14 +28,14 @@ public class DefaultSessionPersistedObje
>> * An object is dirty <em>unless</em> it has the {@link
org.apache.tapestry5.annotations.ImmutableSessionPersistedObject}
>> * annotation.
>> *
>> - * @param object to analyze
>> + * @param sessionPersistedObject to analyze
>> * @return false if immutable, true otherwise
>> */
>> - public boolean isDirty(Object object)
>> + public boolean checkAndResetDirtyState(Object sessionPersistedObject)
>> {
>> - boolean immutable =
object.getClass().getAnnotation(ImmutableSessionPersistedObject.class) !=
null;
>> + boolean immutable =
sessionPersistedObject.getClass().getAnnotation(ImmutableSessionPersistedObject.class)
!= null;
>>
>> - // Imuutable objects are always clean, others are assumed dirty.
>> + // Immutable objects are always clean, others are assumed dirty.
>> // Go implement OptimizedSessionPersistedObject if you don't like it.
>>
>> return !immutable;
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/OptimizedSessionPersistedObjectAnalyzer.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/OptimizedSessionPersistedObjectAnalyzer.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/OptimizedSessionPersistedObjectAnalyzer.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/OptimizedSessionPersistedObjectAnalyzer.java
Sat Jun 25 12:31:36 2011
>> @@ -1,4 +1,4 @@
>> -// Copyright 2008 The Apache Software Foundation
>> +// Copyright 2008, 2011 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.
>> @@ -19,8 +19,8 @@ import org.apache.tapestry5.services.Ses
>>
>> public class OptimizedSessionPersistedObjectAnalyzer implements
SessionPersistedObjectAnalyzer<OptimizedSessionPersistedObject>
>> {
>> - public boolean isDirty(OptimizedSessionPersistedObject object)
>> + public boolean checkAndResetDirtyState(OptimizedSessionPersistedObject
sessionPersistedObject)
>> {
>> - return object.isSessionPersistedObjectDirty();
>> + return sessionPersistedObject.checkAndResetDirtyMarker();
>> }
>> }
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestImpl.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestImpl.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestImpl.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestImpl.java
Sat Jun 25 12:31:36 2011
>> @@ -17,10 +17,8 @@ package org.apache.tapestry5.internal.se
>> import org.apache.tapestry5.ioc.internal.util.InternalUtils;
>> import org.apache.tapestry5.services.Request;
>> import org.apache.tapestry5.services.Session;
>> -import org.apache.tapestry5.services.SessionPersistedObjectAnalyzer;
>>
>> import javax.servlet.http.HttpServletRequest;
>> -import javax.servlet.http.HttpSession;
>> import java.io.UnsupportedEncodingException;
>> import java.util.List;
>> import java.util.Locale;
>> @@ -39,19 +37,20 @@ public class RequestImpl implements Requ
>>
>> private final String requestEncoding;
>>
>> - private final SessionPersistedObjectAnalyzer analyzer;
>> + private final SessionFactory sessionFactory;
>>
>> private boolean encodingSet;
>>
>> - HttpSession hsession;
>> -
>> Session session;
>>
>> - public RequestImpl(HttpServletRequest request, String requestEncoding,
SessionPersistedObjectAnalyzer analyzer)
>> + public RequestImpl(
>> + HttpServletRequest request,
>> + String requestEncoding,
>> + SessionFactory sessionFactory)
>> {
>> this.request = request;
>> this.requestEncoding = requestEncoding;
>> - this.analyzer = analyzer;
>> + this.sessionFactory = sessionFactory;
>> }
>>
>> public List<String> getParameterNames()
>> @@ -105,27 +104,15 @@ public class RequestImpl implements Requ
>>
>> public Session getSession(boolean create)
>> {
>> - if (session != null)
>> + if (session != null && session.isInvalidated())
>> {
>> - // The easy case is when the session was invalidated through the
Tapestry Session
>> - // object. The hard case is when the HttpSession was invalidated
outside of Tapestry,
>> - // in which case, request.getSession() will return a new HttpSession
instance (or null)
>> -
>> - if (session.isInvalidated() || hsession != request.getSession(false))
>> - {
>> - session = null;
>> - hsession = null;
>> - }
>> + session = null;
>> }
>>
>> - if (session == null)
>> + if (session == null )
>> {
>> - hsession = request.getSession(create);
>> -
>> - if (hsession != null)
>> - {
>> - session = new SessionImpl(hsession, analyzer);
>> - }
>> + // TAP5-1489 - Re-storage of session attributes at end of request
should be configurable
>> + session = sessionFactory.getSession(create);
>> }
>>
>> return session;
>> @@ -149,8 +136,7 @@ public class RequestImpl implements Requ
>> try
>> {
>> request.setCharacterEncoding(requestEncoding);
>> - }
>> - catch (UnsupportedEncodingException ex)
>> + } catch (UnsupportedEncodingException ex)
>> {
>> throw new RuntimeException(ex);
>> }
>> @@ -198,7 +184,9 @@ public class RequestImpl implements Requ
>> return request.getLocalPort();
>> }
>>
>> - /** @since 5.2.5 */
>> + /**
>> + * @since 5.2.5
>> + */
>> public int getServerPort()
>> {
>> return request.getServerPort();
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionFactory.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionFactory.java?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionFactory.java
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionFactory.java
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,22 @@
>> +// Copyright 2011 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.tapestry5.internal.services;
>> +
>> +import org.apache.tapestry5.services.Session;
>> +
>> +public interface SessionFactory
>> +{
>> + Session getSession(boolean create);
>> +}
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionFactoryImpl.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionFactoryImpl.java?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionFactoryImpl.java
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionFactoryImpl.java
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,59 @@
>> +// Copyright 2011 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.tapestry5.internal.services;
>> +
>> +import org.apache.tapestry5.SymbolConstants;
>> +import org.apache.tapestry5.ioc.annotations.Symbol;
>> +import org.apache.tapestry5.services.Session;
>> +import org.apache.tapestry5.services.SessionPersistedObjectAnalyzer;
>> +
>> +import javax.servlet.http.HttpServletRequest;
>> +import javax.servlet.http.HttpSession;
>> +
>> +/**
>> + * User: josh_canfield
>> + * Date: 6/25/11
>> + */
>> +public class SessionFactoryImpl implements SessionFactory
>> +{
>> + private boolean clustered;
>> + private final SessionPersistedObjectAnalyzer analyzer;
>> + private final HttpServletRequest request;
>> +
>> + public SessionFactoryImpl(
>> + @Symbol(SymbolConstants.CLUSTERED_SESSIONS)
>> + boolean clustered,
>> + SessionPersistedObjectAnalyzer analyzer,
>> + HttpServletRequest request)
>> + {
>> + this.clustered = clustered;
>> + this.analyzer = analyzer;
>> + this.request = request;
>> + }
>> +
>> + public Session getSession(boolean create)
>> + {
>> + final HttpSession httpSession = request.getSession(create);
>> +
>> + if (httpSession == null ) return null;
>> +
>> + if (clustered)
>> + {
>> + return new ClusteredSessionImpl(request, httpSession, analyzer);
>> + }
>> +
>> + return new SessionImpl(request, httpSession);
>> + }
>> +}
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionImpl.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionImpl.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionImpl.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SessionImpl.java
Sat Jun 25 12:31:36 2011
>> @@ -1,4 +1,4 @@
>> -// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
>> +// Copyright 2006, 2007, 2008, 2009, 2011 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.
>> @@ -19,6 +19,7 @@ import org.apache.tapestry5.ioc.internal
>> import org.apache.tapestry5.services.Session;
>> import org.apache.tapestry5.services.SessionPersistedObjectAnalyzer;
>>
>> +import javax.servlet.http.HttpServletRequest;
>> import javax.servlet.http.HttpSession;
>> import java.util.Collections;
>> import java.util.Enumeration;
>> @@ -30,32 +31,20 @@ import java.util.Map;
>> */
>> public class SessionImpl implements Session
>> {
>> - private final SessionPersistedObjectAnalyzer analyzer;
>> -
>> + private final HttpServletRequest request;
>> private final HttpSession session;
>>
>> private boolean invalidated = false;
>>
>> - /**
>> - * Cache of attribute objects read from, or written to, the real
session.
>> - * This is needed for end-of-request
>> - * processing.
>> - */
>> - private final Map<String, Object> sessionAttributeCache =
CollectionFactory.newMap();
>> -
>> - public SessionImpl(HttpSession session, SessionPersistedObjectAnalyzer
analyzer)
>> + public SessionImpl(HttpServletRequest request, HttpSession session)
>> {
>> + this.request = request;
>> this.session = session;
>> - this.analyzer = analyzer;
>> }
>>
>> public Object getAttribute(String name)
>> {
>> - Object result = session.getAttribute(name);
>> -
>> - sessionAttributeCache.put(name, result);
>> -
>> - return result;
>> + return session.getAttribute(name);
>> }
>>
>> public List<String> getAttributeNames()
>> @@ -66,8 +55,6 @@ public class SessionImpl implements Sess
>> public void setAttribute(String name, Object value)
>> {
>> session.setAttribute(name, value);
>> -
>> - sessionAttributeCache.put(name, value);
>> }
>>
>> public List<String> getAttributeNames(String prefix)
>> @@ -97,12 +84,18 @@ public class SessionImpl implements Sess
>> invalidated = true;
>>
>> session.invalidate();
>> -
>> - sessionAttributeCache.clear();
>> }
>>
>> public boolean isInvalidated()
>> {
>> + if (invalidated) return true;
>> +
>> + // The easy case is when the session was invalidated through the
Tapestry Session
>> + // object. The hard case is when the HttpSession was invalidated
outside of Tapestry,
>> + // in which case, request.getSession() will return a new HttpSession
instance (or null)
>> +
>> + invalidated = request.getSession(false) != session;
>> +
>> return invalidated;
>> }
>>
>> @@ -113,28 +106,6 @@ public class SessionImpl implements Sess
>>
>> public void restoreDirtyObjects()
>> {
>> - if (invalidated) return;
>> -
>> - if (sessionAttributeCache.isEmpty()) return;
>> -
>> - for (Map.Entry<String, Object> entry :
sessionAttributeCache.entrySet())
>> - {
>> - String attributeName = entry.getKey();
>> -
>> - Object attributeValue = entry.getValue();
>>
>> - if (attributeValue == null) continue;
>> -
>> - if (analyzer.isDirty(attributeValue))
>> - {
>> - // TAP5-834: Jetty & Tomcat work by object identity, will not update
the attribute
>> - // and fire the session binding event unless there's a real change. So
we set the
>> - // attribute to null and then to the new value and that should force
the necessary
>> - // notification.
>> -
>> - session.setAttribute(attributeName, null);
>> - session.setAttribute(attributeName, attributeValue);
>> - }
>> - }
>> }
>> }
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/Session.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/Session.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/Session.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/Session.java
Sat Jun 25 12:31:36 2011
>> @@ -72,8 +72,8 @@ public interface Session
>> void invalidate();
>>
>> /**
>> - * Checks to see if the session has been invalidated. Note: this only
catches calls to {@link #invalidate()}, not
>> - * calls to {@link javax.servlet.http.HttpSession#invalidate()}.
>> + * Checks to see if the session has been invalidated. Note: since 5.3.1
this will also catch calls to
>> + * {@link javax.servlet.http.HttpSession#invalidate()}.
>> *
>> * @since 5.1.0.0
>> */
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/SessionPersistedObjectAnalyzer.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/SessionPersistedObjectAnalyzer.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/SessionPersistedObjectAnalyzer.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/SessionPersistedObjectAnalyzer.java
Sat Jun 25 12:31:36 2011
>> @@ -1,4 +1,4 @@
>> -// Copyright 2008 The Apache Software Foundation
>> +// Copyright 2008, 2011 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.
>> @@ -17,10 +17,15 @@ package org.apache.tapestry5.services;
>> import org.apache.tapestry5.ioc.annotations.UsesMappedConfiguration;
>>
>> /**
>> - * Analyzes a session-persisted object, specifically to see if it is
dirty or not. The service implementation uses a
>> - * mapped configuration to form a {@linkplain
org.apache.tapestry5.ioc.services.StrategyBuilder strategy} based on
>> - * object type. The service is injectable using the {@link
org.apache.tapestry5.ioc.annotations.Primary} marker
>> - * annotation.
>> + * Analyzes a session-persisted object, specifically to see if it is
dirty or not.
>> + * <p/>
>> + * This service is provided to support applications which store mutable
session attributes where the
>> + * session is replicated to a slower medium (e.g. RDMBS, Cluster, etc)
this can help alleviate excessive writes
>> + * to the session store while ensuring changes are propagated.
>> + * <p/>
>> + * The service implementation uses a mapped configuration to form a
>> + * {@linkplain org.apache.tapestry5.ioc.services.StrategyBuilder
strategy} based on object type. The service may be
>> + * injected using the {@link
org.apache.tapestry5.ioc.annotations.Primary} marker annotation.
>> *
>> * @see org.apache.tapestry5.annotations.ImmutableSessionPersistedObject
>> * @see org.apache.tapestry5.OptimizedSessionPersistedObject
>> @@ -30,11 +35,15 @@ import org.apache.tapestry5.ioc.annotati
>> public interface SessionPersistedObjectAnalyzer<T>
>> {
>> /**
>> - * Passed an object (never null) to see if it is dirty or not. Dirty
objects that are stored in the session are
>> - * re-stored into the session at the end of the request.
>> + * Atomically check and reset the dirty state of the session persisted
object.
>> + * <p/>
>> + * The implementer should take consideration for the fact that session
attributes are accessed concurrently. A
>> + * naive check/set algorithm may allow changes to go un-noticed.
>> *
>> - * @param object
>> - * @return true if object needs to be re-stored into the session
>> + * @param sessionPersistedObject the session attribute (never null)
>> + * @return true if the object needs to be re-stored into the session
>> + * @since 5.3.1
>> */
>> - boolean isDirty(T object);
>> + boolean checkAndResetDirtyState(T sessionPersistedObject);
>> +
>> }
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
Sat Jun 25 12:31:36 2011
>> @@ -355,14 +355,14 @@ public final class TapestryModule
>> {
>> private final RequestHandler handler;
>> private final String applicationCharset;
>> - private final SessionPersistedObjectAnalyzer analyzer;
>> + private final SessionFactory sessionFactory;
>>
>> public HttpServletRequestHandlerTerminator(RequestHandler handler, String
applicationCharset,
>> - SessionPersistedObjectAnalyzer analyzer)
>> + SessionFactory sessionFactory)
>> {
>> this.handler = handler;
>> this.applicationCharset = applicationCharset;
>> - this.analyzer = analyzer;
>> + this.sessionFactory = sessionFactory;
>> }
>>
>> public boolean service(HttpServletRequest servletRequest,
HttpServletResponse servletResponse)
>> @@ -370,7 +370,7 @@ public final class TapestryModule
>> {
>> requestGlobals.storeServletRequestResponse(servletRequest,
servletResponse);
>>
>> - Request request = new RequestImpl(servletRequest, applicationCharset,
analyzer);
>> + Request request = new RequestImpl(servletRequest, applicationCharset,
sessionFactory);
>> Response response = new ResponseImpl(servletRequest, servletResponse);
>>
>> // TAP5-257: Make sure that the "initial guess" for request/response
>> @@ -484,6 +484,7 @@ public final class TapestryModule
>> binder.bind(ContextPathEncoder.class, ContextPathEncoderImpl.class);
>> binder.bind(ApplicationStatePersistenceStrategy.class,
SessionApplicationStatePersistenceStrategy.class)
>> .withId("SessionApplicationStatePersistenceStrategy");
>> + binder.bind(SessionFactory.class, SessionFactoryImpl.class);
>> binder.bind(AssetPathConverter.class, IdentityAssetPathConverter.class);
>> binder.bind(NumericTranslatorSupport.class);
>> binder.bind(ClientDataEncoder.class, ClientDataEncoderImpl.class);
>> @@ -1115,7 +1116,7 @@ public final class TapestryModule
>> * Adds coercions:
>> * <ul>
>> * <li>String to {@link SelectModel}
>> - * <li>Map to {@link oSelectModel}
>> + * <li>Map to {@link SelectModel}
>> * <li>Collection to {@link GridDataSource}
>> * <li>null to {@link GridDataSource}
>> * <li>List to {@link SelectModel}
>> @@ -1516,11 +1517,10 @@ public final class TapestryModule
>> @Symbol(SymbolConstants.CHARSET)
>> String applicationCharset,
>>
>> - @Primary
>> - SessionPersistedObjectAnalyzer analyzer)
>> + SessionFactory sessionFactory)
>> {
>> HttpServletRequestHandler terminator = new
HttpServletRequestHandlerTerminator(handler, applicationCharset,
>> - analyzer);
>> + sessionFactory);
>>
>> return pipelineBuilder.build(logger, HttpServletRequestHandler.class,
HttpServletRequestFilter.class,
>> configuration, terminator);
>> @@ -2457,6 +2457,8 @@ public final class TapestryModule
>>
>> configuration.add(SymbolConstants.PRODUCTION_MODE, true);
>>
>> + configuration.add(SymbolConstants.CLUSTERED_SESSIONS, true);
>> +
>> configuration.add(SymbolConstants.COMPRESS_WHITESPACE, true);
>>
>> configuration.add(MetaDataConstants.SECURE_PAGE, false);
>> @@ -2704,7 +2706,7 @@ public final class TapestryModule
>> }
>>
>> /**
>> - * The master SessionPesistedObjectAnalyzer.
>> + * The master SessionPersistedObjectAnalyzer.
>> *
>> * @since 5.1.0.0
>> */
>> @@ -2730,7 +2732,7 @@ public final class TapestryModule
>>
>> SessionPersistedObjectAnalyzer<Object> immutable = new
SessionPersistedObjectAnalyzer<Object>()
>> {
>> - public boolean isDirty(Object object)
>> + public boolean checkAndResetDirtyState(Object sessionPersistedObject)
>> {
>> return false;
>> }
>>
>> Copied:
tapestry/tapestry5/trunk/tapestry-core/src/test/cluster/WEB-INF/web.xml
(from r1139143,
tapestry/tapestry5/trunk/tapestry-core/src/test/app5/WEB-INF/web.xml)
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/cluster/WEB-INF/web.xml?p2=tapestry/tapestry5/trunk/tapestry-core/src/test/cluster/WEB-INF/web.xml&p1=tapestry/tapestry5/trunk/tapestry-core/src/test/app5/WEB-INF/web.xml&r1=1139143&r2=1139536&rev=1139536&view=diff
>>
==============================================================================
>> --- tapestry/tapestry5/trunk/tapestry-core/src/test/app5/WEB-INF/web.xml
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/cluster/WEB-INF/web.xml Sat
Jun 25 12:31:36 2011
>> @@ -3,10 +3,10 @@
>> PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
>> "http://java.sun.com/dtd/web-app_2_3.dtd">
>> <web-app>
>> - <display-name>Integration Test App 5 -- Skinning</display-name>
>> + <display-name>Integration Test Cluster</display-name>
>> <context-param>
>> <param-name>tapestry.app-package</param-name>
>> - <param-value>org.apache.tapestry5.integration.app5</param-value>
>> + <param-value>org.apache.tapestry5.integration.cluster</param-value>
>> </context-param>
>> <filter>
>> <filter-name>app</filter-name>
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/ClusterTests.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/ClusterTests.java?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/ClusterTests.java
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/ClusterTests.java
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,248 @@
>> +// Copyright 2011 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.tapestry5.integration.cluster;
>> +
>> +import com.thoughtworks.selenium.DefaultSelenium;
>> +import com.thoughtworks.selenium.Selenium;
>> +import org.apache.tapestry5.test.Jetty7Runner;
>> +import org.apache.tapestry5.test.TapestryTestConstants;
>> +import org.eclipse.jetty.server.Server;
>> +import org.eclipse.jetty.server.session.JDBCSessionIdManager;
>> +import org.eclipse.jetty.server.session.JDBCSessionManager;
>> +import org.eclipse.jetty.server.session.SessionHandler;
>> +import org.eclipse.jetty.webapp.WebAppContext;
>> +import org.openqa.selenium.server.RemoteControlConfiguration;
>> +import org.openqa.selenium.server.SeleniumServer;
>> +import org.testng.annotations.AfterClass;
>> +import org.testng.annotations.BeforeClass;
>> +import org.testng.annotations.Test;
>> +import org.testng.xml.XmlTest;
>> +
>> +import java.sql.Connection;
>> +import java.sql.DriverManager;
>> +import java.sql.SQLException;
>> +import java.sql.Statement;
>> +
>> +import static org.testng.AssertJUnit.assertEquals;
>> +import static org.testng.AssertJUnit.assertTrue;
>> +
>> +/**
>> + * User: josh_canfield Date: 6/24/11
>> + */
>> +public class ClusterTests
>> +{
>> + private static final String FIREFOX_BROWSER_CMD = "*firefox";
>> + private static final int SERVER_A_PORT = 9091;
>> + private static final int SERVER_B_PORT = 9092;
>> + private static final String SERVER_A_NAME = "server_A";
>> + private static final String SERVER_B_NAME = "server_B";
>> +
>> + private static final String CREATE_1 =
"//a[contains(text(),'create1')]";
>> + private static final String VALUE_1 = "value1";
>> +
>> + private static final String CREATE_2 =
"//a[contains(text(),'create2')]";
>> + private static final String VALUE_2 = "value2";
>> +
>> + private static final String UPDATE_1 =
"//a[contains(text(),'update1')]";
>> + private static final String VALUE_3 = "value3";
>> +
>> + private static final String UPDATE_2 =
"//a[contains(text(),'update2')]";
>> + private static final String VALUE_4 = "value4";
>> +
>> + private static final String CLEAR = "//a[contains(text(),'Clear')]";
>> +
>> + Jetty7Runner serverA;
>> +
>> + Jetty7Runner serverB;
>> +
>> + SeleniumServer seleniumServer;
>> + Selenium selenium;
>> +
>> + @BeforeClass
>> + void setupServers(XmlTest xmlTest) throws Exception
>> + {
>> + createJettySessionsTable();
>> +
>> + serverA = configureClusteredJetty(SERVER_A_NAME, SERVER_A_PORT);
>> + serverB = configureClusteredJetty(SERVER_B_NAME, SERVER_B_PORT);
>> +
>> + seleniumServer = new SeleniumServer();
>> + seleniumServer.start();
>> +
>> + String browserStartCommand =
xmlTest.getParameter(TapestryTestConstants.BROWSER_START_COMMAND_PARAMETER);
>> + browserStartCommand = browserStartCommand != null ? browserStartCommand
: FIREFOX_BROWSER_CMD;
>> +
>> + selenium = new DefaultSelenium(
>> + "localhost", RemoteControlConfiguration.DEFAULT_PORT,
>> + browserStartCommand, "http://localhost:9091/"
>> + );
>> + selenium.start();
>> + }
>> +
>> + @AfterClass
>> + void stopServers()
>> + {
>> + serverA.stop();
>> + serverB.stop();
>> + selenium.stop();
>> + seleniumServer.stop();
>> + }
>> +
>> + @Test
>> + public void mutable_pojo_as_session_state_is_always_shared()
>> + {
>> + // Expect all object changes to be transferred to the other server.
>> + String[][] click = {
>> + {CREATE_1, VALUE_1, VALUE_1},
>> + {CLEAR, "", ""},
>> + {CREATE_2, VALUE_2, VALUE_2},
>> + {UPDATE_1, VALUE_3, VALUE_3},
>> + {UPDATE_2, VALUE_4, VALUE_4}
>> + };
>> +
>> + evaluate("PersistedMutablePojoDemo", click);
>> + }
>> +
>> + @Test
>> + public void immutable_session_persisted_object() throws
InterruptedException
>> + {
>> + // expect only create links to transfer over (We've told tapestry it's
immutable)
>> + String[][] data = {
>> + {CREATE_1, VALUE_1, VALUE_1},
>> + {UPDATE_1, VALUE_3, VALUE_1},
>> + {CLEAR, "", ""},
>> + {CREATE_2, VALUE_2, VALUE_2},
>> + {UPDATE_2, VALUE_4, VALUE_2},
>> + {UPDATE_1, VALUE_3, VALUE_2},
>> + };
>> +
>> + evaluate("ImmutableSessionPersistedObjectDemo", data);
>> + }
>> +
>> + @Test
>> + public void session_persisted_object_analyzer() throws
InterruptedException
>> + {
>> + // special cased so that only UPDATE_2 marks as dirty, creates/deletes
still transfer
>> + String[][] data = {
>> + {CREATE_1, VALUE_1, VALUE_1}, // created, session transferred
>> + {UPDATE_1, VALUE_3, VALUE_1}, // update-1 doesn't transfer
>> + {CLEAR, "", ""},
>> + {CREATE_2, VALUE_2, VALUE_2}, // create-2, session transferred
>> + {UPDATE_2, VALUE_4, VALUE_4}, // update-2, session transferred
>> + {UPDATE_1, VALUE_3, VALUE_4}, // update-1, doesn't transfer
>> + };
>> +
>> + evaluate("SessionPersistedObjectAnalyzerDemo", data);
>> + }
>> +
>> + private void evaluate(String page, String[][] expect)
>> + {
>> + for (String[] strings : expect)
>> + {
>> + openOnServerA(page);
>> +
>> + clickAndWait(strings[0]);
>> +
>> + assertText("value", strings[1]);
>> +
>> + openOnServerB(page);
>> +
>> + assertText("value", strings[2]);
>> + }
>> +
>> + clickAndWait(CLEAR);
>> + assertText("value", "");
>> + }
>> +
>> + private void openOnServerA(String page)
>> + {
>> + selenium.open("http://localhost:" + SERVER_A_PORT + "/" + page);
>> + assertServerName(SERVER_A_NAME);
>> + }
>> +
>> + private void openOnServerB(String page)
>> + {
>> + selenium.open("http://localhost:" + SERVER_B_PORT + "/" + page);
>> + assertServerName(SERVER_B_NAME);
>> + }
>> +
>> + private void assertServerName(String serverName)
>> + {
>> + assertTrue(selenium.isElementPresent("//h1[@id='serverName' and
text()='" + serverName + "']"));
>> + }
>> +
>> + private void assertText(String locator, String expected)
>> + {
>> + assertEquals(expected, selenium.getText(locator));
>> + }
>> +
>> + private void clickAndWait(String s)
>> + {
>> + selenium.click(s);
>> + selenium.waitForPageToLoad("5000");
>> + }
>> +
>> + private Jetty7Runner configureClusteredJetty(String name, int port)
throws Exception
>> + {
>> + Jetty7Runner runner = new Jetty7Runner();
>> +
>> + runner.configure("src/test/cluster", "", port, port + 100);
>> +
>> + JDBCSessionIdManager idMgr = new
JDBCSessionIdManager(runner.getServer());
>> + idMgr.setWorkerName(name);
>> + idMgr.setDriverInfo("org.hsqldb.jdbcDriver",
"jdbc:hsqldb:mem:clustertest");
>> +
>> + Server server = runner.getServer();
>> + server.setSessionIdManager(idMgr);
>> +
>> + WebAppContext wac = (WebAppContext) server.getHandler();
>> +
>> + JDBCSessionManager jdbcMgr = new JDBCSessionManager();
>> + jdbcMgr.setIdManager(server.getSessionIdManager());
>> +
>> + // force the session to be read from the database with no delay
>> + // This is an incorrectly documented feature.
>> + jdbcMgr.setSaveInterval(0);
>> +
>> + wac.setSessionHandler(new SessionHandler(jdbcMgr));
>> + wac.getServletContext().setInitParameter("cluster.name", name);
>> + runner.start();
>> + return runner;
>> + }
>> +
>> + private void createJettySessionsTable() throws ClassNotFoundException,
SQLException
>> + {
>> + Class.forName("org.hsqldb.jdbcDriver");
>> +
>> + Connection c =
DriverManager.getConnection("jdbc:hsqldb:mem:clustertest", "sa", "");
>> + String sql = "create table JettySessions (" +
>> + "rowId varchar(60), " +
>> + "sessionId varchar(60)," +
>> + "contextPath varchar(60)," +
>> + "virtualHost varchar(60)," +
>> + "lastNode varchar(60)," +
>> + "accessTime bigint," +
>> + "lastAccessTime bigint," +
>> + "createTime bigint," +
>> + "cookieTime bigint," +
>> + "lastSavedTime bigint," +
>> + "expiryTime bigint," +
>> + "map longvarbinary" +
>> + ");";
>> + Statement statement = c.createStatement();
>> + statement.execute(sql);
>> + statement.close();
>> + }
>> +}
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/base/BaseSessionDemo.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/base/BaseSessionDemo.java?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/base/BaseSessionDemo.java
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/base/BaseSessionDemo.java
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,41 @@
>> +// Copyright 2011 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.tapestry5.integration.cluster.base;
>> +
>> +import org.apache.tapestry5.annotations.Persist;
>> +import org.apache.tapestry5.annotations.Property;
>> +import org.apache.tapestry5.integration.cluster.data.SessionStateObject;
>> +
>> +public abstract class BaseSessionDemo<T extends SessionStateObject> {
>> +
>> + @Property
>> + @Persist
>> + private SessionStateObject data;
>> +
>> + abstract public T create(String value);
>> +
>> + void onCreateValue(String value) {
>> + data = create(value);
>> + }
>> +
>> + void onChangeValue(String value) {
>> + data.setValue(value);
>> + }
>> +
>> + void onClear() {
>> + data = null;
>> + }
>> +
>> +}
>> \ No newline at end of file
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/AnalyzedSessionObject.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/AnalyzedSessionObject.java?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/AnalyzedSessionObject.java
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/AnalyzedSessionObject.java
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,45 @@
>> +// Copyright 2011 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.tapestry5.integration.cluster.data;
>> +
>> +public class AnalyzedSessionObject implements SessionStateObject
>> +{
>> + private String value;
>> +
>> + boolean dirty = false;
>> +
>> + public AnalyzedSessionObject(String value)
>> + {
>> + this.value = value;
>> + }
>> +
>> + public boolean checkAndResetDirtyState()
>> + {
>> + boolean check = dirty;
>> + dirty = false;
>> + return check;
>> + }
>> +
>> + public String getValue()
>> + {
>> + return value;
>> + }
>> +
>> + public void setValue(String value)
>> + {
>> + this.value = value;
>> + dirty = "value4".equals(value);
>> + }
>> +}
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/ImmutableByAnnotation.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/ImmutableByAnnotation.java?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/ImmutableByAnnotation.java
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/ImmutableByAnnotation.java
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,34 @@
>> +// Copyright 2011 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.tapestry5.integration.cluster.data;
>> +
>> +import org.apache.tapestry5.annotations.ImmutableSessionPersistedObject;
>> +
>> +@ImmutableSessionPersistedObject
>> +public class ImmutableByAnnotation implements SessionStateObject {
>> + private String value;
>> +
>> + public ImmutableByAnnotation(String value) {
>> + this.value = value;
>> + }
>> +
>> + public String getValue() {
>> + return value;
>> + }
>> +
>> + public void setValue(String value) {
>> + this.value = value;
>> + }
>> +}
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/MutablePojo.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/MutablePojo.java?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/MutablePojo.java
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/MutablePojo.java
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,32 @@
>> +// Copyright 2011 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.tapestry5.integration.cluster.data;
>> +
>> +public class MutablePojo implements SessionStateObject {
>> +
>> + private String value;
>> +
>> + public MutablePojo(String value) {
>> + this.value = value;
>> + }
>> +
>> + public String getValue() {
>> + return value;
>> + }
>> +
>> + public void setValue(String name) {
>> + this.value = name;
>> + }
>> +}
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/SessionStateObject.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/SessionStateObject.java?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/SessionStateObject.java
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/data/SessionStateObject.java
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,24 @@
>> +// Copyright 2011 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.tapestry5.integration.cluster.data;
>> +
>> +import java.io.Serializable;
>> +
>> +public interface SessionStateObject extends Serializable {
>> +
>> + String getValue();
>> +
>> + void setValue(String v);
>> +}
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/ImmutableSessionPersistedObjectDemo.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/ImmutableSessionPersistedObjectDemo.java?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/ImmutableSessionPersistedObjectDemo.java
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/ImmutableSessionPersistedObjectDemo.java
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,29 @@
>> +// Copyright 2011 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.tapestry5.integration.cluster.pages;
>> +
>> +import org.apache.tapestry5.integration.cluster.base.BaseSessionDemo;
>> +import
org.apache.tapestry5.integration.cluster.data.ImmutableByAnnotation;
>> +
>> +/**
>> + * User: josh_canfield
>> + * Date: 6/24/11
>> + */
>> +public class ImmutableSessionPersistedObjectDemo extends
BaseSessionDemo<ImmutableByAnnotation> {
>> + @Override
>> + public ImmutableByAnnotation create(String value) {
>> + return new ImmutableByAnnotation(value);
>> + }
>> +}
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/PersistedMutablePojoDemo.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/PersistedMutablePojoDemo.java?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/PersistedMutablePojoDemo.java
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/PersistedMutablePojoDemo.java
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,26 @@
>> +// Copyright 2011 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.tapestry5.integration.cluster.pages;
>> +
>> +import org.apache.tapestry5.integration.cluster.base.BaseSessionDemo;
>> +import org.apache.tapestry5.integration.cluster.data.MutablePojo;
>> +
>> +public class PersistedMutablePojoDemo extends
BaseSessionDemo<MutablePojo> {
>> +
>> + @Override
>> + public MutablePojo create(String value) {
>> + return new MutablePojo(value);
>> + }
>> +}
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/SessionPersistedObjectAnalyzerDemo.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/SessionPersistedObjectAnalyzerDemo.java?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/SessionPersistedObjectAnalyzerDemo.java
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/pages/SessionPersistedObjectAnalyzerDemo.java
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,25 @@
>> +// Copyright 2011 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.tapestry5.integration.cluster.pages;
>> +
>> +import org.apache.tapestry5.integration.cluster.base.BaseSessionDemo;
>> +import
org.apache.tapestry5.integration.cluster.data.AnalyzedSessionObject;
>> +
>> +public class SessionPersistedObjectAnalyzerDemo extends
BaseSessionDemo<AnalyzedSessionObject> {
>> + @Override
>> + public AnalyzedSessionObject create(String value) {
>> + return new AnalyzedSessionObject(value);
>> + }
>> +}
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/services/AppModule.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/services/AppModule.java?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/services/AppModule.java
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/cluster/services/AppModule.java
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,36 @@
>> +// Copyright 2011 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.tapestry5.integration.cluster.services;
>> +
>> +import
org.apache.tapestry5.integration.cluster.data.AnalyzedSessionObject;
>> +import org.apache.tapestry5.ioc.MappedConfiguration;
>> +import org.apache.tapestry5.ioc.annotations.Contribute;
>> +import org.apache.tapestry5.services.SessionPersistedObjectAnalyzer;
>> +
>> +public class AppModule
>> +{
>> +
>> + @Contribute(SessionPersistedObjectAnalyzer.class)
>> + public static void analyzer(MappedConfiguration<Class,
SessionPersistedObjectAnalyzer> configuration)
>> + {
>> + configuration.add(AnalyzedSessionObject.class, new
SessionPersistedObjectAnalyzer<AnalyzedSessionObject>()
>> + {
>> + public boolean checkAndResetDirtyState(AnalyzedSessionObject
sessionPersistedObject)
>> + {
>> + return sessionPersistedObject.checkAndResetDirtyState();
>> + }
>> + });
>> + }
>> +}
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/RequestImplTest.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/RequestImplTest.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/RequestImplTest.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/RequestImplTest.java
Sat Jun 25 12:31:36 2011
>> @@ -33,12 +33,13 @@ public class RequestImplTest extends Int
>> public void get_session_doesnt_exist()
>> {
>> HttpServletRequest sr = mockHttpServletRequest();
>> + SessionFactory sf = newMock(SessionFactory.class);
>>
>> - train_getSession(sr, false, null);
>> + expect(sf.getSession(false)).andReturn(null);
>>
>> replay();
>>
>> - Request request = new RequestImpl(sr, CHARSET, null);
>> + Request request = new RequestImpl(sr, CHARSET, sf);
>>
>> assertNull(request.getSession(false));
>>
>> @@ -50,14 +51,15 @@ public class RequestImplTest extends Int
>> {
>> HttpServletRequest sr = mockHttpServletRequest();
>> HttpSession ss = mockHttpSession();
>> + SessionFactory sf = newMock(SessionFactory.class);
>>
>> - train_getSession(sr, true, ss);
>> + expect(sf.getSession(true)).andReturn(new SessionImpl(sr, ss));
>>
>> train_getAttribute(ss, "foo", "bar");
>>
>> replay();
>>
>> - Request request = new RequestImpl(sr, CHARSET, null);
>> + Request request = new RequestImpl(sr, CHARSET, sf);
>> Session session = request.getSession(true);
>>
>> assertEquals(session.getAttribute("foo"), "bar");
>> @@ -202,11 +204,13 @@ public class RequestImplTest extends Int
>> HttpSession hsession1 = mockHttpSession();
>> HttpSession hsession2 = mockHttpSession();
>>
>> - train_getSession(sr, true, hsession1);
>> + SessionFactory sf = newMock(SessionFactory.class);
>> +
>> + expect(sf.getSession(true)).andReturn(new SessionImpl(sr,hsession1));
>>
>> replay();
>>
>> - Request request = new RequestImpl(sr, CHARSET, null);
>> + Request request = new RequestImpl(sr, CHARSET, sf);
>>
>> Session session1 = request.getSession(true);
>>
>> @@ -214,8 +218,11 @@ public class RequestImplTest extends Int
>>
>> hsession1.invalidate();
>>
>> - train_getSession(sr, false, hsession2);
>> - train_getSession(sr, true, hsession2);
>> + expect(sr.getSession(false)).andReturn(null);
>> +
>> + SessionImpl session = new SessionImpl(sr, hsession2);
>> + expect(sf.getSession(true)).andReturn(session);
>> + expect(sf.getSession(true)).andReturn(session);
>>
>> replay();
>>
>>
>> Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/SessionImplTest.java
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/SessionImplTest.java?rev=1139536&r1=1139535&r2=1139536&view=diff
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/SessionImplTest.java
(original)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/SessionImplTest.java
Sat Jun 25 12:31:36 2011
>> @@ -1,4 +1,4 @@
>> -// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
>> +// Copyright 2006, 2007, 2008, 2009, 2011 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.
>> @@ -18,6 +18,7 @@ import java.util.Arrays;
>> import java.util.Collections;
>> import java.util.Enumeration;
>>
>> +import javax.servlet.http.HttpServletRequest;
>> import javax.servlet.http.HttpSession;
>>
>> import org.apache.tapestry5.internal.test.InternalBaseTestCase;
>> @@ -37,7 +38,7 @@ public class SessionImplTest extends Int
>>
>> replay();
>>
>> - Session session = new SessionImpl(hs, null);
>> + Session session = new SessionImpl(null, hs);
>>
>> assertEquals(session.getAttributeNames(), Arrays.asList("barney",
"fred"));
>>
>> @@ -54,7 +55,7 @@ public class SessionImplTest extends Int
>>
>> replay();
>>
>> - Session session = new SessionImpl(hs, null);
>> + Session session = new SessionImpl(null, hs);
>>
>> assertEquals(session.getAttributeNames("f"), Arrays.asList("fanny",
"fred"));
>>
>> @@ -70,7 +71,7 @@ public class SessionImplTest extends Int
>>
>> replay();
>>
>> - Session session = new SessionImpl(hs, null);
>> + Session session = new SessionImpl(null, hs);
>>
>> session.invalidate();
>>
>> @@ -78,6 +79,39 @@ public class SessionImplTest extends Int
>> }
>>
>> @Test
>> + public void http_session_invalidate()
>> + {
>> + HttpSession hs = mockHttpSession();
>> +
>> + HttpServletRequest hsr = mockHttpServletRequest();
>> +
>> + train_getSession(hsr, false, hs);
>> +
>> + replay();
>> +
>> + Session session = new SessionImpl(hsr, hs);
>> +
>> + assertFalse(session.isInvalidated());
>> +
>> + verify();
>> +
>> + train_getSession(hsr, false, null);
>> +
>> + replay();
>> +
>> + assertTrue(session.isInvalidated());
>> +
>> + verify();
>> +
>> + train_getSession(hsr, false, mockHttpSession());
>> +
>> + replay();
>> +
>> + assertTrue(session.isInvalidated());
>> +
>> + }
>> +
>> + @Test
>> public void set_max_inactive()
>> {
>> HttpSession hs = mockHttpSession();
>> @@ -87,7 +121,7 @@ public class SessionImplTest extends Int
>>
>> replay();
>>
>> - Session session = new SessionImpl(hs, null);
>> + Session session = new SessionImpl(null, hs);
>>
>> session.setMaxInactiveInterval(seconds);
>>
>> @@ -104,7 +138,7 @@ public class SessionImplTest extends Int
>>
>> replay();
>>
>> - Session session = new SessionImpl(hs, null);
>> + Session session = new SessionImpl(null, hs);
>>
>> assertEquals(session.getMaxInactiveInterval(), seconds);
>>
>> @@ -115,6 +149,7 @@ public class SessionImplTest extends Int
>> public void dirty_persisted_object_is_forced_to_update()
>> {
>> HttpSession hs = mockHttpSession();
>> + HttpServletRequest hsr = mockHttpServletRequest();
>> SessionPersistedObjectAnalyzer analyzer =
newMock(SessionPersistedObjectAnalyzer.class);
>> Object dirty = new Object();
>>
>> @@ -122,15 +157,16 @@ public class SessionImplTest extends Int
>>
>> replay();
>>
>> - Session session = new SessionImpl(hs, analyzer);
>> + Session session = new ClusteredSessionImpl(hsr, hs, analyzer);
>>
>> assertSame(session.getAttribute("dirty"), dirty);
>>
>> verify();
>>
>> - expect(analyzer.isDirty(dirty)).andReturn(true);
>> + expect(analyzer.checkAndResetDirtyState(dirty)).andReturn(true);
>> +
>> + train_getSession(hsr, false, hs);
>>
>> - hs.setAttribute("dirty", null);
>> hs.setAttribute("dirty", dirty);
>>
>> replay();
>>
>> Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/cluster/base/BaseSessionDemo.tml
>> URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/cluster/base/BaseSessionDemo.tml?rev=1139536&view=auto
>>
==============================================================================
>> ---
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/cluster/base/BaseSessionDemo.tml
(added)
>> +++
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/cluster/base/BaseSessionDemo.tml
Sat Jun 25 12:31:36 2011
>> @@ -0,0 +1,21 @@
>> +<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
>> +<head>
>> + <title>Immutable Annotation Demo</title>
>> +</head>
>> +
>> +<body>
>> +<h1 id="serverName">${symbol:cluster.name}</h1>
>> +
>> +<div id="value">${data?.value}</div>
>> +
>> +<t:eventlink event="clear">Clear</t:eventlink>
>> +
>> +<t:eventlink event="createValue"
context="'value1'">create1</t:eventlink>
>> +<t:eventlink event="createValue"
context="'value2'">create2</t:eventlink>
>> +
>> +<t:eventlink event="changeValue"
context="'value3'">update1</t:eventlink>
>> +<t:eventlink event="changeValue"
context="'value4'">update2</t:eventlink>
>> +
>> +</body>
>> +
>> +</html>
>> \ No newline at end of file
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>