From 9310f0e1ea824d3d93c0ff9feace264003cbcdd7 Mon Sep 17 00:00:00 2001 From: "adam.magyari" Date: Wed, 19 Feb 2025 12:09:29 +0100 Subject: [PATCH] FINERACT-2181: make 'BusinessEventNotifierServiceImpl#isExternalEventConfiguredForPosting` overridable --- .../BusinessEventNotifierServiceImpl.java | 9 +--- ...rnalBusinessEventConfigurationService.java | 26 ++++++++++++ ...BusinessEventConfigurationServiceImpl.java | 41 +++++++++++++++++++ .../ExternalBusinessEventConfiguration.java | 37 +++++++++++++++++ .../BusinessEventNotifierServiceImplTest.java | 31 +++++--------- 5 files changed, 116 insertions(+), 28 deletions(-) create mode 100644 fineract-core/src/main/java/org/apache/fineract/infrastructure/event/business/service/ExternalBusinessEventConfigurationService.java create mode 100644 fineract-core/src/main/java/org/apache/fineract/infrastructure/event/business/service/ExternalBusinessEventConfigurationServiceImpl.java create mode 100644 fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/config/ExternalBusinessEventConfiguration.java diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/business/service/BusinessEventNotifierServiceImpl.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/business/service/BusinessEventNotifierServiceImpl.java index 4543539d1..66eb6824c 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/business/service/BusinessEventNotifierServiceImpl.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/business/service/BusinessEventNotifierServiceImpl.java @@ -34,7 +34,6 @@ import org.apache.fineract.infrastructure.event.business.BusinessEventListener; import org.apache.fineract.infrastructure.event.business.domain.BulkBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.NoExternalEvent; -import org.apache.fineract.infrastructure.event.external.repository.ExternalEventConfigurationRepository; import org.apache.fineract.infrastructure.event.external.service.ExternalEventService; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Service; @@ -56,10 +55,10 @@ public class BusinessEventNotifierServiceImpl implements BusinessEventNotifierSe private final ThreadLocal>> recordedEvents = ThreadLocal.withInitial(ArrayList::new); private final ExternalEventService externalEventService; - private final ExternalEventConfigurationRepository eventConfigurationRepository; private final FineractProperties fineractProperties; private final ThreadLocal>> transactionBusinessEvents = ThreadLocal.withInitial(Stack::new); private final TransactionHelper transactionHelper; + private final ExternalBusinessEventConfigurationService externalBusinessEventConfigurationService; @Override public void afterPropertiesSet() throws Exception { @@ -100,7 +99,7 @@ public class BusinessEventNotifierServiceImpl implements BusinessEventNotifierSe } if (isExternalEvent && isExternalEventPostingEnabled()) { // we only want to create external events for operations that were successful, hence the post listener - if (isExternalEventConfiguredForPosting(businessEvent.getType())) { + if (externalBusinessEventConfigurationService.isExternalEventConfiguredForPosting(businessEvent)) { if (isExternalEventRecordingEnabled()) { recordedEvents.get().add(businessEvent); } else { @@ -143,10 +142,6 @@ public class BusinessEventNotifierServiceImpl implements BusinessEventNotifierSe return fineractProperties.getEvents().getExternal().isEnabled(); } - private boolean isExternalEventConfiguredForPosting(String eventType) { - return eventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(eventType).isEnabled(); - } - private void throwExceptionIfBulkEvent(BusinessEvent businessEvent) { if (businessEvent instanceof BulkBusinessEvent) { throw new IllegalArgumentException("BulkBusinessEvent cannot be raised directly"); diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/business/service/ExternalBusinessEventConfigurationService.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/business/service/ExternalBusinessEventConfigurationService.java new file mode 100644 index 000000000..2a8374674 --- /dev/null +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/business/service/ExternalBusinessEventConfigurationService.java @@ -0,0 +1,26 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.infrastructure.event.business.service; + +import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent; + +public interface ExternalBusinessEventConfigurationService { + + boolean isExternalEventConfiguredForPosting(BusinessEvent businessEvent); +} diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/business/service/ExternalBusinessEventConfigurationServiceImpl.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/business/service/ExternalBusinessEventConfigurationServiceImpl.java new file mode 100644 index 000000000..e1fb6c920 --- /dev/null +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/business/service/ExternalBusinessEventConfigurationServiceImpl.java @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.infrastructure.event.business.service; + +import lombok.RequiredArgsConstructor; +import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent; +import org.apache.fineract.infrastructure.event.external.repository.ExternalEventConfigurationRepository; + +/** + * Default implementation for {@link ExternalBusinessEventConfigurationService}, configured by + * {@link org.apache.fineract.infrastructure.event.external.config.ExternalBusinessEventConfiguration} + */ +@RequiredArgsConstructor +public class ExternalBusinessEventConfigurationServiceImpl implements ExternalBusinessEventConfigurationService { + + private final ExternalEventConfigurationRepository eventConfigurationRepository; + + @Override + public boolean isExternalEventConfiguredForPosting(BusinessEvent businessEvent) { + if (businessEvent == null) { + return false; + } + return eventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(businessEvent.getType()).isEnabled(); + } +} diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/config/ExternalBusinessEventConfiguration.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/config/ExternalBusinessEventConfiguration.java new file mode 100644 index 000000000..36cc7e0f1 --- /dev/null +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/config/ExternalBusinessEventConfiguration.java @@ -0,0 +1,37 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.infrastructure.event.external.config; + +import org.apache.fineract.infrastructure.event.business.service.ExternalBusinessEventConfigurationService; +import org.apache.fineract.infrastructure.event.business.service.ExternalBusinessEventConfigurationServiceImpl; +import org.apache.fineract.infrastructure.event.external.repository.ExternalEventConfigurationRepository; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ExternalBusinessEventConfiguration { + + @ConditionalOnMissingBean(ExternalBusinessEventConfigurationService.class) + @Bean + public ExternalBusinessEventConfigurationService externalBusinessEventConfigurationService( + ExternalEventConfigurationRepository externalEventConfigurationRepository) { + return new ExternalBusinessEventConfigurationServiceImpl(externalEventConfigurationRepository); + } +} diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/business/service/BusinessEventNotifierServiceImplTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/business/service/BusinessEventNotifierServiceImplTest.java index 73d0ee2b9..37ca1b5af 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/business/service/BusinessEventNotifierServiceImplTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/business/service/BusinessEventNotifierServiceImplTest.java @@ -35,8 +35,6 @@ import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.event.business.BusinessEventListener; import org.apache.fineract.infrastructure.event.business.domain.BulkBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent; -import org.apache.fineract.infrastructure.event.external.repository.ExternalEventConfigurationRepository; -import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventConfiguration; import org.apache.fineract.infrastructure.event.external.service.ExternalEventService; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -58,7 +56,7 @@ class BusinessEventNotifierServiceImplTest { private ExternalEventService externalEventService; @Mock - private ExternalEventConfigurationRepository externalEventConfigurationRepository; + private ExternalBusinessEventConfigurationService externalBusinessEventConfigurationService; @Mock private FineractProperties fineractProperties; @@ -80,8 +78,7 @@ class BusinessEventNotifierServiceImplTest { TransactionExecution mockTransaction = mock(TransactionExecution.class); underTest.afterBegin(mockTransaction, null); // when - when(externalEventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.any())) - .thenReturn(new ExternalEventConfiguration("aType", true)); + when(externalBusinessEventConfigurationService.isExternalEventConfiguredForPosting(Mockito.any())).thenReturn(true); when(transactionHelper.hasTransaction()).thenReturn(true); underTest.notifyPostBusinessEvent(event); // then @@ -112,8 +109,7 @@ class BusinessEventNotifierServiceImplTest { underTest.addPostBusinessEventListener(MockBusinessEvent.class, postListener); TransactionExecution mockTransaction = mock(TransactionExecution.class); // when - when(externalEventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.any())) - .thenReturn(new ExternalEventConfiguration("aType", true)); + when(externalBusinessEventConfigurationService.isExternalEventConfiguredForPosting(Mockito.any())).thenReturn(true); when(transactionHelper.hasTransaction()).thenReturn(true); // simulate outer transaction @@ -148,8 +144,7 @@ class BusinessEventNotifierServiceImplTest { underTest.addPostBusinessEventListener(MockBusinessEvent.class, postListener); TransactionExecution mockTransaction = mock(TransactionExecution.class); // when - when(externalEventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.any())) - .thenReturn(new ExternalEventConfiguration("aType", true)); + when(externalBusinessEventConfigurationService.isExternalEventConfiguredForPosting(Mockito.any())).thenReturn(true); when(transactionHelper.hasTransaction()).thenReturn(true); // simulate outer transaction @@ -183,8 +178,7 @@ class BusinessEventNotifierServiceImplTest { TransactionExecution mockTransaction = mock(TransactionExecution.class); underTest.afterBegin(mockTransaction, null); // when - when(externalEventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.any())) - .thenReturn(new ExternalEventConfiguration("aType", true)); + when(externalBusinessEventConfigurationService.isExternalEventConfiguredForPosting(Mockito.any())).thenReturn(true); when(transactionHelper.hasTransaction()).thenReturn(true); underTest.notifyPostBusinessEvent(event); // then @@ -222,8 +216,7 @@ class BusinessEventNotifierServiceImplTest { underTest.addPostBusinessEventListener(MockBusinessEvent.class, postListener); when(transactionHelper.hasTransaction()).thenReturn(false); - when(externalEventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.any())) - .thenReturn(new ExternalEventConfiguration("aType", true)); + when(externalBusinessEventConfigurationService.isExternalEventConfiguredForPosting(Mockito.any())).thenReturn(true); // when underTest.notifyPostBusinessEvent(event); // then @@ -235,8 +228,7 @@ class BusinessEventNotifierServiceImplTest { public void testNotifyPostBusinessEventShouldNotPostAnythingWhenNoEventWasRaisedExternalEventWhenRecordingEnabled() { // given configureExternalEventsProperties(true); - when(externalEventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.any())) - .thenReturn(new ExternalEventConfiguration("aType", true)); + when(externalBusinessEventConfigurationService.isExternalEventConfiguredForPosting(Mockito.any())).thenReturn(true); underTest.startExternalEventRecording(); // when underTest.stopExternalEventRecording(); @@ -248,8 +240,7 @@ class BusinessEventNotifierServiceImplTest { public void testNotifyPostBusinessEventShouldNotifyPostListenersAndPostARegularExternalEventWhenRecordingEnabled() { // given configureExternalEventsProperties(true); - when(externalEventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.any())) - .thenReturn(new ExternalEventConfiguration("aType", true)); + when(externalBusinessEventConfigurationService.isExternalEventConfiguredForPosting(Mockito.any())).thenReturn(true); MockBusinessEvent event = new MockBusinessEvent(); BusinessEventListener postListener = mockListener(); underTest.addPostBusinessEventListener(MockBusinessEvent.class, postListener); @@ -266,8 +257,7 @@ class BusinessEventNotifierServiceImplTest { public void testNotifyPostBusinessEventShouldNotifyPostListenersAndPostAnBulkExternalEventWhenRecordingEnabled() { // given configureExternalEventsProperties(true); - when(externalEventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.any())) - .thenReturn(new ExternalEventConfiguration("aType", true)); + when(externalBusinessEventConfigurationService.isExternalEventConfiguredForPosting(Mockito.any())).thenReturn(true); MockBusinessEvent event = new MockBusinessEvent(); MockBusinessEvent event2 = new MockBusinessEvent(); BusinessEventListener postListener = mockListener(); @@ -323,8 +313,7 @@ class BusinessEventNotifierServiceImplTest { public void testNotifyPostBusinessEventShouldNotifyPostListenersAndShouldNotPostAnExternalEventIfNotConfiguredForPosting() { // given configureExternalEventsProperties(true); - when(externalEventConfigurationRepository.findExternalEventConfigurationByTypeWithNotFoundDetection(Mockito.any())) - .thenReturn(new ExternalEventConfiguration("aType", false)); + when(externalBusinessEventConfigurationService.isExternalEventConfiguredForPosting(Mockito.any())).thenReturn(false); MockBusinessEvent event = new MockBusinessEvent(); BusinessEventListener postListener = mockListener(); underTest.addPostBusinessEventListener(MockBusinessEvent.class, postListener);