This commit is contained in:
2021-12-16 11:42:27 +01:00
parent 27ccc54458
commit 6c17b20c55
60 changed files with 947 additions and 216 deletions

View File

@@ -12,7 +12,6 @@ public class TapasTasksApplication {
public static void main(String[] args) {
SpringApplication tapasTasksApp = new SpringApplication(TapasTasksApplication.class);
tapasTasksApp.run(args);
}
}

View File

@@ -18,6 +18,7 @@ import org.springframework.web.server.ResponseStatusException;
import java.io.IOException;
import java.util.Optional;
import java.util.logging.Logger;
/**
@@ -39,7 +40,9 @@ import java.util.Optional;
public class TaskEventHttpDispatcher {
// The standard media type for JSON Patch registered with IANA
// See: https://www.iana.org/assignments/media-types/application/json-patch+json
private final static String JSON_PATCH_MEDIA_TYPE = "application/json-patch+json";
private static final String JSON_PATCH_MEDIA_TYPE = "application/json-patch+json";
Logger logger = Logger.getLogger(TaskEventHttpDispatcher.class.getName());
/**
* Handles HTTP PATCH requests with a JSON Patch payload. Routes the requests based on the
@@ -55,6 +58,7 @@ public class TaskEventHttpDispatcher {
@PatchMapping(path = "/tasks/{taskId}", consumes = {JSON_PATCH_MEDIA_TYPE})
public ResponseEntity<String> dispatchTaskEvents(@PathVariable("taskId") String taskId,
@RequestBody JsonNode payload) {
logger.info("TaskList | Incoming patch task request for task: " + taskId);
try {
// Throw an exception if the JSON Patch format is invalid. This call is only used to
// validate the JSON PATCH syntax.
@@ -78,6 +82,8 @@ public class TaskEventHttpDispatcher {
case EXECUTED:
listener = new TaskExecutedEventListenerHttpAdapter();
break;
default:
break;
}
}
@@ -92,6 +98,7 @@ public class TaskEventHttpDispatcher {
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add(HttpHeaders.CONTENT_TYPE, TaskJsonRepresentation.MEDIA_TYPE);
logger.info("TaskList | Task with id " + taskId + " patched successfuly");
return new ResponseEntity<>(TaskJsonRepresentation.serialize(task), responseHeaders,
HttpStatus.OK);
} catch (TaskNotFoundException e) {

View File

@@ -17,6 +17,7 @@ import org.springframework.web.server.ResponseStatusException;
import javax.validation.ConstraintViolationException;
import java.util.Optional;
import java.util.logging.Logger;
/**
* Controller that handles HTTP requests for creating new tasks. This controller implements the
@@ -35,6 +36,8 @@ import java.util.Optional;
public class AddNewTaskToTaskListWebController {
private final AddNewTaskToTaskListUseCase addNewTaskToTaskListUseCase;
Logger logger = Logger.getLogger(AddNewTaskToTaskListWebController.class.getName());
// Used to retrieve properties from application.properties
@Autowired
private Environment environment;
@@ -45,6 +48,7 @@ public class AddNewTaskToTaskListWebController {
@PostMapping(path = "/tasks/", consumes = {TaskJsonRepresentation.MEDIA_TYPE})
public ResponseEntity<String> addNewTaskTaskToTaskList(@RequestBody TaskJsonRepresentation payload) {
logger.info("TaskList | Create new task request.");
try {
Task.TaskName taskName = new Task.TaskName(payload.getTaskName());
Task.TaskType taskType = new Task.TaskType(payload.getTaskType());
@@ -76,9 +80,7 @@ public class AddNewTaskToTaskListWebController {
HttpStatus.CREATED);
} catch (JsonProcessingException e) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());
} catch (ConstraintViolationException e) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage());
} catch (NullPointerException e) {
} catch (ConstraintViolationException | NullPointerException e) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage());
}
}

View File

@@ -8,30 +8,28 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;
import java.util.logging.Logger;
import javax.validation.ConstraintViolationException;
@RestController
public class CompleteTaskWebController {
private final CompleteTaskUseCase completeTaskUseCase;
Logger logger = Logger.getLogger(CompleteTaskWebController.class.getName());
public CompleteTaskWebController(CompleteTaskUseCase completeTaskUseCase){
this.completeTaskUseCase = completeTaskUseCase;
}
@PostMapping(path = "/tasks/completeTask")
public ResponseEntity<String> completeTask (@RequestBody TaskJsonRepresentation payload) {
System.out.println("completeTask");
System.out.println(payload.getTaskId());
logger.info("TaskList | Complete task request.");
try {
CompleteTaskCommand command = new CompleteTaskCommand(
@@ -43,6 +41,7 @@ public class CompleteTaskWebController {
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add(HttpHeaders.CONTENT_TYPE, TaskJsonRepresentation.MEDIA_TYPE);
logger.info("TaskList | Task completed successfuly");
return new ResponseEntity<>(TaskJsonRepresentation.serialize(updateATask), responseHeaders, HttpStatus.ACCEPTED);
} catch (JsonProcessingException e) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());

View File

@@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
import java.util.Optional;
import java.util.logging.Logger;
/**
* Controller that handles HTTP GET requests for retrieving tasks. This controller implements the
@@ -22,6 +23,8 @@ import java.util.Optional;
public class RetrieveTaskFromTaskListWebController {
private final RetrieveTaskFromTaskListUseCase retrieveTaskFromTaskListUseCase;
Logger logger = Logger.getLogger(RetrieveTaskFromTaskListWebController.class.getName());
public RetrieveTaskFromTaskListWebController(RetrieveTaskFromTaskListUseCase retrieveTaskFromTaskListUseCase) {
this.retrieveTaskFromTaskListUseCase = retrieveTaskFromTaskListUseCase;
}
@@ -35,6 +38,7 @@ public class RetrieveTaskFromTaskListWebController {
*/
@GetMapping(path = "/tasks/{taskId}")
public ResponseEntity<String> retrieveTaskFromTaskList(@PathVariable("taskId") String taskId) {
logger.info("TaskList | Retrieving task with id: " + taskId);
RetrieveTaskFromTaskListQuery query = new RetrieveTaskFromTaskListQuery(new Task.TaskId(taskId));
Optional<Task> updatedTaskOpt = retrieveTaskFromTaskListUseCase.retrieveTaskFromTaskList(query);

View File

@@ -28,7 +28,6 @@ public class TaskPersistenceAdapter implements
@Override
public Task loadTask(Task.TaskId taskId, TaskList.TaskListName taskListName) {
MongoTaskDocument mongoTaskDocument = taskRepository.findByTaskId(taskId.getValue(),taskListName.getValue());
Task task = taskMapper.mapToDomainEntity(mongoTaskDocument);
return task;
return taskMapper.mapToDomainEntity(mongoTaskDocument);
}
}

View File

@@ -3,8 +3,6 @@ package ch.unisg.tapastasks.tasks.adapter.out.web;
import ch.unisg.tapastasks.tasks.application.port.out.CanTaskBeDeletedPort;
import ch.unisg.tapastasks.tasks.domain.DeleteTaskEvent;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
@@ -16,21 +14,23 @@ import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@Component
@Primary
public class CanTaskBeDeletedWebAdapter implements CanTaskBeDeletedPort {
Logger logger = Logger.getLogger(CanTaskBeDeletedWebAdapter.class.getName());
@Value("${roster.uri}")
String server;
@Override
public boolean canTaskBeDeletedEvent(DeleteTaskEvent event){
//Todo: Question: How do we include the URI from the DeleteTaskEvent? Do we even need it?
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(server+"$/task/" + event.taskId))
.uri(URI.create(server + "/task/" + event.taskId))
.header("Content-Type", "application/task+json")
.DELETE()
.build();
@@ -39,9 +39,10 @@ public class CanTaskBeDeletedWebAdapter implements CanTaskBeDeletedPort {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
return response.statusCode() == HttpStatus.OK.value();
} catch (IOException e){
e.printStackTrace();
logger.log(Level.SEVERE, e.getLocalizedMessage(), e);
} catch (InterruptedException e) {
e.printStackTrace();
logger.log(Level.SEVERE, e.getLocalizedMessage(), e);
Thread.currentThread().interrupt();
}
return false;

View File

@@ -8,9 +8,6 @@ import java.net.http.HttpResponse;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.github.fge.jsonpatch.JsonPatch;
import com.github.fge.jsonpatch.JsonPatchOperation;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -33,6 +30,8 @@ public class ExternalTaskExecutedWebAdapter implements ExternalTaskExecutedEvent
@Override
public void handleEvent(ExternalTaskExecutedEvent externalTaskExecutedEvent) {
logger.info("TaskList | Notify external task-list about task execution.");
JSONObject op1;
JSONObject op2;
try {

View File

@@ -15,24 +15,30 @@ import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@Component
@Primary
public class PublishNewTaskAddedEventWebAdapter implements NewTaskAddedEventPort {
Logger logger = Logger.getLogger(PublishNewTaskAddedEventWebAdapter.class.getName());
@Value("${roster.uri}")
String server;
@Value("${baseuri}")
String baseuri;
@Override
public void publishNewTaskAddedEvent(NewTaskAddedEvent event) {
//Here we would need to work with DTOs in case the payload of calls becomes more complex
// Here we would need to work with DTOs in case the payload of calls becomes more complex
var values = new HashMap<String, String>() {{
put("taskID", event.taskId);
put("taskType", event.taskType);
put("inputData", event.inputData);
}};
var values = new HashMap<String, String>();
values.put("taskID", event.taskId);
values.put("taskType", event.taskType);
values.put("inputData", event.inputData);
var objectMapper = new ObjectMapper();
String requestBody = null;
@@ -46,15 +52,17 @@ public class PublishNewTaskAddedEventWebAdapter implements NewTaskAddedEventPort
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(server+"/task"))
.header("Content-Type", "application/task+json")
.header("Link", "<" + baseuri + "tasks/" + event.taskId + ">; rel=\"task\"")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
client.send(request, HttpResponse.BodyHandlers.ofString());
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
logger.log(Level.SEVERE, e.getLocalizedMessage(), e);
Thread.currentThread().interrupt();
}
}
}

View File

@@ -3,12 +3,13 @@ package ch.unisg.tapastasks.tasks.application.port.in;
import ch.unisg.tapastasks.common.SelfValidating;
import ch.unisg.tapastasks.tasks.domain.Task.OutputData;
import ch.unisg.tapastasks.tasks.domain.Task.TaskId;
import ch.unisg.tapastasks.tasks.domain.Task.TaskResult;
import lombok.EqualsAndHashCode;
import lombok.Value;
import javax.validation.constraints.NotNull;
@Value
@EqualsAndHashCode(callSuper=false)
public class CompleteTaskCommand extends SelfValidating<CompleteTaskCommand> {
@NotNull
private final TaskId taskId;

View File

@@ -3,11 +3,13 @@ package ch.unisg.tapastasks.tasks.application.port.in;
import ch.unisg.tapastasks.common.SelfValidating;
import ch.unisg.tapastasks.tasks.domain.Task.TaskId;
import ch.unisg.tapastasks.tasks.domain.Task.OriginalTaskUri;
import lombok.EqualsAndHashCode;
import lombok.Value;
import javax.validation.constraints.NotNull;
@Value
@EqualsAndHashCode(callSuper=false)
public class DeleteTaskCommand extends SelfValidating<DeleteTaskCommand> {
@NotNull
private final TaskId taskId;

View File

@@ -25,14 +25,11 @@ public class AddNewTaskToTaskListService implements AddNewTaskToTaskListUseCase
private final NewTaskAddedEventPort newTaskAddedEventPort;
private final AddTaskPort addTaskToRepositoryPort;
private final TaskListLock taskListLock;
@Override
public Task addNewTaskToTaskList(AddNewTaskToTaskListCommand command) {
TaskList taskList = TaskList.getTapasTaskList();
// taskListLock.lockTaskList(taskList.getTaskListName());
Task newTask;
if (command.getOriginalTaskUri().isPresent() && command.getInputData().isPresent()) {
@@ -49,7 +46,6 @@ public class AddNewTaskToTaskListService implements AddNewTaskToTaskListUseCase
}
addTaskToRepositoryPort.addTask(newTask);
// taskListLock.releaseTaskList(taskList.getTaskListName());
//Here we are using the application service to emit the domain event to the outside of the bounded context.
//This event should be considered as a light-weight "integration event" to communicate with other services.

View File

@@ -1,6 +1,7 @@
server.port=8081
spring.data.mongodb.uri=mongodb://root:password@localhost:27017/
spring.data.mongodb.database=tapas-tasks
# baseuri=http://e021-77-59-152-182.ngrok.io/
baseuri=https://tapas-tasks.86-119-34-23.nip.io/
roster.uri=http://127.0.0.1:8082

View File

@@ -22,7 +22,7 @@ public class AddNewTaskToTaskListServiceTest {
private final TaskListLock taskListLock = Mockito.mock(TaskListLock.class);
private final NewTaskAddedEventPort newTaskAddedEventPort = Mockito.mock(NewTaskAddedEventPort.class);
private final AddNewTaskToTaskListService addNewTaskToTaskListService = new AddNewTaskToTaskListService(
newTaskAddedEventPort, addTaskPort, taskListLock);
newTaskAddedEventPort, addTaskPort);
@Test
void addingSucceeds() {