Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@mkurz
Copy link
Member

@mkurz mkurz commented Dec 14, 2016

Right now we create a ValidatorFactory each time we need a validator - which is quite often (for every constraint annotation for each request).
But we just need a single ValidatorFactory per app which delivers us the desired validator(s).

Also using usingContext isn't ideal here. What we do right now we create a ValidationFactory via buildDefaultValidatorFactory (which actually is just a shortcut for .byDefaultProvider().configure().buildValidatorFactory()) and then re-configure this just created factory via usingContext(). With my change we now immediately create the factory we want.

This change will save some CPU cycles and heap space 😆

@mkurz
Copy link
Member Author

mkurz commented Dec 14, 2016

We could even backport this.

@marcospereira
Copy link
Member

Are you sure is it being injected for every constraints and for each request? I think that it is created every time a Validar is injected (contrary to every time it is needed). And it is injected only into FormFactory which is a singleton.

Finally, maybe we could just bind and inject the ValidatorFactory itself instead of a ConstraintValidatorFactory (this is considered a Guice best practice).

@mkurz
Copy link
Member Author

mkurz commented Dec 15, 2016

@marcospereira You are completely right - it only gets injected once (for the FormFactory singleton). My bad - I was to optimistic, should have looked further 😄

Anyway I would still merge this pull request because it makes it clear there is only one form factory per app (even though in our case it is like this anyway because of the singleton). This is also what the hibernate validation documention says:

Tip: The generated ValidatorFactory and Validator instances are thread-safe and can be cached. As Hibernate Validator uses the factory as context for caching constraint metadata it is recommended to work with one factory instance within an application.

So I think my change still is valid.

About injecting the ValidatorFactory itself. I am not sure. Please have a look at the "Bootstrapping" section of the validator docs. It's always like Validation.byDefaultProvider().configure()....
I think it's the easiest way to also configure the validator factory. Of course we could set up an separate module which provides us the ValidatorFactory and inject it in the ValidatorProvider. But we would still need our DefaultConstraintValidatorFactory (which we then would inject into the newly validatorFactory module). WDYT?

Please also have a look at the second commit I added. We never cleaned up our validator factory when the app stopped:

Note: If a ValidatorFactory instance is no longer in use, it should be disposed by calling ValidatorFactory#close(). This will free any resources possibly allocated by the factory.

Copy link
Member

@marcospereira marcospereira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkurz looks good to me.

+1 for backport it to 2.5.x.

@mkurz mkurz merged commit 503078e into playframework:master Dec 15, 2016
@mkurz mkurz deleted the validatorFactoryOptimization branch December 15, 2016 12:58
mkurz added a commit that referenced this pull request Dec 15, 2016
* Create validatorFactory just once

* Close validatorFactory when app stops
@mkurz
Copy link
Member Author

mkurz commented Dec 15, 2016

2.5.x: d283729
Did run the tests on my machine

@gmethvin
Copy link
Member

We also should be checking for binary compatibility before merging (using sbt mimaReportBinaryIssues). I'll submit a PR with fixes.

@marcospereira
Copy link
Member

marcospereira commented Dec 28, 2016

@gmethvin and @mkurz, this could be a good point in favor to prefer to backport using a new PR instead of manually doing it to master (or version) branch. Travis would warning us (at the PR checks) that the build was failing because of binary compatibility problems:

https://travis-ci.org/playframework/playframework/builds/184239230

So, maybe a good rule of thumb is that, if you are adding/changing/removing methods, do the backport/forwardport using a PR.

WDYT?

@gmethvin
Copy link
Member

I agree.

@mkurz
Copy link
Member Author

mkurz commented Jan 9, 2017

@marcospereira @gmethvin Sorry about that. I will create a PR next time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants