-
Notifications
You must be signed in to change notification settings - Fork 38.1k
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
Refine Spring profile support with AOT/native #29844
Comments
I'm also in favor of making it easier to activate a profile for the AOT processing phase. We should discuss how this would translate for the generated code, I guess we should generate a Java statement that adds that profile automatically when the AOT sources are executed otherwise we could end up in an inconsistent state if the profile is somehow not activated at runtime. Back to the broader topic of If we wanted to have dynamic
This feature is not trivial and would require important changes in the AOT and the core container itself. I think this would require #29553 to work. In general, I think the build configuration flag is a nice first step and I'm still not convinced that we need full profile support; supporting it would mean that the footprint of native images would increase significantly and they would lose one of their security advantages: not shipping code that's not use and protecting against an entire class of attacks. More, I think that in a native world it's expected to ship different binaries for separate target environments. As Java developers we might be used to shipping a single artifact for multiple environments (a JAR) and I think we should keep doing that. As @sdeleuze said, the native compilation phase should be the very last step before deployment and should not be the reference artifact. |
Related to that, I think the workflow for source-based deployment is already ok, but it may potentially be interesting to explore first class options to create native executable from a Spring Boot executable JAR that does not contain AOT generated code / metadata. |
Notice Spring Framework reference documentation mentions:
I think this is consistent with the refinement proposed in this issue. |
Hello, To the topic - the important thing for me is to have AOT exists for years in development - just see JS apps like angular. The purpose, for me, is to remove the dead code, mostly. If something is under the condition, it should not be perceived as a dead code; to say more, the user is rather aware that it can impact the runtime (they want to enable or disable it) - and probably also the build time, and they agree with that (otherwise why they would use that?). To say more, I could understand that the code was removed if the condition was falsy during the build. But why the bean was still provided when it was truly during the build, and then disabled during the runtime - I do not know. I suppose also that most of the build time is probably consumed on the lib/framework side code, not the user side - which is mostly under the configuration. I think it should be provided somehow - with the flag or by default - anyway. Faster or later users would have to provide some workarounds anyway. One of it I see now is to register beans (did not test) in a functional way, just checking (possible) conditions in the runtime. Please, save me that effort, I am already a bit confused during my migration, which already took me 50 hours of watching that something fails (hopefully) during the build, or (most often) in runtime (reflection/jackson mostly). Note that I have only 5 small/medium services, which do not use very complex features, only reactive web/reactive mongo/jackson/redis/security and cloud gateway. |
As shown in https://github.com/sdeleuze/demo-profile-aot, based on @snicoll insights I figured out we already support defining Spring profile AOT, it was just not easy to figure out based on the documentation. For the various use cases I have seen, this was the biggest need. To be discuss with the wider team, but the fact it is support IMO make less critical the need for more advanced AOT profile management, like begin to have a more advancec mechamsim that evaluate some condition at build-time and some other at runtime. This is not trivial, introduce extra complexity and will likely impact the resulting footprint. If we do something, I tend to think it would have to be explicit (like specifying that a profile or a property could change at runtime so don't remove it AOT), but I am not yet convince it is worth the time we would have spend on this. Maybe we could just make specifying profiles at build time a bit more first class at Boot level. |
Hello, I came here after I got burned - by not reading the manual - and I kind of agree with @Azbesciak on its comments. In business heavy applications - where Spring/SpringBoot dominates, we kind of rely a lot on @conditional and on things like
Which are very handy. I am wondering if the framework can compensate a bit on the above . For example when it detects code with the following conditional Profile
If I define all the available profiles on the spring-maven-plugin and the aot step - could spring - still behave the way we are used to? So I wondering if we can provide to the aot processor ALL the available profiles that we use and then during the runtime Spring to pick - the beans or components that are annotated with the conditionals. Obviously this is not code elimination - but the proposed way forward now - to define the specific profiles during build time - is not scaling a lot -especially if you use Profiles for definining behaviour or other aspects and is not just an indicator for an environment |
It's not as easy as it sound as we have to make sure that there is no side effect in doing so. For instance, let's assume that a x or y or z contributes a bean of type X that is later on injected somewhere else. At runtime it's all good as you'll enable x or y or z but processing all of them at build time does not let us figure that out. It's one example of many. Code elimination is not really the problem and Spring AOT is not meant to do that. If you ignore AOT and focus on native image, which is the primary target of this work, changing behavior at runtime is really something that doesn't work well as it has to go through all paths at build time. |
Yes I understand. I dont really know what is the best answer. For example in my case because I did not want the headache to re-work my build pipeline and introduce extra build steps, I just disabled thanks for your reply I would be following the updates and how the framework will approach this |
Hello. If @ConditionalOnProperty calculates at build time:
In such case spring native has a very narrow niche. Only for organizations wich deploy apps on 1-3 environments. Spring native applications can't compete with go lang native applications (which is fully configurable at runtime).
|
Developers of Spring applications on the JVM are typically accustomed to being able to do advanced configuration at runtime with mechanisms like Spring profiles. Ahead-Of-Time transformations and GraalVM native image by design require one to define at build time the various beans. What can and cannot change at runtime is usually not well understood.
This issue is an attempt to clarify the current state of affairs (could materialize as a documentation update in
6.0.x
), discuss what could be improved, and what will likely not be supported. What is discussed here will likely require related Spring Boot issue(s) since changes are likely to be required on both Spring Framework and Spring Boot projects, but let's start the discussion here.I have created this https://github.com/sdeleuze/demo-profile-aot repository to illustrate the behavior of a generated Spring Boot native executable. It is possible at runtime:
demo-profile-aot --debug
demo-profile-aot -Dlogging.level.org.springframework.beans.factory.support.DefaultListableBeanFactory=debug
demo-profile-aot -Dspring.profiles.active=local
demo-profile-aot -Dsample.message="Customized message from the command line"
What you can't do is enabling at runtime a profile that involves changing the bean configuration (for example adding a new bean specific to a profile). See the repository above for more details.
While this limitation can be initially frustrating, I think it makes sense if we take a step back on what the purpose of AOT transformation is and the goal of native application to ship only what is necessary in the native executable. It is important to have in mind that it is recommended to create the native executable (from sources or from the Spring Boot executable JAR) as late as possible in the deployment process, as close as possible to the target server when it will be deployed, usually as a container. In that sense, the generated native executable is not the strict equivalent of the executable JAR: it is CPU architecture specific and has a predefined set of beans. Removing this limitation is technically possible but would involve a huge refactoring of how conditions are evaluated AOT and would probably end up with increased footprint, build time, and executable size since more code would be shipped. I tend to think our time is better spent on other topics.
That said, I am in favor of adding the capability for people to specify the profiles to use with AOT/Native at build time. Once supported on Spring Framework AOT engine, this could translate on Spring Boot side to adding the capability to specify, for example (the way it is specified would be decided by the Spring Boot team):
gradle nativeCompile -Dspring.profiles.active=prod
mvn -Pnative native:compile -Dspring.profiles.active=prod
This would allow developers to deal for example with different databases (H2 versus PostgreSQL for example) using distinct profiles, with the difference that here this needs to specified Ahead-Of-Time.
I am open to move forward on this proposal in the Spring Framework
6.0.x
or6.1.0
time frame, depending on the feedback from the Spring Boot team and the community.The text was updated successfully, but these errors were encountered: