diff --git a/src/main/java/de/extio/game_engine/module/AbstractModule.java b/src/main/java/de/extio/game_engine/module/AbstractModule.java index a4c40c3..669c5f0 100644 --- a/src/main/java/de/extio/game_engine/module/AbstractModule.java +++ b/src/main/java/de/extio/game_engine/module/AbstractModule.java @@ -10,7 +10,7 @@ import org.slf4j.LoggerFactory; */ public abstract class AbstractModule { - protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractModule.class); + protected final Logger LOGGER = LoggerFactory.getLogger(AbstractModule.class); protected String id = "Module_" + System.identityHashCode(this); diff --git a/src/main/java/de/extio/game_engine/module/ModuleServiceAutoConfiguration.java b/src/main/java/de/extio/game_engine/module/ModuleServiceAutoConfiguration.java index df551e2..4ef106f 100644 --- a/src/main/java/de/extio/game_engine/module/ModuleServiceAutoConfiguration.java +++ b/src/main/java/de/extio/game_engine/module/ModuleServiceAutoConfiguration.java @@ -1,10 +1,9 @@ package de.extio.game_engine.module; -import java.util.List; - import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import de.extio.game_engine.renderer.work.RendererWorkingSet; @@ -15,8 +14,8 @@ public class ModuleServiceAutoConfiguration { @Bean @ConditionalOnMissingBean - ModuleService moduleService(final List initialModules, final RendererWorkingSet rendererWorkingSet) { - return new ModuleServiceImpl(initialModules, rendererWorkingSet); + ModuleService moduleService(final ApplicationContext applicationContext, final RendererWorkingSet rendererWorkingSet) { + return new ModuleServiceImpl(applicationContext, rendererWorkingSet); } @Bean diff --git a/src/main/java/de/extio/game_engine/module/ModuleServiceImpl.java b/src/main/java/de/extio/game_engine/module/ModuleServiceImpl.java index e004b00..6423615 100644 --- a/src/main/java/de/extio/game_engine/module/ModuleServiceImpl.java +++ b/src/main/java/de/extio/game_engine/module/ModuleServiceImpl.java @@ -13,16 +13,18 @@ import java.util.function.Consumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; import de.extio.game_engine.renderer.work.RendererWorkingSet; -public class ModuleServiceImpl implements InitializingBean, ModuleService { +public class ModuleServiceImpl implements ModuleService, ApplicationListener { private static final Logger LOGGER = LoggerFactory.getLogger(ModuleServiceImpl.class); - private final List modulesInitial; - + private final ApplicationContext applicationContext; + private final List modulesAll = Collections.synchronizedList(new ArrayList<>()); private final Map modulesByIdMap = new ConcurrentHashMap<>(); @@ -45,18 +47,19 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService { private final Map> executorCallbackMap = Collections.synchronizedMap(new EnumMap<>(ModuleExecutorCallbacks.class)); - public ModuleServiceImpl(final List initialModules, final RendererWorkingSet rendererWorkingSet) { - this.modulesInitial = initialModules; + public ModuleServiceImpl(ApplicationContext applicationContext, final RendererWorkingSet rendererWorkingSet) { + this.applicationContext = applicationContext; this.rendererWorkingSet = rendererWorkingSet; } + @Override - public void afterPropertiesSet() throws Exception { - if (this.modulesInitial == null || this.modulesInitial.isEmpty()) { + public void onApplicationEvent(ContextRefreshedEvent event) { + final var modulesInitial = this.applicationContext.getBeansOfType(AbstractModule.class, false, false); + if (modulesInitial == null || modulesInitial.isEmpty()) { return; } - this.modulesInitial.forEach(this::load); - this.modulesInitial.clear(); + modulesInitial.values().forEach(this::load); } @Override @@ -97,7 +100,7 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService { synchronized (this.modulesAll) { this.modulesAllView = List.copyOf(this.modulesAll); } - LOGGER.debug("Loaded module " + module.getClass().getName()); + LOGGER.debug("Loaded module {} {}", module.getClass().getName(), module.getId()); this.invokeSafe(module, m -> m.onLoad()); } @@ -124,7 +127,7 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService { this.rendererWorkingSet.clear(clientModule.getId()); } - LOGGER.debug("Unloaded module " + id); + LOGGER.info("Unloaded module {}", id); } catch (final Exception e) { LOGGER.error("Error unloading module " + id, e); @@ -163,7 +166,7 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService { } this.invokeSafe(module, AbstractModule::onDeactivate); - LOGGER.debug("Deactivated " + id); + LOGGER.info("Deactivated {}", id); } }, () -> { if (active) { @@ -191,7 +194,7 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService { } this.invokeSafe(module, AbstractModule::onActivate); - LOGGER.debug("Activated " + id); + LOGGER.info("Activated {}", id); } } }); @@ -216,13 +219,13 @@ public class ModuleServiceImpl implements InitializingBean, ModuleService { if (doDisplay && !curDisplayed) { this.modulesDisplayed.add(clientModule); clientModule.setDisplayed(true); - LOGGER.debug("Displayed {}", id); + LOGGER.info("Displayed {}", id); this.invokeSafe(clientModule, m -> ((AbstractClientModule) m).onShow()); } else if (!doDisplay && curDisplayed) { clientModule.setDisplayed(false); this.modulesDisplayed.removeIf(mod -> mod.getId().equals(id)); - LOGGER.debug("Hidden {}", id); + LOGGER.info("Hidden {}", id); this.invokeSafe(clientModule, m -> ((AbstractClientModule) m).onHide()); } this.modulesDisplayedClientModulesView = List.copyOf(this.modulesDisplayed); diff --git a/src/test/java/de/extio/game_engine/module/ModuleManagerTest.java b/src/test/java/de/extio/game_engine/module/ModuleManagerTest.java index 4a4a19b..a874e0b 100644 --- a/src/test/java/de/extio/game_engine/module/ModuleManagerTest.java +++ b/src/test/java/de/extio/game_engine/module/ModuleManagerTest.java @@ -2,12 +2,16 @@ package de.extio.game_engine.module; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.event.ContextRefreshedEvent; import de.extio.game_engine.renderer.work.RendererWorkingSet; @@ -24,33 +28,37 @@ public class ModuleManagerTest { this.testModule = new TestModule(); this.testClientModule = new TestClientModule(); - final List initialModules = new ArrayList<>(); - initialModules.add(this.testModule); - initialModules.add(this.testClientModule); + final ApplicationContext ctx = mock(ApplicationContext.class); + when(ctx.getBeansOfType(AbstractModule.class, false, false)) + .thenReturn(Map.of("testModule", this.testModule, "testClientModule", this.testClientModule)); - this.moduleManager = new ModuleServiceImpl(initialModules, mock(RendererWorkingSet.class)); - this.moduleManager.afterPropertiesSet(); + this.moduleManager = new ModuleServiceImpl(ctx, mock(RendererWorkingSet.class)); + this.moduleManager.onApplicationEvent(new ContextRefreshedEvent(ctx)); } @Test - public void testAfterPropertiesSet() { + public void testOnApplicationEvent() { assertEquals(2, this.moduleManager.getModulesAll().size()); assertTrue(this.testModule.onLoadCalled); assertTrue(this.testClientModule.onLoadCalled); } @Test - public void testAfterPropertiesSet_EmptyModules() throws Exception { - final ModuleServiceImpl emptyManager = new ModuleServiceImpl(List.of(), mock(RendererWorkingSet.class)); - emptyManager.afterPropertiesSet(); + public void testOnApplicationEvent_EmptyModules() throws Exception { + final ApplicationContext ctx = mock(ApplicationContext.class); + when(ctx.getBeansOfType(AbstractModule.class, false, false)).thenReturn(Map.of()); + final ModuleServiceImpl emptyManager = new ModuleServiceImpl(ctx, mock(RendererWorkingSet.class)); + emptyManager.onApplicationEvent(new ContextRefreshedEvent(ctx)); assertTrue(emptyManager.getModulesAll().isEmpty()); } @Test - public void testAfterPropertiesSet_NullModules() throws Exception { - final ModuleServiceImpl nullManager = new ModuleServiceImpl(null, mock(RendererWorkingSet.class)); - nullManager.afterPropertiesSet(); + public void testOnApplicationEvent_NullModules() throws Exception { + final ApplicationContext ctx = mock(ApplicationContext.class); + when(ctx.getBeansOfType(AbstractModule.class, false, false)).thenReturn(null); + final ModuleServiceImpl nullManager = new ModuleServiceImpl(ctx, mock(RendererWorkingSet.class)); + nullManager.onApplicationEvent(new ContextRefreshedEvent(ctx)); assertTrue(nullManager.getModulesAll().isEmpty()); }