Skip to content

Commit

Permalink
first fully working version of Short Circuit, so #71 is technically
Browse files Browse the repository at this point in the history
addressed
  • Loading branch information
tkohegyi committed Jun 11, 2016
1 parent 116bdda commit ee3d69d
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 29 deletions.
6 changes: 1 addition & 5 deletions wilma-extras/short.circuit/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
Wilma Example - Short Circuit
=============================

This readme file is under construction.
---------------------------------------

Purpose of this example
---------------------------------------
First of all, this is a very complex example, uses almost all features and extension points of Wilma.
Expand All @@ -21,7 +18,7 @@ As an extra bonus, the internal content cache can be saved to disk, and any time
Do you know why it is good? Yes, you may record the traffic, and use it later to stub the traffic, as necessary.

Please note that right now this example caches only responses, those have status code 200,
and the response Content-type is any of the followings: "text/plain", "application/json" and "text/html".
and the response Content-type is any of the followings: "text/plain", "application/json", "text/html" and "text/css".

Implementation
---------------------------------------
Expand Down Expand Up @@ -133,7 +130,6 @@ If you repeat the save request, the plugin will save the cached massages again,

Load a cache from a folder
--------------------------
NOT YET IMPLEMENTED!
To load a Short Circuit cache, just specify a folder that contains Short Circuit files in the following form:
```
GET http://localhost:1234/config/public/services/ShortCircuitInterceptor/circuits?folder={toFolder}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.epam.wilma.domain.http.WilmaHttpRequest;
import com.epam.wilma.domain.stubconfig.dialog.condition.checker.ConditionChecker;
import com.epam.wilma.domain.stubconfig.parameter.ParameterList;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -43,6 +44,14 @@ public class ShortCircuitChecker implements ConditionChecker {

private final Logger logger = LoggerFactory.getLogger(ShortCircuitChecker.class);

public static Map<String, ShortCircuitResponseInformation> getShortCircuitMap() {
return SHORT_CIRCUIT_MAP;
}

public static Object getShortCircuitMapGuard() {
return GUARD;
}

@Override
public boolean checkCondition(final WilmaHttpRequest request, final ParameterList parameters) {
boolean conditionResult = false;
Expand All @@ -56,18 +65,13 @@ public boolean checkCondition(final WilmaHttpRequest request, final ParameterLis
conditionResult = SHORT_CIRCUIT_MAP.get(hashCode) != null;
} else { //we don't have even the request in the map, so put it there
SHORT_CIRCUIT_MAP.put(hashCode, null);
logger.info("ShortCircuit: New request to be cached was detected, hash code: " + hashCode);
//CHECKSTYLE OFF - we must use "new String" here
String decodedEntryKey = new String(Base64.decodeBase64(hashCode)); //make it human readable
//CHECKSTYLE ON
logger.info("ShortCircuit: New request to be cached was detected, hash code: " + decodedEntryKey);
}
}
}
return conditionResult; //true only, if the response is stored, so we know what to answer
}

public static Map<String, ShortCircuitResponseInformation> getShortCircuitMap() {
return SHORT_CIRCUIT_MAP;
}

public static Object getShortCircuitMapGuard() {
return GUARD;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ public void onResponseReceive(WilmaHttpResponse wilmaHttpResponse, ParameterList

/**
* ExternalWilmaService method implementation - entry point to handle the request by the external service.
* @param httpServletRequest is the original request
* @param request is the request string itself (part of the URL, focusing on the requested service)
*
* @param httpServletRequest is the original request
* @param request is the request string itself (part of the URL, focusing on the requested service)
* @param httpServletResponse is the response object
* @return with the body of the response (need to set response code in httpServletResponse object)
*/
Expand Down Expand Up @@ -98,6 +99,7 @@ public String handleRequest(HttpServletRequest httpServletRequest, String reques

/**
* ExternalWilmaService method implementation - provides the list of requests, this service will handle.
*
* @return with the set of handled services.
*/
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,22 +160,28 @@ void preserveResponse(String shortCircuitHashCode, WilmaHttpResponse wilmaHttpRe
}
shortCircuitResponseInformation = new ShortCircuitResponseInformation(wilmaHttpResponse, timeout, shortCircuitHashCode);
shortCircuitMap.put(shortCircuitHashCode, shortCircuitResponseInformation);
logger.info("ShortCircuit: Message captured for hashcode: " + shortCircuitHashCode);
//CHECKSTYLE OFF - we must use "new String" here
String decodedEntryKey = new String(Base64.decodeBase64(shortCircuitHashCode)); //make it human readable
//CHECKSTYLE ON
logger.info("ShortCircuit: Message captured for hashcode: " + decodedEntryKey);

}
} else { //we have response
//take care about timeout
timeout = Calendar.getInstance().getTimeInMillis();
if (timeout > shortCircuitResponseInformation.getTimeout()) {
shortCircuitMap.remove(shortCircuitHashCode);
logger.debug("ShortCircuit: Timeout has happened for hashcode: " + shortCircuitHashCode);
//CHECKSTYLE OFF - we must use "new String" here
String decodedEntryKey = new String(Base64.decodeBase64(shortCircuitHashCode)); //make it human readable
//CHECKSTYLE ON
logger.info("ShortCircuit: Timeout has happened for hashcode: " + decodedEntryKey);
}
}
}
}

boolean allowedContentType(final String contentType) {
return contentType.contains("text/plain") || contentType.contains("application/json") || contentType.contains("text/html");
return contentType.contains("text/plain") || contentType.contains("application/json") || contentType.contains("text/html") || contentType.contains("text/css");
}

/**
Expand All @@ -190,13 +196,19 @@ private String getShortCircuitMap(HttpServletResponse httpServletResponse) {
String[] keySet = shortCircuitMap.keySet().toArray(new String[shortCircuitMap.size()]);
for (int i = 0; i < keySet.length; i++) {
String entryKey = keySet[i];
boolean cached = shortCircuitMap.get(entryKey) != null;
ShortCircuitResponseInformation shortCircuitResponseInformation = shortCircuitMap.get(entryKey);
boolean cached = shortCircuitResponseInformation != null;
long usageCount = 0;
if (shortCircuitResponseInformation != null) {
usageCount = shortCircuitResponseInformation.getUsageCount();
}
//CHECKSTYLE OFF - we must use "new String" here
String decodedEntryKey = new String(Base64.decodeBase64(entryKey)); //make it human readable
//CHECKSTYLE ON
response.append(" { \"id\": \"").append(i)
.append("\", \"hashCode\": \"").append(decodedEntryKey)
.append("\", \"cached\": ").append(cached)
.append(", \"usageCount\": ").append(usageCount)
.append(" }");
if (i < keySet.length - 1) {
response.append(",");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.epam.wilma.domain.stubconfig.dialog.response.template.TemplateFormatter;
import com.epam.wilma.domain.stubconfig.dialog.response.template.TemplateGenerator;
import com.epam.wilma.domain.stubconfig.parameter.ParameterList;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -31,6 +32,7 @@

/**
* This class will generate stub response by using the response captured and cached by the ShortCircuitInterceptor class.
*
* @author tkohegyi, created on 2016. 02. 20.
*/
public class ShortCircuitResponseGenerator implements TemplateGenerator, TemplateFormatter {
Expand All @@ -47,6 +49,9 @@ public byte[] formatTemplate(WilmaHttpRequest wilmaHttpRequest, HttpServletRespo
byte[] newBody;
//prepare a key for this request
String hashCode = wilmaHttpRequest.getHeader(ShortCircuitChecker.SHORT_CIRCUIT_HEADER);
//CHECKSTYLE OFF - we must use "new String" here
String decodedEntryKey = new String(Base64.decodeBase64(hashCode)); //make it human readable
//CHECKSTYLE ON
ShortCircuitResponseInformation shortCircuitResponseInformation = ShortCircuitChecker.getShortCircuitMap().get(hashCode);
if (shortCircuitResponseInformation != null) {
//we have the answer, so set it properly
Expand All @@ -60,11 +65,12 @@ public byte[] formatTemplate(WilmaHttpRequest wilmaHttpRequest, HttpServletRespo
}
}
newBody = shortCircuitResponseInformation.getBody().getBytes();
logger.info("ShortCircuit: Answer generated for request with hashcode: " + hashCode);
shortCircuitResponseInformation.increaseUsageCount(); //hey we just used this cache entry
logger.info("ShortCircuit: Answer generated for request with hashcode: " + decodedEntryKey);
} else {
//this should not happen, we did not find the cached stub answer
newBody = "Ups, ShortCircuit was unable to find the proper answer, sorry.".getBytes();
logger.error("ShortCircuit: Response generator did not find proper response for request with code: " + hashCode);
logger.error("ShortCircuit: Response generator did not find proper response for request with code: " + decodedEntryKey);
}
return newBody;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
import java.util.Map;

/**
* This class holds a single response information, to be used in stub response, and captured from a real response.
* This class holds a single response information, to be usageCount in stub response, and captured from a real response.
*
* @author tkohegyi, created on 2016. 02. 17
*/
class ShortCircuitResponseInformation {
Expand All @@ -35,16 +36,18 @@ class ShortCircuitResponseInformation {
private Map<String, String> headers;

private long timeout;
private long usageCount;

/**
* Creates a new response information, based on the original response, and specifying a timeout.
* Timeout value is the system time, when this response become obsolete.
*
* @param wilmaHttpResponse is the original response object
* @param timeout is the calculated timeout value
* @param hashCode is the header hash code of the message
* @param timeout is the calculated timeout value
* @param hashCode is the header hash code of the message
*/
ShortCircuitResponseInformation(WilmaHttpResponse wilmaHttpResponse, long timeout, String hashCode) {
//need to clone the response perfectly
setContentType(wilmaHttpResponse.getContentType());
setStatusCode(wilmaHttpResponse.getStatusCode());
setBody(wilmaHttpResponse.getBody());
Expand All @@ -56,8 +59,8 @@ class ShortCircuitResponseInformation {
headers.remove("Server");
setHeaders(headers);
setHashCode(hashCode);
//need to clone the response perfectly
this.timeout = timeout;
usageCount = 0;
}

/**
Expand Down Expand Up @@ -112,4 +115,12 @@ Map<String, String> getHeaders() {
void setHeaders(Map<String, String> headers) {
this.headers = headers;
}

void increaseUsageCount() {
usageCount++;
}

long getUsageCount() {
return usageCount;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ private void saveMapObject(FileOutputStreamFactory fileOutputStreamFactory, File
fos.write(" ],\n".getBytes());
}
fos.write(" \"Body\": ".getBytes());
String myBody = new JSONObject().put("Body", encodeString(information.getBody().toString())).toString();
String myBody = new JSONObject().put("Body", encodeString(information.getBody())).toString();
fos.write((myBody + "\n}").getBytes());
fos.close();
}
Expand All @@ -127,7 +127,7 @@ private void saveMapObject(FileOutputStreamFactory fileOutputStreamFactory, File
* @param path is the folder to be used, under Wilma's message folder.
*/
void loadPreservedMessagesToMap(String path) {
Map<String, ShortCircuitResponseInformation> newShortCircuitMap = new HashMap<>();
//Map<String, ShortCircuitResponseInformation> newShortCircuitMap = new HashMap<>();

File folderFile = new File(path);
File[] listOfFiles = folderFile.listFiles();
Expand Down Expand Up @@ -164,7 +164,7 @@ private ShortCircuitResponseInformation loadMapObject(String fileName) {
JSONArray headerArray = obj.getJSONArray("Headers");
ShortCircuitResponseInformation information = null;
if (hashKey != null && contentType != null && body != null) {
information = new ShortCircuitResponseInformation(Integer.MAX_VALUE);
information = new ShortCircuitResponseInformation(Long.MAX_VALUE);
information.setHashCode(hashKey);
information.setStatusCode(responseCode);
information.setContentType(contentType);
Expand Down

0 comments on commit ee3d69d

Please sign in to comment.