From 1768fd14eb13c9995d4faf5a3e89a34462f77bfa Mon Sep 17 00:00:00 2001 From: Sergei Egorov Date: Fri, 31 Jul 2020 11:12:57 +0200 Subject: [PATCH 1/3] Use Spring Jafu (again) --- app/build.gradle | 2 +- .../github/bsideup/liiklus/Application.java | 125 ++++++++---------- .../github/bsideup/liiklus/ProfilesTest.java | 4 +- .../liiklus/test/AbstractIntegrationTest.java | 19 +-- build.gradle | 2 +- 5 files changed, 67 insertions(+), 85 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 27b09c88..506404f4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,7 +20,7 @@ dependencies { compile project(":protocol") compile 'org.springframework.boot:spring-boot-starter-webflux' - compile 'org.springframework.fu:spring-fu-autoconfigure-adapter' + compile 'org.springframework.fu:spring-fu-jafu' compile 'org.pf4j:pf4j' diff --git a/app/src/main/java/com/github/bsideup/liiklus/Application.java b/app/src/main/java/com/github/bsideup/liiklus/Application.java index 97362cc9..7f866a7a 100644 --- a/app/src/main/java/com/github/bsideup/liiklus/Application.java +++ b/app/src/main/java/com/github/bsideup/liiklus/Application.java @@ -4,24 +4,15 @@ import com.github.bsideup.liiklus.plugins.LiiklusPluginManager; import lombok.extern.slf4j.Slf4j; import org.pf4j.PluginManager; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.web.ResourceProperties; import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerInitializer; -import org.springframework.boot.autoconfigure.web.reactive.ResourceCodecInitializer; -import org.springframework.boot.autoconfigure.web.reactive.StringCodecInitializer; -import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties; import org.springframework.boot.context.properties.bind.Binder; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; -import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext; -import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.GenericApplicationContext; -import org.springframework.core.env.SimpleCommandLinePropertySource; -import org.springframework.core.env.StandardEnvironment; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.fu.jafu.Jafu; +import org.springframework.fu.jafu.webflux.WebFluxServerDsl; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; @@ -49,70 +40,58 @@ public static void main(String[] args) throws Exception { start(args); } - public static ConfigurableApplicationContext start(String[] args) { - return createSpringApplication(args).run(args); - } - - 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 + @SafeVarargs + public static ConfigurableApplicationContext start( + String[] args, + ApplicationContextInitializer... additionalInitializers + ) { + return Jafu.reactiveWebApplication(app -> { + var environment = (ConfigurableEnvironment) app.env(); + environment.setDefaultProfiles("exporter", "gateway"); + + 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(); + + app.enable(new GatewayConfiguration()); + app.beans(beans -> { + beans.bean("health", RouterFunction.class, () -> { + return RouterFunctions.route() + .GET("/health", __ -> ServerResponse.ok().bodyValue("OK")) + .build(); + }); + beans.bean(PluginManager.class, () -> pluginManager); + }); + + var extensionClasses = pluginManager.getExtensionClasses(ApplicationContextInitializer.class); + for (Class initializerClass : extensionClasses) { + try { + app.enable(initializerClass.getDeclaredConstructor().newInstance()); + } catch (Exception e) { + throw new RuntimeException(e); + } } - }; - 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(); - }); + for (ApplicationContextInitializer initializer : additionalInitializers) { + app.enable(initializer); + } - applicationContext.registerBean(PluginManager.class, () -> pluginManager); + app.enable(WebFluxServerDsl.webFlux(dsl -> { + try { + var serverPropertiesField = WebFluxServerDsl.class.getDeclaredField("serverProperties"); + serverPropertiesField.setAccessible(true); + serverPropertiesField.set(dsl, Binder.get(app.env()).bindOrCreate("server", ServerProperties.class)); + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new RuntimeException(e); } - ); - - 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; + })); + }).run(args); } } diff --git a/app/src/test/java/com/github/bsideup/liiklus/ProfilesTest.java b/app/src/test/java/com/github/bsideup/liiklus/ProfilesTest.java index 2c83b181..60121dcc 100644 --- a/app/src/test/java/com/github/bsideup/liiklus/ProfilesTest.java +++ b/app/src/test/java/com/github/bsideup/liiklus/ProfilesTest.java @@ -24,7 +24,9 @@ public class ProfilesTest extends AbstractIntegrationTest { "storage.positions.type=MEMORY" ); - Set commonArgs = Sets.newHashSet(); + Set commonArgs = Sets.newHashSet(Set.of( + "server.port=0" + )); ConfigurableApplicationContext lastApplicationContext; diff --git a/app/src/test/java/com/github/bsideup/liiklus/test/AbstractIntegrationTest.java b/app/src/test/java/com/github/bsideup/liiklus/test/AbstractIntegrationTest.java index 5e872f80..4058577d 100644 --- a/app/src/test/java/com/github/bsideup/liiklus/test/AbstractIntegrationTest.java +++ b/app/src/test/java/com/github/bsideup/liiklus/test/AbstractIntegrationTest.java @@ -77,15 +77,16 @@ public static int getPartitionByKey(String key) { "server.port=0" ).stream().map(it -> "--" + it).toArray(String[]::new); - var springApplication = Application.createSpringApplication(args); - springApplication.addInitializers(applicationContext -> { - ((GenericApplicationContext) applicationContext).registerBean( - "processorPluginMock", - ProcessorPluginMock.class, - () -> processorPluginMock - ); - }); - applicationContext = springApplication.run(args); + applicationContext = Application.start( + args, + applicationContext -> { + applicationContext.registerBean( + "processorPluginMock", + ProcessorPluginMock.class, + () -> processorPluginMock + ); + } + ); var pluginManager = applicationContext.getBean(PluginManager.class); boolean useGrpc = false; diff --git a/build.gradle b/build.gradle index 01c35d98..10401d94 100644 --- a/build.gradle +++ b/build.gradle @@ -96,7 +96,7 @@ configure(subprojects.findAll { !it.name.startsWith("examples/") }) { entry 'rsocket-rpc-protobuf' } - dependency 'org.springframework.fu:spring-fu-autoconfigure-adapter:0.2.1' + dependency 'org.springframework.fu:spring-fu-jafu:0.3.2' dependency 'com.google.protobuf:protoc:3.10.1' From e345f9b6ea291bc508d651b861482b75d973a287 Mon Sep 17 00:00:00 2001 From: Sergei Egorov Date: Fri, 31 Jul 2020 14:23:36 +0200 Subject: [PATCH 2/3] fix `ApplicationRunner` --- .../bsideup/liiklus/ApplicationRunner.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tck/src/main/java/com/github/bsideup/liiklus/ApplicationRunner.java b/tck/src/main/java/com/github/bsideup/liiklus/ApplicationRunner.java index c600d002..b73934fe 100644 --- a/tck/src/main/java/com/github/bsideup/liiklus/ApplicationRunner.java +++ b/tck/src/main/java/com/github/bsideup/liiklus/ApplicationRunner.java @@ -3,10 +3,10 @@ import lombok.NonNull; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.SpringApplication; import org.springframework.boot.loader.JarLauncher; import org.springframework.boot.loader.LaunchedURLClassLoader; import org.springframework.boot.loader.archive.JarFileArchive; +import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import java.io.File; @@ -15,6 +15,7 @@ import java.nio.file.StandardCopyOption; import java.util.HashMap; import java.util.Map; +import java.util.Properties; @Slf4j public class ApplicationRunner { @@ -72,18 +73,27 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE }; var currentClassLoader = Thread.currentThread().getContextClassLoader(); + var oldProperties = new Properties(System.getProperties()); try { var appClassLoader = launcher.createClassLoader(); Thread.currentThread().setContextClassLoader(appClassLoader); - var applicationClass = appClassLoader.loadClass("com.github.bsideup.liiklus.Application"); + System.getProperties().putAll(properties); - var createSpringApplicationMethod = applicationClass.getDeclaredMethod("createSpringApplication", String[].class); + var applicationClass = appClassLoader.loadClass("com.github.bsideup.liiklus.Application"); - var application = (SpringApplication) createSpringApplicationMethod.invoke(null, (Object) new String[0]); - application.setDefaultProperties(properties); - return application.run(); + var createSpringApplicationMethod = applicationClass.getDeclaredMethod( + "start", + String[].class, + ApplicationContextInitializer[].class + ); + return (ConfigurableApplicationContext) createSpringApplicationMethod.invoke( + null, + new String[0], + new ApplicationContextInitializer[0] + ); } finally { + System.setProperties(oldProperties); Thread.currentThread().setContextClassLoader(currentClassLoader); } } From 29a464d608a61c0bc9c54275722d75e9f7f93488 Mon Sep 17 00:00:00 2001 From: Sergei Egorov Date: Tue, 4 Aug 2020 22:00:17 +0200 Subject: [PATCH 3/3] cleanup --- .../java/com/github/bsideup/liiklus/Application.java | 9 +++------ app/src/main/resources/application.yml | 4 ++++ settings.gradle | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/github/bsideup/liiklus/Application.java b/app/src/main/java/com/github/bsideup/liiklus/Application.java index 7f866a7a..7b0d73d5 100644 --- a/app/src/main/java/com/github/bsideup/liiklus/Application.java +++ b/app/src/main/java/com/github/bsideup/liiklus/Application.java @@ -10,7 +10,6 @@ import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.GenericApplicationContext; -import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.fu.jafu.Jafu; import org.springframework.fu.jafu.webflux.WebFluxServerDsl; import org.springframework.web.reactive.function.server.RouterFunction; @@ -46,8 +45,7 @@ public static ConfigurableApplicationContext start( ApplicationContextInitializer... additionalInitializers ) { return Jafu.reactiveWebApplication(app -> { - var environment = (ConfigurableEnvironment) app.env(); - environment.setDefaultProfiles("exporter", "gateway"); + var environment = app.env(); var pluginsDir = environment.getProperty("plugins.dir", String.class, "./plugins"); var pathMatcher = environment.getProperty("plugins.pathMatcher", String.class, "*.jar"); @@ -70,8 +68,7 @@ public static ConfigurableApplicationContext start( beans.bean(PluginManager.class, () -> pluginManager); }); - var extensionClasses = pluginManager.getExtensionClasses(ApplicationContextInitializer.class); - for (Class initializerClass : extensionClasses) { + for (var initializerClass : pluginManager.getExtensionClasses(ApplicationContextInitializer.class)) { try { app.enable(initializerClass.getDeclaredConstructor().newInstance()); } catch (Exception e) { @@ -79,7 +76,7 @@ public static ConfigurableApplicationContext start( } } - for (ApplicationContextInitializer initializer : additionalInitializers) { + for (var initializer : additionalInitializers) { app.enable(initializer); } diff --git a/app/src/main/resources/application.yml b/app/src/main/resources/application.yml index 0e9892df..44de1873 100644 --- a/app/src/main/resources/application.yml +++ b/app/src/main/resources/application.yml @@ -1,3 +1,7 @@ +spring: + profiles: + active: exporter,gateway + # Liiklus config defaults grpc: port: 6565 diff --git a/settings.gradle b/settings.gradle index d0987558..570eab8b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -22,7 +22,7 @@ include 'plugins:schema' file('plugins').eachDir { dir -> def projectName = dir.name - if (findProject(":plugins:${projectName}") == null) { + if (projectName != "build" && findProject(":plugins:${projectName}") == null) { throw new GradleException("Plugin /plugins/${projectName} was not included into the build. Check settings.gradle for details.") } }