diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java index dbdc9d83f..ea70324f0 100644 --- a/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java +++ b/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java @@ -2287,6 +2287,14 @@ public class CommandWrapperBuilder { return this; } + public CommandWrapperBuilder executeSchedulerJob(final Long jobId) { + this.actionName = "EXECUTEJOB"; + this.entityName = "SCHEDULER"; + this.entityId = jobId; + this.href = "/jobs/" + jobId + "?command=executeJob"; + return this; + } + public CommandWrapperBuilder createMeeting(final CommandWrapper resourceDetails, final String supportedEntityType, final Long supportedEntityId) { this.actionName = "CREATE"; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/api/SchedulerJobApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/api/SchedulerJobApiResource.java index 12f092da7..6d302edb9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/api/SchedulerJobApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/api/SchedulerJobApiResource.java @@ -227,7 +227,11 @@ public class SchedulerJobApiResource { response = Response.status(400).build(); if (is(commandParam, SchedulerJobApiConstants.COMMAND_EXECUTE_JOB)) { Long jobId = schedulerJobRunnerReadService.retrieveId(idType, identifier); - jobRegisterService.executeJobWithParameters(jobId, jsonRequestBody); + final CommandWrapper commandRequest = new CommandWrapperBuilder() // + .executeSchedulerJob(jobId) // + .withJson(jsonRequestBody) // + .build(); + commandsSourceWritePlatformService.logCommandSource(commandRequest); response = Response.status(202).build(); } else { throw new UnrecognizedQueryParamException(SchedulerJobApiConstants.COMMAND, commandParam); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/handler/ExecuteJobCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/handler/ExecuteJobCommandHandler.java new file mode 100644 index 000000000..83afa584d --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/handler/ExecuteJobCommandHandler.java @@ -0,0 +1,46 @@ +/** + * 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.jobs.handler; + +import lombok.RequiredArgsConstructor; +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; +import org.apache.fineract.infrastructure.jobs.service.JobRegisterService; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +@CommandType(entity = "SCHEDULER", action = "EXECUTEJOB") +public class ExecuteJobCommandHandler implements NewCommandSourceHandler { + + private final JobRegisterService jobRegisterService; + + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + final Long jobId = command.entityId(); + jobRegisterService.executeJobWithParameters(jobId, command.json()); + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withEntityId(jobId) // + .build(); + } +} diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/jobs/handler/ExecuteJobCommandHandlerTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/jobs/handler/ExecuteJobCommandHandlerTest.java new file mode 100644 index 000000000..1120dc084 --- /dev/null +++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/jobs/handler/ExecuteJobCommandHandlerTest.java @@ -0,0 +1,64 @@ +/** + * 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.jobs.handler; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.jobs.service.JobRegisterService; +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; + +@ExtendWith(MockitoExtension.class) +class ExecuteJobCommandHandlerTest { + + @Mock + private JobRegisterService jobRegisterService; + + @Mock + private JsonCommand command; + + @InjectMocks + private ExecuteJobCommandHandler underTest; + + @Test + void shouldExecuteJobAndReturnCommandResult() { + // given + Long jobId = 123L; + Long commandId = 456L; + String json = "{\"includeTasks\":true}"; + when(command.entityId()).thenReturn(jobId); + when(command.commandId()).thenReturn(commandId); + when(command.json()).thenReturn(json); + + // when + CommandProcessingResult result = underTest.processCommand(command); + + // then + verify(jobRegisterService).executeJobWithParameters(jobId, json); + assertEquals(commandId, result.getCommandId()); + assertEquals(jobId, result.getResourceId()); + } +} diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AuditIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AuditIntegrationTest.java index 5c17dba4d..e95becaae 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AuditIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AuditIntegrationTest.java @@ -36,6 +36,7 @@ import java.util.List; import org.apache.fineract.integrationtests.common.AuditHelper; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.OfficeHelper; +import org.apache.fineract.integrationtests.common.SchedulerJobHelper; import org.apache.fineract.integrationtests.common.Utils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -51,6 +52,7 @@ public class AuditIntegrationTest { private RequestSpecification requestSpec; private ClientHelper clientHelper; private AuditHelper auditHelper; + private SchedulerJobHelper schedulerJobHelper; private static final SecureRandom rand = new SecureRandom(); /** @@ -65,6 +67,7 @@ public class AuditIntegrationTest { this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); this.auditHelper = new AuditHelper(this.requestSpec, this.responseSpec); this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); + this.schedulerJobHelper = new SchedulerJobHelper(this.requestSpec); } @Test @@ -157,4 +160,19 @@ public class AuditIntegrationTest { } + @SuppressWarnings("unchecked") + @Test + public void executeSchedulerJobShouldCreateAuditEntry() { + // given + int jobId = schedulerJobHelper.getSchedulerJobIdByShortName("SA_AANF"); + List> auditsRecievedInitial = auditHelper.getAuditDetails(jobId, "EXECUTEJOB", "SCHEDULER"); + + // when + schedulerJobHelper.runSchedulerJob(jobId); + + // then + List> auditsRecieved = auditHelper.getAuditDetails(jobId, "EXECUTEJOB", "SCHEDULER"); + auditHelper.verifyMultipleAuditsOnserver(auditsRecievedInitial, auditsRecieved, jobId, "EXECUTEJOB", "SCHEDULER"); + } + }