103 lines
3.8 KiB
Markdown
103 lines
3.8 KiB
Markdown
# Implementation Details: Trigger Detection with JDT
|
|
|
|
## 1. Finding `sendEvent` Calls
|
|
We can use an `ASTVisitor` to find all `MethodInvocation` nodes.
|
|
|
|
```java
|
|
public class SendEventVisitor extends ASTVisitor {
|
|
@Override
|
|
public boolean visit(MethodInvocation node) {
|
|
if ("sendEvent".equals(node.getName().getIdentifier())) {
|
|
// Found a call!
|
|
// 1. Extract event (first argument)
|
|
// 2. Identify the enclosing method and class
|
|
}
|
|
return super.visit(node);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Challenges in Event Extraction
|
|
Events can be:
|
|
- Enum constants: `Events.SUBMIT`
|
|
- Strings: `"SUBMIT"`
|
|
- Variables: `sm.sendEvent(eventFromPayload)` (Hard to resolve statically)
|
|
|
|
We should reuse `CodebaseContext.resolveState` logic (which is basically resolving an expression to a value/fqn).
|
|
|
|
## 2. Identifying Enclosing Context
|
|
Once a `sendEvent` is found, we can traverse up the AST to find the `MethodDeclaration` and `TypeDeclaration`.
|
|
|
|
```java
|
|
ASTNode parent = node.getParent();
|
|
while (parent != null && !(parent instanceof MethodDeclaration)) {
|
|
parent = parent.getParent();
|
|
}
|
|
// parent is now the MethodDeclaration
|
|
```
|
|
|
|
### 2. Extracting Annotations
|
|
From `MethodDeclaration`, we can check for mappings:
|
|
- `@PostMapping`, `@GetMapping`, etc.
|
|
- `@KafkaListener`: Extract `topics`, `groupId`.
|
|
- `@RabbitListener`: Extract `queues`, `bindings` (Exchange/RoutingKey).
|
|
|
|
From `TypeDeclaration`, we can check for:
|
|
- `@RestController`, `@Controller`
|
|
- `@RequestMapping` at class level (to get base path)
|
|
|
|
## 3. Specialized WebFlux Analysis
|
|
|
|
### Annotation-based WebFlux
|
|
This is largely identical to Spring MVC. The challenge is if the `sendEvent` is wrapped in a reactive operator.
|
|
```java
|
|
public Mono<Void> submit(Order order) {
|
|
return service.save(order)
|
|
.doOnNext(o -> stateMachine.sendEvent(Events.SUBMIT))
|
|
.then();
|
|
}
|
|
```
|
|
**Static Strategy**: We need to look inside `LambdaExpression` nodes passed to reactive operators (`doOnNext`, `flatMap`, `map`, `subscribe`). The `ASTVisitor` should traverse into these lambdas.
|
|
|
|
### Functional WebFlux (RouterFunctions)
|
|
Functional endpoints are often defined as Beans returning `RouterFunction`.
|
|
```java
|
|
@Bean
|
|
public RouterFunction<ServerResponse> route(OrderHandler handler) {
|
|
return RouterFunctions.route(POST("/orders"), handler::submitOrder);
|
|
}
|
|
```
|
|
**Static Strategy**:
|
|
1. Find methods returning `RouterFunction`.
|
|
2. Analyze the `MethodInvocation` chain (`route`, `andRoute`, `nest`).
|
|
3. Extract the URI pattern and the `HandlerFunction` reference.
|
|
4. If the handler is a method reference (`handler::submitOrder`), link it to the corresponding `MethodDeclaration`.
|
|
|
|
## 4. Specialized RabbitMQ Analysis
|
|
`@RabbitListener` can be complex:
|
|
```java
|
|
@RabbitListener(bindings = @QueueBinding(
|
|
value = @Queue(value = "orderQueue", durable = "true"),
|
|
exchange = @Exchange(value = "orderExchange"),
|
|
key = "order.created"
|
|
))
|
|
public void onOrder(Order order) { ... }
|
|
```
|
|
**Static Strategy**:
|
|
1. Find `@RabbitListener`.
|
|
2. If it has `bindings`, drill down into `@QueueBinding`, `@Queue`, `@Exchange` to extract the topology.
|
|
3. If it only has `queues`, resolve the queue name (might be a SpEL expression or property placeholder, which we can try to resolve or just keep as-is).
|
|
|
|
## 5. Indirect Flow Detection (The "Service Link")
|
|
If the project has multiple state machines, we need to know which one is being targeted.
|
|
Usually, this is done via:
|
|
- Autowiring by type: `StateMachine<States, Events> sm;`
|
|
- Autowiring by name: `@Qualifier("mySm") StateMachine sm;`
|
|
|
|
We can look at the fields of the class where `sendEvent` is called.
|
|
|
|
## 6. Output Enhancement
|
|
The `Exporter` should be modified to:
|
|
- In DOT: Add nodes for Endpoints/Listeners and link them to the Events/Transitions.
|
|
- In SCXML: Add metadata to transitions.
|