I have a requirement to not depend on HttpSession, but the Form component has a @Persist field that Tapestry wants to store in a session. What are some options to avoid this?

I may have posted this before, but here it is again. I think it's a pretty good solution.

I created a session persistence strategy that only stores non-null values, and extended the Form to only store the validation if there are errors... The changes to the existing classes are minor.

Here's the code.

import org.apache.tapestry.ValidationTracker;
import org.apache.tapestry.ValidationTrackerImpl;
import org.apache.tapestry.annotations.Persist;

/**
* Overrides the core [EMAIL PROTECTED] org.apache.tapestry.corelib.components.Form} in order to store the validation tracker only
 * when there is something to track.
 * <p/>
 * Created by IntelliJ IDEA.
 * User: joshcanfield
 * Date: Oct 26, 2007
 */
public class Form extends org.apache.tapestry.corelib.components.Form {
    @Persist("nonnull")
    private ValidationTracker _tracker;

    private ValidationTracker _nonPersistedTracker;

    public ValidationTracker getDefaultTracker() {
        if (_nonPersistedTracker == null) {
            if (_tracker != null) {
// _tracker is loaded via injection magic when it's in the session
                _nonPersistedTracker = _tracker;
            } else {
                _nonPersistedTracker = new ValidationTrackerImpl();
            }
        }
        return _nonPersistedTracker;
    }

    public void setDefaultTracker(ValidationTracker defaultTracker) {
        _nonPersistedTracker = defaultTracker;
    }

    protected void onAction() {
        if (_nonPersistedTracker.getHasErrors()) {
            _tracker = _nonPersistedTracker;
        } else {
            _tracker = null;
        }
    }

}


import org.apache.tapestry.internal.services.PersistentFieldChangeImpl;
import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
import org.apache.tapestry.services.PersistentFieldChange;
import org.apache.tapestry.services.PersistentFieldStrategy;
import org.apache.tapestry.services.Request;
import org.apache.tapestry.services.Session;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: joshcanfield
 * Date: Oct 26, 2007
 */
public class NonNullSessionPersistentFieldStrategy implements PersistentFieldStrategy {
    /**
     * Prefix used to identify keys stored in the session.
     */
    static final String PREFIX = "nonnull:";

    private final Request _request;

    protected NonNullSessionPersistentFieldStrategy(Request request) {
        _request = request;
    }

public final Collection<PersistentFieldChange> gatherFieldChanges(String pageName) {
        Session session = _request.getSession(false);

        if (session == null) return Collections.emptyList();

        List<PersistentFieldChange> result = newList();

        String fullPrefix = PREFIX + pageName + ":";

        for (String name : session.getAttributeNames(fullPrefix)) {
PersistentFieldChange change = buildChange(name, session.getAttribute(name));

            result.add(change);
        }

        return result;
    }

    public void discardChanges(String pageName) {
        Session session = _request.getSession(false);

        if (session == null) return;

        String fullPrefix = PREFIX + pageName + ":";

        for (String name : session.getAttributeNames(fullPrefix)) {
            session.setAttribute(name, null);
        }
    }

private PersistentFieldChange buildChange(String name, Object attribute) { // TODO: Regexp is probably too expensive for what we need here. Maybe an IOC InternalUtils
        // method for this purpose?

        String[] chunks = name.split(":");

        // Will be empty string for the root component
        String componentId = chunks[2];
        String fieldName = chunks[3];

return new PersistentFieldChangeImpl(componentId, fieldName, attribute);
    }

public final void postChange(String pageName, String componentId, String fieldName, Object newValue) {
        notBlank(pageName, "pageName");
        notBlank(fieldName, "fieldName");
        StringBuilder builder = new StringBuilder(PREFIX);
        builder.append(pageName);
        builder.append(':');

        if (componentId != null) builder.append(componentId);

        builder.append(':');
        builder.append(fieldName);
// because we don't want to create a session when the object is null
        Session session = _request.getSession(newValue != null);
        if (session != null) {
            session.setAttribute(builder.toString(), newValue);
        }
    }

}

Add this to your app module:

    public void contributePersistentFieldManager(
MappedConfiguration<String, PersistentFieldStrategy> configuration, Request request) { configuration.add("nonnull", new NonNullSessionPersistentFieldStrategy(request));
    }



On Apr 6, 2008, at 2:22 PM, Fernando Padilla wrote:

I have a requirement to not depend on HttpSession, but the Form component has a @Persist field that Tapestry wants to store in a session. What are some options to avoid this?


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



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

Reply via email to