-
Notifications
You must be signed in to change notification settings - Fork 40.9k
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
Allow Spring Data JPA's bootstrap mode to be configured via the environment #13833
Comments
What do you think @olivergierke? |
It's actually more than 10% for the Petclinic. Startup time is down from 5000ms to 3600ms on my laptop. |
See also https://jira.spring.io/browse/DATAJPA-1380 (if fixed it would make it easier to prevent eager initialization of the |
We've investigated that option quite a while ago in the context of Spring Framework adding support for parallel IIRC, I briefly spoke with Jürgen about framework means to enforce the "lazinization" of a component based on a flag on its bean definition, so that our configuration code could add that based on a configuration switch, but we didn't pursue that any further. Another issue that played into our decision is that the repository bootstrap already performs query validation for manually defined queries, interacts with the JPA metamodel etc. I.e. a lazification of repositories in general will lead to the app to bootstrap into an unverified state, which in a bad case will just cause an initialization error to occur on first request. Even worse: with JPA we have the problem, that we need to trigger exception-causing code (to detect whether a query method is backed by a named query), which – according to the spec – will have to trigger a transaction rollback. Even if the actual request can be performed properly. That leads to the weird effect of a first request hitting a particular repository to result in an error, but all follow up ones to succeed. To avoid that situation is actually one of the reasons we explicitly introduced the ability to activate eager initialization in our CDI extension as that is lazy by default, which makes that weird scenario the default case. That said, I am still willing to reconsider if we got better support from the framework side to consistently enable lazy injection for a certain set of bean definitions. I can also picture e.g. the Spring Boot dev tools to enable that to be introduced switch, as I'd argue we can assume the validation to be executed in integration tests and during "normal" application startup. Does that help? /cc @jhoeller |
Devtools is probably a good scenario to push this feature a bit harder, and of course integration tests. If the option becomes available we could make it the default in devtools (for instance) but optional otherwise. That way issues to do with query validation etc. as described above would have to be opted into. |
A quick heads up on the progress so far: We have tickets and prototypical implementations for DATACMNS-1368 and DATAJPA-1397 (consume via a manual Spring Data JPA dependency declaration using
Based on that I'd love to see an application property to trigger both the deferred mode and the asynchronous |
Here is a prototype of some changes to Boot that allow the bootstrap mode to be configured using I guess we also need a property for asynchronous entity manager initialisation. @olivergierke can you educate me on how that's enabled please? |
You basically register a I wonder if we should use a slightly broader property name as ideally, the developer would only have to tweak one to trigger both aspects as they only really make sense in combination with each other and are likely (read: will have to) to be set together. Or maybe we can have another property that triggers both then, but I guess then we'd have to resolve them being set in conflicting ways. Also, – although not strictly required – that mode works for all repositories, i.e. using something that's not tied to the JPA namespace might be worth considering as well. In general, I think the asynchronous EMF bootstrap in combination with the deferred mode is a decent choice even for production scenarios as it combines the faster startup but still keeps the validation in the right spot. I'd love to see that combination to be easy to activate to eventually even make it the default. Devtools could then even go further and set the mode to lazy to prevent the repository initialization entirely. |
We can't provide a single broader-named property that customises the bootstrap mode and enables asynchronous initialisation of the EMF without only allowing one bootstrap mode to be specified, unless that property's values are the three supported bootstrap modes and we infer from that whether or not the task executor should be configured on the EMF. At that point, I think we might as well stick with a
That's interesting. If it were a Data-wide property (rather than being tied to a specific store) I'd be less sure about inferring the EMF's task executor configuration from the property's value. Given that we already have individual properties for auto-enabling of each repository type (the |
I'm fine with the property name as is. My core concern was that I'd like to see a single property to switch on all necessary bits and pieces. If you can derive the EMF bootstrap mode from the repository one, awesome. |
The feature branches in Spring Data Commons and JPA are merged into master now. I also prepared a more complete example to showcase the effect of the different modes. Feel free to ping me once the Boot support is ready, so that I can update it to throw out the additional (then obsolete) custom configuration. |
I've retitled this issue to reflect the fact that we're focussing on Data JPA for now. We could add similar properties for the other repository types if that goes well. |
In Spring Data Lovelace, repositories' bootstrap mode can be configured via @EnableJpaRepositories. This commit adds support for configuring the mode via the environment rather than having to use the annotation. Additionally, when deferred or lazy bootstrapping is being used, the LocalContainerEntityManagerFactoryBean is configured to use a bootstrap executor. This allows JPA's initialization to be performed on a separate thread, allowing the rest of application context initialization to proceed in parallel. Closes spring-projectsgh-13833
Setting
RepositoryFactoryBeanSupport.lazyInit
totrue
(in aBeanPostProcessor
) speeds up the Petclinic startup by about 10%. Maybe a good thing to expose as a@ConfigurationProperties
option in Spring Boot?N.B. if you want to try it, remember to add
@Lazy
to the injection points of all the repositories as well (all controllers).The text was updated successfully, but these errors were encountered: