/**
* Declare a Reactive-based web {@link ApplicationDsl application} that allows to configure a Spring Boot
* application using Jafu DSL and functional bean registration.
*/
public static JafuApplication reactiveWebApplication(Consumer<ApplicationDsl> dsl) {
return new JafuApplication(new ApplicationDsl(dsl)) {
@Override
protected ConfigurableApplicationContext createContext() {
return new ReactiveWebServerApplicationContext();
}
};
}
@Test
void createAnEmptyApplicationAndCheckMessageSource() {
var app = application(a -> {});
var context = app.run();
assertFalse(context instanceof ReactiveWebServerApplicationContext);
var messageSource = context.getBean(MessageSource.class);
assertEquals("Spring Fu!", messageSource.getMessage("sample.message", null, Locale.getDefault()));
context.close();
}
public static SpringApplication createSpringApplication(String[] args) {
var environment = new StandardEnvironment();
environment.setDefaultProfiles("exporter", "gateway");
environment.getPropertySources().addFirst(new SimpleCommandLinePropertySource(args));
var pluginsDir = environment.getProperty("plugins.dir", String.class, "./plugins");
var pathMatcher = environment.getProperty("plugins.pathMatcher", String.class, "*.jar");
var pluginsRoot = Paths.get(pluginsDir).toAbsolutePath().normalize();
log.info("Loading plugins from '{}' with matcher: '{}'", pluginsRoot, pathMatcher);
var pluginManager = new LiiklusPluginManager(pluginsRoot, pathMatcher);
pluginManager.loadPlugins();
pluginManager.startPlugins();
var binder = Binder.get(environment);
var application = new SpringApplication(Application.class) {
@Override
protected void load(ApplicationContext context, Object[] sources) {
// We don't want the annotation bean definition reader
}
};
application.setWebApplicationType(WebApplicationType.REACTIVE);
application.setApplicationContextClass(ReactiveWebServerApplicationContext.class);
application.setEnvironment(environment);
application.addInitializers(
new StringCodecInitializer(false, true),
new ResourceCodecInitializer(false),
new ReactiveWebServerInitializer(
binder.bind("server", ServerProperties.class).orElseGet(ServerProperties::new),
binder.bind("spring.resources", ResourceProperties.class).orElseGet(ResourceProperties::new),
binder.bind("spring.webflux", WebFluxProperties.class).orElseGet(WebFluxProperties::new),
new NettyReactiveWebServerFactory()
),
new GatewayConfiguration(),
(GenericApplicationContext applicationContext) -> {
applicationContext.registerBean("health", RouterFunction.class, () -> {
return RouterFunctions.route()
.GET("/health", __ -> ServerResponse.ok().bodyValue("OK"))
.build();
});
applicationContext.registerBean(PluginManager.class, () -> pluginManager);
}
);
application.addInitializers(
pluginManager.getExtensionClasses(ApplicationContextInitializer.class).stream()
.map(it -> {
try {
return it.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
})
.toArray(ApplicationContextInitializer[]::new)
);
return application;
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationContextInitializedEvent) {
ApplicationContextInitializedEvent initialized = (ApplicationContextInitializedEvent) event;
ConfigurableApplicationContext context = initialized.getApplicationContext();
if (!(context instanceof GenericApplicationContext)) {
throw new IllegalStateException("ApplicationContext must be a GenericApplicationContext");
}
if (!isEnabled(context.getEnvironment())) {
return;
}
GenericApplicationContext generic = (GenericApplicationContext) context;
ConditionService conditions = initialize(generic);
functional(generic, conditions);
apply(generic, initialized.getSpringApplication(), conditions);
}
else if (event instanceof ApplicationEnvironmentPreparedEvent) {
ApplicationEnvironmentPreparedEvent prepared = (ApplicationEnvironmentPreparedEvent) event;
if (!isEnabled(prepared.getEnvironment())) {
return;
}
logger.info("Preparing application context");
SpringApplication application = prepared.getSpringApplication();
findInitializers(application);
WebApplicationType type = getWebApplicationType(application, prepared.getEnvironment());
Class<?> contextType = getApplicationContextType(application);
if (type == WebApplicationType.NONE) {
if (contextType == AnnotationConfigApplicationContext.class || contextType == null) {
application.setApplicationContextClass(GenericApplicationContext.class);
}
}
else if (type == WebApplicationType.REACTIVE) {
if (contextType == AnnotationConfigReactiveWebApplicationContext.class || contextType == null) {
application.setApplicationContextClass(ReactiveWebServerApplicationContext.class);
}
}
else if (type == WebApplicationType.SERVLET) {
if (contextType == AnnotationConfigServletWebServerApplicationContext.class || contextType == null) {
application.setApplicationContextClass(ServletWebServerApplicationContext.class);
}
}
}
}