Fix export metadata scoping and call-chain resolution gaps.
Correct machine-scope filtering for domain paths and Spring type erasure, skip phantom REST interfaces, resolve custom message wrapper events, scope JDT call-chain lookup per machine, and wire scan-time analysis indexes with JDT/heuristic parity tests. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -45,4 +45,44 @@ class MachineScopeFilterEntryPointTest {
|
||||
.contains("POST /api/orders/pay", "POST /api/commands/{commandKey}")
|
||||
.doesNotContain("POST /api/documents/submit");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldKeepDedicatedOrderEndpointOnStandardOrderMachineInMultiModuleCodebase() {
|
||||
EntryPoint orderPay = EntryPoint.builder()
|
||||
.type(EntryPoint.Type.REST)
|
||||
.name("POST /api/orders/pay")
|
||||
.className("click.kamil.examples.statemachine.layered.web.OrderController")
|
||||
.methodName("pay")
|
||||
.metadata(Map.of("path", "/api/orders/pay"))
|
||||
.build();
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
List<EntryPoint> scoped = MachineScopeFilter.filterEntryPointsForMachine(
|
||||
List.of(orderPay),
|
||||
"click.kamil.examples.statemachine.layered.order.config.StandardOrderStateMachineConfiguration",
|
||||
context);
|
||||
|
||||
assertThat(scoped).extracting(EntryPoint::getName)
|
||||
.containsExactly("POST /api/orders/pay");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldKeepOrdersPathOnNonDomainNamedMachineConfig() {
|
||||
EntryPoint ordersSubmit = EntryPoint.builder()
|
||||
.type(EntryPoint.Type.REST)
|
||||
.name("POST /api/v2/orders/submit")
|
||||
.className("click.kamil.examples.statemachine.inheritance.api.OrderControllerImpl")
|
||||
.methodName("submitOrder")
|
||||
.metadata(Map.of("path", "/api/v2/orders/submit"))
|
||||
.build();
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
List<EntryPoint> scoped = MachineScopeFilter.filterEntryPointsForMachine(
|
||||
List.of(ordersSubmit),
|
||||
"click.kamil.examples.statemachine.inheritance.config.InheritanceStateMachineConfig",
|
||||
context);
|
||||
|
||||
assertThat(scoped).extracting(EntryPoint::getName)
|
||||
.containsExactly("POST /api/v2/orders/submit");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package click.kamil.springstatemachineexporter.analysis.enricher.routing;
|
||||
|
||||
import click.kamil.springstatemachineexporter.analysis.model.CallChain;
|
||||
import click.kamil.springstatemachineexporter.analysis.model.TriggerPoint;
|
||||
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -9,6 +10,7 @@ import org.junit.jupiter.api.io.TempDir;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@@ -165,4 +167,37 @@ public class HeuristicBeanResolutionEngineTest {
|
||||
engine.isRoutedToCorrectMachine(chain, "com.example.DocumentStateMachineConfig", context),
|
||||
"Ambiguous shared gateway should not attach to every machine");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAcceptTriggerWhenSpringErasureDiffersFromStringMachineTypes(@TempDir Path tempDir) throws Exception {
|
||||
Files.writeString(tempDir.resolve("InheritanceStateMachineConfig.java"), """
|
||||
package com.example;
|
||||
@org.springframework.statemachine.config.EnableStateMachine
|
||||
public class InheritanceStateMachineConfig
|
||||
extends org.springframework.statemachine.config.StateMachineConfigurerAdapter<String, String> {}
|
||||
""");
|
||||
Files.writeString(tempDir.resolve("ProcessingServiceImpl.java"), """
|
||||
package com.example;
|
||||
public class ProcessingServiceImpl {
|
||||
public void doProcess() {}
|
||||
}
|
||||
""");
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallChain triggerProbe = CallChain.builder()
|
||||
.triggerPoint(TriggerPoint.builder()
|
||||
.className("com.example.ProcessingServiceImpl")
|
||||
.methodName("doProcess")
|
||||
.event("INHERITED_SUBMIT")
|
||||
.stateTypeFqn("java.lang.Object")
|
||||
.eventTypeFqn("java.lang.Object")
|
||||
.build())
|
||||
.methodChain(List.of())
|
||||
.build();
|
||||
|
||||
assertTrue(engine.isRoutedToCorrectMachine(
|
||||
triggerProbe, "com.example.InheritanceStateMachineConfig", context));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package click.kamil.springstatemachineexporter.analysis.index;
|
||||
|
||||
import click.kamil.springstatemachineexporter.analysis.resolver.ConstantResolver;
|
||||
import click.kamil.springstatemachineexporter.analysis.service.ConstructorAnalyzer;
|
||||
import click.kamil.springstatemachineexporter.analysis.service.ConstantExtractor;
|
||||
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class AnalysisPerformanceCacheTest {
|
||||
|
||||
@TempDir
|
||||
Path tempDir;
|
||||
|
||||
CodebaseContext context;
|
||||
ConstantExtractor constantExtractor;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws IOException {
|
||||
context = new CodebaseContext();
|
||||
context.setResolveBindings(true);
|
||||
context.setSourcepath(List.of(tempDir.toAbsolutePath().toString()));
|
||||
ConstantResolver constantResolver = context.getConstantResolver();
|
||||
constantExtractor = new ConstantExtractor(context, constantResolver, mi -> null);
|
||||
constantExtractor.setConstructorAnalyzer(new ConstructorAnalyzer(context, constantResolver));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrecomputeIndexedFieldConstants() throws IOException {
|
||||
writeJava("com/example/Payload.java", """
|
||||
package com.example;
|
||||
public class Payload {
|
||||
private String event = "PAY";
|
||||
public String getEvent() { return event; }
|
||||
}
|
||||
""");
|
||||
scan();
|
||||
|
||||
List<String> precomputed = context.getIndexedFieldConstantsIndex()
|
||||
.lookup("com.example.Payload", "getEvent")
|
||||
.orElseThrow();
|
||||
assertThat(precomputed).containsExactly("PAY");
|
||||
|
||||
List<String> first = constantExtractor.resolveMethodReturnConstant(
|
||||
"com.example.Payload", "getEvent", 0, new HashSet<>(), null);
|
||||
List<String> second = constantExtractor.resolveMethodReturnConstant(
|
||||
"com.example.Payload", "getEvent", 0, new HashSet<>(), null);
|
||||
assertThat(first).containsExactly("PAY");
|
||||
assertThat(second).isEqualTo(first);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findMethodDeclarationShouldBeMemoized() throws IOException {
|
||||
writeJava("com/example/Demo.java", """
|
||||
package com.example;
|
||||
public class Demo {
|
||||
public void run() {}
|
||||
}
|
||||
""");
|
||||
scan();
|
||||
|
||||
TypeDeclaration type = context.getTypeDeclaration("com.example.Demo");
|
||||
MethodDeclaration first = context.findMethodDeclaration(type, "run", true);
|
||||
MethodDeclaration second = context.findMethodDeclaration(type, "run", true);
|
||||
|
||||
assertThat(first).isNotNull();
|
||||
assertThat(second).isSameAs(first);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldMemoizePolymorphicClassCompatibility() throws IOException {
|
||||
writeJava("com/example/EventSource.java", """
|
||||
package com.example;
|
||||
public interface EventSource {}
|
||||
""");
|
||||
writeJava("com/example/PayEvent.java", """
|
||||
package com.example;
|
||||
public class PayEvent implements EventSource {}
|
||||
""");
|
||||
scan();
|
||||
|
||||
assertThat(context.areClassesPolymorphicallyCompatible(
|
||||
"com.example.PayEvent", "com.example.EventSource")).isTrue();
|
||||
assertThat(context.areClassesPolymorphicallyCompatible(
|
||||
"com.example.PayEvent", "com.example.EventSource")).isTrue();
|
||||
}
|
||||
|
||||
private void scan() throws IOException {
|
||||
context.scan(tempDir);
|
||||
}
|
||||
|
||||
private void writeJava(String relativePath, String source) throws IOException {
|
||||
Path file = tempDir.resolve(relativePath);
|
||||
Files.createDirectories(file.getParent());
|
||||
Files.writeString(file, source);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package click.kamil.springstatemachineexporter.analysis.index;
|
||||
|
||||
import click.kamil.springstatemachineexporter.analysis.pipeline.AccessorResolver;
|
||||
import click.kamil.springstatemachineexporter.analysis.pipeline.ResolutionBudget;
|
||||
import click.kamil.springstatemachineexporter.analysis.resolver.ConstantResolver;
|
||||
import click.kamil.springstatemachineexporter.analysis.service.ConstructorAnalyzer;
|
||||
import click.kamil.springstatemachineexporter.analysis.service.ConstantExtractor;
|
||||
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class GetterChainIndexTest {
|
||||
|
||||
@TempDir
|
||||
Path tempDir;
|
||||
|
||||
CodebaseContext context;
|
||||
AccessorResolver accessorResolver;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws IOException {
|
||||
context = new CodebaseContext();
|
||||
context.setResolveBindings(true);
|
||||
context.setSourcepath(List.of(tempDir.toAbsolutePath().toString()));
|
||||
ConstantResolver constantResolver = context.getConstantResolver();
|
||||
ConstantExtractor constantExtractor = new ConstantExtractor(context, constantResolver, mi -> null);
|
||||
ConstructorAnalyzer constructorAnalyzer = new ConstructorAnalyzer(context, constantResolver);
|
||||
accessorResolver = new AccessorResolver(context, constantExtractor, constructorAnalyzer, constantResolver);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrecomputeGetterChainEdgeWithFieldInitializerCic() throws IOException {
|
||||
writeJava("com/example/Payload.java", """
|
||||
package com.example;
|
||||
public class Payload {
|
||||
public String getType() { return "PAY"; }
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/Inner.java", """
|
||||
package com.example;
|
||||
public class Inner {
|
||||
private final Payload payload = new Payload();
|
||||
public Payload getPayload() { return payload; }
|
||||
}
|
||||
""");
|
||||
scan();
|
||||
|
||||
GetterChainIndex index = context.getGetterChainIndex();
|
||||
assertThat(index.edgeCount()).isGreaterThan(0);
|
||||
|
||||
GetterChainEdge edge = index.lookup("com.example.Inner", "getPayload").orElseThrow();
|
||||
assertThat(edge.nextTypeFqn()).contains("Payload");
|
||||
assertThat(edge.fieldInitializerCic()).isNotNull();
|
||||
|
||||
AccessorResolver.GetterChainStep step = accessorResolver.resolveGetterChainStep(
|
||||
"com.example.Inner", "getPayload", ResolutionBudget.defaults());
|
||||
assertThat(step).isNotNull();
|
||||
assertThat(step.typeFqn()).isEqualTo(edge.nextTypeFqn());
|
||||
assertThat(step.cic()).isSameAs(edge.fieldInitializerCic());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTypeDeclarationShouldUseFlatIndex() throws IOException {
|
||||
writeJava("com/example/Demo.java", """
|
||||
package com.example;
|
||||
public class Demo {
|
||||
public String getValue() { return "X"; }
|
||||
}
|
||||
""");
|
||||
scan();
|
||||
|
||||
TypeDeclaration first = context.getTypeDeclaration("com.example.Demo");
|
||||
TypeDeclaration second = context.getTypeDeclaration("com.example.Demo");
|
||||
|
||||
assertThat(first).isNotNull();
|
||||
assertThat(second).isSameAs(first);
|
||||
}
|
||||
|
||||
private void scan() throws IOException {
|
||||
context.scan(tempDir);
|
||||
}
|
||||
|
||||
private void writeJava(String relativePath, String source) throws IOException {
|
||||
Path file = tempDir.resolve(relativePath);
|
||||
Files.createDirectories(file.getParent());
|
||||
Files.writeString(file, source);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
package click.kamil.springstatemachineexporter.analysis.index;
|
||||
|
||||
import click.kamil.springstatemachineexporter.analysis.resolver.ConstantResolver;
|
||||
import click.kamil.springstatemachineexporter.analysis.service.ConstructorAnalyzer;
|
||||
import click.kamil.springstatemachineexporter.analysis.service.ConstantExtractor;
|
||||
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PolymorphicAccessorIndexTest {
|
||||
|
||||
@TempDir
|
||||
Path tempDir;
|
||||
|
||||
CodebaseContext context;
|
||||
ConstantExtractor constantExtractor;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
context = new CodebaseContext();
|
||||
constantExtractor = new ConstantExtractor(
|
||||
context,
|
||||
new ConstantResolver(),
|
||||
mi -> null);
|
||||
constantExtractor.setConstructorAnalyzer(new ConstructorAnalyzer(context, context.getConstantResolver()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrecomputeWidenedConstantsForThreeEventImplementations() throws IOException {
|
||||
writeJava("com/example/EventSource.java", """
|
||||
package com.example;
|
||||
public interface EventSource {
|
||||
String getEvent();
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/PayEvent.java", """
|
||||
package com.example;
|
||||
public class PayEvent implements EventSource {
|
||||
public String getEvent() { return "PAY"; }
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/ShipEvent.java", """
|
||||
package com.example;
|
||||
public class ShipEvent implements EventSource {
|
||||
public String getEvent() { return "SHIP"; }
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/CancelEvent.java", """
|
||||
package com.example;
|
||||
public class CancelEvent implements EventSource {
|
||||
public String getEvent() { return "CANCEL"; }
|
||||
}
|
||||
""");
|
||||
scan();
|
||||
|
||||
PolymorphicAccessorIndex index = context.getPolymorphicAccessorIndex();
|
||||
assertThat(index.entryCount()).isGreaterThan(0);
|
||||
|
||||
List<String> precomputed = index.widenedReturnConstants("com.example.EventSource", "getEvent")
|
||||
.orElseThrow();
|
||||
assertThat(precomputed).containsExactlyInAnyOrder("PAY", "SHIP", "CANCEL");
|
||||
|
||||
List<String> resolved = constantExtractor.resolveMethodReturnConstant(
|
||||
"com.example.EventSource", "getEvent", 0, new HashSet<>(), null);
|
||||
assertThat(resolved).containsExactlyInAnyOrder("PAY", "SHIP", "CANCEL");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldIncludeDefaultMethodAndConcreteOverrides() throws IOException {
|
||||
writeJava("com/example/EventSource.java", """
|
||||
package com.example;
|
||||
public interface EventSource {
|
||||
default String getEvent() { return "DEFAULT"; }
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/PayEvent.java", """
|
||||
package com.example;
|
||||
public class PayEvent implements EventSource {
|
||||
public String getEvent() { return "PAY"; }
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/ShipEvent.java", """
|
||||
package com.example;
|
||||
public class ShipEvent implements EventSource {
|
||||
public String getEvent() { return "SHIP"; }
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/CancelEvent.java", """
|
||||
package com.example;
|
||||
public class CancelEvent implements EventSource {
|
||||
public String getEvent() { return "CANCEL"; }
|
||||
}
|
||||
""");
|
||||
scan();
|
||||
|
||||
List<String> precomputed = context.getPolymorphicAccessorIndex()
|
||||
.widenedReturnConstants("com.example.EventSource", "getEvent")
|
||||
.orElseThrow();
|
||||
assertThat(precomputed).containsExactlyInAnyOrder("DEFAULT", "PAY", "SHIP", "CANCEL");
|
||||
}
|
||||
|
||||
@Nested
|
||||
class AbstractStateMachineInheritance {
|
||||
|
||||
@Test
|
||||
void shouldResolveEventsFromThreeConcreteConfigsExtendingAbstractBase() throws IOException {
|
||||
writeJava("com/example/OrderState.java", """
|
||||
package com.example;
|
||||
public enum OrderState { CREATED, PAID, SHIPPED, CANCELLED }
|
||||
""");
|
||||
writeJava("com/example/OrderEvent.java", """
|
||||
package com.example;
|
||||
public enum OrderEvent { PAY, SHIP, CANCEL }
|
||||
""");
|
||||
writeJava("com/example/EventSource.java", """
|
||||
package com.example;
|
||||
public interface EventSource {
|
||||
OrderEvent getEvent();
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/PayEvent.java", """
|
||||
package com.example;
|
||||
public class PayEvent implements EventSource {
|
||||
public OrderEvent getEvent() { return OrderEvent.PAY; }
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/ShipEvent.java", """
|
||||
package com.example;
|
||||
public class ShipEvent implements EventSource {
|
||||
public OrderEvent getEvent() { return OrderEvent.SHIP; }
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/CancelEvent.java", """
|
||||
package com.example;
|
||||
public class CancelEvent implements EventSource {
|
||||
public OrderEvent getEvent() { return OrderEvent.CANCEL; }
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/BaseOrderStateMachineConfig.java", """
|
||||
package com.example;
|
||||
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
public abstract class BaseOrderStateMachineConfig
|
||||
extends StateMachineConfigurerAdapter<OrderState, OrderEvent> {
|
||||
protected void registerTransition(
|
||||
StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions,
|
||||
EventSource source) {
|
||||
transitions.withExternal()
|
||||
.source(OrderState.CREATED)
|
||||
.target(OrderState.PAID)
|
||||
.event(source.getEvent());
|
||||
}
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/PayOrderStateMachineConfig.java", """
|
||||
package com.example;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
public class PayOrderStateMachineConfig extends BaseOrderStateMachineConfig {
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions)
|
||||
throws Exception {
|
||||
registerTransition(transitions, new PayEvent());
|
||||
}
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/ShipOrderStateMachineConfig.java", """
|
||||
package com.example;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
public class ShipOrderStateMachineConfig extends BaseOrderStateMachineConfig {
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions)
|
||||
throws Exception {
|
||||
registerTransition(transitions, new ShipEvent());
|
||||
}
|
||||
}
|
||||
""");
|
||||
writeJava("com/example/CancelOrderStateMachineConfig.java", """
|
||||
package com.example;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
public class CancelOrderStateMachineConfig extends BaseOrderStateMachineConfig {
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions)
|
||||
throws Exception {
|
||||
registerTransition(transitions, new CancelEvent());
|
||||
}
|
||||
}
|
||||
""");
|
||||
scan();
|
||||
|
||||
List<String> widened = context.getPolymorphicAccessorIndex()
|
||||
.widenedReturnConstants("com.example.EventSource", "getEvent")
|
||||
.orElseThrow();
|
||||
assertThat(widened).containsExactlyInAnyOrder("OrderEvent.PAY", "OrderEvent.SHIP", "OrderEvent.CANCEL");
|
||||
|
||||
List<String> resolved = constantExtractor.resolveMethodReturnConstant(
|
||||
"com.example.EventSource", "getEvent", 0, new HashSet<>(), null);
|
||||
assertThat(resolved).containsExactlyInAnyOrder("OrderEvent.PAY", "OrderEvent.SHIP", "OrderEvent.CANCEL");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void getImplementationsShouldBeMemoized() throws IOException {
|
||||
writeJava("com/example/EventSource.java", """
|
||||
package com.example;
|
||||
public interface EventSource {}
|
||||
""");
|
||||
writeJava("com/example/PayEvent.java", """
|
||||
package com.example;
|
||||
public class PayEvent implements EventSource {}
|
||||
""");
|
||||
scan();
|
||||
|
||||
List<String> first = context.getImplementations("com.example.EventSource");
|
||||
List<String> second = context.getImplementations("com.example.EventSource");
|
||||
|
||||
assertThat(second).isSameAs(first);
|
||||
}
|
||||
|
||||
private void scan() throws IOException {
|
||||
context.scan(tempDir);
|
||||
}
|
||||
|
||||
private void writeJava(String relativePath, String source) throws IOException {
|
||||
Path file = tempDir.resolve(relativePath);
|
||||
Files.createDirectories(file.getParent());
|
||||
Files.writeString(file, source);
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ class AnalysisCacheCorrectnessTest {
|
||||
List<CallChain> first = intelligence.findCallChains(entryPoints, triggers);
|
||||
List<CallChain> second = intelligence.findCallChains(entryPoints, triggers);
|
||||
|
||||
assertThat(second).isSameAs(first);
|
||||
assertThat(second).isEqualTo(first);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,8 +20,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* <p>Each test embeds a miniature codebase as a string so humans and agents can see the full
|
||||
* REST → dispatcher → sendEvent pipeline without opening another module.
|
||||
*
|
||||
* <p>DTO setter/getter propagation is covered by {@code HeuristicCallGraphEngineTypeTest}.
|
||||
* Cross-hop routing helpers that return computed strings are covered by literal-forwarding tests above.
|
||||
* <p>Cross-hop routing helpers and DTO constructor→getter propagation are covered by Tier 1 tests below.
|
||||
*/
|
||||
class CentralDispatcherResolutionTest {
|
||||
|
||||
@@ -418,6 +417,105 @@ class CentralDispatcherResolutionTest {
|
||||
"OrderEvent.PAY");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tier 1 — field-injected routing helper returns string literals consumed by central dispatcher.
|
||||
*
|
||||
* <pre>
|
||||
* pay() → gateway.routeAndPay() → dispatch("ORDER", routingHelper.payAction()) → OrderEvent.PAY
|
||||
* ship() → gateway.routeAndShip() → dispatch("ORDER", routingHelper.shipAction()) → OrderEvent.SHIP
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
void fieldWiredRoutingHelperShouldForwardLiteralsToCentralDispatcher(@TempDir Path tempDir) throws Exception {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class ApiController {
|
||||
CommandGateway gateway;
|
||||
public void pay() { gateway.routeAndPay(); }
|
||||
public void ship() { gateway.routeAndShip(); }
|
||||
}
|
||||
class CommandGateway {
|
||||
OrderRoutingHelper routingHelper;
|
||||
CentralDispatcher dispatcher;
|
||||
void routeAndPay() { dispatcher.dispatch("ORDER", routingHelper.payAction()); }
|
||||
void routeAndShip() { dispatcher.dispatch("ORDER", routingHelper.shipAction()); }
|
||||
}
|
||||
class OrderRoutingHelper {
|
||||
String payAction() { return "PAY"; }
|
||||
String shipAction() { return "SHIP"; }
|
||||
}
|
||||
class CentralDispatcher {
|
||||
void dispatch(String domain, String action) {
|
||||
StateMachine sm = new StateMachine();
|
||||
sm.sendEvent(OrderEvent.valueOf(action));
|
||||
}
|
||||
}
|
||||
enum OrderEvent { PAY, SHIP }
|
||||
class StateMachine { public void sendEvent(OrderEvent e) {} }
|
||||
class OrderStateMachineConfig {}
|
||||
""";
|
||||
CodebaseContext context = scanSource(source, tempDir);
|
||||
|
||||
CallChain payChain = resolveChain(context, CONTROLLER, "pay", STATE_MACHINE);
|
||||
CallChain shipChain = resolveChain(context, CONTROLLER, "ship", STATE_MACHINE);
|
||||
|
||||
assertPolyEvents(payChain, "OrderEvent.PAY");
|
||||
assertPolyEvents(shipChain, "OrderEvent.SHIP");
|
||||
|
||||
assertLinkedEvent(
|
||||
linkEndpointToTransition(payChain, MACHINE_CONFIG,
|
||||
transition("NEW", "PAID", "OrderEvent.PAY"),
|
||||
transition("PAID", "SHIPPED", "OrderEvent.SHIP")),
|
||||
"OrderEvent.PAY");
|
||||
assertLinkedEvent(
|
||||
linkEndpointToTransition(shipChain, MACHINE_CONFIG,
|
||||
transition("NEW", "PAID", "OrderEvent.PAY"),
|
||||
transition("PAID", "SHIPPED", "OrderEvent.SHIP")),
|
||||
"OrderEvent.SHIP");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tier 1 — DTO field set via constructor in controller, read via getter in gateway.
|
||||
*
|
||||
* <pre>
|
||||
* submit() → gateway.submit(new OrderRequest(OrderEvent.SUBMIT)) → req.getType() → OrderEvent.SUBMIT
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
void dtoCrossHopFieldFlowShouldReachCentralDispatcher(@TempDir Path tempDir) throws Exception {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class ApiController {
|
||||
CommandGateway gateway;
|
||||
public void submit() { gateway.submit(new OrderRequest(OrderEvent.SUBMIT)); }
|
||||
}
|
||||
class CommandGateway {
|
||||
void submit(OrderRequest req) {
|
||||
StateMachine sm = new StateMachine();
|
||||
sm.sendEvent(req.getType());
|
||||
}
|
||||
}
|
||||
class OrderRequest {
|
||||
private final OrderEvent type;
|
||||
OrderRequest(OrderEvent type) { this.type = type; }
|
||||
OrderEvent getType() { return type; }
|
||||
}
|
||||
enum OrderEvent { SUBMIT, PAY }
|
||||
class StateMachine { public void sendEvent(OrderEvent e) {} }
|
||||
class OrderStateMachineConfig {}
|
||||
""";
|
||||
CodebaseContext context = scanSource(source, tempDir);
|
||||
|
||||
CallChain submitChain = resolveChain(context, CONTROLLER, "submit", STATE_MACHINE);
|
||||
|
||||
assertPolyEvents(submitChain, "OrderEvent.SUBMIT");
|
||||
assertLinkedEvent(
|
||||
linkEndpointToTransition(submitChain, MACHINE_CONFIG,
|
||||
transition("DRAFT", "SUBMITTED", "OrderEvent.SUBMIT"),
|
||||
transition("SUBMITTED", "PAID", "OrderEvent.PAY")),
|
||||
"OrderEvent.SUBMIT");
|
||||
}
|
||||
|
||||
/**
|
||||
* Chained field-backed trivial getters ({@code return this.field}) through a central dispatcher.
|
||||
*/
|
||||
|
||||
@@ -26,6 +26,11 @@ final class CentralDispatcherTestSupport {
|
||||
private CentralDispatcherTestSupport() {
|
||||
}
|
||||
|
||||
enum EngineKind {
|
||||
HEURISTIC,
|
||||
JDT
|
||||
}
|
||||
|
||||
static CodebaseContext scanSource(String source, Path tempDir) throws Exception {
|
||||
Files.writeString(tempDir.resolve("App.java"), source);
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
@@ -38,7 +43,18 @@ final class CentralDispatcherTestSupport {
|
||||
String controllerClass,
|
||||
String controllerMethod,
|
||||
String stateMachineClass) {
|
||||
HeuristicCallGraphEngine engine = new HeuristicCallGraphEngine(context);
|
||||
return resolveChain(context, controllerClass, controllerMethod, stateMachineClass, EngineKind.HEURISTIC);
|
||||
}
|
||||
|
||||
static CallChain resolveChain(
|
||||
CodebaseContext context,
|
||||
String controllerClass,
|
||||
String controllerMethod,
|
||||
String stateMachineClass,
|
||||
EngineKind engineKind) {
|
||||
AbstractCallGraphEngine engine = engineKind == EngineKind.JDT
|
||||
? new JdtCallGraphEngine(context, null)
|
||||
: new HeuristicCallGraphEngine(context);
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className(controllerClass)
|
||||
.methodName(controllerMethod)
|
||||
@@ -50,7 +66,8 @@ final class CentralDispatcherTestSupport {
|
||||
.build();
|
||||
List<CallChain> chains = engine.findChains(List.of(entryPoint), List.of(trigger));
|
||||
assertThat(chains)
|
||||
.as("expected one call chain from %s.%s to %s.sendEvent", controllerClass, controllerMethod, stateMachineClass)
|
||||
.as("expected one call chain from %s.%s to %s.sendEvent via %s",
|
||||
controllerClass, controllerMethod, stateMachineClass, engineKind)
|
||||
.hasSize(1);
|
||||
return chains.get(0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package click.kamil.springstatemachineexporter.analysis.service;
|
||||
|
||||
import click.kamil.springstatemachineexporter.analysis.model.CallChain;
|
||||
import click.kamil.springstatemachineexporter.analysis.model.EntryPoint;
|
||||
import click.kamil.springstatemachineexporter.analysis.model.TriggerPoint;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static click.kamil.springstatemachineexporter.analysis.service.CentralDispatcherTestSupport.EngineKind;
|
||||
import static click.kamil.springstatemachineexporter.analysis.service.CentralDispatcherTestSupport.assertPolyEvents;
|
||||
import static click.kamil.springstatemachineexporter.analysis.service.CentralDispatcherTestSupport.scanSource;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class CustomMessageTriggerResolutionTest {
|
||||
|
||||
private static final String SOURCE = """
|
||||
package com.example;
|
||||
enum OrderEvent { PROCESS, COMPLETE }
|
||||
class CustomStateMachineMessage<T, P> {
|
||||
CustomStateMachineMessage(T payload, P customPayload) {}
|
||||
}
|
||||
class StateMachineService {
|
||||
void sendCustomMessage(CustomStateMachineMessage<OrderEvent, String> customMessage) {}
|
||||
}
|
||||
class RabbitOrderListener {
|
||||
private StateMachineService stateMachineService;
|
||||
void handleCustomTransition(String payload) {
|
||||
CustomStateMachineMessage<OrderEvent, String> customMessage =
|
||||
new CustomStateMachineMessage<>(OrderEvent.PROCESS, "payload: " + payload);
|
||||
stateMachineService.sendCustomMessage(customMessage);
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(EngineKind.class)
|
||||
void customStateMachineMessageShouldExtractEventFromConstructor(EngineKind engineKind, @TempDir Path tempDir)
|
||||
throws Exception {
|
||||
var context = scanSource(SOURCE, tempDir);
|
||||
AbstractCallGraphEngine engine = engineKind == EngineKind.JDT
|
||||
? new JdtCallGraphEngine(context, null)
|
||||
: new HeuristicCallGraphEngine(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.RabbitOrderListener")
|
||||
.methodName("handleCustomTransition")
|
||||
.build();
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.StateMachineService")
|
||||
.methodName("sendCustomMessage")
|
||||
.event("customMessage")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = engine.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
assertPolyEvents(chains.get(0), "OrderEvent.PROCESS");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package click.kamil.springstatemachineexporter.analysis.service;
|
||||
|
||||
import click.kamil.springstatemachineexporter.exporter.JsonExporter;
|
||||
import click.kamil.springstatemachineexporter.service.ExportService;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* End-to-end verification for {@code state_machines/inheritance_sample}:
|
||||
* interface-mapped REST → injected service impl → {@code sendEvent}.
|
||||
*/
|
||||
class InheritanceSampleChainTest {
|
||||
|
||||
private static Path findProjectRoot() {
|
||||
Path current = Path.of(".").toAbsolutePath();
|
||||
while (current != null && !Files.exists(current.resolve("settings.gradle"))) {
|
||||
current = current.getParent();
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
@Test
|
||||
void exportShouldIncludeTriggerAndCallChain(@TempDir Path tempDir) throws Exception {
|
||||
Path sampleRoot = findProjectRoot().resolve("state_machines/inheritance_sample");
|
||||
|
||||
ExportService exportService = new ExportService(List.of(new JsonExporter()));
|
||||
exportService.runExporter(sampleRoot, tempDir, List.of("json"), true, List.of(), null, null,
|
||||
click.kamil.springstatemachineexporter.exporter.EnumFormat.fn,
|
||||
click.kamil.springstatemachineexporter.exporter.EnumFormat.fn);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
Path jsonFile;
|
||||
try (var stream = Files.walk(tempDir)) {
|
||||
jsonFile = stream.filter(p -> p.getFileName().toString().contains("InheritanceStateMachineConfig")
|
||||
&& p.getFileName().toString().endsWith(".json")).findFirst().orElseThrow();
|
||||
}
|
||||
JsonNode metadata = mapper.readTree(jsonFile.toFile()).path("metadata");
|
||||
|
||||
assertThat(metadata.path("triggers").size()).as("triggers").isGreaterThan(0);
|
||||
assertThat(metadata.path("callChains").size()).as("callChains").isGreaterThan(0);
|
||||
|
||||
JsonNode chain = metadata.path("callChains").get(0);
|
||||
assertThat(chain.path("entryPoint").path("name").asText())
|
||||
.isEqualTo("POST /api/v2/orders/submit");
|
||||
assertThat(chain.path("methodChain").toString())
|
||||
.contains("OrderControllerImpl.submitOrder")
|
||||
.contains("ProcessingServiceImpl.doProcess");
|
||||
assertThat(chain.path("triggerPoint").path("event").asText())
|
||||
.isIn("INHERITED_SUBMIT", "java.lang.String.INHERITED_SUBMIT", "String.INHERITED_SUBMIT");
|
||||
assertThat(chain.path("matchedTransitions").size()).isEqualTo(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package click.kamil.springstatemachineexporter.analysis.service;
|
||||
|
||||
import click.kamil.springstatemachineexporter.analysis.model.CallChain;
|
||||
import click.kamil.springstatemachineexporter.analysis.model.MatchedTransition;
|
||||
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static click.kamil.springstatemachineexporter.analysis.service.CentralDispatcherTestSupport.EngineKind;
|
||||
import static click.kamil.springstatemachineexporter.analysis.service.CentralDispatcherTestSupport.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Ensures the production {@link JdtCallGraphEngine} resolves single-dispatcher endpoints the same
|
||||
* way as {@link HeuristicCallGraphEngine} for Tier-1 central-dispatcher patterns.
|
||||
*/
|
||||
class JdtCentralDispatcherParityTest {
|
||||
|
||||
private static final String CONTROLLER = "com.example.ApiController";
|
||||
private static final String STATE_MACHINE = "com.example.StateMachine";
|
||||
private static final String MACHINE_CONFIG = "com.example.OrderStateMachineConfig";
|
||||
|
||||
@Test
|
||||
void jdtShouldMatchHeuristicForFieldWiredRoutingHelper(@TempDir Path tempDir) throws Exception {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class ApiController {
|
||||
CommandGateway gateway;
|
||||
public void pay() { gateway.routeAndPay(); }
|
||||
public void ship() { gateway.routeAndShip(); }
|
||||
}
|
||||
class CommandGateway {
|
||||
OrderRoutingHelper routingHelper;
|
||||
CentralDispatcher dispatcher;
|
||||
void routeAndPay() { dispatcher.dispatch("ORDER", routingHelper.payAction()); }
|
||||
void routeAndShip() { dispatcher.dispatch("ORDER", routingHelper.shipAction()); }
|
||||
}
|
||||
class OrderRoutingHelper {
|
||||
String payAction() { return "PAY"; }
|
||||
String shipAction() { return "SHIP"; }
|
||||
}
|
||||
class CentralDispatcher {
|
||||
void dispatch(String domain, String action) {
|
||||
StateMachine sm = new StateMachine();
|
||||
sm.sendEvent(OrderEvent.valueOf(action));
|
||||
}
|
||||
}
|
||||
enum OrderEvent { PAY, SHIP }
|
||||
class StateMachine { public void sendEvent(OrderEvent e) {} }
|
||||
class OrderStateMachineConfig {}
|
||||
""";
|
||||
CodebaseContext context = scanSource(source, tempDir);
|
||||
|
||||
CallChain heuristicPay = resolveChain(context, CONTROLLER, "pay", STATE_MACHINE, EngineKind.HEURISTIC);
|
||||
CallChain jdtPay = resolveChain(context, CONTROLLER, "pay", STATE_MACHINE, EngineKind.JDT);
|
||||
CallChain heuristicShip = resolveChain(context, CONTROLLER, "ship", STATE_MACHINE, EngineKind.HEURISTIC);
|
||||
CallChain jdtShip = resolveChain(context, CONTROLLER, "ship", STATE_MACHINE, EngineKind.JDT);
|
||||
|
||||
assertThat(jdtPay.getTriggerPoint().getPolymorphicEvents())
|
||||
.containsExactlyInAnyOrderElementsOf(heuristicPay.getTriggerPoint().getPolymorphicEvents());
|
||||
assertThat(jdtShip.getTriggerPoint().getPolymorphicEvents())
|
||||
.containsExactlyInAnyOrderElementsOf(heuristicShip.getTriggerPoint().getPolymorphicEvents());
|
||||
|
||||
MatchedTransition heuristicLink = linkEndpointToTransition(heuristicPay, MACHINE_CONFIG,
|
||||
transition("NEW", "PAID", "OrderEvent.PAY"),
|
||||
transition("PAID", "SHIPPED", "OrderEvent.SHIP"));
|
||||
MatchedTransition jdtLink = linkEndpointToTransition(jdtPay, MACHINE_CONFIG,
|
||||
transition("NEW", "PAID", "OrderEvent.PAY"),
|
||||
transition("PAID", "SHIPPED", "OrderEvent.SHIP"));
|
||||
assertThat(jdtLink.getEvent()).isEqualTo(heuristicLink.getEvent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void jdtShouldMatchHeuristicForDtoCrossHop(@TempDir Path tempDir) throws Exception {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class ApiController {
|
||||
CommandGateway gateway;
|
||||
public void submit() { gateway.submit(new OrderRequest(OrderEvent.SUBMIT)); }
|
||||
}
|
||||
class CommandGateway {
|
||||
void submit(OrderRequest req) {
|
||||
StateMachine sm = new StateMachine();
|
||||
sm.sendEvent(req.getType());
|
||||
}
|
||||
}
|
||||
class OrderRequest {
|
||||
private final OrderEvent type;
|
||||
OrderRequest(OrderEvent type) { this.type = type; }
|
||||
OrderEvent getType() { return type; }
|
||||
}
|
||||
enum OrderEvent { SUBMIT, PAY }
|
||||
class StateMachine { public void sendEvent(OrderEvent e) {} }
|
||||
class OrderStateMachineConfig {}
|
||||
""";
|
||||
CodebaseContext context = scanSource(source, tempDir);
|
||||
|
||||
CallChain heuristic = resolveChain(context, CONTROLLER, "submit", STATE_MACHINE, EngineKind.HEURISTIC);
|
||||
CallChain jdt = resolveChain(context, CONTROLLER, "submit", STATE_MACHINE, EngineKind.JDT);
|
||||
|
||||
assertThat(jdt.getTriggerPoint().getPolymorphicEvents())
|
||||
.containsExactlyInAnyOrderElementsOf(heuristic.getTriggerPoint().getPolymorphicEvents());
|
||||
|
||||
MatchedTransition heuristicLink = linkEndpointToTransition(heuristic, MACHINE_CONFIG,
|
||||
transition("DRAFT", "SUBMITTED", "OrderEvent.SUBMIT"),
|
||||
transition("SUBMITTED", "PAID", "OrderEvent.PAY"));
|
||||
MatchedTransition jdtLink = linkEndpointToTransition(jdt, MACHINE_CONFIG,
|
||||
transition("DRAFT", "SUBMITTED", "OrderEvent.SUBMIT"),
|
||||
transition("SUBMITTED", "PAID", "OrderEvent.PAY"));
|
||||
assertThat(jdtLink.getEvent()).isEqualTo(heuristicLink.getEvent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void jdtShouldMatchHeuristicForSingleDispatcherNamedMethods(@TempDir Path tempDir) throws Exception {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class ApiController {
|
||||
CentralDispatcher dispatcher;
|
||||
public void pay() { dispatcher.orderPay(); }
|
||||
public void ship() { dispatcher.orderShip(); }
|
||||
}
|
||||
class CentralDispatcher {
|
||||
public void orderPay() {
|
||||
StateMachine sm = new StateMachine();
|
||||
sm.sendEvent(OrderEvent.PAY);
|
||||
}
|
||||
public void orderShip() {
|
||||
StateMachine sm = new StateMachine();
|
||||
sm.sendEvent(OrderEvent.SHIP);
|
||||
}
|
||||
}
|
||||
enum OrderEvent { PAY, SHIP }
|
||||
class StateMachine { public void sendEvent(OrderEvent e) {} }
|
||||
class OrderStateMachineConfig {}
|
||||
""";
|
||||
CodebaseContext context = scanSource(source, tempDir);
|
||||
|
||||
for (String method : List.of("pay", "ship")) {
|
||||
CallChain heuristic = resolveChain(context, CONTROLLER, method, STATE_MACHINE, EngineKind.HEURISTIC);
|
||||
CallChain jdt = resolveChain(context, CONTROLLER, method, STATE_MACHINE, EngineKind.JDT);
|
||||
assertThat(jdt.getTriggerPoint().getPolymorphicEvents())
|
||||
.containsExactlyInAnyOrderElementsOf(heuristic.getTriggerPoint().getPolymorphicEvents());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,4 +71,40 @@ class SpringMvcDetectorTest {
|
||||
assertThat(entryPoints).anyMatch(ep ->
|
||||
"POST /api/orders/pay".equals(ep.getName()) && "pay".equals(ep.getMethodName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDetectInterfaceMappedRestEndpointOnImplOnly(@TempDir Path tempDir) throws Exception {
|
||||
String apiSource = """
|
||||
package com.example;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@RequestMapping("/api/v2/orders")
|
||||
public interface OrderApi {
|
||||
@PostMapping("/submit")
|
||||
void submitOrder();
|
||||
}
|
||||
""";
|
||||
String implSource = """
|
||||
package com.example;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@RestController
|
||||
public class OrderControllerImpl implements OrderApi {
|
||||
@Override
|
||||
public void submitOrder() {}
|
||||
}
|
||||
""";
|
||||
Files.writeString(tempDir.resolve("OrderApi.java"), apiSource);
|
||||
Files.writeString(tempDir.resolve("OrderControllerImpl.java"), implSource);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.setResolveBindings(true);
|
||||
context.scan(tempDir);
|
||||
|
||||
SpringMvcDetector detector = new SpringMvcDetector(context, context.getConstantResolver());
|
||||
org.eclipse.jdt.core.dom.TypeDeclaration impl = context.getTypeDeclaration("com.example.OrderControllerImpl");
|
||||
List<EntryPoint> entryPoints = detector.detect((org.eclipse.jdt.core.dom.CompilationUnit) impl.getRoot());
|
||||
|
||||
assertThat(entryPoints).hasSize(1);
|
||||
assertThat(entryPoints.get(0).getName()).isEqualTo("POST /api/v2/orders/submit");
|
||||
assertThat(entryPoints.get(0).getClassName()).isEqualTo("com.example.OrderControllerImpl");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,120 +147,6 @@
|
||||
} ]
|
||||
} ],
|
||||
"callChains" : [ {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/machine/document/submit",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineController",
|
||||
"methodName" : "submitDocument",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/machine/document/submit",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "userId",
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestParam" ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.enterprise.web.StateMachineController.submitDocument", "click.kamil.enterprise.web.StateMachineDispatcher.submitDocument" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "click.kamil.enterprise.machines.document.DocumentEvent.SUBMIT",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineDispatcher",
|
||||
"methodName" : "submitDocument",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineDispatcher.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 44,
|
||||
"polymorphicEvents" : [ "click.kamil.enterprise.machines.document.DocumentEvent.SUBMIT" ],
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "click.kamil.enterprise.machines.document.DocumentState.DRAFT",
|
||||
"targetState" : "click.kamil.enterprise.machines.document.DocumentState.IN_REVIEW",
|
||||
"event" : "click.kamil.enterprise.machines.document.DocumentEvent.SUBMIT"
|
||||
} ]
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/machine/document/approve",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineController",
|
||||
"methodName" : "approveDocument",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/machine/document/approve",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "userId",
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestParam" ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.enterprise.web.StateMachineController.approveDocument", "click.kamil.enterprise.web.StateMachineDispatcher.approveDocument" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "click.kamil.enterprise.machines.document.DocumentEvent.APPROVE",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineDispatcher",
|
||||
"methodName" : "approveDocument",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineDispatcher.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 51,
|
||||
"polymorphicEvents" : [ "click.kamil.enterprise.machines.document.DocumentEvent.APPROVE" ],
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "click.kamil.enterprise.machines.document.DocumentState.IN_REVIEW",
|
||||
"targetState" : "click.kamil.enterprise.machines.document.DocumentState.APPROVED",
|
||||
"event" : "click.kamil.enterprise.machines.document.DocumentEvent.APPROVE"
|
||||
} ]
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/machine/document/reject",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineController",
|
||||
"methodName" : "rejectDocument",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/machine/document/reject",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "userId",
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestParam" ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.enterprise.web.StateMachineController.rejectDocument", "click.kamil.enterprise.web.StateMachineDispatcher.rejectDocument" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "click.kamil.enterprise.machines.document.DocumentEvent.REJECT",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineDispatcher",
|
||||
"methodName" : "rejectDocument",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineDispatcher.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 58,
|
||||
"polymorphicEvents" : [ "click.kamil.enterprise.machines.document.DocumentEvent.REJECT" ],
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "click.kamil.enterprise.machines.document.DocumentState.IN_REVIEW",
|
||||
"targetState" : "click.kamil.enterprise.machines.document.DocumentState.DRAFT",
|
||||
"event" : "click.kamil.enterprise.machines.document.DocumentEvent.REJECT"
|
||||
} ]
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/machine/{machineType}/transition/{event}",
|
||||
|
||||
@@ -182,8 +182,112 @@
|
||||
"stateTypeFqn" : "String",
|
||||
"eventTypeFqn" : "String",
|
||||
"metadata" : {
|
||||
"triggers" : [ ],
|
||||
"triggers" : [ {
|
||||
"event" : "java.lang.String.AUDIT_EVENT",
|
||||
"className" : "click.kamil.examples.enterprise.api.SecurityInterceptor",
|
||||
"methodName" : "preHandle",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/api/SecurityInterceptor.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 17,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
}, {
|
||||
"event" : "java.lang.String.PLACE_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.service.OrderServiceImpl",
|
||||
"methodName" : "place",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/service/OrderServiceImpl.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 16,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
}, {
|
||||
"event" : "java.lang.String.CANCEL_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.service.OrderServiceImpl",
|
||||
"methodName" : "cancel",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/service/OrderServiceImpl.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 21,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
}, {
|
||||
"event" : "java.lang.String.PAY_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.service.ReactivePaymentService",
|
||||
"methodName" : "processPayment",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/service/ReactivePaymentService.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 18,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
}, {
|
||||
"event" : "java.lang.String.SHIP_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.messaging.ShippingJmsListener",
|
||||
"methodName" : "onShippingReady",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/messaging/ShippingJmsListener.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 17,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
}, {
|
||||
"event" : "java.lang.String.RETURN_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.messaging.ReturnsRabbitListener",
|
||||
"methodName" : "onReturn",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/messaging/ReturnsRabbitListener.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 17,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/enterprise/orders/place",
|
||||
"className" : "click.kamil.examples.enterprise.api.OrderController",
|
||||
"methodName" : "placeOrder",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/api/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/enterprise/orders/place",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/enterprise/orders/{id}/cancel",
|
||||
"className" : "click.kamil.examples.enterprise.api.OrderController",
|
||||
"methodName" : "cancelOrder",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/api/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/enterprise/orders/{id}/cancel",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "id",
|
||||
"type" : "String",
|
||||
"annotations" : [ "PathVariable" ]
|
||||
} ]
|
||||
}, {
|
||||
"type" : "CUSTOM",
|
||||
"name" : "INTERCEPTOR: SecurityInterceptor.preHandle",
|
||||
"className" : "click.kamil.examples.enterprise.api.SecurityInterceptor",
|
||||
@@ -239,7 +343,222 @@
|
||||
"annotations" : [ ]
|
||||
} ]
|
||||
} ],
|
||||
"callChains" : [ ],
|
||||
"callChains" : [ {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/enterprise/orders/place",
|
||||
"className" : "click.kamil.examples.enterprise.api.OrderController",
|
||||
"methodName" : "placeOrder",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/api/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/enterprise/orders/place",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.examples.enterprise.api.OrderController.placeOrder", "click.kamil.examples.enterprise.service.OrderServiceImpl.place" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "java.lang.String.PLACE_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.service.OrderServiceImpl",
|
||||
"methodName" : "place",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/service/OrderServiceImpl.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 16,
|
||||
"polymorphicEvents" : [ "java.lang.String.PLACE_ORDER" ],
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "String.NEW",
|
||||
"targetState" : "String.CHECK_AVAILABILITY",
|
||||
"event" : "String.PLACE_ORDER"
|
||||
} ]
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/enterprise/orders/{id}/cancel",
|
||||
"className" : "click.kamil.examples.enterprise.api.OrderController",
|
||||
"methodName" : "cancelOrder",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/api/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/enterprise/orders/{id}/cancel",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "id",
|
||||
"type" : "String",
|
||||
"annotations" : [ "PathVariable" ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.examples.enterprise.api.OrderController.cancelOrder", "click.kamil.examples.enterprise.service.OrderServiceImpl.cancel" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "java.lang.String.CANCEL_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.service.OrderServiceImpl",
|
||||
"methodName" : "cancel",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/service/OrderServiceImpl.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 21,
|
||||
"polymorphicEvents" : [ "java.lang.String.CANCEL_ORDER" ],
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "String.PAID",
|
||||
"targetState" : "String.CANCELLED",
|
||||
"event" : "String.CANCEL_ORDER"
|
||||
} ]
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "CUSTOM",
|
||||
"name" : "INTERCEPTOR: SecurityInterceptor.preHandle",
|
||||
"className" : "click.kamil.examples.enterprise.api.SecurityInterceptor",
|
||||
"methodName" : "preHandle",
|
||||
"sourceFile" : null,
|
||||
"metadata" : {
|
||||
"interceptorType" : "Spring MVC Interceptor"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.examples.enterprise.api.SecurityInterceptor.preHandle" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "java.lang.String.AUDIT_EVENT",
|
||||
"className" : "click.kamil.examples.enterprise.api.SecurityInterceptor",
|
||||
"methodName" : "preHandle",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/api/SecurityInterceptor.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 17,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : null
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/enterprise/payments",
|
||||
"className" : "click.kamil.examples.enterprise.api.ReactivePaymentController",
|
||||
"methodName" : "pay",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/api/ReactivePaymentController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/enterprise/payments",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "orderId",
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestBody" ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.examples.enterprise.api.ReactivePaymentController.pay", "click.kamil.examples.enterprise.service.ReactivePaymentService.processPayment" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "java.lang.String.PAY_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.service.ReactivePaymentService",
|
||||
"methodName" : "processPayment",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/service/ReactivePaymentService.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 18,
|
||||
"polymorphicEvents" : [ "java.lang.String.PAY_ORDER" ],
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "String.PENDING_PAYMENT",
|
||||
"targetState" : "String.PAID",
|
||||
"event" : "String.PAY_ORDER"
|
||||
} ]
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "JMS",
|
||||
"name" : "JMS: shipping.queue",
|
||||
"className" : "click.kamil.examples.enterprise.messaging.ShippingJmsListener",
|
||||
"methodName" : "onShippingReady",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/messaging/ShippingJmsListener.java",
|
||||
"metadata" : {
|
||||
"protocol" : "JMS",
|
||||
"destination" : "shipping.queue"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "orderId",
|
||||
"type" : "String",
|
||||
"annotations" : [ ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.examples.enterprise.messaging.ShippingJmsListener.onShippingReady" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "java.lang.String.SHIP_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.messaging.ShippingJmsListener",
|
||||
"methodName" : "onShippingReady",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/messaging/ShippingJmsListener.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 17,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "String.PAID",
|
||||
"targetState" : "String.SHIPPED",
|
||||
"event" : "String.SHIP_ORDER"
|
||||
} ]
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "RABBIT",
|
||||
"name" : "RABBIT: returns.queue",
|
||||
"className" : "click.kamil.examples.enterprise.messaging.ReturnsRabbitListener",
|
||||
"methodName" : "onReturn",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/messaging/ReturnsRabbitListener.java",
|
||||
"metadata" : {
|
||||
"protocol" : "RABBIT",
|
||||
"destination" : "returns.queue"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "orderId",
|
||||
"type" : "String",
|
||||
"annotations" : [ ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.examples.enterprise.messaging.ReturnsRabbitListener.onReturn" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "java.lang.String.RETURN_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.messaging.ReturnsRabbitListener",
|
||||
"methodName" : "onReturn",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/enterprise/messaging/ReturnsRabbitListener.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 17,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "String.DELIVERED",
|
||||
"targetState" : "String.RETURNED",
|
||||
"event" : "String.RETURN_ORDER"
|
||||
} ]
|
||||
} ],
|
||||
"properties" : {
|
||||
"default" : { }
|
||||
}
|
||||
|
||||
@@ -182,40 +182,6 @@
|
||||
} ]
|
||||
} ],
|
||||
"callChains" : [ {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/orders/resume",
|
||||
"className" : "click.kamil.examples.statemachine.extended.web.OrderController",
|
||||
"methodName" : "resumeOrder",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/orders/resume",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "orderId",
|
||||
"type" : "String",
|
||||
"annotations" : [ ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.examples.statemachine.extended.web.OrderController.resumeOrder", "click.kamil.examples.statemachine.extended.service.OrderService.resumeOrder" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "[LIFECYCLE:RESTORE]",
|
||||
"className" : "click.kamil.examples.statemachine.extended.service.OrderService",
|
||||
"methodName" : "resumeOrder",
|
||||
"sourceFile" : null,
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 29,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : "orderId",
|
||||
"matchedTransitions" : null
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/payment/{id}/capture",
|
||||
|
||||
@@ -182,40 +182,6 @@
|
||||
} ]
|
||||
} ],
|
||||
"callChains" : [ {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/orders/resume",
|
||||
"className" : "click.kamil.examples.statemachine.extended.web.OrderController",
|
||||
"methodName" : "resumeOrder",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/extended/web/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/orders/resume",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "orderId",
|
||||
"type" : "String",
|
||||
"annotations" : [ ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.examples.statemachine.extended.web.OrderController.resumeOrder", "click.kamil.examples.statemachine.extended.service.OrderService.resumeOrder" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "[LIFECYCLE:RESTORE]",
|
||||
"className" : "click.kamil.examples.statemachine.extended.service.OrderService",
|
||||
"methodName" : "resumeOrder",
|
||||
"sourceFile" : null,
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 29,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : "orderId",
|
||||
"matchedTransitions" : null
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/payment/{id}/capture",
|
||||
|
||||
@@ -32,9 +32,67 @@
|
||||
"stateTypeFqn" : "String",
|
||||
"eventTypeFqn" : "String",
|
||||
"metadata" : {
|
||||
"triggers" : [ ],
|
||||
"entryPoints" : [ ],
|
||||
"callChains" : [ ],
|
||||
"triggers" : [ {
|
||||
"event" : "java.lang.String.INHERITED_SUBMIT",
|
||||
"className" : "click.kamil.examples.statemachine.inheritance.service.ProcessingServiceImpl",
|
||||
"methodName" : "doProcess",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/inheritance/service/ProcessingServiceImpl.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 15,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/v2/orders/submit",
|
||||
"className" : "click.kamil.examples.statemachine.inheritance.api.OrderControllerImpl",
|
||||
"methodName" : "submitOrder",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/inheritance/api/OrderControllerImpl.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/v2/orders/submit",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
} ],
|
||||
"callChains" : [ {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/v2/orders/submit",
|
||||
"className" : "click.kamil.examples.statemachine.inheritance.api.OrderControllerImpl",
|
||||
"methodName" : "submitOrder",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/inheritance/api/OrderControllerImpl.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/v2/orders/submit",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.examples.statemachine.inheritance.api.OrderControllerImpl.submitOrder", "click.kamil.examples.statemachine.inheritance.service.ProcessingServiceImpl.doProcess" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "java.lang.String.INHERITED_SUBMIT",
|
||||
"className" : "click.kamil.examples.statemachine.inheritance.service.ProcessingServiceImpl",
|
||||
"methodName" : "doProcess",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/inheritance/service/ProcessingServiceImpl.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 15,
|
||||
"polymorphicEvents" : [ "java.lang.String.INHERITED_SUBMIT" ],
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "String.START",
|
||||
"targetState" : "String.WORKING",
|
||||
"event" : "String.INHERITED_SUBMIT"
|
||||
} ]
|
||||
} ],
|
||||
"properties" : {
|
||||
"default" : { }
|
||||
}
|
||||
|
||||
@@ -60,8 +60,61 @@
|
||||
"eventTypeFqn" : "String",
|
||||
"metadata" : {
|
||||
"triggers" : [ ],
|
||||
"entryPoints" : [ ],
|
||||
"callChains" : [ ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
"name" : "POST /maven/orders/submit",
|
||||
"className" : "click.kamil.maven.core.MavenOrderStateMachine.OrderController",
|
||||
"methodName" : "submitOrder",
|
||||
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
|
||||
"metadata" : {
|
||||
"path" : "/maven/orders/submit",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "orderId",
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestBody" ]
|
||||
} ]
|
||||
} ],
|
||||
"callChains" : [ {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /maven/orders/submit",
|
||||
"className" : "click.kamil.maven.core.MavenOrderStateMachine.OrderController",
|
||||
"methodName" : "submitOrder",
|
||||
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
|
||||
"metadata" : {
|
||||
"path" : "/maven/orders/submit",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "orderId",
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestBody" ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.maven.core.MavenOrderStateMachine.OrderController.submitOrder" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "java.lang.String.SUBMIT",
|
||||
"className" : "click.kamil.maven.core.MavenOrderStateMachine.OrderController",
|
||||
"methodName" : "submitOrder",
|
||||
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 40,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "String.INIT",
|
||||
"targetState" : "String.BUSY",
|
||||
"event" : "String.SUBMIT"
|
||||
} ]
|
||||
} ],
|
||||
"properties" : {
|
||||
"default" : { }
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
"rawName" : "\"BUSY\"",
|
||||
"fullIdentifier" : "BUSY"
|
||||
} ],
|
||||
"event" : "ORDER_EVENT",
|
||||
"event" : "SUBMIT",
|
||||
"guard" : null,
|
||||
"actions" : [ {
|
||||
"expression" : "loggingAction()",
|
||||
@@ -61,6 +61,20 @@
|
||||
"lineNumber" : 23
|
||||
} ],
|
||||
"order" : null
|
||||
}, {
|
||||
"type" : "EXTERNAL",
|
||||
"sourceStates" : [ {
|
||||
"rawName" : "\"BUSY\"",
|
||||
"fullIdentifier" : "BUSY"
|
||||
} ],
|
||||
"targetStates" : [ {
|
||||
"rawName" : "\"DONE\"",
|
||||
"fullIdentifier" : "DONE"
|
||||
} ],
|
||||
"event" : "ORDER_EVENT",
|
||||
"guard" : null,
|
||||
"actions" : [ ],
|
||||
"order" : null
|
||||
} ],
|
||||
"endStates" : [ "DONE" ]
|
||||
}
|
||||
|
||||
@@ -59,7 +59,20 @@
|
||||
"stateTypeFqn" : "String",
|
||||
"eventTypeFqn" : "String",
|
||||
"metadata" : {
|
||||
"triggers" : [ ],
|
||||
"triggers" : [ {
|
||||
"event" : "java.lang.String.SUBMIT",
|
||||
"className" : "click.kamil.multi.core.OrderController",
|
||||
"methodName" : "submitOrder",
|
||||
"sourceFile" : "core-module/src/main/java/click/kamil/multi/core/OrderController.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 18,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
"name" : "POST /orders/submit",
|
||||
@@ -75,23 +88,46 @@
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestBody" ]
|
||||
} ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /orders/submit",
|
||||
"className" : "click.kamil.multi.api.OrderApi",
|
||||
"methodName" : "submitOrder",
|
||||
"sourceFile" : "api-module/src/main/java/click/kamil/multi/api/OrderApi.java",
|
||||
"metadata" : {
|
||||
"path" : "/orders/submit",
|
||||
"verb" : "POST"
|
||||
} ],
|
||||
"callChains" : [ {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /orders/submit",
|
||||
"className" : "click.kamil.multi.core.OrderController",
|
||||
"methodName" : "submitOrder",
|
||||
"sourceFile" : "core-module/src/main/java/click/kamil/multi/core/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/orders/submit",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "orderId",
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestBody" ]
|
||||
} ]
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "orderId",
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestBody" ]
|
||||
"methodChain" : [ "click.kamil.multi.core.OrderController.submitOrder" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "java.lang.String.SUBMIT",
|
||||
"className" : "click.kamil.multi.core.OrderController",
|
||||
"methodName" : "submitOrder",
|
||||
"sourceFile" : "core-module/src/main/java/click/kamil/multi/core/OrderController.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 18,
|
||||
"polymorphicEvents" : null,
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "String.NEW",
|
||||
"targetState" : "String.PROCESSING",
|
||||
"event" : "String.SUBMIT"
|
||||
} ]
|
||||
} ],
|
||||
"callChains" : [ ],
|
||||
"properties" : {
|
||||
"default" : { }
|
||||
}
|
||||
|
||||
@@ -124,82 +124,6 @@
|
||||
} ]
|
||||
} ],
|
||||
"callChains" : [ {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/machine/order/pay",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineController",
|
||||
"methodName" : "payOrder",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/machine/order/pay",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "userId",
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestParam" ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.enterprise.web.StateMachineController.payOrder", "click.kamil.enterprise.web.StateMachineDispatcher.payOrder" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "click.kamil.enterprise.machines.order.OrderEvent.PAY",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineDispatcher",
|
||||
"methodName" : "payOrder",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineDispatcher.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 30,
|
||||
"polymorphicEvents" : [ "click.kamil.enterprise.machines.order.OrderEvent.PAY" ],
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "click.kamil.enterprise.machines.order.OrderState.NEW",
|
||||
"targetState" : "click.kamil.enterprise.machines.order.OrderState.PENDING",
|
||||
"event" : "click.kamil.enterprise.machines.order.OrderEvent.PAY"
|
||||
} ]
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/machine/order/ship",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineController",
|
||||
"methodName" : "shipOrder",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/machine/order/ship",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "userId",
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestParam" ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.enterprise.web.StateMachineController.shipOrder", "click.kamil.enterprise.web.StateMachineDispatcher.shipOrder" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "click.kamil.enterprise.machines.order.OrderEvent.SHIP",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineDispatcher",
|
||||
"methodName" : "shipOrder",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineDispatcher.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 37,
|
||||
"polymorphicEvents" : [ "click.kamil.enterprise.machines.order.OrderEvent.SHIP" ],
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "click.kamil.enterprise.machines.order.OrderState.PENDING",
|
||||
"targetState" : "click.kamil.enterprise.machines.order.OrderState.SHIPPED",
|
||||
"event" : "click.kamil.enterprise.machines.order.OrderEvent.SHIP"
|
||||
} ]
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/machine/{machineType}/transition/{event}",
|
||||
|
||||
@@ -87,6 +87,39 @@
|
||||
"ambiguous" : false
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/documents/submit",
|
||||
"className" : "click.kamil.examples.statemachine.layered.web.DocumentController",
|
||||
"methodName" : "submit",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/layered/web/DocumentController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/documents/submit",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/documents/approve",
|
||||
"className" : "click.kamil.examples.statemachine.layered.web.DocumentController",
|
||||
"methodName" : "approve",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/layered/web/DocumentController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/documents/approve",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/documents/reject",
|
||||
"className" : "click.kamil.examples.statemachine.layered.web.DocumentController",
|
||||
"methodName" : "reject",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/layered/web/DocumentController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/documents/reject",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/commands/{commandKey}",
|
||||
"className" : "click.kamil.examples.statemachine.layered.web.GenericCommandController",
|
||||
|
||||
@@ -87,6 +87,83 @@
|
||||
"ambiguous" : false
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/orders/pay",
|
||||
"className" : "click.kamil.examples.statemachine.layered.web.OrderController",
|
||||
"methodName" : "pay",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/layered/web/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/orders/pay",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/orders/ship",
|
||||
"className" : "click.kamil.examples.statemachine.layered.web.OrderController",
|
||||
"methodName" : "ship",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/layered/web/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/orders/ship",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/orders/cancel",
|
||||
"className" : "click.kamil.examples.statemachine.layered.web.OrderController",
|
||||
"methodName" : "cancel",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/layered/web/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/orders/cancel",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/string-dispatch/orders/pay",
|
||||
"className" : "click.kamil.examples.statemachine.layered.web.StringDispatchController",
|
||||
"methodName" : "payWithStringKey",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/layered/web/StringDispatchController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/string-dispatch/orders/pay",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/string-dispatch/orders/ship",
|
||||
"className" : "click.kamil.examples.statemachine.layered.web.StringDispatchController",
|
||||
"methodName" : "shipWithStringKey",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/layered/web/StringDispatchController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/string-dispatch/orders/ship",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/orders/rich/pay",
|
||||
"className" : "click.kamil.examples.statemachine.layered.web.RichOrderController",
|
||||
"methodName" : "payViaRichEvent",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/layered/web/RichOrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/orders/rich/pay",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/orders/rich/ship",
|
||||
"className" : "click.kamil.examples.statemachine.layered.web.RichOrderController",
|
||||
"methodName" : "shipViaRichEvent",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/layered/web/RichOrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/orders/rich/ship",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/commands/{commandKey}",
|
||||
"className" : "click.kamil.examples.statemachine.layered.web.GenericCommandController",
|
||||
|
||||
@@ -130,6 +130,50 @@
|
||||
"ambiguous" : false
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/orders/process",
|
||||
"className" : "click.kamil.web.OrderController",
|
||||
"methodName" : "processOrder",
|
||||
"sourceFile" : "web/src/main/java/click/kamil/web/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/orders/process",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/orders/complete",
|
||||
"className" : "click.kamil.web.OrderController",
|
||||
"methodName" : "completeOrder",
|
||||
"sourceFile" : "web/src/main/java/click/kamil/web/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/orders/complete",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/orders/cancel",
|
||||
"className" : "click.kamil.web.OrderController",
|
||||
"methodName" : "cancelOrder",
|
||||
"sourceFile" : "web/src/main/java/click/kamil/web/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/orders/cancel",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/orders/functional-complete",
|
||||
"className" : "click.kamil.web.OrderController",
|
||||
"methodName" : "functionalCompleteOrder",
|
||||
"sourceFile" : "web/src/main/java/click/kamil/web/OrderController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/orders/functional-complete",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ ]
|
||||
}, {
|
||||
"type" : "RABBIT",
|
||||
"name" : "RABBIT: order.custom.transition.queue",
|
||||
"className" : "click.kamil.web.RabbitOrderListener",
|
||||
@@ -342,13 +386,17 @@
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 78,
|
||||
"polymorphicEvents" : [ ],
|
||||
"polymorphicEvents" : [ "click.kamil.domain.OrderEvent.PROCESS" ],
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : null
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "click.kamil.domain.OrderState.NEW",
|
||||
"targetState" : "click.kamil.domain.OrderState.PROCESSING",
|
||||
"event" : "click.kamil.domain.OrderEvent.PROCESS"
|
||||
} ]
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "JMS",
|
||||
|
||||
@@ -117,78 +117,6 @@
|
||||
} ]
|
||||
} ],
|
||||
"callChains" : [ {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/machine/user/verify",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineController",
|
||||
"methodName" : "verifyUser",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/machine/user/verify",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "userId",
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestParam" ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.enterprise.web.StateMachineController.verifyUser", "click.kamil.enterprise.web.StateMachineDispatcher.verifyUser" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "click.kamil.enterprise.machines.user.UserEvent.VERIFY",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineDispatcher",
|
||||
"methodName" : "verifyUser",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineDispatcher.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 65,
|
||||
"polymorphicEvents" : [ "click.kamil.enterprise.machines.user.UserEvent.VERIFY" ],
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
"sourceState" : "click.kamil.enterprise.machines.user.UserState.REGISTERED",
|
||||
"targetState" : "click.kamil.enterprise.machines.user.UserState.VERIFIED",
|
||||
"event" : "click.kamil.enterprise.machines.user.UserEvent.VERIFY"
|
||||
} ]
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/machine/user/suspend",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineController",
|
||||
"methodName" : "suspendUser",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineController.java",
|
||||
"metadata" : {
|
||||
"path" : "/api/machine/user/suspend",
|
||||
"verb" : "POST"
|
||||
},
|
||||
"parameters" : [ {
|
||||
"name" : "userId",
|
||||
"type" : "String",
|
||||
"annotations" : [ "RequestParam" ]
|
||||
} ]
|
||||
},
|
||||
"methodChain" : [ "click.kamil.enterprise.web.StateMachineController.suspendUser", "click.kamil.enterprise.web.StateMachineDispatcher.suspendUser" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "click.kamil.enterprise.machines.user.UserEvent.SUSPEND",
|
||||
"className" : "click.kamil.enterprise.web.StateMachineDispatcher",
|
||||
"methodName" : "suspendUser",
|
||||
"sourceFile" : "src/main/java/click/kamil/enterprise/web/StateMachineDispatcher.java",
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 72,
|
||||
"polymorphicEvents" : [ "click.kamil.enterprise.machines.user.UserEvent.SUSPEND" ],
|
||||
"external" : false,
|
||||
"constraint" : null,
|
||||
"ambiguous" : false
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : null
|
||||
}, {
|
||||
"entryPoint" : {
|
||||
"type" : "REST",
|
||||
"name" : "POST /api/machine/{machineType}/transition/{event}",
|
||||
|
||||
Reference in New Issue
Block a user