RegexpValidator failing for all of my Vaadin 6-style form fields using Conv

In porting to Vaadin 7, my Form (don’t want to convert everything just yet!) has several fields that make use of some of our types (like we have EsfString and EsfInteger classes for our own handling of strings and integers). I found that nothing would work until I created a Converter for these fields, which I did, so they can convert between String and their types.

But now they are all failing the RegexpValidator check. I know that before it did the validation on the String presentation value, so the regular expressions worked, but I wonder now if it won’t work if the base field type needs the converter to function first. Is that true? Does it not convert the field to String before sending to the RegexpValidator?

The chain is Field->Converter->Validator->DataSource, so if you convert the value from a String to something else, then you need to use that something else in your validator.

Thanks, Thomas. I’m not sure what is different then. I mean, my validator always worked on a String, and I’m getting a String as expected in my Validator, but one issue I’m facing is that the field is optional (not required), so it can be blank. It’s as if under Vaadin 6, a blank/null value in a TextField that was optional didn’t call the validator, but now it does. Is that possible?

Further checking seems to indicate that my EsfName class which is tied to a TextField and has a Converter to go between String/EsfName displays fine in the form, but when it comes time to run my Validator, it receives an EsfName object which the regular expression validator cannot handle. So the validator appears to be getting directly from the data source without being converted to a string, which is only a bit confusing because if the user types in the TextField, it will be just a String until it’s validated and can be converted to my EsfName type.

It seems I can no longer just extend RegexpValidator regardless of the Converter.

That does sound correct. The whole point of the converters was to convert the data to a more ‘real’ format before validations/storage…

Perhaps, but it’s not as easy as under Vaadin 6 where I needed no converter AND I could subclass the RegexpValidator to validate my own objects.

I guess I’m a bit confused on how to proceed with this. My object has a perfectly good String representation, and the Converter handles this well (though automatic in Vaadin 6 via toString() and a constructor that takes a string).

But the validator is attempting to convert the string to my object type BEFORE it’s been validated, and if the value entered into the TextField is not valid, it cannot even create my model object. I need to check the string version held in the TextField first. This is particularly an issue because of my object can only hold values 0 and 1, for example, and the user enters 2, the object cannot be created, and then on validation failure it then attempts to take the bad object and convert it to a string for the text field. I must be missing something about how this is done in Vaadin 7 since this worked like a charm in Vaadin 6.

Maybe I’m going about this the wrong way. Perhaps I don’t need to use a Validator for the field anymore, but can rely on the Converter to throw an exception if it’s not in the valid format. Is that the new way?

Unfortunately, it seems that if I add an error message to the ConversionException, that does not get displayed to the user when they hover over the error indicator. They just get a “Could not convert value to EsfName” which is meaningless to our users. I’d like the conversion exception to be thrown and show it’s message, or when I throw it, it still calls my validator so that message can be shown as the reason for the invalid field.

But I don’t see how it can call my validator using an object rather than the string entered since an object cannot be created using an invalid value to begin with. This appears to be incorrect and the validator should only operate on the string value of the input field (in this case a TextField) since the validator can convert to its own type necessary, but surely the validation has to take place on what is entered by the user and not after any convert-to-model.

Is this a bug in the validators (being given an instance of of our Model object instead of the Presentation object) or is there a correct way to do this?

It seems to me that it’s clear that the validators can only operate on the presentation value (what’s been entered by the user) and not on the model value (as the model object should only be correctly instantiated if the presentation value is valid for the model).

Sorry for the delay…

I just tested this to be sure; Validators are run on the Model value, not the Presentation value. The field tries to convert the value first. If that fails, there is a conversion exception. Then it runs the validators, which can throw ValidationExceptions.

So in your case, where the actual conversion is the issue, I would do as you suggested yourself and move the checks to a custom Converter instead. The exception it throws is similarly handled to a ValidationException anyway.

So are you saying this peculiar logic is not a bug and will stay implemented as is in Vaadin 7? This is not natural and seems incorrect to me and should be a bug. It was handled correctly under Vaadin 6.

It does not make sense that I am validating a Model object when the data was entered into the Presentation object. If the Presentation object’s value is not valid, it is an error to then create the Model object.

I have blocked the creation of the Model object when the data is not valid, but I shouldn’t really have to do this because my validator should reject the creation of model objects that are not in a valid format to begin with. Well, I guess it would be “somewhat workable” if the exception message thrown by the converters was shown as the error to the user rather than the generic “Could not convert value to MODELCLASSNAME” which is not meaningful to a user who cares nothing about model class names. But that’s not really correct either, and of course wouldn’t happen if the validator ran first.

The validator should only work on the presentation object since it is validating input from the presentation layer, not validating my existing model objects.

Since validators are added to presentation widgets, they should operate on presentation objects. Or at the very least, the exception thrown for presentation-to-model conversions should show the exception text (though this is definitely less than ideal since validators tend to be customized per input field and converters can be shared easily rather than writing special versions just to report specialized errors). That is, a converter may allow the string “1000” to be converted to a number model object because it’s a valid number, but a validator may reject it because the number should be between 1 and 10.

In the end, though, creating a model object on data that is not validated first is just wrong. It makes sense to validate the input before creating the model object. We’d like to know before we attempt to change our model to work around this new Vaadin 7 design for validators that was never the case in Vaadin 6.

I have created ticket
http://dev.vaadin.com/ticket/11942
to track this as I believe it’s a bug in that validators should just work on presentation data. But even if that’s not the case, then the error message included in the ConversionException when converting from presentation to model should be shown to the user instead the generic message that is not user friendly.

We discussed this internally, and came to a couple of realizations;

  • there is an omission with the ConversionException, the message should be displayed in the field.
  • some of us agreed with you that the converter is not the correct place to validate, while others thought that validation the model data is more logical.
    No consensus here then; the more important point is that we are already at a stable release, so we can’t break anything.

There are a couple of tickets associated with this:
http://dev.vaadin.com/ticket/8100
and
http://dev.vaadin.com/ticket/10930
.

In your case, it is probably easiest to not use converters. Instead, you make String validators (like you used to) and create custom Properties instead, that take a String value but store your model objects.

And about the ticket you created; unfortunately that will break many existing V7 apps, and as such is very likely a wontfix. It will get better after we fix the conversion error messages, though.

edit wrong thread :slight_smile:

I think the new Vaadin 7 way to do this is to add a field.setConverterError(String) so that when the data model object conversions fails – if you have model objects you should really consider having a converter to deal with the possibility of your objects being created with pre-validated user input – it doesn’t show the exception text, but instead shows the text you put in setConvertError().

It seems to be working for me except for PopupDateField which seems to produce its own error when an invalid date like “D” is entered – as if it’s not using a String to Date converter that throws an exception so my error can be shown (or the configured error is just ignored).

It’s just more of a pain since we basically have more to do when using model objects with Vaadin:

  1. a Converter between your model object and typically a String for the presentation layer, and one that also checks the presentation data to ensure it’s “valid enough” to at least instantiate your model object with it;
  2. For each field that uses that model object, add a field.setConverterError(“invalid input”) to give an nice error when the input is not valid for creating the object (like “D” for Integer, Date, UUID and of course model objects like IPAddress, EmailAddress…whatever);
  3. Create a Validator if your model object also has other validations beside whether the input data is correct, such as range checking or the like (many of our validators were for input only checking, so that code is now in the Converter and the message that is displayed when invalid is moved to field.setConverterError().