v2 extended analysis render

This commit is contained in:
2026-06-14 21:15:04 +02:00
parent 744439c99d
commit 2b6b727de6
18 changed files with 1540 additions and 66 deletions

View File

@@ -0,0 +1,26 @@
package click.kamil.ultimate.api;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import lombok.RequiredArgsConstructor;
import org.springframework.statemachine.StateMachine;
import org.springframework.stereotype.Component;
@Path("/jaxrs/ticket")
@Component
@RequiredArgsConstructor
public class JerseyResource {
private final StateMachine<String, String> stateMachine;
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void createJaxRs(String payload) {
stateMachine.sendEvent("CREATE_JAXRS");
}
@PUT
@Path("/{id}/resolve")
public void resolve(@PathParam("id") String id) {
stateMachine.sendEvent("RESOLVE");
}
}

View File

@@ -0,0 +1,60 @@
package click.kamil.ultimate.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import java.util.EnumSet;
@Configuration
@EnableStateMachine
public class UltimateStateMachineConfig extends EnumStateMachineConfigurerAdapter<String, String> {
@Override
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
states
.withStates()
.initial("NEW")
.state("TRIAGE")
.state("IN_PROGRESS")
.state("ESCALATED")
.end("RESOLVED")
.end("CLOSED");
}
@Override
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
transitions
.withExternal()
.source("NEW").target("TRIAGE").event("CREATE")
.and()
.withExternal()
.source("NEW").target("IN_PROGRESS").event("CREATE_REACTIVE")
.and()
.withExternal()
.source("NEW").target("IN_PROGRESS").event("CREATE_JAXRS")
.and()
.withExternal()
.source("TRIAGE").target("IN_PROGRESS").event("ASSIGN")
.and()
.withExternal()
.source("IN_PROGRESS").target("ESCALATED").event("ESCALATE")
.and()
.withExternal()
.source("IN_PROGRESS").target("RESOLVED").event("RESOLVE")
.and()
.withExternal()
.source("ESCALATED").target("RESOLVED").event("RESOLVE")
.and()
.withExternal()
.source("RESOLVED").target("CLOSED").event("CLOSE_TICKET")
.and()
.withExternal()
.source("IN_PROGRESS").target("TRIAGE").event("SNS_UPDATE")
.and()
.withExternal()
.source("TRIAGE").target("ESCALATED").event("SQS_UPDATE");
}
}

View File

@@ -0,0 +1,17 @@
package click.kamil.ultimate.messaging;
import lombok.RequiredArgsConstructor;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.statemachine.StateMachine;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class JmsTicketListener {
private final StateMachine<String, String> stateMachine;
@JmsListener(destination = "ticket.close.queue")
public void onCloseMessage(String ticketId) {
stateMachine.sendEvent("CLOSE_TICKET");
}
}

View File

@@ -0,0 +1,17 @@
package click.kamil.ultimate.messaging;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.statemachine.StateMachine;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class RabbitTicketListener {
private final StateMachine<String, String> stateMachine;
@RabbitListener(queues = "ticket.escalate.exchange")
public void onEscalate(String payload) {
stateMachine.sendEvent("ESCALATE");
}
}

View File

@@ -0,0 +1,17 @@
package click.kamil.ultimate.messaging;
import io.awspring.cloud.sns.annotation.SnsListener;
import lombok.RequiredArgsConstructor;
import org.springframework.statemachine.StateMachine;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class SnsTicketListener {
private final StateMachine<String, String> stateMachine;
@SnsListener("ticket-sns-topic")
public void onSnsMessage(String subject, String message) {
stateMachine.sendEvent("SNS_UPDATE");
}
}

View File

@@ -0,0 +1,17 @@
package click.kamil.ultimate.messaging;
import io.awspring.cloud.sqs.annotation.SqsListener;
import lombok.RequiredArgsConstructor;
import org.springframework.statemachine.StateMachine;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class SqsTicketListener {
private final StateMachine<String, String> stateMachine;
@SqsListener("ticket-updates-queue")
public void onUpdate(String message) {
stateMachine.sendEvent("SQS_UPDATE");
}
}

View File

@@ -0,0 +1,12 @@
package click.kamil.ultimate.model;
import lombok.Data;
@Data
public class TicketRequest {
private String subject;
private String description;
private Priority priority;
public enum Priority { LOW, MEDIUM, HIGH }
}

View File

@@ -0,0 +1,21 @@
package click.kamil.ultimate.web;
import lombok.RequiredArgsConstructor;
import org.springframework.statemachine.StateMachine;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/ticket/reactive")
@RequiredArgsConstructor
public class ReactiveController {
private final StateMachine<String, String> stateMachine;
@PostMapping
public Mono<Void> createReactive(@RequestBody String data) {
return Mono.fromRunnable(() -> stateMachine.sendEvent("CREATE_REACTIVE"));
}
}

View File

@@ -0,0 +1,23 @@
package click.kamil.ultimate.web;
import click.kamil.ultimate.model.TicketRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.statemachine.StateMachine;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/ticket")
@RequiredArgsConstructor
public class WebController {
private final StateMachine<String, String> stateMachine;
@PostMapping("/create")
public void createTicket(@RequestBody TicketRequest request) {
stateMachine.sendEvent("CREATE");
}
@PostMapping("/{id}/assign")
public void assignTicket(@PathVariable String id, @RequestParam String userId) {
stateMachine.sendEvent("ASSIGN");
}
}