solved an issue on flow save
This commit is contained in:
parent
802be88452
commit
e23eeb3d9c
4
pom.xml
4
pom.xml
|
|
@ -79,10 +79,10 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>2.0.2</version>
|
||||
<version>2.8.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
package it.cnr.isti.workflow.manager.configurations;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme.Type;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class OpenApiConfig {
|
||||
|
||||
@Bean
|
||||
public OpenAPI customOpenAPI() {
|
||||
final String securitySchemeName = "bearerAuth";
|
||||
|
||||
return new OpenAPI()
|
||||
.info(new Info().title("API Docs").version("v1"))
|
||||
.components(new io.swagger.v3.oas.models.Components()
|
||||
.addSecuritySchemes(securitySchemeName,
|
||||
new SecurityScheme()
|
||||
.name(securitySchemeName)
|
||||
.type(Type.HTTP)
|
||||
.scheme("bearer")
|
||||
.bearerFormat("JWT")
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -14,7 +14,6 @@ import org.springframework.security.config.http.SessionCreationPolicy;
|
|||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity
|
||||
|
|
@ -26,17 +25,19 @@ public class SecurityConfig {
|
|||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
return http
|
||||
.cors(Customizer.withDefaults())
|
||||
.csrf(csrf -> csrf.disable())
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/auth/**").permitAll()
|
||||
.requestMatchers(HttpMethod.GET,"/health").permitAll()
|
||||
.requestMatchers(HttpMethod.GET,"/types/nodes/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
.build();
|
||||
.cors(Customizer.withDefaults())
|
||||
.csrf(csrf -> csrf.disable())
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/auth/**").permitAll()
|
||||
//.requestMatchers(HttpMethod.GET, "/health").permitAll()
|
||||
.requestMatchers(HttpMethod.GET, "/types/nodes/**").permitAll()
|
||||
.requestMatchers("/swagger-ui.html").permitAll()
|
||||
.requestMatchers("/swagger-ui/**").permitAll()
|
||||
.requestMatchers("/v3/api-docs/**").permitAll()
|
||||
.anyRequest().authenticated())
|
||||
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -8,14 +8,17 @@ import java.util.stream.Collectors;
|
|||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.web.server.WebServerException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import it.cnr.isti.workflow.manager.exceptions.WebException;
|
||||
import it.cnr.isti.workflow.manager.executors.ExecutionObject;
|
||||
import it.cnr.isti.workflow.manager.model.ExecutionContext;
|
||||
import it.cnr.isti.workflow.manager.model.flows.Flow;
|
||||
|
|
@ -28,6 +31,44 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
/**
|
||||
* The ExecutionController class provides RESTful endpoints for managing
|
||||
* execution objects and their associated contexts and inputs. It allows
|
||||
* clients to create, retrieve, update, and delete execution objects, as
|
||||
* well as prepare inputs for executions.
|
||||
*
|
||||
* <p>Endpoints include:
|
||||
* <ul>
|
||||
* <li>Creating a new execution for a given flow</li>
|
||||
* <li>Retrieving all executions or a specific execution by ID</li>
|
||||
* <li>Retrieving all execution contexts</li>
|
||||
* <li>Starting an execution</li>
|
||||
* <li>Preparing string or file inputs for an execution</li>
|
||||
* <li>Deleting an execution</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Exception handling is provided for cases where a requested flow or
|
||||
* execution is not found, returning appropriate HTTP status codes.
|
||||
*
|
||||
* <p>Security is enforced using the "bearerAuth" security requirement.
|
||||
*
|
||||
* <p>Dependencies:
|
||||
* <ul>
|
||||
* <li>{@link FlowRepository} for accessing flow data</li>
|
||||
* <li>{@link ExecutionService} for managing execution logic</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Logging is performed using SLF4J to provide insights into the operations
|
||||
* performed by the controller.
|
||||
*
|
||||
* <p>Annotations:
|
||||
* <ul>
|
||||
* <li>{@code @RestController} to define this class as a REST controller</li>
|
||||
* <li>{@code @RequestMapping("/executions")} to map requests to the "/executions" path</li>
|
||||
* <li>{@code @SecurityRequirement(name = "bearerAuth")} to enforce security</li>
|
||||
* </ul>
|
||||
*/
|
||||
@SecurityRequirement(name = "bearerAuth")
|
||||
@RestController
|
||||
@RequestMapping("/executions")
|
||||
public class ExecutionController {
|
||||
|
|
@ -40,6 +81,16 @@ public class ExecutionController {
|
|||
@Autowired
|
||||
ExecutionService executionService;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new execution object for the specified flow.
|
||||
*
|
||||
* @param flowId the ID of the flow for which the execution is to be created
|
||||
* @return the created {@link ExecutionObject}
|
||||
* @throws IllegalArgumentException if the flow with the specified ID is not found
|
||||
* @throws WebServerException if an error occurs while creating the execution
|
||||
*/
|
||||
@Operation(summary = "Creates an execution", description = "Creates a new execution object for the specified flow.")
|
||||
@PostMapping()
|
||||
public ExecutionObject create(@RequestBody String flowId) {
|
||||
logger.info("Creating execution for flow {}", flowId);
|
||||
|
|
@ -50,39 +101,104 @@ public class ExecutionController {
|
|||
return eo;
|
||||
} catch (Throwable e) {
|
||||
logger.error("Error creating execution for flow {}", flowId, e);
|
||||
throw new WebServerException("Error while creating execution", e);
|
||||
throw new WebException(HttpStatus.INTERNAL_SERVER_ERROR,"Error while creating execution");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all executions.
|
||||
*
|
||||
* @return a list of {@link ExecutionObject} representing all executions.
|
||||
*/
|
||||
@Operation(summary = "Retrieves executions", description = "Retrieves a list of all executions")
|
||||
@GetMapping()
|
||||
public List<ExecutionObject> getAll() {
|
||||
return executionService.getAllExecutions();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves all execution contexts.
|
||||
*
|
||||
* @return a map of execution IDs to their corresponding {@link ExecutionContext}
|
||||
*/
|
||||
@Operation(summary = "Retrieves contexts", description = "Retrieves all execution contexts")
|
||||
@GetMapping(path = "contexts")
|
||||
public Map<String,ExecutionContext> getAllContexts() {
|
||||
return executionService.getAllExecutions().stream().collect(Collectors.toMap(ExecutionObject::getId, ExecutionObject::getContext));
|
||||
}
|
||||
|
||||
@GetMapping(path = "{id}")
|
||||
/**
|
||||
* Retrieves a specific execution by its ID.
|
||||
*
|
||||
* @param id the ID of the execution to retrieve
|
||||
* @return the {@link ExecutionObject} with the specified ID
|
||||
* @throws IllegalArgumentException if the execution with the specified ID is not found
|
||||
*/
|
||||
@Operation(summary = "Retrieves an execution", description = "Retrieves a specific execution by its ID")
|
||||
public ExecutionObject get(@PathVariable String id) {
|
||||
return executionService.getExecution(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an execution with the specified ID.
|
||||
*
|
||||
* @param id the unique identifier of the execution to be deleted
|
||||
* @return a ResponseEntity indicating the result of the operation
|
||||
*/
|
||||
@DeleteMapping(path = "{id}")
|
||||
@Operation(summary = "Deletes an execution", description = "Deletes an execution with the specified ID")
|
||||
public ResponseEntity<?> delete(@PathVariable String id) {
|
||||
executionService.removeExecution(id);
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the execution of a workflow with the given ID.
|
||||
*
|
||||
* @param id the unique identifier of the workflow to start
|
||||
* @return the {@link ExecutionObject} representing the started execution
|
||||
*/
|
||||
@PutMapping(path = "{id}/start")
|
||||
@Operation(summary = "Starts an execution", description = "Starts the execution of a workflow with the given ID")
|
||||
public ExecutionObject start(@PathVariable String id) {
|
||||
return executionService.startExecution(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepares the input for an execution by associating a given input string
|
||||
* with a specific input name and execution ID.
|
||||
*
|
||||
* @param input The input string to be prepared and associated.
|
||||
* @param inputName The name of the input to be associated with the execution.
|
||||
* @param id The unique identifier of the execution.
|
||||
* @return An {@link ExecutionObject} representing the updated execution state
|
||||
* after preparing the input.
|
||||
*/
|
||||
@PutMapping(path = "{id}/input/{inputName}")
|
||||
@Operation(summary = "Prepares string inputs", description = "Prepares the input for an execution by associating a given input string with a specific input name and execution ID.")
|
||||
public ExecutionObject prepareStringInputs(@RequestBody String input, @PathVariable String inputName,
|
||||
@PathVariable String id) {
|
||||
return executionService.prepareInput(id, inputName, input);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepares file inputs for a specific execution by uploading a file and associating it
|
||||
* with the given input name and execution ID.
|
||||
*
|
||||
* @param file The multipart file to be uploaded and processed.
|
||||
* @param inputName The name of the input to associate the file with.
|
||||
* @param id The ID of the execution to which the input belongs.
|
||||
* @return An {@link ExecutionObject} representing the updated execution state after
|
||||
* preparing the input.
|
||||
* @throws WebServerException If an error occurs while creating or transferring the file.
|
||||
*/
|
||||
@PutMapping(path = "{id}/input/{inputName}", consumes = "multipart/form-data")
|
||||
@ResponseBody
|
||||
@Operation(summary = "Prepares file inputs", description = "Prepares file inputs for a specific execution by uploading a file and associating it with the given input name and execution ID.")
|
||||
public ExecutionObject prepareFileInputs(@RequestParam("file") MultipartFile file, @PathVariable String inputName,
|
||||
@PathVariable String id) {
|
||||
try {
|
||||
|
|
@ -95,8 +211,4 @@ public class ExecutionController {
|
|||
|
||||
}
|
||||
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
public ResponseEntity<?> executionNotFound(IllegalArgumentException exc) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ import org.springframework.http.HttpStatus;
|
|||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import it.cnr.isti.workflow.manager.exceptions.WebException;
|
||||
import it.cnr.isti.workflow.manager.model.auth.LoginEntity;
|
||||
import it.cnr.isti.workflow.manager.model.flows.Flow;
|
||||
|
|
@ -29,7 +29,32 @@ import org.springframework.web.bind.annotation.GetMapping;
|
|||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Controller for managing flows.
|
||||
*
|
||||
* This controller provides endpoints for creating, updating, retrieving, and listing flows.
|
||||
* It enforces security requirements and ensures that users can only access or modify flows
|
||||
* they have created or that are marked as public.
|
||||
*
|
||||
* Endpoints:
|
||||
* - POST /flows: Create a new flow.
|
||||
* - PUT /flows/{id}: Update an existing flow.
|
||||
* - GET /flows: Retrieve all flows created by the user or public flows.
|
||||
* - GET /flows/{id}: Retrieve a specific flow by its ID.
|
||||
*
|
||||
* Security:
|
||||
* - Requires bearer authentication.
|
||||
* - Users can only modify or retrieve flows they created unless the flow is public.
|
||||
*
|
||||
* Dependencies:
|
||||
* - FlowRepository: Repository for accessing and managing flow data.
|
||||
* - Logger: Used for logging flow creation and updates.
|
||||
*
|
||||
* Exceptions:
|
||||
* - WebException: Thrown for various HTTP error scenarios, such as invalid input,
|
||||
* unauthorized access, or resource not found.
|
||||
*/
|
||||
@SecurityRequirement(name = "bearerAuth")
|
||||
@RestController
|
||||
@RequestMapping("/flows")
|
||||
public class FlowsController {
|
||||
|
|
@ -40,7 +65,20 @@ public class FlowsController {
|
|||
FlowRepository flowRepository;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new flow.
|
||||
*
|
||||
* This method handles HTTP POST requests with a JSON payload to create a new flow.
|
||||
* It validates that the flow ID is null (as it must be generated during creation),
|
||||
* sets the creator's username, and saves the flow to the repository.
|
||||
*
|
||||
* @param flow The flow object to be created, provided in the request body.
|
||||
* @param userDetails The authenticated user's details, used to set the creator of the flow.
|
||||
* @return The saved flow object with its generated ID and other persisted details.
|
||||
* @throws WebException If the flow ID is not null, indicating an invalid creation request.
|
||||
*/
|
||||
@PostMapping(consumes = "application/json")
|
||||
@Operation(summary = "Create a new flow", description = "Creates a new flow in the system.")
|
||||
public Flow createFlow(@RequestBody Flow flow, @AuthenticationPrincipal LoginEntity userDetails) {
|
||||
//validateFlow(flow);
|
||||
if (flow.getId() != null)
|
||||
|
|
@ -52,7 +90,19 @@ public class FlowsController {
|
|||
return savedFlow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates and saves an existing Flow entity.
|
||||
*
|
||||
* @param id The ID of the Flow to be updated. Must match the ID of the provided Flow object.
|
||||
* @param flow The Flow object containing the updated data.
|
||||
* @param userDetails The authenticated user's details, used to verify ownership of the Flow.
|
||||
* @return The updated and saved Flow object.
|
||||
* @throws WebException If the provided Flow ID does not match the path variable ID (BAD_REQUEST),
|
||||
* if the Flow is not found (NOT_FOUND),
|
||||
* or if the authenticated user is not the creator of the Flow (FORBIDDEN).
|
||||
*/
|
||||
@PutMapping(path = "{id}", consumes = "application/json")
|
||||
@Operation(summary = "Update an existing flow", description = "Updates an existing flow in the system.")
|
||||
public Flow saveFlow(@PathVariable String id, @RequestBody Flow flow, @AuthenticationPrincipal LoginEntity userDetails) {
|
||||
//validateFlow(flow);
|
||||
if (!id.equals(flow.getId()))
|
||||
|
|
@ -62,12 +112,26 @@ public class FlowsController {
|
|||
if (!savedFlow.getCreatedBy().equals(userDetails.getUsername()))
|
||||
throw new WebException(HttpStatus.FORBIDDEN, "Flow not created by user");
|
||||
|
||||
savedFlow = flowRepository.save(savedFlow);
|
||||
savedFlow = flowRepository.save(flow);
|
||||
logger.info("Flow saved: {} ",savedFlow.getId());
|
||||
return savedFlow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all flows created by the authenticated user or public flows.
|
||||
*
|
||||
* <p>This endpoint is mapped to a GET request and provides a list of flows
|
||||
* that are either created by the currently authenticated user or are marked
|
||||
* as public. The method uses the user's authentication details to filter
|
||||
* the flows accordingly.</p>
|
||||
*
|
||||
* @param userDetails The authentication principal containing the details of
|
||||
* the currently authenticated user.
|
||||
* @return A list of {@link Flow} objects representing the flows accessible
|
||||
* to the authenticated user.
|
||||
*/
|
||||
@GetMapping()
|
||||
@Operation(summary = "Get all flows", description = "Retrieves all flows created by the user or public flows.")
|
||||
public List<Flow> getAllFlows(@AuthenticationPrincipal LoginEntity userDetails) {
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
System.out.println("Authentication: " + auth);
|
||||
|
|
@ -77,6 +141,21 @@ public class FlowsController {
|
|||
}
|
||||
|
||||
@GetMapping("{id}")
|
||||
@Operation(summary = "Get a flow by ID", description = "Retrieves a specific flow by its ID.")
|
||||
/**
|
||||
* Retrieves a specific flow by its ID.
|
||||
*
|
||||
* <p>This endpoint is mapped to a GET request and allows the retrieval of
|
||||
* a flow based on its unique identifier. The method checks if the flow
|
||||
* exists and whether the authenticated user has permission to access it.</p>
|
||||
*
|
||||
* @param id The ID of the flow to be retrieved.
|
||||
* @param userDetails The authentication principal containing the details of
|
||||
* the currently authenticated user.
|
||||
* @return The {@link Flow} object representing the requested flow.
|
||||
* @throws WebException If the flow is not found (NOT_FOUND) or if the user
|
||||
* does not have permission to access it (FORBIDDEN).
|
||||
*/
|
||||
public Flow getFlow(@PathVariable String id, @AuthenticationPrincipal LoginEntity userDetails) {
|
||||
Flow flowEntity = flowRepository.findById(id).orElseThrow(() -> new WebException(HttpStatus.NOT_FOUND,"Flow not found"));
|
||||
if (!flowEntity.getCreatedBy().equals(userDetails.getUsername()) && !flowEntity.isPublic())
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import it.cnr.isti.workflow.manager.exceptions.WebException;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import it.cnr.isti.workflow.manager.executors.Executor;
|
||||
import it.cnr.isti.workflow.manager.model.ExecutorDescriptor;
|
||||
import it.cnr.isti.workflow.manager.model.types.NodeDefinition;
|
||||
|
|
@ -29,46 +29,32 @@ public class NodeDefinitionController {
|
|||
@Autowired
|
||||
private List<Executor> executors;
|
||||
|
||||
@SecurityRequirement(name = "bearerAuth")
|
||||
@GetMapping("/nodes")
|
||||
public List<NodeDefinition> getNodes() {
|
||||
try {
|
||||
return (List<NodeDefinition>) repository.findAll();
|
||||
} catch (Throwable e) {
|
||||
logger.error("Error retrieving nodes", e);
|
||||
throw new RuntimeException("Error retrieving nodes", e);
|
||||
}
|
||||
return (List<NodeDefinition>) repository.findAll();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/nodes/types")
|
||||
public List<String> getStoredNodeTypes() {
|
||||
try {
|
||||
return repository.getUsedTypes();
|
||||
} catch (Throwable e) {
|
||||
logger.error("Error retrieving stored types", e);
|
||||
throw new WebException(HttpStatus.INTERNAL_SERVER_ERROR, "Error retrieving stored types");
|
||||
}
|
||||
return repository.getUsedTypes();
|
||||
|
||||
}
|
||||
|
||||
@GetMapping("/nodes/categories")
|
||||
public List<String> getStoredNodeCategories() {
|
||||
try {
|
||||
return repository.getCategories();
|
||||
} catch (Throwable e) {
|
||||
logger.error("Error retrieving stored categories", e);
|
||||
throw new WebException(HttpStatus.INTERNAL_SERVER_ERROR, "Error retrieving stored categories");
|
||||
}
|
||||
return repository.getCategories();
|
||||
}
|
||||
|
||||
@SecurityRequirement(name = "bearerAuth")
|
||||
@PostMapping("/nodes")
|
||||
void addNode(@RequestBody NodeDefinition node) {
|
||||
try {
|
||||
repository.save(node);
|
||||
} catch (Exception e) {
|
||||
logger.error("Error saving node", e);
|
||||
throw new RuntimeException("Error saving node", e);
|
||||
}
|
||||
repository.save(node);
|
||||
}
|
||||
|
||||
@SecurityRequirement(name = "bearerAuth")
|
||||
@GetMapping("/executors")
|
||||
public List<ExecutorDescriptor> getAvailableExecutors() {
|
||||
return executors.stream().map(entry -> entry.getDescriptor(null)).toList();
|
||||
|
|
|
|||
|
|
@ -1,16 +1,23 @@
|
|||
package it.cnr.isti.workflow.manager.exceptions;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
|
||||
@ControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler(WebException.class)
|
||||
public ResponseEntity<String> handleWebException(WebException ex) {
|
||||
@ExceptionHandler(ResourceNotFoundException.class)
|
||||
public ResponseEntity<String> handleNotFound(ResourceNotFoundException ex, WebRequest request) {
|
||||
return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ResponseEntity<String> handleGenericException(Exception ex) {
|
||||
return ResponseEntity
|
||||
.status(ex.getStatus())
|
||||
.body(ex.getMessage());
|
||||
.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body("An unexpected error occurred: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package it.cnr.isti.workflow.manager.exceptions;
|
||||
|
||||
public class InvalidStateException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public InvalidStateException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public InvalidStateException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public InvalidStateException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public InvalidStateException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package it.cnr.isti.workflow.manager.exceptions;
|
||||
|
||||
public class ResourceNotFoundException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ResourceNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ResourceNotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -13,4 +13,4 @@ public class WebException extends RuntimeException {
|
|||
public HttpStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,22 +14,29 @@ import lombok.Setter;
|
|||
public class ExecutionContext {
|
||||
|
||||
public enum Status {
|
||||
CREATED(true),
|
||||
INITIALIZING(true),
|
||||
READY(true),
|
||||
RUNNING(false),
|
||||
SUCCESS(false),
|
||||
ERROR(false);
|
||||
CREATED(true, false),
|
||||
INITIALIZING(true, false),
|
||||
READY(true, false),
|
||||
RUNNING(false, false),
|
||||
SUCCESS(false, true),
|
||||
ERROR(false, true);
|
||||
|
||||
private boolean initState;
|
||||
|
||||
Status(boolean initState) {
|
||||
private boolean finalState;
|
||||
|
||||
Status(boolean initState, boolean finalState) {
|
||||
this.initState = initState;
|
||||
this.finalState = finalState;
|
||||
}
|
||||
|
||||
public boolean isInitState() {
|
||||
return initState;
|
||||
}
|
||||
|
||||
public boolean isFinaltate() {
|
||||
return finalState;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> inputs = new HashMap<>();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import java.util.Map;
|
|||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import it.cnr.isti.workflow.manager.executors.ExecutionObject;
|
||||
import it.cnr.isti.workflow.manager.model.ExecutionContext.Status;
|
||||
import it.cnr.isti.workflow.manager.model.flows.Flow;
|
||||
|
|
@ -26,7 +25,10 @@ public class ExecutionService {
|
|||
}
|
||||
|
||||
public ExecutionObject getExecution(String id) {
|
||||
return executions.get(id);
|
||||
ExecutionObject toReturn = executions.get(id);
|
||||
if (toReturn == null)
|
||||
throw new IllegalArgumentException("Execution with id " + id + " not found");
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public List<ExecutionObject> getAllExecutions() {
|
||||
|
|
@ -34,14 +36,16 @@ public class ExecutionService {
|
|||
}
|
||||
|
||||
public void removeExecution(String id) {
|
||||
if (!executions.containsKey(id))
|
||||
throw new IllegalArgumentException("Execution with id " + id + " not found");
|
||||
if (executions.get(id).getContext().getStatus() == Status.RUNNING)
|
||||
throw new IllegalStateException("Execution with id "+id+" is still running");
|
||||
executions.remove(id);
|
||||
}
|
||||
|
||||
public ExecutionObject prepareInput(String id, String key, Object input) {
|
||||
ExecutionObject eo = getExecution(id);
|
||||
if (eo == null)
|
||||
throw new IllegalArgumentException("Execution with id " + id + " not found");
|
||||
|
||||
|
||||
if (!eo.getContext().getStatus().isInitState()) {
|
||||
throw new IllegalStateException("Execution with id " + id
|
||||
+ " is not in initialization status (CURRENT STATUS is " + eo.getContext().getStatus() + ")");
|
||||
|
|
@ -58,8 +62,7 @@ public class ExecutionService {
|
|||
|
||||
public ExecutionObject startExecution(String id) {
|
||||
ExecutionObject eo = getExecution(id);
|
||||
if (eo == null)
|
||||
throw new IllegalArgumentException("Execution with id " + id + " not found");
|
||||
|
||||
if (eo.getContext().getStatus() != Status.READY) {
|
||||
throw new IllegalStateException("Execution with id " + id + " is not in READY status (CURRENT STATUS is "
|
||||
+ eo.getContext().getStatus() + ")");
|
||||
|
|
|
|||
Loading…
Reference in New Issue