grails validate method on domain object - grails

I wrote a very simple test case and found that Grails does only a shallow validation when i call validate on a domain object. Is it possible for me to do a deep validation in grails? Can anybody help me?
class Person {
Address address
}
class Address {
String city
}
When i do new Address().validate() it returns false but when i do new Person(address: new Address()).validate it returns true.

While "deep validation" currently isn't documented for the validate() and save() methods, it will be in future (the document states that the documentation has been missing, while being relevant for the complete 1.3.x tree). The documentation on these methods' deepValidate parameter then will state:
#deepValidate# (optional) - Determines
whether associations of the domain
instance should also be validated,
i.e. whether validation cascades or
not. This is #true# by default - set
to #false# to disable cascading
validation.
Tests, however, show that "deep validation" is not performed in any of these cases:
one-to-one associations
one-to-many associations
associated objects assigned using the matching setter
associated objects assigned using the matching addTo*(..) method, e.g., person.addToAddresses(..)
using both the validate() and save() methods,
and also, using both methods with an explicit deepValidate: true parameter
Similar findings have been published at another place, categorizing the "non-behavior" as a "known issue". My own, comprehensive, test cases can be downloaded from here.
The solution, finally, is to manually invoke validation on the child object:
class Person {
Address primaryAddress
static hasMany = [secondaryAddresses: Address]
static constraints = {
primaryAddress validator: {
it?.validate()
}
secondaryAddresses validator: {
it?.every { it?.validate() }
}
}
}

Related

Domain not persisted even after explicit save() when using read() to get it

I retrieved the domain object using read(), changed some properties on it and explicitly saved it using save(). I can see version being updated but not properties
Properties should be updated along with the version as mentioned in grails read() documentation
Example Domain:
class AdhocChargeType{
String adHocChargeType
String glCode
}
Controller test method:
class AdhocChargeTypeController
{
def testRead(Long id)
{
AdhocChargeType adHocChargeType = AdhocChargeType.read(id)
adHocChargeType.properties = [adHocChargeType:"changed?"]
adHocChargeType.save()
}
}
Grails save() method silently fails. If you have validation errors, then it will not save.
try with
save flush:true, failOnError:true
Resolve if there is any validation errors. The data should persist after that.
Upon saving a domain instance, Grails validates it using the defined constraints. The save will fail, if values in the domain instance violate those constraints. The problem is, this failure occurs quietly: you only know about it if you check the return value of save() or call hasErrors().
if (!adHocChargeType.save()) {
// Save failed! Present the errors to the user.
...
}
Another approach is :
adHocChargeType.save(failOnError: true)
I suggest have a look into GORM best practices:
http://spring.io/blog/2010/06/23/gorm-gotchas-part-1/
http://spring.io/blog/2010/07/02/gorm-gotchas-part-2/
http://spring.io/blog/2010/07/28/gorm-gotchas-part-3/

Override getter in grails domain class for relation version issues

I have an existing application with the following domain classes/relations:
class Contact {
static hasMany = [phones: Phone]
}
I would like to modify the structure to allow for a delete flag to be set in the Phone class and then not have to modify existing calls to the getter for phones to get phones that have not had that delete flag set.
ex:
contact.phones
I have seen a post on this site detailing how to do this.
StackOverflowPost
I have tried that approach(modifications showed below) but GORM is behaving oddly by incrementing the version when it shouldn't be. I'll hit the contact edit page and then when a version comparison is done on the server after submitting the form the version in the DB has incremented up about 5 or 6 times compared to the version value that was passed to the edit.gsp. I have also applied this pattern to two more relations so I'm thinking they are also causing the version to increment. I'm going to test with only one domain relation modification to see if I can find a pattern. Does anyone have any ideas as to the right way to do this or how to avoid version incrementing?
class Contact {
Set<Phone> phones
static hasMany = [phones: Phone]
Set<Phone> getPhones() {
phones.findAll { !it.deleted }
}
}
Not a direct answer to your question, but i use methods in my class, which instead of returning the actual domain instances, returns the detached criteria that callers can use, add new restrictions, and finally get the results.
​class Contact {
DetachedCriteria<Phone> phones() {
def criteria = new DetachedCriteria(Phone).build {
eq "deleted", false
eq "contact", this
}
return criteria
}
}​
The contact class will return a criteria with main restrictions added, and callers can add more restrictions if they have to.
List phones = contact.phones().list()
or
List phones = contact.phones().list {
eq "country", "xxx"
}
This gives callers more flexibility.

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.

Grails: Rollback associations done by data binding in a service

Given the following two domain classes:
class Book {
String title
static hasMany = [authors: Author]
static belongsTo = Author
static constraints = {
title(nullable: false)
}
}
class Author {
static hasMany = [books: Books]
}
We create and persist domain objects in services and make use of the data binding feature of Grails. Such a method looks like the following one:
def createAndPersistBook(params) throws ValidationException {
log.debug("Attempt to create and persist book")
Book book = new Book(params)
book.save(flush: true, failOnError: true)
log.debug("Created: ${book}")
book
}
When we pass the params map
params = ["authors": "[2]"]
to the service method (there is no title defined thus validation will fail) the association from the newly created book to the already existing author (and vice-versa) is done by data binding. But since the title is nullable: false and not defined a ValidationException is thrown and the transaction is rolled back.
What we expected now is that the book is not being saved, but Book.list().isEmpty() returns false. We think that this is because of the dirty-check by hibernate, meaning the books collection of the existing author has changed and will be persisted and this save gets cascaded to the book instance.
What is the best way to prevent grails from saving the book in this scenario? Or why is the association done by data binding not properly rolled back when validation fails?
If you've specified that your service is transactional, any uncaught exception will cause a transaction to rollback within a service method. The only thing that might stand in your way is if your RDBMS does not support true transactions/rollback.
Have you specified whether the service is transactional? You should have a statement such as below to declare the service is transactional.
def transactional = true

Grails Plugins Requiring External Relationships

I posted this on the Grails mailing list yesterday and haven't had any hits. Figured I'd try here as well today.
I'm considering writing a grails plugin but this plugin would require some sort of relationship to an account / user object. However, I don't want to force a particular security model on the plugin. For example, say was writing a comment system plugin (I'm not). I'd have a comment object...
class Comment {
String comment
Date dateCreated
// etc etc
}
The comment is missing a couple of things:
Who added the comment
What the comment was added to.
I'd like to first focus on #1. So someone might be using the Spring security plugin and use the default Person object, or maybe they changed that to User. Who knows. Is there any way that anyone can think of to configure that relationship without hard coding it in the plugin?
One thing I've thought about was to have the grails app extend the plugin's domain classes to add this relationship. so I might do something like...
class ArticleComment extends Comment {
static belongsTo = [user:User]
}
But in a larger plugin, that might be a lot of inheritance requirements. Not the end of the world, but just looking for other possible options.
You can use the same technique employed by the Commentable plugin:
The user of your plugin will need to declare a closure in Config.groovy to evaluate the logged user:
grails.myplugin.user.evaluator = { session.user }
And you can use something like this in your plugin's code to call the user configured closure:
def evaluateUser() {
def evaluator = grailsApplication.config.grails.myplugin.user.evaluator
def user
if(evaluator instanceof Closure) {
evaluator.delegate = this
evaluator.resolveStrategy = Closure.DELEGATE_ONLY
user = evaluator.call()
}
if(!user) {
throw new Exception("No [grails.myplugin.user.evaluator] setting defined or the evaluator doesn't evaluate to an entity. Please define the evaluator correctly in grails-app/conf/Config.groovy")
}
if(!user.id) {
throw new Exception("The evaluated user is not a persistent instance.")
}
return user
}
I think you can do it like SpringSecurity do. Instead of let people extend your Comment class, You can write 2 class CommentUser & CommentPlace; then let others extends them. I think it's more simple.

Resources