Skip to content

Commit

Permalink
chore: move message creation to service
Browse files Browse the repository at this point in the history
  • Loading branch information
bbortt committed Nov 10, 2023
1 parent f821113 commit a0ca1c6
Show file tree
Hide file tree
Showing 19 changed files with 254 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import org.citrusframework.message.MessageHeaders;
import org.citrusframework.simulator.model.Message.Direction;
import org.citrusframework.simulator.model.ScenarioExecution;
import org.citrusframework.simulator.service.ActivityService;
import org.citrusframework.simulator.service.MessageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
Expand All @@ -36,11 +36,12 @@
@Component
public class EndpointMessageHandler {

private static Logger LOG = LoggerFactory.getLogger(EndpointMessageHandler.class);
private final ActivityService activityService;
private static final Logger logger = LoggerFactory.getLogger(EndpointMessageHandler.class);

public EndpointMessageHandler(ActivityService activityService) {
this.activityService = activityService;
private final MessageService messageService;

public EndpointMessageHandler(MessageService messageService) {
this.messageService = messageService;
}

public void handleSentMessage(Message message, TestContext context) {
Expand All @@ -54,19 +55,30 @@ public void handleReceivedMessage(Message message, TestContext context) {
private void saveScenarioMessage(Message message, TestContext context, Direction direction) {
Optional<Long> executionId = extractExecutionId(context);
Optional<String> citrusMessageId = extractCitrusMessageId(message);

if (executionId.isPresent() && citrusMessageId.isPresent()) {
activityService.saveScenarioMessage(executionId.get(), direction,
message.getPayload(String.class), citrusMessageId.get(), message.getHeaders());
messageService.attachMessageToScenarioExecutionAndSave(
executionId.get(),
direction,
message.getPayload(String.class),
citrusMessageId.get(),
message.getHeaders()
);
}
}

private Optional<Long> extractExecutionId(TestContext context) {
final String executionId;

try {
executionId = context.getVariable(ScenarioExecution.EXECUTION_ID);
} catch (CitrusRuntimeException e) {
// citrus throws a CitrusRuntimeException if you try to access a variable in the
// test context that does not exist.
// citrus throws a CitrusRuntimeException if you try to access a variable in the TextContext that does not
// exist.
if (logger.isDebugEnabled()) {
logger.warn("Tried to save Message in TestContext without execution id! Did you correctly configure the Scenario?", e);
}

return Optional.empty();
}

Expand All @@ -75,8 +87,9 @@ private Optional<Long> extractExecutionId(TestContext context) {
return Optional.of(Long.parseLong(executionId));
}
} catch (NumberFormatException e) {
LOG.error("Error parsing the execution id. Was expecting a Long", e);
logger.error("Error parsing the execution id: Was expecting a Long!", e);
}

return Optional.empty();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
@Repository
public interface MessageHeaderRepository extends JpaRepository<MessageHeader, Long>, JpaSpecificationExecutor<MessageHeader> {

default Optional<MessageHeader> findOneWithEagerRelationships(Long id) {
return this.findOneWithToOneRelationships(id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

/**
Expand Down Expand Up @@ -39,4 +40,10 @@ default Page<Message> findAllWithEagerRelationships(Pageable pageable) {
@Override
@EntityGraph(attributePaths = {"headers", "scenarioExecution"})
Page<Message> findAll(Specification<Message> spec, Pageable pageable);

default List<Message> findAllForScenarioExecution(Long scenarioExecutionId, String citrusMessageId, Message.Direction direction) {
return findAllByScenarioExecutionExecutionIdEqualsAndCitrusMessageIdEqualsIgnoreCaseAndDirectionEquals(scenarioExecutionId, citrusMessageId, direction.getId());
}

List<Message> findAllByScenarioExecutionExecutionIdEqualsAndCitrusMessageIdEqualsIgnoreCaseAndDirectionEquals(@Param("scenarioExecutionId") Long scenarioExecutionId, @Param("citrusMessageId") String citrusMessageId, @Param("direction") Integer direction);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

/**
* Spring Data JPA repository for the {@link ScenarioAction} entity.
*/
@Repository
public interface ScenarioActionRepository extends JpaRepository<ScenarioAction, Long>, JpaSpecificationExecutor<ScenarioAction> {

default Optional<ScenarioAction> findOneWithEagerRelationships(Long id) {
return this.findOneWithToOneRelationships(id);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.citrusframework.simulator.repository;

import org.citrusframework.simulator.model.ScenarioExecution;
import org.citrusframework.simulator.model.TestResult;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

/**
* Spring Data JPA repository for the {@link ScenarioParameter} entity.
*/
@Repository
public interface ScenarioParameterRepository extends JpaRepository<ScenarioParameter, Long>, JpaSpecificationExecutor<ScenarioParameter> {

default Optional<ScenarioParameter> findOneWithEagerRelationships(Long id) {
return this.findOneWithToOneRelationships(id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,20 @@
package org.citrusframework.simulator.service;

import jakarta.transaction.Transactional;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
import org.citrusframework.TestAction;
import org.citrusframework.TestCase;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.simulator.model.Message;
import org.citrusframework.simulator.model.ScenarioAction;
import org.citrusframework.simulator.model.ScenarioExecution;
import org.citrusframework.simulator.repository.ScenarioExecutionRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.Iterator;
import java.util.List;

/**
* Service for persisting and retrieving {@link ScenarioExecution} data.
*/
Expand All @@ -49,52 +43,9 @@ public class ActivityService {
private final TimeProvider timeProvider = new TimeProvider();

private final ScenarioExecutionRepository scenarioExecutionRepository;
private final MessageService messageService;

public ActivityService(ScenarioExecutionRepository scenarioExecutionRepository, MessageService messageService) {
public ActivityService(ScenarioExecutionRepository scenarioExecutionRepository) {
this.scenarioExecutionRepository = scenarioExecutionRepository;
this.messageService = messageService;
}

private ScenarioExecution getScenarioExecutionById(Long id) {
return scenarioExecutionRepository.findById(id).orElseThrow(() -> new CitrusRuntimeException(String.format("Failed to find scenario execution for id %s", id)));
}

/**
* Persists the message along with the scenario execution details. With the help of the {@code citrusMessageId}
* a check is made to determine whether the message has already been persisted. If it has then there's nothing
* to be done and the persisted message is simply returned.
*
* @param executionId the scenario execution id
* @param direction the direction of the message
* @param payload the message content
* @param citrusMessageId the internal citrus message id
* @param headers the message headers
* @return the already or newly persisted message
*/
public Message saveScenarioMessage(Long executionId, Message.Direction direction, String payload, String citrusMessageId, Map<String, Object> headers) {
final ScenarioExecution scenarioExecution = getScenarioExecutionById(executionId);
Collection<Message> messages = scenarioExecution.getScenarioMessages();
if (messages != null) {
Optional<Message> message = messages.stream()
.filter(scenarioMessage -> scenarioMessage.getCitrusMessageId().equalsIgnoreCase(citrusMessageId))
.findFirst();
if (message.isPresent()) {
// message is already persisted and attached to execution scenario
return message.get();
}
}

Message message = messageService.save(
Message.builder()
.direction(direction)
.payload(payload)
.citrusMessageId(citrusMessageId)
.headers(headers)
.build()
);
scenarioExecution.addScenarioMessage(message);
return message;
}

public void createTestAction(TestCase testCase, TestAction testAction) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* Service Interface for managing {@link MessageHeader}.
*/
public interface MessageHeaderService {

/**
* Save a messageHeader.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.Map;
import java.util.Optional;

/**
* Service Interface for managing {@link Message}.
*/
public interface MessageService {

/**
* Save a message.
*
Expand All @@ -49,4 +51,18 @@ public interface MessageService {
* @return the entity.
*/
Optional<Message> findOne(Long messageId);

/**
* Persists the message along with the scenario execution details. With the help of the {@code citrusMessageId}
* a check is made to determine whether the message has already been persisted. If it has then there's nothing
* to be done and the persisted message is simply returned.
*
* @param scenarioExecutionId the scenario execution id
* @param direction the direction of the message
* @param payload the message content
* @param citrusMessageId the internal citrus message id
* @param headers the message headers
* @return the already or newly persisted message
*/
Message attachMessageToScenarioExecutionAndSave(Long scenarioExecutionId, Message.Direction direction, String payload, String citrusMessageId, Map<String, Object> headers);
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
* Service Interface for managing {@link ScenarioAction}.
*/
public interface ScenarioActionService {

/**
* Save a scenarioAction.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* Service Interface for managing {@link ScenarioParameter}.
*/
public interface ScenarioParameterService {

/**
* Save a scenarioParameter.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* Service Interface for managing {@link org.citrusframework.simulator.model.TestParameter}.
*/
public interface TestParameterService {

/**
* Save a testParameter.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,20 @@

package org.citrusframework.simulator.service.impl;

import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.simulator.model.Message;
import org.citrusframework.simulator.repository.MessageRepository;
import org.citrusframework.simulator.service.MessageService;
import org.citrusframework.simulator.service.ScenarioExecutionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
Expand All @@ -38,9 +42,11 @@ public class MessageServiceImpl implements MessageService {
private static final Logger logger = LoggerFactory.getLogger(MessageServiceImpl.class);

private final MessageRepository messageRepository;
private final ScenarioExecutionService scenarioExecutionService;

public MessageServiceImpl(MessageRepository messageRepository) {
public MessageServiceImpl(MessageRepository messageRepository, ScenarioExecutionService scenarioExecutionService) {
this.messageRepository = messageRepository;
this.scenarioExecutionService = scenarioExecutionService;
}

@Override
Expand All @@ -62,4 +68,35 @@ public Optional<Message> findOne(Long messageId) {
logger.debug("Request to get Message : {}", messageId);
return messageRepository.findOneWithEagerRelationships(messageId);
}

@Override
public Message attachMessageToScenarioExecutionAndSave(Long scenarioExecutionId, Message.Direction direction, String payload, String citrusMessageId, Map<String, Object> headers) {
logger.debug("Request to save {} Message with citrusMessageId '{}' in correlation with ScenarioExecution : {}", direction, citrusMessageId, scenarioExecutionId);

List<Message> messages = messageRepository.findAllForScenarioExecution(scenarioExecutionId, citrusMessageId, direction);
if (!messages.isEmpty()) {
logger.trace("Message is already persisted and attached to execution scenario");
return messages.get(0);
}

Message message = messageRepository.save(
Message.builder()
.direction(direction)
.payload(payload)
.citrusMessageId(citrusMessageId)
.headers(headers)
.build()
);

scenarioExecutionService.save(
scenarioExecutionService.findOne(scenarioExecutionId)
.map(scenarioExecution -> {
scenarioExecution.addScenarioMessage(message);
return scenarioExecution;
})
.orElseThrow(() -> new CitrusRuntimeException(String.format("Error while attaching Message to ScenarioExecution %s: Did not find corresponding ScenarioExecution!", scenarioExecutionId)))
);

return message;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@
package org.citrusframework.simulator.service.impl;

import jakarta.annotation.Nullable;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;

import org.citrusframework.TestCase;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.simulator.model.ScenarioExecution;
Expand All @@ -35,9 +29,13 @@
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.Optional;
import org.springframework.util.CollectionUtils;

/**
* Service Implementation for managing {@link ScenarioExecution}.
Expand Down
Loading

0 comments on commit a0ca1c6

Please sign in to comment.