开发者

ConversionErrorInterceptor throws conversion error during quit/cancel (Struts 2)

The scenario of the problem is this

1) We map the struts field values to the dtos. The dtos contain integer fields which again are displayed on the screen.

2) Now I enter an incorrect value which gives conversion error for that integer field.

3) At that point in time I decide to quit the page(i.e pres开发者_开发问答s cancel), I get a conversion error. This is because the StrutsConversionErrorInterceptor gets called everytime.

Is there any way that I can skip the strutsConversionErrorInterceptor when I am calling a particular method the way we can skip validation using excludeMethods


Use this code to override Struts's StrutsConversionErrorInterceptor...

public class MyConversionErrorInterceptor extends AbstractInterceptor {

    private static final long serialVersionUID = 1L;

    public static final String ORIGINAL_PROPERTY_OVERRIDE = "original.property.override";

    protected Object getOverrideExpr(ActionInvocation invocation, Object value) {
         ValueStack stack = invocation.getStack();

            try {
                stack.push(value);

                return "'" + stack.findValue("top", String.class) + "'";
            } finally {
                stack.pop();
            }
    }

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {

        ActionContext invocationContext = invocation.getInvocationContext();
        Map<String, Object> conversionErrors = invocationContext.getConversionErrors();
        ValueStack stack = invocationContext.getValueStack();

        HashMap<Object, Object> fakie = null;

        BaseAction baseAction = (BaseAction) invocation.getAction();
        String buttonName = baseAction.getButtonName();

        for (Map.Entry<String, Object> entry : conversionErrors.entrySet()) {
            String propertyName = entry.getKey();
            Object value = entry.getValue();

            if (shouldAddError(propertyName, value)) {
                String message = XWorkConverter.getConversionErrorMessage(propertyName, stack);

                Object action = invocation.getAction();
                if (action instanceof ValidationAware) {
                    ValidationAware va = (ValidationAware) action;
                      if(buttonName.equalsIgnoreCas("Next")){
                          va.addFieldError(propertyName, message);
                      }
                }

                if (fakie == null) {
                    fakie = new HashMap<Object, Object>();
                }
                 if(buttonName.equalsIgnoreCas("Next")){
                     fakie.put(propertyName, getOverrideExpr(invocation, value));
                 }
            }
        }

        if (fakie != null) {
            // if there were some errors, put the original (fake) values in
            // place right before the result
            stack.getContext().put(ORIGINAL_PROPERTY_OVERRIDE, fakie);
            invocation.addPreResultListener(new PreResultListener() {
                public void beforeResult(ActionInvocation invocation, String resultCode) {
                    Map<Object, Object> fakie = (Map<Object, Object>) invocation.getInvocationContext().get(ORIGINAL_PROPERTY_OVERRIDE);

                    if (fakie != null) {
                        invocation.getStack().setExprOverrides(fakie);
                    }
                }
            });
        }

        return invocation.invoke();
    }

    protected boolean shouldAddError(String propertyName, Object value) {

        if (value == null) {
            return false;
        }

        if ("".equals(value)) {
            return false;
        }

        if (value instanceof String[]) {
            String[] array = (String[]) value;

            if (array.length == 0) {
                return false;
            }

            if (array.length > 1) {
                return true;
            }

            String str = array[0];

            if ("".equals(str)) {
                return false;
            }
        }

        return true;

    }

}

You can specify you button names on which you want validation to fire. In above code I have used "Next" in code you can see

if(buttonName.equalsIgnoreCas("Next"))


Yes, you can skip calling the interceptor.

Just remove the interceptor definition from your action definition in struts.xml file. i.e., remove <interceptor-ref name="conversionError"/>

Mainly this interceptor adds any error found in the ActionContext's conversionErrors map as a field error (provided that the action implements ValidationAware). In addition, any field that contains a validation error has its original value saved such that any subsequent requests for that value return the original value rather than the value in the action. This is important because if the value "abc" is submitted and can't be converted to an int, we want to display the original string ("abc") again rather than the int value (likely 0, which would make very little sense to the user).

After you removed this interceptor, if the struts failed to map the field with parameter of the object(i.e., from string to int), it throws result input action error.


This seems to be a better method to handle this scenario - using Conversion Validator. Repopulating Field upon conversion Error section is something very useful:

http://struts.apache.org/2.0.14/docs/conversion-validator.html

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜