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.ApiRequestDTO;
import com.eactive.testmaster.client.dto.ApiResponse; 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.client.service.ApiClientFactory;
import com.eactive.testmaster.loadtest.service.VirtualUser;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator; import org.springframework.validation.Validator;
@@ -30,9 +30,8 @@ public class ApiClientController {
if (bindingResult.hasErrors()) { if (bindingResult.hasErrors()) {
throw new IllegalArgumentException(bindingResult.getAllErrors().get(0).getDefaultMessage()); throw new IllegalArgumentException(bindingResult.getAllErrors().get(0).getDefaultMessage());
} }
VirtualUser virtualUser = new VirtualUser(request.getId(), apiClientFactory);
ApiClient client = apiClientFactory.getClient(request); return virtualUser.processApiAndReturn(request);
return client.handleRequest(request).get();
} }
} }
@@ -7,6 +7,7 @@ import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
@@ -47,6 +48,9 @@ public class ApiLayout {
@OneToMany(mappedBy = "apiLayout", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) @OneToMany(mappedBy = "apiLayout", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
private List<ApiLayoutItem> layoutItems = new ArrayList<>(); private List<ApiLayoutItem> layoutItems = new ArrayList<>();
@Lob
private String computedLayoutItemRoot;
public String getId() { public String getId() {
return id; return id;
} }
@@ -164,4 +168,11 @@ public class ApiLayout {
this.layoutItems.add(item); 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; package com.eactive.testmaster.client.mapper;
import com.eactive.testmaster.client.dto.ApiLayoutDTO; 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.ApiLayout;
import com.eactive.testmaster.client.entity.ApiRequestInfo; import com.eactive.testmaster.client.entity.ApiRequestInfo;
import com.eactive.testmaster.client.repository.ApiLayoutRepository; import com.eactive.testmaster.client.repository.ApiLayoutRepository;
import com.eactive.testmaster.client.repository.ApiRequestRepository; import com.eactive.testmaster.client.repository.ApiRequestRepository;
import com.eactive.testmaster.common.mapper.CommonMapper; import com.eactive.testmaster.common.mapper.CommonMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List; import java.util.List;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
@@ -19,6 +21,8 @@ import org.springframework.stereotype.Component;
@Component @Component
public abstract class ApiLayoutMapper { public abstract class ApiLayoutMapper {
ObjectMapper objectMapper = new ObjectMapper();
@Autowired @Autowired
private ApiLayoutRepository apiLayoutRepository; private ApiLayoutRepository apiLayoutRepository;
@@ -32,6 +36,31 @@ public abstract class ApiLayoutMapper {
@Mapping(target = "apiRequestId", source = "apiRequestInfo") @Mapping(target = "apiRequestId", source = "apiRequestInfo")
public abstract ApiLayoutDTO map(ApiLayout entity); 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) { public ApiRequestInfo mapApiRequestInfo(String id) {
if (id == null) { if (id == null) {
return 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.ApiLayoutRepository;
import com.eactive.testmaster.client.repository.ApiRequestRepository; import com.eactive.testmaster.client.repository.ApiRequestRepository;
import com.eactive.testmaster.common.exception.NotFoundException; import com.eactive.testmaster.common.exception.NotFoundException;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -64,6 +63,7 @@ public class ApiLayoutMgmtService {
layout.setModfMgtStusDstCd(updatedLayout.getModfMgtStusDstCd()); layout.setModfMgtStusDstCd(updatedLayout.getModfMgtStusDstCd());
layout.setUseYn(updatedLayout.getUseYn()); layout.setUseYn(updatedLayout.getUseYn());
layout.setVerInfo(updatedLayout.getVerInfo()); layout.setVerInfo(updatedLayout.getVerInfo());
layout.setComputedLayoutItemRoot(updatedLayout.getComputedLayoutItemRoot());
if (updatedLayout.getLayoutItems() != null && !updatedLayout.getLayoutItems().isEmpty()) { if (updatedLayout.getLayoutItems() != null && !updatedLayout.getLayoutItems().isEmpty()) {
layout.getLayoutItems().clear(); layout.getLayoutItems().clear();
@@ -36,8 +36,8 @@ public class VirtualUser implements Runnable {
private Thread runningThread; private Thread runningThread;
private final LoadTestService loadTestService; private LoadTestService loadTestService;
private final ApiClientFactory apiClientFactory; private ApiClientFactory apiClientFactory;
private static Map<String, String> globals = new ConcurrentHashMap<>(); private static Map<String, String> globals = new ConcurrentHashMap<>();
private Map<String, String> variables = new ConcurrentHashMap<>(); private Map<String, String> variables = new ConcurrentHashMap<>();
@@ -57,7 +57,11 @@ public class VirtualUser implements Runnable {
this.maxCount = maxCount; this.maxCount = maxCount;
this.apiClientFactory = apiClientFactory; this.apiClientFactory = apiClientFactory;
this.latch = latch; this.latch = latch;
}
public VirtualUser(String testId, ApiClientFactory apiClientFactory) {
this.testId = testId;
this.apiClientFactory = apiClientFactory;
} }
public void pause() { public void pause() {
@@ -130,7 +134,7 @@ public class VirtualUser implements Runnable {
visitedNodes.add(currentNode); visitedNodes.add(currentNode);
if (currentNode.getClassName().equalsIgnoreCase("api")) { if (currentNode.getClassName().equalsIgnoreCase("api")) {
processApi(currentNode); processApi(currentNode.getApiRequest());
} }
if (currentNode.getConnections() != null && !currentNode.getConnections().isEmpty()) { if (currentNode.getConnections() != null && !currentNode.getConnections().isEmpty()) {
@@ -143,10 +147,35 @@ public class VirtualUser implements Runnable {
logger.debug("Action performed or interrupted"); 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 { try {
if (currentNode.getApiRequest() != null) { response = apiClientFactory.getClient(replaced).handleRequest(replaced).get();
ApiRequestDTO cloned = SerializationUtils.clone(currentNode.getApiRequest()); } 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; ApiRequestDTO replaced = null;
executePreRequestScript(cloned); executePreRequestScript(cloned);
@@ -175,7 +204,8 @@ public class VirtualUser implements Runnable {
engine.put("variables", variables); engine.put("variables", variables);
engine.put("request", apiRequest); engine.put("request", apiRequest);
try { try {
engine.eval(apiRequest.getPreRequestScript()); if(apiRequest.getPreRequestScript() != null)
engine.eval(apiRequest.getPreRequestScript());
} catch (ScriptException e) { } catch (ScriptException e) {
logger.error("Error executing pre-request script", e); logger.error("Error executing pre-request script", e);
e.printStackTrace(); e.printStackTrace();
@@ -191,7 +221,9 @@ public class VirtualUser implements Runnable {
engine.put("request", apiRequest); engine.put("request", apiRequest);
engine.put("response", response); engine.put("response", response);
try { try {
engine.eval(apiRequest.getPostRequestScript()); if (apiRequest.getPostRequestScript() != null){
engine.eval(apiRequest.getPostRequestScript());
}
} catch (ScriptException e) { } catch (ScriptException e) {
logger.error("Error executing post-request script", e); logger.error("Error executing post-request script", e);
e.printStackTrace(); e.printStackTrace();
@@ -227,14 +259,38 @@ public class VirtualUser implements Runnable {
if (apiRequest.getQueryParams() != null) { if (apiRequest.getQueryParams() != null) {
apiRequest.setQueryParams(replaceInList(apiRequest.getQueryParams(), placeholder, value)); apiRequest.setQueryParams(replaceInList(apiRequest.getQueryParams(), placeholder, value));
} }
if (apiRequest.getLayout() != null && apiRequest.getLayout().getLayoutItems() != null) { if (apiRequest.getLayout() != null && apiRequest.getLayout().getLayoutItems() != null) {
apiRequest.getLayout().setLayoutItems(replaceInLayoutItems(apiRequest.getLayout().getLayoutItems(), placeholder, value)); 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; 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) { private List<ApiLayoutItemDTO> replaceInLayoutItems(List<ApiLayoutItemDTO> originalList, String placeholder, String value) {
List<ApiLayoutItemDTO> replacedList = new ArrayList<>(); List<ApiLayoutItemDTO> replacedList = new ArrayList<>();
Pattern pattern = Pattern.compile(placeholder); Pattern pattern = Pattern.compile(placeholder);
File diff suppressed because one or more lines are too long