Flat Message Layout

This commit is contained in:
현성필
2024-05-13 20:37:46 +09:00
parent 128bf60b54
commit a87f59dfd8
6 changed files with 111 additions and 16 deletions
@@ -2,8 +2,8 @@ package com.eactive.testmaster.client.controller;
import com.eactive.testmaster.client.dto.ApiRequestDTO;
import com.eactive.testmaster.client.dto.ApiResponse;
import com.eactive.testmaster.client.service.ApiClient;
import com.eactive.testmaster.client.service.ApiClientFactory;
import com.eactive.testmaster.loadtest.service.VirtualUser;
import java.util.concurrent.ExecutionException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
@@ -30,9 +30,8 @@ public class ApiClientController {
if (bindingResult.hasErrors()) {
throw new IllegalArgumentException(bindingResult.getAllErrors().get(0).getDefaultMessage());
}
ApiClient client = apiClientFactory.getClient(request);
return client.handleRequest(request).get();
VirtualUser virtualUser = new VirtualUser(request.getId(), apiClientFactory);
return virtualUser.processApiAndReturn(request);
}
}
@@ -7,6 +7,7 @@ import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@@ -47,6 +48,9 @@ public class ApiLayout {
@OneToMany(mappedBy = "apiLayout", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
private List<ApiLayoutItem> layoutItems = new ArrayList<>();
@Lob
private String computedLayoutItemRoot;
public String getId() {
return id;
}
@@ -164,4 +168,11 @@ public class ApiLayout {
this.layoutItems.add(item);
}
public String getComputedLayoutItemRoot() {
return computedLayoutItemRoot;
}
public void setComputedLayoutItemRoot(String computedLayoutItemRoot) {
this.computedLayoutItemRoot = computedLayoutItemRoot;
}
}
@@ -1,11 +1,13 @@
package com.eactive.testmaster.client.mapper;
import com.eactive.testmaster.client.dto.ApiLayoutDTO;
import com.eactive.testmaster.client.dto.ApiLayoutItemDTO;
import com.eactive.testmaster.client.entity.ApiLayout;
import com.eactive.testmaster.client.entity.ApiRequestInfo;
import com.eactive.testmaster.client.repository.ApiLayoutRepository;
import com.eactive.testmaster.client.repository.ApiRequestRepository;
import com.eactive.testmaster.common.mapper.CommonMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@@ -19,6 +21,8 @@ import org.springframework.stereotype.Component;
@Component
public abstract class ApiLayoutMapper {
ObjectMapper objectMapper = new ObjectMapper();
@Autowired
private ApiLayoutRepository apiLayoutRepository;
@@ -32,6 +36,31 @@ public abstract class ApiLayoutMapper {
@Mapping(target = "apiRequestId", source = "apiRequestInfo")
public abstract ApiLayoutDTO map(ApiLayout entity);
public String treeToString(ApiLayoutItemDTO value) {
if (value == null) {
return null;
}
try {
return objectMapper.writeValueAsString(value);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to convert ApiLayoutItemDTO to JSON", e);
}
}
public ApiLayoutItemDTO stringToTree(String value) {
if (value == null) {
return null;
}
try {
return objectMapper.readValue(value, ApiLayoutItemDTO.class);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to convert JSON to ApiLayoutItemDTO", e);
}
}
public ApiRequestInfo mapApiRequestInfo(String id) {
if (id == null) {
return null;
@@ -6,7 +6,6 @@ import com.eactive.testmaster.client.entity.ApiRequestInfo;
import com.eactive.testmaster.client.repository.ApiLayoutRepository;
import com.eactive.testmaster.client.repository.ApiRequestRepository;
import com.eactive.testmaster.common.exception.NotFoundException;
import java.util.Optional;
import java.util.UUID;
import javax.transaction.Transactional;
import org.springframework.stereotype.Service;
@@ -64,6 +63,7 @@ public class ApiLayoutMgmtService {
layout.setModfMgtStusDstCd(updatedLayout.getModfMgtStusDstCd());
layout.setUseYn(updatedLayout.getUseYn());
layout.setVerInfo(updatedLayout.getVerInfo());
layout.setComputedLayoutItemRoot(updatedLayout.getComputedLayoutItemRoot());
if (updatedLayout.getLayoutItems() != null && !updatedLayout.getLayoutItems().isEmpty()) {
layout.getLayoutItems().clear();
@@ -36,8 +36,8 @@ public class VirtualUser implements Runnable {
private Thread runningThread;
private final LoadTestService loadTestService;
private final ApiClientFactory apiClientFactory;
private LoadTestService loadTestService;
private ApiClientFactory apiClientFactory;
private static Map<String, String> globals = new ConcurrentHashMap<>();
private Map<String, String> variables = new ConcurrentHashMap<>();
@@ -57,7 +57,11 @@ public class VirtualUser implements Runnable {
this.maxCount = maxCount;
this.apiClientFactory = apiClientFactory;
this.latch = latch;
}
public VirtualUser(String testId, ApiClientFactory apiClientFactory) {
this.testId = testId;
this.apiClientFactory = apiClientFactory;
}
public void pause() {
@@ -130,7 +134,7 @@ public class VirtualUser implements Runnable {
visitedNodes.add(currentNode);
if (currentNode.getClassName().equalsIgnoreCase("api")) {
processApi(currentNode);
processApi(currentNode.getApiRequest());
}
if (currentNode.getConnections() != null && !currentNode.getConnections().isEmpty()) {
@@ -143,10 +147,35 @@ public class VirtualUser implements Runnable {
logger.debug("Action performed or interrupted");
}
private void processApi(ScenarioNode currentNode) {
public ApiResponse processApiAndReturn(ApiRequestDTO apiRequest) {
ApiRequestDTO cloned = SerializationUtils.clone(apiRequest);
ApiRequestDTO replaced = null;
executePreRequestScript(cloned);
replaced = replacePlaceHoldersWithVariables(cloned);
// long startTime = System.currentTimeMillis();
ApiResponse response = null;
try {
if (currentNode.getApiRequest() != null) {
ApiRequestDTO cloned = SerializationUtils.clone(currentNode.getApiRequest());
response = apiClientFactory.getClient(replaced).handleRequest(replaced).get();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
// long endTime = System.currentTimeMillis();
// long responseTime = endTime - startTime;
executePostRequestScript(replaced, response);
return response;
}
public void processApi(ApiRequestDTO apiRequest) {
try {
if (apiRequest != null) {
ApiRequestDTO cloned = SerializationUtils.clone(apiRequest);
ApiRequestDTO replaced = null;
executePreRequestScript(cloned);
@@ -175,7 +204,8 @@ public class VirtualUser implements Runnable {
engine.put("variables", variables);
engine.put("request", apiRequest);
try {
engine.eval(apiRequest.getPreRequestScript());
if(apiRequest.getPreRequestScript() != null)
engine.eval(apiRequest.getPreRequestScript());
} catch (ScriptException e) {
logger.error("Error executing pre-request script", e);
e.printStackTrace();
@@ -191,7 +221,9 @@ public class VirtualUser implements Runnable {
engine.put("request", apiRequest);
engine.put("response", response);
try {
engine.eval(apiRequest.getPostRequestScript());
if (apiRequest.getPostRequestScript() != null){
engine.eval(apiRequest.getPostRequestScript());
}
} catch (ScriptException e) {
logger.error("Error executing post-request script", e);
e.printStackTrace();
@@ -227,14 +259,38 @@ public class VirtualUser implements Runnable {
if (apiRequest.getQueryParams() != null) {
apiRequest.setQueryParams(replaceInList(apiRequest.getQueryParams(), placeholder, value));
}
if (apiRequest.getLayout() != null && apiRequest.getLayout().getLayoutItems() != null) {
apiRequest.getLayout().setLayoutItems(replaceInLayoutItems(apiRequest.getLayout().getLayoutItems(), placeholder, value));
}
if (apiRequest.getLayout() !=null && apiRequest.getLayout().getComputedLayoutItemRoot() !=null){
replaceLayoutItemTree(apiRequest.getLayout().getComputedLayoutItemRoot(), placeholder, value);
}
}
return apiRequest;
}
private void replaceLayoutItemTree(ApiLayoutItemDTO computedLayoutItemRoot, String placeholder, String value) {
if (computedLayoutItemRoot == null) {
return; // Base case: if the node is null, just return.
}
// Replace the value in the current node if it contains the placeholder
if (computedLayoutItemRoot.getValue() != null) {
String replacedValue = computedLayoutItemRoot.getValue().replaceAll(placeholder, value);
computedLayoutItemRoot.setValue(replacedValue);
}
// Recursively replace the value in each child
if (computedLayoutItemRoot.getChildren() != null) {
for (ApiLayoutItemDTO child : computedLayoutItemRoot.getChildren()) {
replaceLayoutItemTree(child, placeholder, value);
}
}
}
private List<ApiLayoutItemDTO> replaceInLayoutItems(List<ApiLayoutItemDTO> originalList, String placeholder, String value) {
List<ApiLayoutItemDTO> replacedList = new ArrayList<>();
Pattern pattern = Pattern.compile(placeholder);
File diff suppressed because one or more lines are too long