feat(module): Integrate EventService into ModuleService for event management

This commit is contained in:
extio-de
2025-12-26 15:58:09 +01:00
parent 64adf9c9f9
commit b48ac87ae5
4 changed files with 36 additions and 7 deletions

View File

@@ -6,6 +6,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import de.extio.game_engine.event.EventService;
import de.extio.game_engine.renderer.work.RendererWorkingSet; import de.extio.game_engine.renderer.work.RendererWorkingSet;
@AutoConfiguration @AutoConfiguration
@@ -14,8 +15,8 @@ public class ModuleServiceAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
ModuleService moduleService(final ApplicationContext applicationContext, final RendererWorkingSet rendererWorkingSet) { ModuleService moduleService(final ApplicationContext applicationContext, final RendererWorkingSet rendererWorkingSet, final EventService eventService) {
return new ModuleServiceImpl(applicationContext, rendererWorkingSet); return new ModuleServiceImpl(applicationContext, rendererWorkingSet, eventService);
} }
@Bean @Bean

View File

@@ -17,6 +17,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.ContextRefreshedEvent;
import de.extio.game_engine.event.EventService;
import de.extio.game_engine.renderer.work.RendererWorkingSet; import de.extio.game_engine.renderer.work.RendererWorkingSet;
public class ModuleServiceImpl implements ModuleService, ApplicationListener<ContextRefreshedEvent> { public class ModuleServiceImpl implements ModuleService, ApplicationListener<ContextRefreshedEvent> {
@@ -30,6 +31,8 @@ public class ModuleServiceImpl implements ModuleService, ApplicationListener<Con
private final Map<String, AbstractModule> modulesByIdMap = new ConcurrentHashMap<>(); private final Map<String, AbstractModule> modulesByIdMap = new ConcurrentHashMap<>();
private final RendererWorkingSet rendererWorkingSet; private final RendererWorkingSet rendererWorkingSet;
private final EventService eventService;
private List<AbstractModule> modulesAllView = List.of(); private List<AbstractModule> modulesAllView = List.of();
@@ -47,9 +50,10 @@ public class ModuleServiceImpl implements ModuleService, ApplicationListener<Con
private final Map<ModuleExecutorCallbacks, List<AbstractModule>> executorCallbackMap = Collections.synchronizedMap(new EnumMap<>(ModuleExecutorCallbacks.class)); private final Map<ModuleExecutorCallbacks, List<AbstractModule>> executorCallbackMap = Collections.synchronizedMap(new EnumMap<>(ModuleExecutorCallbacks.class));
public ModuleServiceImpl(ApplicationContext applicationContext, final RendererWorkingSet rendererWorkingSet) { public ModuleServiceImpl(ApplicationContext applicationContext, final RendererWorkingSet rendererWorkingSet, final EventService eventService) {
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
this.rendererWorkingSet = rendererWorkingSet; this.rendererWorkingSet = rendererWorkingSet;
this.eventService = eventService;
} }
@@ -123,6 +127,8 @@ public class ModuleServiceImpl implements ModuleService, ApplicationListener<Con
} }
this.invokeSafe(module, m -> m.onUnload()); this.invokeSafe(module, m -> m.onUnload());
this.eventService.unregisterAll(module.getId());
if (module instanceof final AbstractClientModule clientModule) { if (module instanceof final AbstractClientModule clientModule) {
this.rendererWorkingSet.clear(clientModule.getId()); this.rendererWorkingSet.clear(clientModule.getId());
} }
@@ -153,6 +159,7 @@ public class ModuleServiceImpl implements ModuleService, ApplicationListener<Con
.map(m -> (AbstractClientModule) m) .map(m -> (AbstractClientModule) m)
.toList(); .toList();
} }
this.eventService.unregisterAll(module.getId());
if (module instanceof final AbstractClientModule clientModule) { if (module instanceof final AbstractClientModule clientModule) {
this.rendererWorkingSet.clear(clientModule.getId()); this.rendererWorkingSet.clear(clientModule.getId());
} }
@@ -164,6 +171,7 @@ public class ModuleServiceImpl implements ModuleService, ApplicationListener<Con
} }
} }
} }
this.invokeSafe(module, AbstractModule::onDeactivate); this.invokeSafe(module, AbstractModule::onDeactivate);
LOGGER.info("Deactivated {}", id); LOGGER.info("Deactivated {}", id);

View File

@@ -70,7 +70,7 @@ public class Container extends AbstractClientModule implements InitializingBean
@Override @Override
public void onDeactivate() { public void onDeactivate() {
this.eventService.unregister(ViewportResizeEvent.class, this.id);
} }
protected void onViewportResize(final ViewportResizeEvent event) { protected void onViewportResize(final ViewportResizeEvent event) {

View File

@@ -2,6 +2,7 @@ package de.extio.game_engine.module;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.util.List; import java.util.List;
@@ -12,6 +13,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.ContextRefreshedEvent;
import de.extio.game_engine.event.EventService;
import de.extio.game_engine.renderer.work.RendererWorkingSet; import de.extio.game_engine.renderer.work.RendererWorkingSet;
public class ModuleServiceTest { public class ModuleServiceTest {
@@ -22,16 +24,19 @@ public class ModuleServiceTest {
private TestClientModule testClientModule; private TestClientModule testClientModule;
private EventService eventService;
@BeforeEach @BeforeEach
public void setUp() throws Exception { public void setUp() throws Exception {
this.testModule = new TestModule(); this.testModule = new TestModule();
this.testClientModule = new TestClientModule(); this.testClientModule = new TestClientModule();
this.eventService = mock(EventService.class);
final ApplicationContext ctx = mock(ApplicationContext.class); final ApplicationContext ctx = mock(ApplicationContext.class);
when(ctx.getBeansOfType(AbstractModule.class, false, false)) when(ctx.getBeansOfType(AbstractModule.class, false, false))
.thenReturn(Map.of("testModule", this.testModule, "testClientModule", this.testClientModule)); .thenReturn(Map.of("testModule", this.testModule, "testClientModule", this.testClientModule));
this.moduleManager = new ModuleServiceImpl(ctx, mock(RendererWorkingSet.class)); this.moduleManager = new ModuleServiceImpl(ctx, mock(RendererWorkingSet.class), this.eventService);
this.moduleManager.onApplicationEvent(new ContextRefreshedEvent(ctx)); this.moduleManager.onApplicationEvent(new ContextRefreshedEvent(ctx));
} }
@@ -46,7 +51,7 @@ public class ModuleServiceTest {
public void testOnApplicationEvent_EmptyModules() throws Exception { public void testOnApplicationEvent_EmptyModules() throws Exception {
final ApplicationContext ctx = mock(ApplicationContext.class); final ApplicationContext ctx = mock(ApplicationContext.class);
when(ctx.getBeansOfType(AbstractModule.class, false, false)).thenReturn(Map.of()); when(ctx.getBeansOfType(AbstractModule.class, false, false)).thenReturn(Map.of());
final ModuleServiceImpl emptyManager = new ModuleServiceImpl(ctx, mock(RendererWorkingSet.class)); final ModuleServiceImpl emptyManager = new ModuleServiceImpl(ctx, mock(RendererWorkingSet.class), mock(EventService.class));
emptyManager.onApplicationEvent(new ContextRefreshedEvent(ctx)); emptyManager.onApplicationEvent(new ContextRefreshedEvent(ctx));
assertTrue(emptyManager.getModulesAll().isEmpty()); assertTrue(emptyManager.getModulesAll().isEmpty());
@@ -56,7 +61,7 @@ public class ModuleServiceTest {
public void testOnApplicationEvent_NullModules() throws Exception { public void testOnApplicationEvent_NullModules() throws Exception {
final ApplicationContext ctx = mock(ApplicationContext.class); final ApplicationContext ctx = mock(ApplicationContext.class);
when(ctx.getBeansOfType(AbstractModule.class, false, false)).thenReturn(null); when(ctx.getBeansOfType(AbstractModule.class, false, false)).thenReturn(null);
final ModuleServiceImpl nullManager = new ModuleServiceImpl(ctx, mock(RendererWorkingSet.class)); final ModuleServiceImpl nullManager = new ModuleServiceImpl(ctx, mock(RendererWorkingSet.class), mock(EventService.class));
nullManager.onApplicationEvent(new ContextRefreshedEvent(ctx)); nullManager.onApplicationEvent(new ContextRefreshedEvent(ctx));
assertTrue(nullManager.getModulesAll().isEmpty()); assertTrue(nullManager.getModulesAll().isEmpty());
@@ -103,6 +108,13 @@ public class ModuleServiceTest {
assertTrue(this.testModule.onUnloadCalled); assertTrue(this.testModule.onUnloadCalled);
} }
@Test
public void testUnloadModule_UnregistersEvents() {
this.moduleManager.unloadModule(this.testModule.getId());
verify(this.eventService).unregisterAll(this.testModule.getId());
}
@Test @Test
public void testUnloadModule_NotLoaded() { public void testUnloadModule_NotLoaded() {
final int initialSize = this.moduleManager.getModulesAll().size(); final int initialSize = this.moduleManager.getModulesAll().size();
@@ -142,6 +154,14 @@ public class ModuleServiceTest {
assertTrue(this.testModule.onDeactivateCalled); assertTrue(this.testModule.onDeactivateCalled);
} }
@Test
public void testDeactivate_UnregistersEvents() {
this.moduleManager.changeActiveState(this.testModule.getId(), true);
this.moduleManager.changeActiveState(this.testModule.getId(), false);
verify(this.eventService).unregisterAll(this.testModule.getId());
}
@Test @Test
public void testChangeActiveState_AlreadyActive() { public void testChangeActiveState_AlreadyActive() {
this.moduleManager.changeActiveState(this.testModule.getId(), true); this.moduleManager.changeActiveState(this.testModule.getId(), true);