3

I am using the OmniFaces <o:viewParam> taghandler in my current project. I like it, it's great. And even greater is the <o:viewParamValidationFailed>. Now, we are able to send an error if validation or conversion fails. But I wonder, whether it is possible to distinguish between conversion failure and validation failure.

Let's say we want to send a Bad Request if the given view param in malformed and can not be converted; for that matter send a Not Found if conversion succeeded, but the object could not be found in the database; and send a Forbidden if the successfully fetched object should not be accessed by the user.

Does anybody know a way to achieve this?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
darefilz
  • 641
  • 6
  • 19

1 Answers1

4

It's unfortunately not possible to distinguish between a ConverterException and ValidatorException when you've only UIInput#isValid() at hands. Theoretically, you could check and test the faces message to see if it represents a conversion or validation error, but this is not a robust approach, certainly not when it's localized.

On the other hand, it's possible to declare multiple view parameters on the same parameter name. You do not necessarily need to specify a value to set it as model value.

Here's an example based on your description, note that the model value is only set on the last one:

<o:viewParam name="foo">
    <f:converter converterId="yourFooConverter" />
    <o:viewParamValidationFailed sendError="400" />
</o:viewParam>
<o:viewParam name="foo">
    <f:converter converterId="yourFooConverter" />
    <f:validateRequired />
    <o:viewParamValidationFailed sendError="404" />
</o:viewParam>
<o:viewParam name="foo" value="#{bean.foo}">
    <f:converter converterId="yourFooConverter" />
    <f:validateRequired />
    <f:validator validatorId="yourRestrictedAccessValidator" />
    <o:viewParamValidationFailed sendError="403" />
</o:viewParam>

To avoid the expensive job of calling the DB on every conversion, let the YourFooConverter implementation store the converted value as a custom attribute of the FacesContext and then check it on every pass.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • It works. Great job. I already tried this approach, but missed to specify the converter in each viewParam taghandler. – darefilz Nov 08 '14 at 12:26
  • I just wrote this optimization (store the converted value as a custom attribute), but apparently the given `UIComponent` is the `o:viewParam` of each pass and therefore not consistent. I simply add the value to the given `FacesContext` which works fine in all tests. Is there any reason not to do so? – darefilz Nov 19 '14 at 21:34