I've pasted my UserForm.java class below, as well as userForm.page and
the code for the "hiddenUserRoles" component.  There is no Exception,
the hidden fields I'm trying to render simply don't show up.

UserForm.java
----------------------
package org.appfuse.webapp.action;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationTrustResolver;
import org.acegisecurity.AuthenticationTrustResolverImpl;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.apache.commons.lang.StringUtils;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.engine.IEngineService;
import org.apache.tapestry.engine.ILink;
import org.apache.tapestry.event.PageBeginRenderListener;
import org.apache.tapestry.event.PageEvent;
import org.apache.tapestry.form.IPropertySelectionModel;
import org.apache.tapestry.valid.IValidationDelegate;
import org.apache.tapestry.valid.ValidationConstraint;
import org.appfuse.Constants;
import org.appfuse.model.Role;
import org.appfuse.model.User;
import org.appfuse.service.MailEngine;
import org.appfuse.service.RoleManager;
import org.appfuse.service.UserExistsException;
import org.appfuse.service.UserManager;
import org.appfuse.util.StringUtil;
import org.appfuse.webapp.util.RequestUtil;
import org.springframework.mail.SimpleMailMessage;

public abstract class UserForm extends BasePage implements
PageBeginRenderListener {
    public abstract IPropertySelectionModel getAvailableRoles();
    public abstract void setAvailableRoles(IPropertySelectionModel model);
    //public abstract List getUserRoles();
    //public abstract void setUserRoles(List roles);
    public abstract IPropertySelectionModel getCountries();
    public abstract void setCountries(IPropertySelectionModel model);
    public abstract IEngineService getEngineService();
    public abstract MailEngine getMailEngine();
    public abstract SimpleMailMessage getMailMessage();
    public abstract UserManager getUserManager();
    public abstract RoleManager getRoleManager();
    public abstract void setUser(User user);
    public abstract User getUser();
    public abstract void setFrom(String from);
    public abstract String getFrom();

    public void pageBeginRender(PageEvent event) {
        // if user doing an add, create an empty user with default settings
        if ((getUser() == null) && !event.getRequestCycle().isRewinding()) {
            setUser(new User());
            setFrom("list"); // shows role selection
            getUser().addRole(new Role(Constants.USER_ROLE));
        } else if (event.getRequestCycle().isRewinding()) { // before population
            setUser(new User());
        }

        // initialize drop-downs
        if (getAvailableRoles() == null) {
            List roles = (List)
getServletContext().getAttribute(Constants.AVAILABLE_ROLES);
            setAvailableRoles(new RoleModel(roles));
        }
        /*
        List selectedRoles = new ArrayList(getUser().getRoles().size());

        for (Iterator it = getUser().getRoles().iterator();
                 (it != null) && it.hasNext();) {
            Role role = (Role) it.next();
            selectedRoles.add(role.getName());
        }
        setUserRoles(selectedRoles);*/

        if (getCountries() == null) {
            setCountries(new CountryModel(getLocale()));
        }

        // if user logged in with remember me, display a warning that
they can't change passwords
        log.debug("checking for remember me login...");

        AuthenticationTrustResolver resolver = new
AuthenticationTrustResolverImpl();
        SecurityContext ctx = SecurityContextHolder.getContext();

        if (ctx != null) {
            Authentication auth = ctx.getAuthentication();

            if (resolver.isRememberMe(auth)) {
                getSession().setAttribute("cookieLogin", "true");

                // add warning message
                setMessage(getText("userProfile.cookieLogin"));
            }
        }
    }

    public ILink cancel(IRequestCycle cycle) {
        if (log.isDebugEnabled()) {
            log.debug("Entering 'cancel' method");
        }

        if (getFrom() != null && getFrom().equalsIgnoreCase("list")) {
            return getEngineService().getLink(false, "users");
        } else {
            return getEngineService().getLink(false, "mainMenu");
        }
    }

    public ILink save(IRequestCycle cycle) throws UserExistsException {
        if (log.isDebugEnabled()) {
            log.debug("entered save method");
        }

        HttpServletRequest request = getRequest();

        // make sure the password fields match
        IValidationDelegate delegate = getValidationDelegate();

        if (!StringUtils.equals(getUser().getPassword(),
getUser().getConfirmPassword())) {
            addError(delegate, "confirmPasswordField",
                     getMessages().format("errors.twofields",
                            getText("user.confirmPassword"),
getText("user.password")),
                     ValidationConstraint.CONSISTENCY);
        }

        if (delegate.getHasErrors()) {
            return null;
        }

        String password = getUser().getPassword();
        String originalPassword = getRequest().getParameter("originalPassword");

        Boolean encrypt = (Boolean)
getConfiguration().get(Constants.ENCRYPT_PASSWORD);
        boolean doEncrypt = (encrypt != null) ? encrypt.booleanValue() : false;

        if (doEncrypt &&
(StringUtils.equals(getRequest().getParameter("encryptPass"), "true")
||
                !StringUtils.equals("S"+password, originalPassword)) ||
                ("X".equals(request.getParameter(("version"))))) {
            String algorithm = (String)
getConfiguration().get(Constants.ENC_ALGORITHM);

            if (algorithm == null) { // should only happen for test case
                log.debug("assuming testcase, setting algorigthm to 'SHA'");
                algorithm = "SHA";
            }

            getUser().setPassword(StringUtil.encodePassword(password,
algorithm));
        }

        // workaround for input tags that don't aren't set by Tapestry
(who knows why)
        boolean fromList = StringUtils.equals(getFrom(), "list");
        String[] userRoles = null;

        if (fromList) {
            userRoles = getRequest().getParameterValues("userRoles");
        } else {
            userRoles = getRequest().getParameterValues("hiddenUserRoles");
        }

        User user = getUser();
        UserManager userManager = getUserManager();

        user.getRoles().clear();
        for (int i = 0; (userRoles != null) && (i < userRoles.length); i++) {
            String roleName = userRoles[i];
            user.addRole(getRoleManager().getRole(roleName));
        }

        try {
            userManager.saveUser(user);
        } catch (UserExistsException e) {
            log.warn(e.getMessage());
            addError(delegate, "emailField",
                     getMessages().format("errors.existing.user",
user.getUsername(),
                            user.getEmail()), ValidationConstraint.CONSISTENCY);
            getUser().setPassword(user.getConfirmPassword());
            getUser().setVersion(null);
            return null;
        }

        if (!fromList &&
user.getUsername().equals(getRequest().getRemoteUser())) {
            // add success messages
            MainMenu nextPage = (MainMenu) cycle.getPage("mainMenu");
            nextPage.setMessage(getText("user.saved", user.getFullName()));
            return getEngineService().getLink(false, nextPage.getPageName());
        } else {
            // add success messages
            if ("X".equals(request.getParameter(("version")))) {
                sendNewUserEmail(request, user);
                UserList nextPage = (UserList) cycle.getPage("users");
                nextPage.setMessage(getText("user.added", user.getFullName()));
                //cycle.activate(nextPage); // return to the list screen
                return getEngineService().getLink(false,
nextPage.getPageName());
            } else {
                setMessage(getText("user.updated.byAdmin", user.getFullName()));
                //cycle.activate("userForm"); // return to current page
                return getEngineService().getLink(false, "userForm");
            }
        }
    }

    public ILink delete(IRequestCycle cycle) {
        if (log.isDebugEnabled()) {
            log.debug("entered delete method");
        }

        getUserManager().removeUser(getUser().getUsername());

        UserList nextPage = (UserList) cycle.getPage("users");
        nextPage.setMessage(getText("user.deleted", getUser().getFullName()));
        return getEngineService().getLink(false, nextPage.getPageName());
    }

    public List getUserRoles() {
        List selectedRoles = new ArrayList(getUser().getRoles().size());

        for (Iterator it = getUser().getRoles().iterator();
                 (it != null) && it.hasNext();) {
            Role role = (Role) it.next();
            selectedRoles.add(role.getName());
        }
        return selectedRoles;
    }

    private void sendNewUserEmail(HttpServletRequest request, User user) {
        // Send user an e-mail
        if (log.isDebugEnabled()) {
            log.debug("Sending user '" + user.getUsername() + "' an
account ingetTextion e-mail");
        }

        SimpleMailMessage message = getMailMessage();
        message.setTo(user.getFullName() + "<" + user.getEmail() + ">");

        StringBuffer msg = new StringBuffer();
        msg.append(getText("newuser.email.message", user.getFullName()));
        msg.append("\n\n" + getText("user.username"));
        msg.append(": " + user.getUsername() + "\n");
        msg.append(getText("user.password") + ": ");
        msg.append(user.getPassword());
        msg.append("\n\nLogin at: " + RequestUtil.getAppURL(request));
        message.setText(msg.toString());

        message.setSubject(getText("signup.email.subject"));
        getMailEngine().send(message);
    }
}

userForm.page:
--------------------------------
<?xml version="1.0"?>
<!DOCTYPE page-specification PUBLIC
    "-//Apache Software Foundation//Tapestry Specification 4.0//EN"
    "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd";>

<page-specification class="org.appfuse.webapp.action.UserForm">
        <inject property="engineService" object="engine-service:page"/>
        <inject property="request"
object="service:tapestry.globals.HttpServletRequest"/>
    <inject property="response"
object="service:tapestry.globals.HttpServletResponse"/>

    <bean name="delegate" class="org.apache.tapestry.valid.ValidationDelegate"/>
    <bean name="multipleCheckboxRenderer"
class="org.appfuse.webapp.tapestry.CheckBoxMultiplePropertySelectionRenderer"/>
    <bean name="hiddenCheckboxRenderer"
class="org.appfuse.webapp.tapestry.HiddenMultiplePropertySelectionRenderer"/>

    <bean name="zipValidator"
class="org.apache.tapestry.valid.PatternValidator">
        <!--set name="patternString" value="\\d{5}(-\\d{4})?"/-->
        <set name="required" value="true"/>
        <set name="patternNotMatchedMessage" value="message:errors.zip"/>
        <set name="clientScriptingEnabled" value="true"/>
    </bean>

    <bean name="phoneValidator"
class="org.apache.tapestry.valid.StringValidator">
        <set name="required" value="true"/>
        <set name="minimumLength" value="11"/>
        <set name="clientScriptingEnabled" value="true"/>
    </bean>

    <bean name="emailValidator"
class="org.apache.tapestry.valid.EmailValidator">
        <set name="clientScriptingEnabled" value="true"/>
        <set name="minimumLength" value="8"/>
        <set name="required" value="true"/>
        <set name="clientScriptingEnabled" value="true"/>
    </bean>

    <component id="form" type="Form">
        <binding name="delegate" value="beans.delegate"/>
        <binding name="clientValidationEnabled" value="true"/>
    </component>

    <inject property="userManager" object="spring:userManager"/>
    <inject property="roleManager" object="spring:roleManager"/>
    <property name="user"/>
    <property name="from"/>
    <property name="userRoles"/>
    <property name="message" persist="flash"/>

    <component id="usernameField" type="TextField">
        <binding name="value" value="user.username"/>
        <binding name="validator" value="validators:required"/>
        <binding name="displayName" value="message:user.username"/>
    </component>

    <component id="passwordField" type="TextField">
        <binding name="hidden" value="true"/>
        <binding name="value" value="user.password"/>
        <binding name="validator" value="validators:required"/>
        <binding name="displayName" value="message:user.password"/>
    </component>

    <component id="confirmPasswordField" type="TextField">
        <binding name="hidden" value="true"/>
        <binding name="value" value="user.confirmPassword"/>
        <binding name="validator" value="validators:required"/>
        <binding name="displayName" value="message:user.confirmPassword"/>
    </component>

    <component id="firstNameField" type="TextField">
        <binding name="value" value="user.firstName"/>
        <binding name="validator" value="validators:required"/>
        <binding name="displayName" value="message:user.firstName"/>
    </component>

    <component id="lastNameField" type="TextField">
        <binding name="value" value="user.lastName"/>
        <binding name="validator" value="validators:required"/>
        <binding name="displayName" value="message:user.lastName"/>
    </component>

    <component id="cityField" type="TextField">
        <binding name="value" value="user.address.city"/>
        <binding name="validator" value="validators:required"/>
        <binding name="displayName" value="message:user.address.city"/>
    </component>

    <component id="stateField" type="TextField">
        <binding name="value" value="user.address.province"/>
        <binding name="validator" value="validators:required"/>
        <binding name="displayName" value="message:user.address.province"/>
    </component>

    <!-- TODO: Validate this field -->
    <component id="countryField" type="PropertySelection">
        <binding name="model" value="countries"/>
        <binding name="value" value="user.address.country"/>
        <!-- Doesn't work -->
        <!--message-binding name="displayName" key="user.address.country"/-->
    </component>

    <component id="addressField" type="TextField">
        <binding name="value" value="user.address.address"/>
    </component>

    <component id="postalCodeField" type="TextField">
        <binding name="value" value="user.address.postalCode"/>
        <binding name="validator" value="beans.zipValidator"/>
        <binding name="displayName" value="message:user.address.postalCode"/>
    </component>

    <component id="emailField" type="TextField">
        <binding name="value" value="user.email"/>
        <binding name="validator" value="beans.emailValidator"/>
        <binding name="displayName" value="message:user.email"/>
    </component>

    <component id="phoneNumberField" type="TextField">
        <binding name="value" value="user.phoneNumber"/>
        <binding name="validator" value="beans.phoneValidator"/>
    </component>

    <component id="websiteField" type="TextField">
        <binding name="value" value="user.website"/>
        <binding name="validator" value="validators:required"/>
        <binding name="displayName" value="message:user.website"/>
    </component>

    <component id="passwordHintField" type="TextField">
        <binding name="value" value="user.passwordHint"/>
        <binding name="validator" value="validators:required"/>
        <binding name="displayName" value="message:user.passwordHint"/>
    </component>

    <component id="userRoles" type="contrib:MultiplePropertySelection">
       <binding name="model" value="availableRoles"/>
       <binding name="selectedList" value="userRoles"/>
       <binding name="renderer" value="beans.multipleCheckboxRenderer"/>
    </component>

    <component id="hiddenUserRoles" type="contrib:MultiplePropertySelection">
       <binding name="model" value="availableRoles"/>
       <binding name="selectedList" value="userRoles"/>
       <binding name="renderer" value="beans.hiddenCheckboxRenderer"/>
    </component>
</page-specification>

HiddenMultiplePropertySelectionRenderer.java:
---------------------------------------------------------------------
package org.appfuse.webapp.tapestry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.contrib.form.IMultiplePropertySelectionRenderer;
import org.apache.tapestry.contrib.form.MultiplePropertySelection;
import org.apache.tapestry.form.IPropertySelectionModel;

/**
 *  Implementation of [EMAIL PROTECTED] IMultiplePropertySelectionRenderer} that
 *  produces hidden fields.  This is designed so some users can see checkboxes
 *  and others can't.
 *
 *  @author Matt Raible
 *
 **/
public class HiddenMultiplePropertySelectionRenderer
    implements IMultiplePropertySelectionRenderer {
    protected final Log log = LogFactory.getLog(getClass());

    /**
     *  Writes the &lt;table&gt; element.
     *
     **/
    public void beginRender(MultiplePropertySelection component,
                            IMarkupWriter writer, IRequestCycle cycle) {
    }

    /**
     *  Closes the &lt;table&gt; element.
     *
     **/
    public void endRender(MultiplePropertySelection component,
                          IMarkupWriter writer, IRequestCycle cycle) {
    }

    public void renderOption(MultiplePropertySelection component,
                             IMarkupWriter writer, IRequestCycle cycle,
                             IPropertySelectionModel model, Object option,
                             int index, boolean selected) {
        if (selected) {
            writer.begin("input");
            writer.attribute("type", "hidden");
            writer.attribute("name", component.getName());

            String id = component.getName() + "." + model.getValue(index);
            writer.attribute("id", id);
            writer.attribute("value", model.getValue(index));
            writer.end();
            writer.print(model.getLabel(index));
            if (index < (model.getOptionCount()-2)) {
                writer.printRaw(", ");
            }
            writer.println();
        }
    }
}

Thanks,

Matt
On 3/6/06, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote:
> Indeed odd.
> Can you post some code + the exception you're getting?
>
> From  Matt Raible <[EMAIL PROTECTED]>:
>
> > On 3/5/06, Jesse Kuhnert <[EMAIL PROTECTED]> wrote:
> > > That sounds odd. What happens if you try making it "ognl:getUserRoles()"
> > > instead?
> >
> > I tried this based on your recommendation.  Unfortunately, it does not work.
> >
> > Matt
> >
> > >
> > >
> > > On 3/5/06, Matt Raible < [EMAIL PROTECTED]> wrote:
> > > > Yes, I am using the 4.0 DTD with the following:
> > > >
> > > >     <component id="userRoles"
> > > type="contrib:MultiplePropertySelection">
> > > >        <binding name="model" value="availableRoles"/>
> > > >        <binding name="selectedList" value="userRoles"/>
> > > >        <binding name="renderer" value="beans.multipleCheckboxRenderer"/>
> > > >     </component>
> > > >
> > > > Matt
> > > >
> > > > On 3/5/06, [EMAIL PROTECTED] < [EMAIL PROTECTED]> wrote:
> > > > > Aren't you using the 4.0 dtd?
> > > > > It should be
> > > > > <binding name="selectedList" value="userRoles"/>
> > > > >
> > > > >
> > > > > From Matt Raible < [EMAIL PROTECTED]>:
> > > > >
> > > > > > In Tapestry 3, I had methods in my pages like the following:
> > > > > >
> > > > > >     public List getUserRoles() {
> > > > > >         List selectedRoles = new
> > > ArrayList(getUser().getRoles().size());
> > > > > >
> > > > > >         for (Iterator it =
> > > getUser().getRoles().iterator();
> > > > > >                  (it != null) && it.hasNext();) {
> > > > > >             Role role = (Role) it.next();
> > > > > >             selectedRoles.add(role.getName());
> > > > > >         }
> > > > > >
> > > > > >         return selectedRoles;
> > > > > >     }
> > > > > >
> > > > > > I then called them in my .page specification using:
> > > > > >
> > > > > >     <component id="userRoles"
> > > type="contrib:MultiplePropertySelection">
> > > > > >        <binding name="model" expression="availableRoles"/>
> > > > > >        <binding name="selectedList" expression="userRoles"/>
> > > > > >        <binding name="renderer"
> > > > > > expression="beans.multipleCheckboxRenderer"/>
> > > > > >     </component>
> > > > > >
> > > > > > Hower, it doesn't seem that this is possible with Tapestry 4 - even
> > if
> > > > > > I use expression="ognl:userRoles".  I have to add an abstract
> > > > > > getUserRoles() method and put the above logic in my
> > pageBeginRender()
> > > > > > method.
> > > > > >
> > > > > > Is this "as designed" or am I doing something wrong?
> > > > > >
> > > > > > Thanks,
> > > > > >
> > > > > > Matt
> > > > > >
> > > > > >
> > > ---------------------------------------------------------------------
> > > > > > 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]
> > > >
> > > >
> > >
> > >
> >
> > ---------------------------------------------------------------------
> > 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