How to make business validations on fields in editable Table? - vaadin

Here is the deal: I have a Table who uses a BeanItemContainer of "MyBean". "MyBean" is not really relevant, it contains only 1 String and 2 Date objects.
But the user must be allowed to change theses values for each instance of MyBean in my container.
To do that, it's easy, just do myTable.setEditable(true). Or a little bit more complex, create a Table.ColumnGenerator who returns a Field (add a ValueChangeListener to push the new value inside the bean).
With the Table.ColumnGenerator, I'm also able to add specific validations for each Field, that's great!
The purpose of this is to render the Field in "error mode".
But there is something I'm not able to do: make my business validations after the user clicks on the "Save" button and retrieve the corresponding field to call the method setComponentError(...).
Only basic validations can be done (integer only, max value, date time range, ...) but for more complex validations (business requirements) I don't know...
How can I do that?

You can write your own custom validators by implementing Validator interface and in them implement custom business logic.
public class MyValidator implements Validator {
void validate(Object valueToValidate) throws Validator.InvalidValueException {
//Your Business logic
}
}

Related

Grails binding one to one associations

When you generate grails views, grails looks at your relationships and generates the right html for your form data to be automatically binded to the back end domain. For one to one associations grails creates a drop down list.
However, you might not want to present that property as a drop down list but something more custom (for example a text field with autocomplete). As soon as you do that the value that comes to the controller from that field, comes in as a String and you have to first:
Clear errors
Perform a findBy based on a given param and assign it to the property of the domain
I really want to avoid doing findBys in the controller as much as possible because it seems like I am doing logic/things that should not go there. The controller should delegate to the Service layer. It is not clear to me from the grails documentation how would I do that by using bindData which seems to work really well with String, date, Integer properties etc.. but I do not see how bindData is used for properties that are other domains.
I also really want to avoid passing the params object to the Service layer as it seems less reusable (or maybe not, correct me if I am wrong). I guess that I do not like how it looks semantically. I would prefer the first over the second:
#Transactional
class WithdrawService {
def addWithdraw(Withdraw withdraw) {
//perform business logic here
}
def createWithdraw(Map params){
//perform business logic here
}
}
Let's take the following example:
class Withdraw {
Person person
Date withdrawDate
}
and the parent lookup table
class Person {
String name
String lastName
static constraints = {
}
#Override
public String toString() {
return "$name $lastName"
}
}
In order for the bind to happen automatically without any extra work grails passes in the following request params to automatically bind the one to one:
person.id
a person map with the id.
[person.id:2, person:[id:2], withdrawDate:date.struct, withdrawDate_month:11, create:Create, withdrawDate_year:2015, withdrawDate_day:10, action:save, format:null, controller:withdraw]
What is the best way to go about this?
Pass two hidden fields that look exactly like this: person.id:2, person:[id:2] that get populated as a result of the Ajax call that populates the autocomplete?
In the controller do a Person.findBySomeKnownProperty(params.someKnownValue)
Or any other approach?

MVC Model binding / validation

After a year or so of MVC experience I'm still confused about one thing: How to effectively use the DataAnnotations with ModelState.IsValid? For simple tutorial example this all works just fine and I have no questions about that. But supposed I have the following model:
Public Class Movie
Public Property MovieID As Integer
Public Property Title As String
Public Property Year As Integer
Public Property AddedByUser As String
End Class
Now the field AddedByUser is required in the database however I don't want the user to provide this but rather the business logic based on the currently logged in user. How would I use the DataAnnotation attributes for this scenario? If I make this field required then in the controller when I say:
Public Function SaveMovie(ByVal entity as Movie) As ActionResult
If ModelState.IsValid
// Save to DB here...
End If
Return View(entity)
End Function
... the validation will fail because I don't have that field in the view bindings. Should I have a hidden field for this? Should I write a custom view model for SaveMovie action? I suppose I could write my own validation in business logic but then why use model validation at all? Custom model binder perhaps? What is the best way to handle these types of scenarios?
Just to give another example scenario what about the difference between insert and update operation and validation? For update operations object's primary key is required. However that is not the case for inserts. Are you supposed to have separate models for insert and update just because of this one key property?
so the way that I handle this is I use the DataAnnotation based validation for user input type stuff. i.e. Validation on email addresses, dates, required fields etc. Stuff that you need a quick 'sanity check' on and need to double check the users entries on.
I don't put any DataAnnotations on the fields that my Database controls or my code controls, i.e. Primary Keys, your [AddedByUser] property as the user doesn't access these properties directly and so you shouldn't have to add validation checks on this. Since your code is the only thing that updates these properties, why validate them?
For more 'business rule' type validation I implement IValidatableObject on my model which gets run, in MVC, after all property-level validations have succeeded. Note that it won't run if the property-level validations fail. And this makes sense, because if the data is 'dirty' you wouldn't want to proceed to run more complex validation etc.
Hope this helps :)

in a well-constructured cms-type system where in the architecture should a business object be created?

This is a question regarding architecture.
Let's say that I have created a layered system in ASP.NET MVC with a good domain layer which uses the repository pattern for data-access. One of those domain objects is Product. At the CMS-side I have a view for creating and editing products. And I have a front-end where that product should be shown. And these views differ considerably so that a different viewmodel for them is appropriate.
1) Where should a new Product object be created when the user enters data for a new product in the data entrance view? In the controller? But making the controller responsible for object creation could hurt the Single Responsibility principle. Or should the factory pattern be used? That would mean that the factory would be very specific, because the data entered would be passed 'as is' to the factory. So coding against an IProductFactory would not be possible, because the input data is specific to that data entrance view. So is it right that we have a tight coupling between this controller and the factory?
2) The Product viewmodel to be shown at the frontend, where should that come from? The answer seems to me a ViewModelFactory that takes the domain object Product and creates a view from it. But again, this viewmodelfactory would be specific for this view, because the viewmodel we are asking for is specific. So is it right then that the controller and the viewmodelfactory would be tightly coupled?
3) Validation: The input data should be validated at the frontend, but the domain layer should also validate the product (because the domain layer knows nothing about the UI and does not even know IF the UI does validation and thus should not depend upon validation there). but where should the validation go? The ProductFactory seems to be a good choice; it seems to me that that adheres to SRP, if the task of a product factory is described as 'creating valid product objects.'
But perhaps the Product business object should contain the validation. That seems more appropriate because validation of a product will not only be needed at creation time but at other places as well. But how can we validate a Product that is not yet created? Should the Product business object then have methods like IsNameValid, IsPriceValid etc??
I'm going to answer your second question first.
Yes, viewmodels should be tightly coupled with the controller. You shouldn't need a ViewModelFactory though. Something like AutoMapper or ValueInjecter should be good enough for converting domain Product to ProductViewModel.
As for your first question, you should keep your domain Product Factory separate from your controller. There are a few different approaches you could use. One would be creating a factory method that only takes scalar values as method arguments -- for example string, bool, etc, other primitives, and pure .NET types.
You can then have your controller pass the scalars to the factory method from the viewmodel. This is loosely coupled, and highly cohesive.
For example:
[HttpPost]
public ActionResult CreateProduct(ProductViewModel model)
{
if (ModelState.IsValid)
{
// assuming product factory is constructor-injected
var domainProduct = _productFactory.BuildProduct(
model.Name, model.Price, model.Description);
// ... eventually return a result
}
return View(model);
}
Another approach is to put the methods for passing viewmodel properties directly on the domain object, but for this approach, it is best to make your property setters non-public:
[HttpPost]
public ActionResult CreateProduct(ProductViewModel model)
{
if (ModelState.IsValid)
{
// assuming no product factory
var domainProduct = new Domain.Product();
domainProduct.SetName(model.Name);
domainProduct.SetPrice(model.Price);
domainProduct.SetDescription(model.Description);
// ... eventually return a result
}
return View(model);
}
I prefer the first option because it's less verbose, and keeps object creation in your domain layer. However both are loosely coupled, because you are not sharing viewmodel types between your MVC layer and your domain layer. Instead your higher layer (MVC) is taking a dependency in the domain layer, but your domain layer is free from all MVC concerns.
Response to first 2 comments
Second comment first, re validation: It doesn't necessarily have to be the product factory's responsibility to enforce validation, but if you want to enforce business rules in the domain, validation should happen at the factory or lower. For example, a product factory could instantiate a product and then delegate build operations to methods on the entity -- similar to the SetXyzProperty methods above (difference being those methods might be internal to the domain lib instead of public). In this case, it would be the product entity's responsibility to enforce validation on itself.
If you throw exceptions to enforce validation, those would bubble up through the factory and into the controller. This is what I generally try to do. If a business rule ever ends up bubbling to the controller, then it means MVC is missing a validation rule and ModelState.IsValid should be false. Also, this way you don't have to worry about passing messages back from the factory -- business rule violations will come in the form of an exception.
As for your first comment, yes: MVC takes a dependency on the domain, not vice versa. If you wanted to pass a viewmodel to the factory, your domain would be taking a dependency on whatever lib the viewmodel class is in (which should be MVC). It's true that you could end up with a lot of factory method args, or factory method overload explosion. If you find this happening, it might be better to expose more granular methods on the entity itself than relying on the factory.
For example, you might have a form where the user can quickly click to change just the name or price of a Product, without going through the whole form. That action could even happen over ajax using JSON instead of a full browser POST. When the controller handles it, it might be easier to just invoke myProduct.SetPriceOrName(object priceOrName) instead of productFactory.RePriceOrRename(int productId, object priceOrName).
Response to question update
Others may have different opinions, but in mine, the business domain should not expose a validation API. That's not to say you can't have an IsValidPrice method on the entity. However, I don't think it should be exposed as part of the public API. Consider the following:
namespace NinetyNineCentStore.Domain
{
public class Product
{
public decimal Price { get; protected set; }
public void SetPrice(decimal price)
{
ValidatePrice(price);
Price = price;
}
internal static bool IsPriceValid(decimal price)
{
return IsPriceAtLeast99Cents(price)
&& IsPriceAtMostNineteen99(price)
&& DoesPriceEndIn99Cents(price);
}
private static bool IsPriceAtLeast99Cents(decimal price)
{
return (price >= 0.99m);
}
private static bool IsPriceAtMostNineteen99(decimal price)
{
return (price <= 19.99m);
}
private static bool DoesPriceEndIn99Cents(decimal price)
{
return (price % 1 == 99);
}
private static void ValidatePrice(decimal price)
{
if (!IsPriceAtLeast99Cents(price))
throw new InvalidOperationException(
"Product price must be at least 99 cents.");
if (!IsPriceAtMostNineteen99(price))
throw new InvalidOperationException(
"Product price must be no greater than 19.99.");
if (!DoesPriceEndIn99Cents(price))
throw new InvalidOperationException(
"Product price must end with 99 cents.");
}
}
}
The above encapsulates validation on the entity, without exposing it in the API. Your factory can still invoke the internal IsPriceValid, but doesn't need to be concerned with every little business rule permutation. When any client, internal or public, tries to violate the rule, an exception is thrown.
This pattern might seem like overkill, but consider business rules that involve more than one property on an entity. For example, say you can break the DoesPriceEndIn99Cents rule when the Product.IsOnSale == true. You already have ValidatePrice encapsulated, so you can accommodate that rule without having to expose a new validation API method.

Make a required class properties not required

I have a class set up to hold values on a registration form (VB.NET, MVC), and among the properties is a Password property:
Public Class RegisterModel
...
Private _password As String
<DisplayName("Password:"), Required(), ValidatePasswordLength(), DataType(DataType.Password)> _
Public Property Password() As String
Get
Return _password
End Get
Set(ByVal value As String)
_password = value
End Set
End Property
This works great when registering a new user, but I'd like to use the same class to update existing users. (Note: this app is run by an admin who is in charge of registering individuals and assigning passwords.) The way I'd like it to behave is if the admin leaves the password blank, then the password is not changed, but the rest of the information is. If I use this class, the password can't be left blank because it fails on the Required() and ValidatePasswordLength() calls.
Is there a way to use this class but tell the model to ignore these particular validations? Even if I leave the password field off my edit form, it still fails. Do I need to create a whole duplicate class without these restrictions on the password field? There must be a better way.
You could implement IDataErrorInfo and have a flag set on the model which indicates whether it is being used by an admin or not - you could then validate conditionally.
But overall, I'd say this is a bit of a code smell. You're using a model for two different, incompatible purposes. It'd be better to use a separate view model.
I'd recommend using the FluentValidation library. It's a fantastic way to separate the concerns of your view (view model) and the actual validation you want to perform. You could pass parameters into it to drive different behavior. Check out When/Unless conditions or just writing completely custom validation methods with the Must operator.
public class RegisterModelValidator: AbstractValidator<RegisterModel>
{
public RegisterModelValidator(bool isAdmin)
{
RuleFor(x => x.Password).NotEmpty().Unless(isAdmin);
...
}
}
As long as your view model would have identical properties in both scenarios, you should use the one view model and one validation class. If the model varies at all I'd use two view models as David recommends.
You can do this in 2 ways:
1: add the [ValidateInput(false )] attribute to the action
or
2: Add a new property to the Register Model
public bool IsNewUser {get;}
3: Create a new class level attribute that takes IsNewUser into account when validating

Custom validation with Data annotations

I'm using data annotations to check data that's being entered, but I'm stuck when it comes to more custom way to validate data.
I need to run queries against database to see if stuff exists there or not, and then report back to user if a "custom db-check error" appears, such as "The Companyname already exists"
How can I implement such a thing together with dataannotations?
I have all the queries done etc using linq and entity framework that comes with 3.5sp1
/M
Custom attributes that extend data annotations
You will have to write your own attributes that will do the validation of your object instance against data store.
Make sure your classes inherit System.ComponentModel.DataAnnotations.ValidationAttribute class:
public class MustNotExist: ValidationAttribute
{
...
}
Caution
I've run into a similar situation when I needed to validate that the object is unique within data store. But this kind of validation wasn't possible on the entity class itself, since it should only work for those entities that are being created but not when you return your entity from the data store already.
My solution was to have a separate interface, class and attribute.
public interface IExternalValidator ...
class DBUniqueValidator: IExternalValidator ...
class ValidateExternallyAttribute: FilterAttribute, IActionFilter
{
...
public ValidateExternallyAttribute(Type validatorType, Type entityType) ...
...
}
I was able to place my attribute on controller actions that get entity parameters. Filter action attribute then checks controller action parameters (it can easily access their types and values) and runs external validator against correct parameters (provided types in attribute definition) and populates ModelState errors when validation fails.
[ValidateExternally(typeof(DBUniqueValidator), typeof(User))]
public ActionResult RegisterUser(User newUser)
{
if (!this.ModelState.IsValid)
{
// act accordingly - probably return some error depending on model state errors
}
// register new user in data store
}
This way I was able to run external validation only on those actions that actually needed it, and this technique also helped my controller actions code to stay clean and short. All I had to do is to check if there are any model state errors.

Resources