Didn't know about gist... :-( Promise not posting code in emails again...

The solution I posted is just a quick fix - not the solution. I
thought adding a "endEvents" property to the Wizard Annotation and a
check in the ActionBeanPropertyBinder would solve the problem quickly
without loosing backwards compatibility. But hey, this is up to the
stripes developers :-)

On Wed, Feb 10, 2010 at 9:28 AM,  <[email protected]> wrote:
> Thanks a lot Richard for your Code. I think instead of marking
> Just the final Steps, we should define the whole order of the EventHandlers.
>
> This would allow stripes to ensure that the user passes trough step by step.
> Another benefit we would get is, that we can allow "backward navigation" 
> without
> Displaying invalid error messages.
>
> I have opened a jira ticket and illustrated my thoughts in a gist:
>
> Ticket: http://www.stripesframework.org/jira/browse/STS-737
> Gist: https://gist.github.com/1072357cbedbcbf0f587
>
> Cheers,
> Yves Senn
>
>
> -----Ursprüngliche Nachricht-----
> Von: Richard Hauswald [mailto:[email protected]]
> Gesendet: Dienstag, 9. Februar 2010 14:27
> An: Stripes Users List
> Betreff: Re: [Stripes-users] Skip pages in Wizards
>
> Hello Stripes Users,
> I set up a test case and it proves Yves Senn 's statement.
> You can solve this issue temporarily by using a custom PropertyBinder
> and a new Annotation marking the method called at the end of a wizard.
> Cheers,
> Richard
>
> Example:
>
> web.xml
> <init-param>
>        <param-name>ActionBeanPropertyBinder.Class</param-name>
>        <param-value>x.y.z.WizardPropertyBinder</param-value>
> </init-param>
>
>
> LastWizardPage.java
>
> import java.lang.annotation.ElementType;
> import java.lang.annotation.Retention;
> import java.lang.annotation.RetentionPolicy;
> import java.lang.annotation.Target;
>
> @Target(ElementType.METHOD)
> @Retention(RetentionPolicy.RUNTIME)
> public @interface LastWizardPage {
>
> }
>
> WizardPropertyBinder.java
> import java.lang.reflect.Method;
> import java.util.Collection;
> import java.util.HashMap;
> import java.util.HashSet;
> import java.util.Map;
> import java.util.Set;
>
> import javax.servlet.http.HttpServletRequest;
>
> import net.sourceforge.stripes.action.ActionBean;
> import net.sourceforge.stripes.action.ActionBeanContext;
> import net.sourceforge.stripes.action.Wizard;
> import net.sourceforge.stripes.config.Configuration;
> import net.sourceforge.stripes.controller.ActionResolver;
> import net.sourceforge.stripes.controller.DefaultActionBeanPropertyBinder;
> import net.sourceforge.stripes.controller.ParameterName;
> import net.sourceforge.stripes.controller.StripesRequestWrapper;
> import net.sourceforge.stripes.exception.StripesServletException;
> import net.sourceforge.stripes.util.Log;
> import net.sourceforge.stripes.validation.ValidationErrors;
> import net.sourceforge.stripes.validation.ValidationMetadata;
>
> public class WizardPropertyBinder extends DefaultActionBeanPropertyBinder {
>        private static final Log log =
> Log.getInstance(DefaultActionBeanPropertyBinder.class);
>
>       �...@override
>        protected void validateRequiredFields(Map<ParameterName, String[]>
> parameters, ActionBean bean, ValidationErrors errors) {
>                log.debug("Running required field validation on bean class ",
> bean.getClass().getName());
>
>                // Assemble a set of names that we know have indexed 
> parameters, so
> we won't check
>                // for required-ness the regular way
>                Set<String> indexedParams = new HashSet<String>();
>                for (ParameterName name : parameters.keySet()) {
>                        if (name.isIndexed()) {
>                                indexedParams.add(name.getStrippedName());
>                        }
>                }
>
>                Map<String, ValidationMetadata> validationInfos =
> getConfiguration().getValidationMetadataProvider().getValidationMetadata(bean.getClass());
>                ActionBeanContext context = bean.getContext();
>                HttpServletRequest request = context.getRequest();
>                StripesRequestWrapper stripesReq =
> StripesRequestWrapper.findStripesWrapper(request);
>
>                if (validationInfos != null) {
>                        boolean wizard = 
> bean.getClass().getAnnotation(Wizard.class) != null;
>                        boolean lastWizardPage = 
> isLastWizardPage(getConfiguration(), context, bean);
>                        Collection<String> fieldsOnPage = 
> getFieldsPresentInfo(bean);
>
>                        for (Map.Entry<String, ValidationMetadata> entry :
> validationInfos.entrySet()) {
>                                String propertyName = entry.getKey();
>                                ValidationMetadata validationInfo = 
> entry.getValue();
>
>                                // If the field is required, and we don't have 
> index params that collapse
>                                // to that property name, check that it was 
> supplied
>                                if 
> (validationInfo.requiredOn(context.getEventName()) &&
> !indexedParams.contains(propertyName)) {
>
>                                        // Make the added check that if the 
> form is a wizard, the required field is
>                                        // in the set of fields that were on 
> the page
>                                        if (!wizard || lastWizardPage || 
> fieldsOnPage.contains(propertyName)) {
>                                                String[] values = 
> trim(request.getParameterValues(propertyName),
> validationInfo);
>                                                log.debug("Checking required 
> field: ", propertyName, ", with
> values: ", values);
>                                                
> checkSingleRequiredField(propertyName, propertyName, values,
> stripesReq, errors);
>                                        }
>                                }
>                        }
>                }
>
>                // Now the easy work is done, figure out which rows of indexed 
> props
> had values submitted
>                // and what to flag up as failing required field validation
>                if (indexedParams.size() > 0) {
>                        Map<String, Row> rows = new HashMap<String, Row>();
>
>                        for (Map.Entry<ParameterName, String[]> entry : 
> parameters.entrySet()) {
>                                ParameterName name = entry.getKey();
>                                String[] values = entry.getValue();
>
>                                if (name.isIndexed()) {
>                                        String rowKey = 
> name.getName().substring(0,
> name.getName().indexOf(']') + 1);
>                                        if (!rows.containsKey(rowKey)) {
>                                                rows.put(rowKey, new Row());
>                                        }
>
>                                        rows.get(rowKey).put(name, values);
>                                }
>                        }
>
>                        for (Row row : rows.values()) {
>                                if (row.hasNonEmptyValues()) {
>                                        for (Map.Entry<ParameterName, 
> String[]> entry : row.entrySet()) {
>                                                ParameterName name = 
> entry.getKey();
>                                                String[] values = 
> entry.getValue();
>                                                ValidationMetadata 
> validationInfo =
> validationInfos.get(name.getStrippedName());
>
>                                                if (validationInfo != null &&
> validationInfo.requiredOn(context.getEventName())) {
>                                                        
> checkSingleRequiredField(name.getName(),
> name.getStrippedName(), values, stripesReq, errors);
>                                                }
>                                        }
>                                } else {
>                                        // If the row is full of empty data, 
> get rid of it all to
>                                        // prevent problems in downstream 
> validation
>                                        for (ParameterName name : 
> row.keySet()) {
>                                                parameters.remove(name);
>                                        }
>                                }
>                        }
>
>                }
>        }
>
>        protected boolean isLastWizardPage(Configuration config,
> ActionBeanContext context, ActionBean bean) {
>                try {
>                        ActionResolver resolver = config.getActionResolver();
>
>                        // Then lookup the event name and handler method etc.
>                        String eventName = context.getEventName();
>
>                        final Method handler;
>                        if (eventName != null) {
>                                handler = resolver.getHandler(bean.getClass(), 
> eventName);
>                        } else {
>                                handler = 
> resolver.getDefaultHandler(bean.getClass());
>                                if (handler != null) {
>                                        
> context.setEventName(resolver.getHandledEvent(handler));
>                                }
>                        }
>                        return 
> handler.isAnnotationPresent(LastWizardPage.class);
>                } catch (StripesServletException e) {
>                        throw new RuntimeException("This should never happen 
> :-) - only a
> quick fix");
>                }
>
>        }
>        /**
>         * An inner class that represents a "row" of form properties that all
> have the same index
>         * so that we can validate all those properties together.
>         */
>        protected static class Row extends HashMap<ParameterName, String[]> {
>                private static final long serialVersionUID = 1L;
>
>                private boolean hasNonEmptyValues = false;
>
>                /**
>                 * Adds the value to the map, along the way checking to see if 
> there
> are any non-null values for
>                 * the row so far.
>                 */
>               �...@override
>                public String[] put(ParameterName key, String[] values) {
>                        if (!hasNonEmptyValues) {
>                                hasNonEmptyValues = (values != null) && 
> (values.length > 0) &&
> (values[0] != null) && (values[0].trim().length() > 0);
>
>                        }
>                        return super.put(key, values);
>                }
>
>                /** Returns true if the row had any non-empty values in it,
> otherwise false. */
>                public boolean hasNonEmptyValues() {
>                        return this.hasNonEmptyValues;
>                }
>        }
> }
>
>
> On Mon, Feb 8, 2010 at 2:37 PM,  <[email protected]> wrote:
>> Hey Stripes Users
>>
>> We have a lot of multi-page forms implemented with the @Wizard Annotation.
>> This allows us to split required fields over multiple pages. We just noticed 
>> that it
>> Is possible to jump over given pages when changing the name="" Attribute of 
>> the submit button.
>>
>> Since Stripes just validates the fields contained within "__fp" it is 
>> possible to just enter the data
>> On the first page and skip over the whole form process to the last page. The 
>> last page then gets
>> Displayed accordingly. Is this behavior intended?
>>
>> Is there a way to mark an EventHandler in a Wizard to validate all fields 
>> and ignore the "__fp" parameter?
>> We need to be sure that the user passed all steps in the process.
>>
>> Cheers,
>> Yves Senn
>>
>>
>> Sicherheitshinweis:
>> Dieses E-Mail von PostFinance ist signiert. Weitere Informationen finden Sie 
>> unter:
>> https://www.postfinance.ch/e-signature.
>> Geben Sie Ihre Sicherheitselemente niemals Dritten bekannt.
>> ------------------------------------------------------------------------------
>> The Planet: dedicated and managed hosting, cloud storage, colocation
>> Stay online with enterprise data centers and the best network in the business
>> Choose flexible plans and management services without long-term contracts
>> Personal 24x7 support from experience hosting pros just a phone call away.
>> http://p.sf.net/sfu/theplanet-com
>> _______________________________________________
>> Stripes-users mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/stripes-users
>>
>>
>
>
>
> --
> Richard Hauswald
> Blog: http://tnfstacc.blogspot.com/
> LinkedIn: http://www.linkedin.com/in/richardhauswald
> Xing: http://www.xing.com/profile/Richard_Hauswald
>
> ------------------------------------------------------------------------------
> The Planet: dedicated and managed hosting, cloud storage, colocation
> Stay online with enterprise data centers and the best network in the business
> Choose flexible plans and management services without long-term contracts
> Personal 24x7 support from experience hosting pros just a phone call away.
> http://p.sf.net/sfu/theplanet-com
> _______________________________________________
> Stripes-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/stripes-users
>
> Sicherheitshinweis:
> Dieses E-Mail von PostFinance ist signiert. Weitere Informationen finden Sie 
> unter:
> https://www.postfinance.ch/e-signature.
> Geben Sie Ihre Sicherheitselemente niemals Dritten bekannt.
> ------------------------------------------------------------------------------
> SOLARIS 10 is the OS for Data Centers - provides features such as DTrace,
> Predictive Self Healing and Award Winning ZFS. Get Solaris 10 NOW
> http://p.sf.net/sfu/solaris-dev2dev
> _______________________________________________
> Stripes-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/stripes-users
>
>



-- 
Richard Hauswald
Blog: http://tnfstacc.blogspot.com/
LinkedIn: http://www.linkedin.com/in/richardhauswald
Xing: http://www.xing.com/profile/Richard_Hauswald

------------------------------------------------------------------------------
SOLARIS 10 is the OS for Data Centers - provides features such as DTrace,
Predictive Self Healing and Award Winning ZFS. Get Solaris 10 NOW
http://p.sf.net/sfu/solaris-dev2dev
_______________________________________________
Stripes-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-users

Reply via email to