Open
Description
SpringApplication
makes it hard to get hold of the application context before it's refreshed. @michael-simons came up with this:
SpringApplication springApplication = new SpringApplication(Application.class);
springApplication.addInitializers((GenericApplicationContext ctx) -> {
ctx.registerBean(Greeter.class, Greeter::new);
});
springApplication.run(args);
It would be nice if the initialiser wasn't needed and the API provided an easier way to access the context before it's refreshed.
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
michael-simons commentedon Jan 26, 2017
Background was (again) creating an example for my book how to use Spring 5 enhancements out of the box with Spring Boot. I assume that this question will arise, especially with the functional router.
dsyer commentedon Jan 26, 2017
Isn't that the definition of an
ApplicationContextInitializer
? How could the API be any simpler without duplicating?michael-simons commentedon Jan 26, 2017
I - as a user - would have been looking for something like
and having Boot delegate to an Initializer for me.
dsyer commentedon Jan 26, 2017
As a user I'd expect to have something that worked in integration tests with
@SpringBootTest
as well as when I run my main method (changing the API ofSpringApplication
doesn't help there).wilkinsona commentedon Jan 26, 2017
I'm not sure, however the pure Spring example in the Kotlin blog post involves less ceremony:
It's a shame that
SpringApplication
gives you an extra hoop to jump through. Perhaps we'll have to live with that, but I think it's worth some thought.michael-simons commentedon Jan 26, 2017
Doesn't seem to take integration tests with
@SpringBootTest
into account as well… It's a good point!sdeleuze commentedon Jan 26, 2017
+1 for allowing using the functional bean registration API with Spring Boot, even if I am not sure yet exactly where should be the entry point. For the record, here is the Kotlin function bean registration I used before switching to the app to Boot. I found no proper wat to integrate with Boot so I had to remove it to use
@Bean
but I would be happy to restore it if you provide a way to do that easily.If I remember well I had no way to integrate my functional bean registration at the right level in Spring Boot application context lifecycle even with @bclozel help.
dsyer commentedon Jan 26, 2017
Just to complete that loop: if you define the initializer above as a standalone class and declare it in spring.factories it will work with
@SpringBootTest
and in a simple one-linemain()
method. I see no reason why that wouldn't work with Kotlin if anyone cares.michael-simons commentedon Jan 26, 2017
I think that @dsyer's approach is ok, can also be used through
context.initializer.classes
, but if people see those nice examples, they forget about IT tests… (like I did).wilkinsona commentedon Jan 26, 2017
Sounds like this might be turning into a documentation issue
dsyer commentedon Jan 26, 2017
What about an annotation instead of spring.factories, and a special component scan just for initializers and listeners? That's not even Spring 5 specific.
Fix example of functional bean registration
36 remaining items
daliborfilus commentedon Oct 23, 2020
I don't want to hijack this thread by something non-relevant, so please excuse me if it is.
I'm currently trying to migrate my application into BeanDefinitionDsl style and I stumbled upon this issue too.
Using
runApplication(...) { beans() }
doesn't work from tests, as some of you have already mentioned.So I currently need to have an initializer class, which delegates into the functional DSL (not a big deal):
where
beans()
is a your averagefun beans() = beans { /* ... */ }
.Then I need to have
context.initializer.classes=app.BeansInitializer
inapplication.properties
.This works correctly in tests - without modifying them in any way.
However, tests annotated with
@JsonTest
doesn't work, because in thatbeans { /* ... */ }
, I'm creating beans that useref<NamedParameterJdbcTemplate>()
and that of course isn't present in the@JsonTest
context.Is it somehow possible to know from ApplicationContextInitializer (like
beans {}
is) if I have full context loaded, or if I'm in the slice test? I tried to useif (!context.containsBean("namedParameterJdbcTemplate")) { beans().initialize(context) }
, but this 1) doesn't work (maybe ordering issue or the bean is named differently?) and 2) is fragile - it would require updating every time I change bean definitions.Or I have to use general
@SpringBootTest
if I want to use BeanDefinitionDSL?wilkinsona commentedon Oct 24, 2020
@daliborfilus I think you'll have to use
@SpringBootTest
to use the DSL for bean registration.daliborfilus commentedon Oct 25, 2020
@wilkinsona I thought so. It's not a big problem, really. Thank you for corfimation.
dsyer commentedon Oct 25, 2020
If you were prepared to put some conditional logic around all the bean definitions in the DSL I think maybe you could get it to work. Probably not what you want though, and not the “house style” with Spring Fu.
albertocavalcante commentedon Mar 10, 2023
Is this still being considered? Thanks
wilkinsona commentedon Mar 10, 2023
@albertocavalcante Yes. The issue would have been closed if that was not the case. We don't have any plans to work on it in the near future as we have other higher priority work on our plates. This is indicated by the issue being in the general backlog milestone.
dsyer commentedon Mar 10, 2023
FWIW there are already quite a few options for using functional bean definitions via
SpringApplication
(e.g. add an initializer) or normal@Configuration
(e.g. provide aBeanDefinitionRegistryPostProcessor
). Changes to Spring Boot could make that more prominent in the programming model, I suppose, but it wouldn't change the user configuration code much. Most of my comments above were directed to work towards providing a reflection-free alternative, but if you don't care about that you can still write functional bean definitions.wakingrufus commentedon Jul 3, 2024
I have published a way of solving this problem. Based on Spring-Fu, I incorporated some additional functionality that I needed to implement this approach at my day job, which allows it to be used within existing Autoconfiguration-based applications. Take a look: https://github.com/wakingrufus/spring-funk A good place to start to read more is here: https://wakingrufus.github.io/spring-funk/introduction.html Feel free to reach out to me
@wakingrufus
on the kotlin slack, or open a discussion on https://github.com/wakingrufus/spring-funk/discussions I welcome feedback. This is a project I am willing to work on long term if it has traction on making the functional approach to Spring Boot more accessible and mainstreamsdeleuze commentedon Mar 6, 2025
Spring Framework 7 introduces first class support for programmatic bean registration with
@Configuration
+BeanRegistrar
, see spring-projects/spring-framework#18353 (comment) for more details. Happy to explore with the Spring Boot team how that could be used for Boot use cases, and if this issue should be closed or if we are missing important use cases.