-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@Multitenant appears to cause hasErrors to always return false #37
Comments
It appears this plugin is dead - and not working correctly for me - is there an alternative approach that I can use? |
@dalelotts I have not experienced this error and I have used the Multitenant plugin on a few projects. |
I use this plugin all the time and have not experienced any issues Sent from my iPhone
|
It's probably something I am doing wrong - I will post a simple project on github tomorrow it would be great if someone would be willing to have a look and let me know what I am doing wrong. |
It was super simple to re-create - Please see https://github.com/dalelotts/MultiTenantTest @scryan7371, @cogdachris, @kimble, or @burtbeckwith, are you willing to have a look and let me know what I can do to correct this issue? |
Hi Dale, Sorry for the delayed response. I think you have found a legitimate bug here. I was suspicious at 1st because I use this plugin in a production app and I use the unique: 'tenantId' feature the same way you've done in your example. After banging my head against this for awhile I looked at my live app and found this:
Embarrassing... I believe the issue is that GORM validation occurs before the mt plugin (which uses Hibernate Filters) updates the tenantId of the to-be-saved object. GORM validation passes because the tenantId is undefined during validation, then the Hibernate Filters apply the real tenantId and the DB throws that constraint violation, which is what you are seeing. Long story short, it is a bug. You can work around it by setting the tenantId before calling .hasErrors() or .save() on any @MultiTenant domain objects. I know that the workaround is not ideal. I'm not sure if I will have time to figure out a fix for the underlying problem anytime soon. Hope that helps, |
Hi Steve, Thanks for having a look at this! Now I feel like I can move forward, so that's good news! The not-so-good news is that I have 40+ @MultiTenant domain objects. =( This may be a crazy idea, but what if the plug-in would override save() and validate() to set the tenantId? Thanks again for the workaround! |
We just use a custom validator in our domain base class and annotate all the fields that should be unique by tenanted and it seems to work fine Sent from my iPhone
|
Me too. Custom validators worked great instead of the workaround and using the
|
@scryan7371 and @lucastex I'm not completely sure what you are describing - can you post a short example Domain class? or perhaps update the test project (linked above) with the fix? |
Hi Steve, et al; This just keeps getting more interesting. The sample project is using standard generated controllers from Grails 2.3.7 - there is no call to .validate() prior to calling .hasErrros() Adding As the code is written, it calls .hasErrrors() before calling .save() - no matter what I do, .hasErrors() returns false (There is one exception, setting tenantId to 1 in the form - for some reason .hasErrors() behaves correctly) If I first call .validate() - it returns false and hasErrors() will then return true as expected. The documentation for .hasErrors() says it can report errors following data binding, since this is following data binding I would expect .hasErrors() to work without a call do validate(). I guess the authors of the controller templates thought so also since they did not include a call to validate() I have no idea how a custom validator might correct this behavior, but I hope it will. Ah, the 50 shades of Grails! |
Hi @dalelotts , just cloned your repo. |
Hi @lucastex - Hmm, I thought I included the steps in the readme file...anyway, here they are. Steps to reproduce: Repeat the steps above with the "TagController" - the validation error is correctly reported. |
Hi @dalelotts Check this commit: lucastex/MultiTenantTest@eb59f5a This is what we're saying on using custom validators. |
Does it worked @dalelotts ? |
Hey Dale, I think a previous version of this plugin took that approach, if I remember correctly there were some issues with that solution because other plugins may also try to hijack those methods. I'll see if I can figure out if that is a viable solution or if there is another more appropriate solution. It looks like Lucas jumped in with another potential workaround for now. We need to look a little deeper into this plugin anyway with Hibernate 4 (which has a multi-tenant feature) now as a GORM implementation it may be worthwhile to upgrade this plugin to use those features. -Steve P.S. Sorry for closing and reopening the issue, hit the wrong button :-/ |
@lucastex The unique constraint should be on name and tenantId. For example, it is valid for two tenants to have a tag with the same name, but it is not valid for one tenant to have two tags with the same name. It looks to me like the constraint in your example is just a unique name constraint. Furthermore, I don't think changing the custom validator to look for tenantId:name duplicates would solve the problem since the root of the issue is that tentantId is not yet set at the point at which the controller is performing the validation. I admit I did not test this. If you tested the change and you see the correct behavior (i.e. tenantId:name unique constraint) please let me know. |
@dalelotts That was just an example of a custom validator trying to do it. @sronderos i haven't looked deeper into Hibernate4 MT feature, but AFAIK (from people that looked into it), the MT feature only works for different databases, or even different schemas in the same database. |
@sronderos yeah, this is right... The Hibernate 4 Multi Tenancy strategy for a "single-db" approach would be the DISCRIMINATOR strategy. Check its definition:
Perfect! But:
Sad but true :/ |
I have a simple project using Grails 2.3.7 and this plugin. I have two identical tables, one with @MultiTenant and one without. Both tables have a name field with a unique constraint. name(nullable: false, blank: false, unique: 'tenantId') for the multi-tenant table.
Saving a new record that violates the unique name constraint for the multi-tenant table throws a DataIntegrityViolationException (as if failOnError:true), while the non-multi-tenant table behaves as expected ( .save returns null and .errors list is populated)
The controller checks .hasErrors() before calling .save() - the @MultiTenant table always returns false from hasErrors().
Is there something I have configured incorrectly? It does not seem like this plugin should impact the handling of validation.
The text was updated successfully, but these errors were encountered: