From 61ca7bb0e033ded643c8e23fa11e0ac770131a2b Mon Sep 17 00:00:00 2001 From: Arnold Galovics Date: Mon, 9 Jan 2023 19:24:58 +0100 Subject: [PATCH] FINERACT-1724: Added the possibility to use username and password for JMS for remote jobs + the ability to disable remote jobs completely for non-batch instances --- ...eractRemoteJobMessageHandlerCondition.java | 59 ++++--- .../core/config/FineractProperties.java | 6 + .../JmsBrokerConfiguration.java | 5 + .../src/main/resources/application.properties | 2 + ...tRemoteJobMessageHandlerConditionTest.java | 157 ++++++++++++++++++ 5 files changed, 204 insertions(+), 25 deletions(-) create mode 100644 fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/condition/FineractRemoteJobMessageHandlerConditionTest.java diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/condition/FineractRemoteJobMessageHandlerCondition.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/condition/FineractRemoteJobMessageHandlerCondition.java index e4e8840b164..95d55a28d28 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/condition/FineractRemoteJobMessageHandlerCondition.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/condition/FineractRemoteJobMessageHandlerCondition.java @@ -18,41 +18,50 @@ */ package org.apache.fineract.infrastructure.core.condition; -import java.util.Optional; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Condition; -import org.springframework.context.annotation.ConditionContext; -import org.springframework.core.type.AnnotatedTypeMetadata; +import org.apache.fineract.infrastructure.core.config.FineractProperties; @Slf4j -public class FineractRemoteJobMessageHandlerCondition implements Condition { +public class FineractRemoteJobMessageHandlerCondition extends PropertiesCondition { @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - boolean isSpringEventsEnabled = Optional - .ofNullable( - context.getEnvironment().getProperty("fineract.remote-job-message-handler.spring-events.enabled", Boolean.class)) - .orElse(true); - boolean isJmsEnabled = Optional - .ofNullable(context.getEnvironment().getProperty("fineract.remote-job-message-handler.jms.enabled", Boolean.class)) - .orElse(true); - boolean isBatchManagerModeEnabled = Optional - .ofNullable(context.getEnvironment().getProperty("fineract.mode.batch-manager-enabled", Boolean.class)).orElse(true); - boolean isBatchWorkerModeEnabled = Optional - .ofNullable(context.getEnvironment().getProperty("fineract.mode.batch-worker-enabled", Boolean.class)).orElse(true); - // TODO extend this expression with other message handlers in the future + protected boolean matches(FineractProperties properties) { + boolean isSpringEventsEnabled = properties.getRemoteJobMessageHandler().getSpringEvents().isEnabled(); + boolean conditionFails = false; - boolean onlyOneMessageHandlerEnabled = isSpringEventsEnabled ^ isJmsEnabled; - if (!onlyOneMessageHandlerEnabled) { - conditionFails = true; - log.error("For remote partitioning jobs exactly one Message Handler must be enabled."); - } - if (isSpringEventsEnabled) { - if (!(isBatchManagerModeEnabled && isBatchWorkerModeEnabled)) { + if (isAnyMessageHandlerConfigured(properties) && isBatchInstance(properties)) { + if (!isOnlyOneMessageHandlerEnabled(properties)) { + conditionFails = true; + log.error("For remote partitioning jobs exactly one Message Handler must be enabled."); + } else if (isSpringEventsEnabled && !isBatchManagerAndWorkerTogether(properties)) { conditionFails = true; log.error("If Spring Event Message Handler is enabled, the instance must be Batch Manager and Batch Worker too."); } } return conditionFails; } + + private boolean isOnlyOneMessageHandlerEnabled(FineractProperties properties) { + boolean isSpringEventsEnabled = properties.getRemoteJobMessageHandler().getSpringEvents().isEnabled(); + boolean isJmsEnabled = properties.getRemoteJobMessageHandler().getJms().isEnabled(); + return isSpringEventsEnabled ^ isJmsEnabled; + } + + private boolean isAnyMessageHandlerConfigured(FineractProperties properties) { + boolean isSpringEventsEnabled = properties.getRemoteJobMessageHandler().getSpringEvents().isEnabled(); + boolean isJmsEnabled = properties.getRemoteJobMessageHandler().getJms().isEnabled(); + return isSpringEventsEnabled || isJmsEnabled; + } + + private boolean isBatchInstance(FineractProperties properties) { + boolean isBatchManagerModeEnabled = properties.getMode().isBatchManagerEnabled(); + boolean isBatchWorkerModeEnabled = properties.getMode().isBatchWorkerEnabled(); + return isBatchManagerModeEnabled || isBatchWorkerModeEnabled; + } + + private boolean isBatchManagerAndWorkerTogether(FineractProperties properties) { + boolean isBatchManagerModeEnabled = properties.getMode().isBatchManagerEnabled(); + boolean isBatchWorkerModeEnabled = properties.getMode().isBatchWorkerEnabled(); + return isBatchManagerModeEnabled && isBatchWorkerModeEnabled; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java index f6e47e502ec..36c016da2c2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java @@ -125,6 +125,12 @@ public static class FineractRemoteJobMessageHandlerJmsProperties { private boolean enabled; private String requestQueueName; private String brokerUrl; + private String brokerUsername; + private String brokerPassword; + + public boolean isBrokerPasswordProtected() { + return StringUtils.isNotBlank(brokerUsername) || StringUtils.isNotBlank(brokerPassword); + } } @Getter diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/messagehandler/JmsBrokerConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/messagehandler/JmsBrokerConfiguration.java index 96df69941f1..2e5ef2c8a33 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/messagehandler/JmsBrokerConfiguration.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/springbatch/messagehandler/JmsBrokerConfiguration.java @@ -37,6 +37,11 @@ public ActiveMQConnectionFactory connectionFactory() { ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(); connectionFactory.setBrokerURL(fineractProperties.getRemoteJobMessageHandler().getJms().getBrokerUrl()); connectionFactory.setTrustAllPackages(true); + FineractProperties.FineractRemoteJobMessageHandlerJmsProperties jmsProps = fineractProperties.getRemoteJobMessageHandler().getJms(); + if (jmsProps.isBrokerPasswordProtected()) { + connectionFactory.setUserName(jmsProps.getBrokerUsername()); + connectionFactory.setPassword(jmsProps.getBrokerPassword()); + } return connectionFactory; } } diff --git a/fineract-provider/src/main/resources/application.properties b/fineract-provider/src/main/resources/application.properties index 21584870c6a..7ecc24686dd 100644 --- a/fineract-provider/src/main/resources/application.properties +++ b/fineract-provider/src/main/resources/application.properties @@ -52,6 +52,8 @@ fineract.remote-job-message-handler.spring-events.enabled=${FINERACT_REMOTE_JOB_ fineract.remote-job-message-handler.jms.enabled=${FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_ENABLED:false} fineract.remote-job-message-handler.jms.request-queue-name=${FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_QUEUE_NAME:JMS-request-queue} fineract.remote-job-message-handler.jms.broker-url=${FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_BROKER_URL:tcp://127.0.0.1:61616} +fineract.remote-job-message-handler.jms.broker-username=${FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_BROKER_USERNAME:} +fineract.remote-job-message-handler.jms.broker-password=${FINERACT_REMOTE_JOB_MESSAGE_HANDLER_JMS_BROKER_PASSWORD:} fineract.events.external.enabled=${FINERACT_EXTERNAL_EVENTS_ENABLED:false} fineract.events.external.producer.read-batch-size=${FINERACT_EXTERNAL_EVENTS_PRODUCER_READ_BATCH_SIZE:1000} diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/condition/FineractRemoteJobMessageHandlerConditionTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/condition/FineractRemoteJobMessageHandlerConditionTest.java new file mode 100644 index 00000000000..7d360b6dcc6 --- /dev/null +++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/condition/FineractRemoteJobMessageHandlerConditionTest.java @@ -0,0 +1,157 @@ +/** + * 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.core.condition; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.mock.env.MockEnvironment; + +@ExtendWith(MockitoExtension.class) +class FineractRemoteJobMessageHandlerConditionTest { + + @Mock + private ConditionContext conditionContext; + + @Mock + private AnnotatedTypeMetadata metadata; + + private MockEnvironment environment; + + @InjectMocks + private FineractRemoteJobMessageHandlerCondition underTest = new FineractRemoteJobMessageHandlerCondition(); + + @BeforeEach + public void setUp() { + environment = new MockEnvironment(); + given(conditionContext.getEnvironment()).willReturn(environment); + } + + @Test + public void testMatchesShouldReturnFalseWhenSpringEventsIsEnabledAndManagerAndWorker() { + // given + environment.withProperty("fineract.remote-job-message-handler.spring-events.enabled", "true"); + environment.withProperty("fineract.remote-job-message-handler.jms.enabled", "false"); + environment.withProperty("fineract.mode.batch-manager-enabled", "true"); + environment.withProperty("fineract.mode.batch-worker-enabled", "true"); + // when + boolean result = underTest.matches(conditionContext, metadata); + // then + assertThat(result).isFalse(); + } + + @Test + public void testMatchesShouldReturnTrueWhenSpringEventsIsEnabledAndManagerOnly() { + // given + environment.withProperty("fineract.remote-job-message-handler.spring-events.enabled", "true"); + environment.withProperty("fineract.remote-job-message-handler.jms.enabled", "false"); + environment.withProperty("fineract.mode.batch-manager-enabled", "true"); + environment.withProperty("fineract.mode.batch-worker-enabled", "false"); + // when + boolean result = underTest.matches(conditionContext, metadata); + // then + assertThat(result).isTrue(); + } + + @Test + public void testMatchesShouldReturnTrueWhenSpringEventsIsEnabledAndWorkerOnly() { + // given + environment.withProperty("fineract.remote-job-message-handler.spring-events.enabled", "true"); + environment.withProperty("fineract.remote-job-message-handler.jms.enabled", "false"); + environment.withProperty("fineract.mode.batch-manager-enabled", "false"); + environment.withProperty("fineract.mode.batch-worker-enabled", "true"); + // when + boolean result = underTest.matches(conditionContext, metadata); + // then + assertThat(result).isTrue(); + } + + @Test + public void testMatchesShouldReturnFalseWhenJmsIsEnabledAndManagerAndWorker() { + // given + environment.withProperty("fineract.remote-job-message-handler.spring-events.enabled", "false"); + environment.withProperty("fineract.remote-job-message-handler.jms.enabled", "true"); + environment.withProperty("fineract.mode.batch-manager-enabled", "true"); + environment.withProperty("fineract.mode.batch-worker-enabled", "true"); + // when + boolean result = underTest.matches(conditionContext, metadata); + // then + assertThat(result).isFalse(); + } + + @Test + public void testMatchesShouldReturnFalseWhenJmsIsEnabledAndManagerOnly() { + // given + environment.withProperty("fineract.remote-job-message-handler.spring-events.enabled", "false"); + environment.withProperty("fineract.remote-job-message-handler.jms.enabled", "true"); + environment.withProperty("fineract.mode.batch-manager-enabled", "true"); + environment.withProperty("fineract.mode.batch-worker-enabled", "false"); + // when + boolean result = underTest.matches(conditionContext, metadata); + // then + assertThat(result).isFalse(); + } + + @Test + public void testMatchesShouldReturnFalseWhenJmsIsEnabledAndWorkerOnly() { + // given + environment.withProperty("fineract.remote-job-message-handler.spring-events.enabled", "false"); + environment.withProperty("fineract.remote-job-message-handler.jms.enabled", "true"); + environment.withProperty("fineract.mode.batch-manager-enabled", "false"); + environment.withProperty("fineract.mode.batch-worker-enabled", "true"); + // when + boolean result = underTest.matches(conditionContext, metadata); + // then + assertThat(result).isFalse(); + } + + @Test + public void testMatchesShouldReturnTrueWhenSpringEventsIsEnabledAndJmsIsEnabled() { + // given + environment.withProperty("fineract.remote-job-message-handler.spring-events.enabled", "true"); + environment.withProperty("fineract.remote-job-message-handler.jms.enabled", "true"); + environment.withProperty("fineract.mode.batch-manager-enabled", "true"); + environment.withProperty("fineract.mode.batch-worker-enabled", "true"); + // when + boolean result = underTest.matches(conditionContext, metadata); + // then + assertThat(result).isTrue(); + } + + @Test + public void testMatchesShouldReturnFalseWhenNoMessagingIsConfiguredAndNotManagerOrWorker() { + // given + environment.withProperty("fineract.remote-job-message-handler.spring-events.enabled", "false"); + environment.withProperty("fineract.remote-job-message-handler.jms.enabled", "false"); + environment.withProperty("fineract.mode.batch-manager-enabled", "false"); + environment.withProperty("fineract.mode.batch-worker-enabled", "false"); + // when + boolean result = underTest.matches(conditionContext, metadata); + // then + assertThat(result).isFalse(); + } +}