This project discovers the rest-endpoints and rest-clients from the bytecode of a microservice. Given a set of compiled microservice artifacts, it can also generate a rest flow graph among those endpoints and clients.
To get started clone the Github repository.
$ git clone https://github.com/cloudhubs/rad.git
-
Analyzer: Analyzes a
CtClass
object and detects allRestEntity
in that class. Currently there are four different analyzer:JaxRSAnalyzer
,SpringEndpointAnalyzer
,SpringClientAnalyzer
, andSpringClientWrapperAnalyzer
. -
Instruction scanner: Scans the bytecode instructions of a
CtMethod
and creates a list of simplifiedInstructionInfo
. -
Dataflow: Detects rest client method calls along with URL and return type. It takes a list of
InstructionInfo
and performs backward dataflow analysis. -
Flow matcher: Find pairs of server and client
RestEntity
by matching HTTP method, URL, and other properties. -
Graph generator: Generates a graphviz file to visualize rest communication between microservices.
We will use a fork of TMS as our test bed. Clone and package each microservice into JARs.
$ git clone https://github.com/cloudhubs/tms-testbed.git
$ cd tms-testbed
$ ./buildAll.sh
$ git clone https://github.com/cloudhubs/rad.git
$ cd rad
$ mvn clean install -DskipTests
$ java -jar application/target/rad-application-0.0.5.jar
curl --request POST \
--url http://localhost:8080/ \
--header 'content-type: application/json' \
--data '{
"pathToCompiledMicroservices":"C:\\baylor\\cil-tms",
"organizationPath":"edu/baylor/ecs",
"outputPath":"C:\\baylor\\cil-rad.gv"
}'
{
"request": {
"pathToCompiledMicroservices": "C:\\baylor\\cil-tms",
"organizationPath": "edu/baylor/ecs",
"outputPath": "C:\\baylor\\cil-rad.gv"
},
"restEntityContexts": [
{
"resourcePath": "C:\\baylor\\cil-tms\\tms-cms\\target\\cms-0.0.1-SNAPSHOT.jar",
"restEntities": [
{
"url": "http://localhost:10003/categoryInfo",
"applicationName": null,
"ribbonServerName": null,
"resourcePath": "C:\\baylor\\cil-tms\\tms-cms\\target\\cms-0.0.1-SNAPSHOT.jar",
"className": "edu.baylor.ecs.cms.controller.CategoryInfoController",
"methodName": "getCategoryInfo",
"returnType": "java.util.List<java.lang.Object>",
"path": "/categoryInfo",
"httpMethod": "GET",
"pathParams": null,
"queryParams": null,
"consumeType": null,
"produceType": null,
"client": false
},
...
]
},
...
],
"restFlowContext": {
"restFlows": [
{
"resourcePath": "C:\\baylor\\cil-tms\\tms-cms\\target\\cms-0.0.1-SNAPSHOT.jar",
"className": "edu.baylor.ecs.cms.service.UmsService",
"methodName": "isEmailValid",
"servers": [
{
"url": "http://localhost:9004/userinfo/emailInUse/{email}",
"applicationName": null,
"ribbonServerName": null,
"resourcePath": "C:\\baylor\\cil-tms\\tms-ums\\target\\ums-1.0-SNAPSHOT.jar",
"className": "edu.baylor.ecs.ums.controller.UserInfoController",
"methodName": "isEmailInUse",
"returnType": null,
"path": "/userinfo/emailInUse/{email}",
"httpMethod": "GET",
"pathParams": [
{
"name": "VARIABLE_NAME",
"defaultValue": ""
}
],
"queryParams": null,
"consumeType": null,
"produceType": null,
"client": false
}
]
},
...
]
}
}
$ git clone https://github.com/cloudhubs/rad.git
$ cd rad
$ mvn clean install -DskipTests
<dependency>
<groupId>edu.baylor.ecs.cloudhubs</groupId>
<artifactId>rad</artifactId>
<version>0.0.5</version>
</dependency>
@Autowired
private final RestDiscoveryService restDiscoveryService;
public ResponseContext getRadResponseContext(RequestContext request) {
return restDiscoveryService.generateResponseContext(request);
}
public class RequestContext {
private String pathToCompiledMicroservices;
private String organizationPath;
private String outputPath;
}
public class ResponseContext {
private RequestContext request;
private List<RestEntityContext> restEntityContexts = new ArrayList<>();
private RestFlowContext restFlowContext;
}
public class RestEntityContext {
private String resourcePath;
private List<RestEntity> restEntities = new ArrayList<>();
}
public class RestFlowContext {
private List<RestFlow> restFlows = new ArrayList<>();
}
public class RestEntity {
private boolean isClient;
private String url;
private String applicationName; // used in eureka discovery
private String ribbonServerName;
private String resourcePath;
private String className;
private String methodName;
private String returnType;
private String path;
private HttpMethod httpMethod;
private List<Param> pathParams;
private List<Param> queryParams;
private String consumeType; // can be any mime type
private String produceType; // can be any mime type
}
public class RestFlow {
private String resourcePath;
private String className;
private String methodName;
private List<RestEntity> servers;
}