Analyzing Spring Boot RESTful web services

The spring-boot GitHub repository has several test controllers and example calls that we can analyze. First we need to clone the repository:

rootDirectory := 'spring-boot' asFileReference
  
IceGitCliPlatform current install.
rootDirectory ensureDeleteAll.
repository := IceRepository repositoryClass creatorClass
		fromUrl: 'https://github.com/spring-projects/spring-boot.git'
		to: rootDirectory.
rootDirectory
  

Once the repository is cloned, we can analyze the Java source:

model := GtSmaCCJavaImporter new
		baseDirectory: rootDirectory;
		buildJavaModel;
		model
  

At this point, we only have a Java model and do not have anything specific for Spring Boot, but we can add that analysis:

GtJavaSpringBootImporter new
	model: model;
	buildSpringModel.
model
  

From here, we can see all RestControllers, Mappings, and calls to the Mappings. We can see the source of each and the links between them. For example, we can see the UserVehicleController.VehicleDetailsHtml mapping and the calls to it:

controller := model allGtJavaSpringRestControllers
		entityNamed: #UserVehicleController
  
mapping := (controller handlers collect: #gtJavaSpringMapping)
		detect: [ :each | each fullPaths anySatisfy: [ :path | path endsWith: '.html' ] ]
  

The GtJavaSpringBootImporter>>#springBootCallsDo: springBootCallsDo: aBlock model allInvocations do: [ :each | each gtASTNode ifNotNil: [ :ast | | name | name := each signature. ((#('delete' 'get' 'patch' 'post' 'put') includes: name) and: [ ast expressions size = 1 and: [ (self doesName: ast receiver include: 'MockMvcRequestBuilders') or: [ ast receiver isNil and: [ ast topParent imports anySatisfy: [ :imp | imp staticToken notNil and: [ self doesName: imp name include: 'MockMvcRequestBuilders' ] ] ] ] ] ]) ifTrue: [ aBlock valueWithPossibleArgs: {each. self urlFrom: ast expressions first. name. self getAcceptFromBuilder: ast. self getContentTypeFromBuilder: ast} ]. (name = 'exchange' and: [ ast expressions size > 2 ]) ifTrue: [ aBlock valueWithPossibleArgs: {each. self urlFrom: ast expressions first. self requestTypeFrom: ast expressions second. self getAcceptFromExchange: ast. self getContentTypeFromExchange: ast} ] ] ] has the logic to determine service calls from Java. By default, it looks for calls to MockMvcRequestBuilders.delete/get/patch/post/put as well as calls to RestTemplate.exchange. If your application uses other methods to make service calls, then you'll need to define a subclass and override the stringBootCallsDo: method. That method should evaluate the argument block for each service call passing the invocation, url, and request type (get, put, delete, etc).